vfs: require i_size <= SIZE_MAX in kernel_read_file()
authorEric Biggers <ebiggers@google.com>
Fri, 7 Sep 2018 19:16:24 +0000 (12:16 -0700)
committerMimi Zohar <zohar@linux.ibm.com>
Wed, 10 Oct 2018 16:56:14 +0000 (12:56 -0400)
On 32-bit systems, the buffer allocated by kernel_read_file() is too
small if the file size is > SIZE_MAX, due to truncation to size_t.

Fortunately, since the 'count' argument to kernel_read() is also
truncated to size_t, only the allocated space is filled; then, -EIO is
returned since 'pos != i_size' after the read loop.

But this is not obvious and seems incidental.  We should be more
explicit about this case.  So, fail early if i_size > SIZE_MAX.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
fs/exec.c

index 1ebf6e5a521d9924aa6572bedba504efaf32ee9b..fc281b738a9822a652f7d19bb60ae15acd7a7ebf 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -908,14 +908,14 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,
                goto out;
 
        i_size = i_size_read(file_inode(file));
-       if (max_size > 0 && i_size > max_size) {
-               ret = -EFBIG;
-               goto out;
-       }
        if (i_size <= 0) {
                ret = -EINVAL;
                goto out;
        }
+       if (i_size > SIZE_MAX || (max_size > 0 && i_size > max_size)) {
+               ret = -EFBIG;
+               goto out;
+       }
 
        if (id != READING_FIRMWARE_PREALLOC_BUFFER)
                *buf = vmalloc(i_size);