summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Kasatkin <dmitry.kasatkin@huawei.com>2014-10-26 12:42:07 +0200
committerMimi Zohar <zohar@linux.vnet.ibm.com>2016-05-01 09:23:51 -0400
commit39d637af5aa7577f655c58b9e55587566c63a0af (patch)
treef185c2730ff632c3decf311d9f0a580a846883f0
parentda20dfe6b50ea4c1a82797b7ee8655a370535d73 (diff)
vfs: forbid write access when reading a file into memory
This patch is based on top of the "vfs: support for a common kernel file loader" patch set. In general when the kernel is reading a file into memory it does not want anything else writing to it. The kernel currently only forbids write access to a file being executed. This patch extends this locking to files being read by the kernel. Changelog: - moved function to kernel_read_file() - Mimi - updated patch description - Mimi Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com> Cc: Al Viro <viro@ZenIV.linux.org.uk> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Reviewed-by: Luis R. Rodriguez <mcgrof@kernel.org> Acked-by: Kees Cook <keescook@chromium.org>
-rw-r--r--fs/exec.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/fs/exec.c b/fs/exec.c
index c4010b8207a1..fdecb7615587 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -850,15 +850,25 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,
if (ret)
return ret;
+ ret = deny_write_access(file);
+ if (ret)
+ return ret;
+
i_size = i_size_read(file_inode(file));
- if (max_size > 0 && i_size > max_size)
- return -EFBIG;
- if (i_size <= 0)
- return -EINVAL;
+ if (max_size > 0 && i_size > max_size) {
+ ret = -EFBIG;
+ goto out;
+ }
+ if (i_size <= 0) {
+ ret = -EINVAL;
+ goto out;
+ }
*buf = vmalloc(i_size);
- if (!*buf)
- return -ENOMEM;
+ if (!*buf) {
+ ret = -ENOMEM;
+ goto out;
+ }
pos = 0;
while (pos < i_size) {
@@ -876,18 +886,21 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,
if (pos != i_size) {
ret = -EIO;
- goto out;
+ goto out_free;
}
ret = security_kernel_post_read_file(file, *buf, i_size, id);
if (!ret)
*size = pos;
-out:
+out_free:
if (ret < 0) {
vfree(*buf);
*buf = NULL;
}
+
+out:
+ allow_write_access(file);
return ret;
}
EXPORT_SYMBOL_GPL(kernel_read_file);