On 14/05/2020 01:27, Kees Cook wrote: > On Wed, May 13, 2020 at 11:37:16AM -0400, Stephen Smalley wrote: >> On Tue, May 5, 2020 at 11:33 AM Mickaël Salaün <mic@xxxxxxxxxxx> wrote: >>> >>> Enable to forbid access to files open with O_MAYEXEC. Thanks to the >>> noexec option from the underlying VFS mount, or to the file execute >>> permission, userspace can enforce these execution policies. This may >>> allow script interpreters to check execution permission before reading >>> commands from a file, or dynamic linkers to allow shared object loading. >>> >>> Add a new sysctl fs.open_mayexec_enforce to enable system administrators >>> to enforce two complementary security policies according to the >>> installed system: enforce the noexec mount option, and enforce >>> executable file permission. Indeed, because of compatibility with >>> installed systems, only system administrators are able to check that >>> this new enforcement is in line with the system mount points and file >>> permissions. A following patch adds documentation. >>> >>> For tailored Linux distributions, it is possible to enforce such >>> restriction at build time thanks to the CONFIG_OMAYEXEC_STATIC option. >>> The policy can then be configured with CONFIG_OMAYEXEC_ENFORCE_MOUNT and >>> CONFIG_OMAYEXEC_ENFORCE_FILE. >>> >>> Being able to restrict execution also enables to protect the kernel by >>> restricting arbitrary syscalls that an attacker could perform with a >>> crafted binary or certain script languages. It also improves multilevel >>> isolation by reducing the ability of an attacker to use side channels >>> with specific code. These restrictions can natively be enforced for ELF >>> binaries (with the noexec mount option) but require this kernel >>> extension to properly handle scripts (e.g., Python, Perl). To get a >>> consistent execution policy, additional memory restrictions should also >>> be enforced (e.g. thanks to SELinux). >>> >>> Signed-off-by: Mickaël Salaün <mic@xxxxxxxxxxx> >>> Reviewed-by: Thibaut Sautereau <thibaut.sautereau@xxxxxxxxxxx> >>> Cc: Aleksa Sarai <cyphar@xxxxxxxxxx> >>> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> >>> Cc: Kees Cook <keescook@xxxxxxxxxxxx> >>> --- >> >>> diff --git a/fs/namei.c b/fs/namei.c >>> index 33b6d372e74a..70f179f6bc6c 100644 >>> --- a/fs/namei.c >>> +++ b/fs/namei.c >>> @@ -411,10 +412,90 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask) >> <snip> >>> +#if defined(CONFIG_SYSCTL) && !defined(CONFIG_OMAYEXEC_STATIC) >>> +int proc_omayexec(struct ctl_table *table, int write, void __user *buffer, >>> + size_t *lenp, loff_t *ppos) >>> +{ >>> + int error; >>> + >>> + if (write) { >>> + struct ctl_table table_copy; >>> + int tmp_mayexec_enforce; >>> + >>> + if (!capable(CAP_MAC_ADMIN)) >>> + return -EPERM; >> >> Not fond of using CAP_MAC_ADMIN here (or elsewhere outside of security >> modules). The ability to set this sysctl is not equivalent to being >> able to load a MAC policy, set arbitrary MAC labels on >> processes/files, etc. > > That's fair. In that case, perhaps this could just use the existing > _sysadmin helper? (Though I should note that these perm checks actually > need to be in the open, not the read/write ... I thought there was a > series to fix that, but I can't find it now. Regardless, that's > orthogonal to this series.) OK, I'll switch to CAP_SYS_ADMIN with proc_dointvec_minmax_sysadmin().