Re: [PATCH v6 1/8] fs: introduce kernel_pread_file* support

2020-06-05 Thread Scott Branden

Hi Matthew,

On 2020-06-05 8:20 p.m., Matthew Wilcox wrote:

On Fri, Jun 05, 2020 at 03:59:52PM -0700, Scott Branden wrote:

-int kernel_read_file(struct file *file, void **buf, loff_t *size,
-loff_t max_size, enum kernel_read_file_id id)
-{
-   loff_t i_size, pos;
+int kernel_pread_file(struct file *file, void **buf, loff_t *size,
+ loff_t pos, loff_t max_size,
+ enum kernel_pread_opt opt,
+ enum kernel_read_file_id id)

What is this 'kernel_pread_opt' foolishness?  Why not just pass in
~0UL as max_size if you want the entire file?

That is not how existing kernel_read_file api works - max_size is specified.
I guess not everyone has unlimited memory to read a file on any size.



-int kernel_read_file_from_path_initns(const char *path, void **buf,
- loff_t *size, loff_t max_size,
- enum kernel_read_file_id id)
+extern int kernel_pread_file_from_path_initns(const char *path, void **buf,

extern?  really?  i'm shocked gcc doesn't vomit on that.

A typo.  thanks.  You'll have to ask the compiler gods about your shock.



Re: [PATCH v6 1/8] fs: introduce kernel_pread_file* support

2020-06-05 Thread Matthew Wilcox
On Fri, Jun 05, 2020 at 03:59:52PM -0700, Scott Branden wrote:
> -int kernel_read_file(struct file *file, void **buf, loff_t *size,
> -  loff_t max_size, enum kernel_read_file_id id)
> -{
> - loff_t i_size, pos;
> +int kernel_pread_file(struct file *file, void **buf, loff_t *size,
> +   loff_t pos, loff_t max_size,
> +   enum kernel_pread_opt opt,
> +   enum kernel_read_file_id id)

What is this 'kernel_pread_opt' foolishness?  Why not just pass in
~0UL as max_size if you want the entire file?

> -int kernel_read_file_from_path_initns(const char *path, void **buf,
> -   loff_t *size, loff_t max_size,
> -   enum kernel_read_file_id id)
> +extern int kernel_pread_file_from_path_initns(const char *path, void **buf,

extern?  really?  i'm shocked gcc doesn't vomit on that.



[PATCH v6 1/8] fs: introduce kernel_pread_file* support

2020-06-05 Thread Scott Branden
Add kernel_pread_file* support to kernel to allow for partial read
of files with an offset into the file.  Existing kernel_read_file
functions call new kernel_pread_file functions with offset=0 and
opt=KERNEL_PREAD_WHOLE.

Signed-off-by: Scott Branden 
---
 fs/exec.c  | 95 --
 include/linux/fs.h | 29 ++
 2 files changed, 103 insertions(+), 21 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index de90a66587ab..e5c241c07b75 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -925,10 +925,15 @@ struct file *open_exec(const char *name)
 }
 EXPORT_SYMBOL(open_exec);
 
-int kernel_read_file(struct file *file, void **buf, loff_t *size,
-loff_t max_size, enum kernel_read_file_id id)
-{
-   loff_t i_size, pos;
+int kernel_pread_file(struct file *file, void **buf, loff_t *size,
+ loff_t pos, loff_t max_size,
+ enum kernel_pread_opt opt,
+ enum kernel_read_file_id id)
+{
+   loff_t alloc_size;
+   loff_t buf_pos;
+   loff_t read_end;
+   loff_t i_size;
ssize_t bytes = 0;
int ret;
 
@@ -948,21 +953,31 @@ int kernel_read_file(struct file *file, void **buf, 
loff_t *size,
ret = -EINVAL;
goto out;
}
-   if (i_size > SIZE_MAX || (max_size > 0 && i_size > max_size)) {
+
+   /* Default read to end of file */
+   read_end = i_size;
+
+   /* Allow reading partial portion of file */
+   if ((opt == KERNEL_PREAD_PART) &&
+   (i_size > (pos + max_size)))
+   read_end = pos + max_size;
+
+   alloc_size = read_end - pos;
+   if (i_size > SIZE_MAX || (max_size > 0 && alloc_size > max_size)) {
ret = -EFBIG;
goto out;
}
 
if (id != READING_FIRMWARE_PREALLOC_BUFFER)
-   *buf = vmalloc(i_size);
+   *buf = vmalloc(alloc_size);
if (!*buf) {
ret = -ENOMEM;
goto out;
}
 
-   pos = 0;
-   while (pos < i_size) {
-   bytes = kernel_read(file, *buf + pos, i_size - pos, );
+   buf_pos = 0;
+   while (pos < read_end) {
+   bytes = kernel_read(file, *buf + buf_pos, read_end - pos, );
if (bytes < 0) {
ret = bytes;
goto out_free;
@@ -970,14 +985,16 @@ int kernel_read_file(struct file *file, void **buf, 
loff_t *size,
 
if (bytes == 0)
break;
+
+   buf_pos += bytes;
}
 
-   if (pos != i_size) {
+   if (pos != read_end) {
ret = -EIO;
goto out_free;
}
 
-   ret = security_kernel_post_read_file(file, *buf, i_size, id);
+   ret = security_kernel_post_read_file(file, *buf, alloc_size, id);
if (!ret)
*size = pos;
 
@@ -993,10 +1010,20 @@ int kernel_read_file(struct file *file, void **buf, 
loff_t *size,
allow_write_access(file);
return ret;
 }
+
+int kernel_read_file(struct file *file, void **buf, loff_t *size,
+loff_t max_size, enum kernel_read_file_id id)
+{
+   return kernel_pread_file(file, buf, size, 0, max_size,
+KERNEL_PREAD_WHOLE, id);
+}
 EXPORT_SYMBOL_GPL(kernel_read_file);
 
-int kernel_read_file_from_path(const char *path, void **buf, loff_t *size,
-  loff_t max_size, enum kernel_read_file_id id)
+int kernel_pread_file_from_path(const char *path, void **buf,
+   loff_t *size, loff_t pos,
+   loff_t max_size,
+   enum kernel_pread_opt opt,
+   enum kernel_read_file_id id)
 {
struct file *file;
int ret;
@@ -1008,15 +1035,24 @@ int kernel_read_file_from_path(const char *path, void 
**buf, loff_t *size,
if (IS_ERR(file))
return PTR_ERR(file);
 
-   ret = kernel_read_file(file, buf, size, max_size, id);
+   ret = kernel_pread_file(file, buf, size, pos, max_size, opt, id);
fput(file);
return ret;
 }
+
+int kernel_read_file_from_path(const char *path, void **buf, loff_t *size,
+  loff_t max_size, enum kernel_read_file_id id)
+{
+   return kernel_pread_file_from_path(path, buf, size, 0, max_size,
+  KERNEL_PREAD_WHOLE, id);
+}
 EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
 
-int kernel_read_file_from_path_initns(const char *path, void **buf,
- loff_t *size, loff_t max_size,
- enum kernel_read_file_id id)
+extern int kernel_pread_file_from_path_initns(const char *path, void **buf,
+ loff_t *size, loff_t pos,
+ loff_t max_size,
+