From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from e23smtp01.au.ibm.com ([202.81.31.143]:46496 "EHLO e23smtp01.au.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756625AbcBSNkK (ORCPT ); Fri, 19 Feb 2016 08:40:10 -0500 Received: from localhost by e23smtp01.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 19 Feb 2016 23:40:08 +1000 Message-ID: <1455889152.2906.107.camel@linux.vnet.ibm.com> Subject: Re: [PATCH] vfs: forbid write access when reading a file into memory From: Mimi Zohar To: "Luis R. Rodriguez" Cc: linux-security-module , Dmitry Kasatkin , Al Viro , Kees Cook , Dave Young , linux-fsdevel@vger.kernel.org, Dmitry Kasatkin Date: Fri, 19 Feb 2016 08:39:12 -0500 In-Reply-To: <20160216214333.GF25240@wotan.suse.de> References: <1455656045-21463-1-git-send-email-zohar@linux.vnet.ibm.com> <20160216214333.GF25240@wotan.suse.de> Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Sender: linux-fsdevel-owner@vger.kernel.org List-ID: 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 Cc: Al Viro Signed-off-by: Mimi Zohar Reviewed-by: Luis R. Rodriguez Acked-by: Kees Cook --- fs/exec.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 604f669..1b7d617 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -846,15 +846,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) { @@ -872,18 +882,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); -- 2.1.0