Re: [RFC PATCH v8 1/3] fs: Introduce AT_INTERPRETED flag for faccessat2(2)
From: Mimi Zohar <zohar@linux.ibm.com>
Date: 2020-09-08 17:33:57
Also in:
linux-fsdevel, linux-integrity, linux-security-module, lkml
On Tue, 2020-09-08 at 14:43 +0200, Mickaël Salaün wrote:
On 08/09/2020 14:28, Mimi Zohar wrote:quoted
Hi Mickael, On Tue, 2020-09-08 at 09:59 +0200, Mickaël Salaün wrote:quoted
diff --git a/fs/open.c b/fs/open.c index 9af548fb841b..879bdfbdc6fa 100644 --- a/fs/open.c +++ b/fs/open.c@@ -405,9 +405,13 @@ static long do_faccessat(int dfd, const char __user *filename, int mode, int fla if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; - if (flags & ~(AT_EACCESS | AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) + if (flags & ~(AT_EACCESS | AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH | + AT_INTERPRETED)) return -EINVAL; + /* Only allows X_OK with AT_INTERPRETED for now. */ + if ((flags & AT_INTERPRETED) && !(mode & S_IXOTH)) + return -EINVAL; if (flags & AT_SYMLINK_NOFOLLOW) lookup_flags &= ~LOOKUP_FOLLOW; if (flags & AT_EMPTY_PATH)@@ -426,7 +430,30 @@ static long do_faccessat(int dfd, const char __user *filename, int mode, int fla inode = d_backing_inode(path.dentry); - if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) { + if ((flags & AT_INTERPRETED)) { + /* + * For compatibility reasons, without a defined security policy + * (via sysctl or LSM), using AT_INTERPRETED must map the + * execute permission to the read permission. Indeed, from + * user space point of view, being able to execute data (e.g. + * scripts) implies to be able to read this data. + * + * The MAY_INTERPRETED_EXEC bit is set to enable LSMs to add + * custom checks, while being compatible with current policies. + */ + if ((mode & MAY_EXEC)) {Why is the ISREG() test being dropped? Without dropping it, there would be no reason for making the existing test an "else" clause.The ISREG() is not dropped, it is just moved below with the rest of the original code. The corresponding code (with the path_noexec call) for AT_INTERPRETED is added with the next commit, and it relies on the sysctl configuration for compatibility reasons.
Dropping the S_ISREG() check here without an explanation is wrong and probably unsafe, as it is only re-added in the subsequent patch and only for the "sysctl_interpreted_access" case. Adding this new test after the existing test is probably safer. If the original test fails, it returns the same value as this test -EACCES. Mimi
quoted
quoted
+ mode |= MAY_INTERPRETED_EXEC; + /* + * For compatibility reasons, if the system-wide policy + * doesn't enforce file permission checks, then + * replaces the execute permission request with a read + * permission request. + */ + mode &= ~MAY_EXEC; + /* To be executed *by* user space, files must be readable. */ + mode |= MAY_READ;