Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp4417445ybz; Tue, 28 Apr 2020 10:57:29 -0700 (PDT) X-Google-Smtp-Source: APiQypLcEwpiY1L2mJ8sP/lcvQUPYo4PoDblurRlor/tr9RN1m6iMh5w4UURrg5UgnaaA2EJbWou X-Received: by 2002:aa7:dcc3:: with SMTP id w3mr22537009edu.231.1588096649040; Tue, 28 Apr 2020 10:57:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1588096649; cv=none; d=google.com; s=arc-20160816; b=OPjJt11admY73592YkvUjJep9GZnIyvOiRyCiNVJyzhX2LGuSBaDEuF3CJvkk2cbGX rGVK4VVLOtC5CpjMNNsRnAxPJUfNxPRdGhHFPRvDw/EGHGfo0AuAWj9A8tAyGQAyyvuA KshrLp0FcdvIaumlenslzcNLyDQP210GgxV9lYs4b79a7Q1lHfUF5g1m/pvRD28cxccV OFFizpKEHmlyxlvig4I8M5tP8WNspCREqf3QE8vJ9YxXWxaP0gCVRol5RNCIQBkstOn8 jhR1fj58l1Y76hBpPHf2FGjgNOpdaM98/b4MpOmixeRsb8+xP9gueZ1T3XPOzNfsw1Cf Sj5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=duKNSBGJM9kEGrF5px/Q4Rve9+NfqvlL0geWuWploBU=; b=ThUH3m/oS2JaAc5HFFeoFMgOFnJA2QGM66QGBhz9SUr5BIQgYCls2zFTM6yjfBHU+J y/0EPRS1fdXeTt5mODOkikuZiCgR5r3HNmyrzc1EN5hYEBR2nof1Y5ZfXqJuCLeNQt2w qIUuKszLLXO4IC9jev9zhfmYZ+Ad4JIEIkk9QJQjGeWvN6wubIlLRaabCLJsTQo+Mp67 WW6MH5ubu38Ng7e2eHO5rR9FUg7kfqehThMKgBSzhB9yIuuYbkddanls5kb7dEq2PcZ6 Ub1QF30YDYZ+UI7jC/jGlaek9dd7tvKwjK1z7WweEFh4/Raoi2Mjd6i7bkLLMXoPlkQP 13ug== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id q10si2153094eji.306.2020.04.28.10.57.05; Tue, 28 Apr 2020 10:57:29 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728690AbgD1RwP (ORCPT + 99 others); Tue, 28 Apr 2020 13:52:15 -0400 Received: from smtp-bc0a.mail.infomaniak.ch ([45.157.188.10]:42855 "EHLO smtp-bc0a.mail.infomaniak.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728337AbgD1RwO (ORCPT ); Tue, 28 Apr 2020 13:52:14 -0400 Received: from smtp-2-0000.mail.infomaniak.ch (unknown [10.5.36.107]) by smtp-3-3000.mail.infomaniak.ch (Postfix) with ESMTPS id 49BTjT34bjzlhPD2; Tue, 28 Apr 2020 19:51:41 +0200 (CEST) Received: from localhost (unknown [94.23.54.103]) by smtp-2-0000.mail.infomaniak.ch (Postfix) with ESMTPA id 49BTjS6tr8zmVZjD; Tue, 28 Apr 2020 19:51:40 +0200 (CEST) From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= To: linux-kernel@vger.kernel.org Cc: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= , Aleksa Sarai , Alexei Starovoitov , Al Viro , Andy Lutomirski , Christian Heimes , Daniel Borkmann , Deven Bowers , Eric Chiang , Florian Weimer , James Morris , Jan Kara , Jann Horn , Jonathan Corbet , Kees Cook , Matthew Garrett , Matthew Wilcox , Michael Kerrisk , =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= , Mimi Zohar , =?UTF-8?q?Philippe=20Tr=C3=A9buchet?= , Scott Shell , Sean Christopherson , Shuah Khan , Steve Dower , Steve Grubb , Thibaut Sautereau , Vincent Strubel , kernel-hardening@lists.openwall.com, linux-api@vger.kernel.org, linux-security-module@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v3 1/5] fs: Add support for a RESOLVE_MAYEXEC flag on openat2(2) Date: Tue, 28 Apr 2020 19:51:25 +0200 Message-Id: <20200428175129.634352-2-mic@digikod.net> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200428175129.634352-1-mic@digikod.net> References: <20200428175129.634352-1-mic@digikod.net> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Antivirus: Dr.Web (R) for Unix mail servers drweb plugin ver.6.0.2.8 X-Antivirus-Code: 0x100000 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When the RESOLVE_MAYEXEC flag is passed, openat2(2) may be subject to additional restrictions depending on a security policy managed by the kernel through a sysctl or implemented by an LSM thanks to the inode_permission hook. The underlying idea is to be able to restrict scripts interpretation according to a policy defined by the system administrator. For this to be possible, script interpreters must use the RESOLVE_MAYEXEC flag appropriately. To be fully effective, these interpreters also need to handle the other ways to execute code: command line parameters (e.g., option -e for Perl), module loading (e.g., option -m for Python), stdin, file sourcing, environment variables, configuration files... According to the threat model, it may be acceptable to allow some script interpreters (e.g. Bash) to interpret commands from stdin, may it be a TTY or a pipe, because it may not be enough to (directly) perform syscalls. Further documentation can be found in a following patch. A simple security policy implementation, configured through a dedicated sysctl, is available in a following patch. This is an updated subset of the patch initially written by Vincent Strubel for CLIP OS 4: https://github.com/clipos-archive/src_platform_clip-patches/blob/f5cb330d6b684752e403b4e41b39f7004d88e561/1901_open_mayexec.patch This patch has been used for more than 11 years with customized script interpreters. Some examples (with the original name O_MAYEXEC) can be found here: https://github.com/clipos-archive/clipos4_portage-overlay/search?q=O_MAYEXEC Signed-off-by: Mickaël Salaün Signed-off-by: Thibaut Sautereau Signed-off-by: Vincent Strubel Cc: Aleksa Sarai Cc: Al Viro Cc: Kees Cook --- Changes since v2: * Replace O_MAYEXEC with RESOLVE_MAYEXEC from openat2(2). This change enables to not break existing application using bogus O_* flags that may be ignored by current kernels by using a new dedicated flag, only usable through openat2(2) (suggested by Jeff Layton). Using this flag will results in an error if the running kernel does not support it. User space needs to manage this case, as with other RESOLVE_* flags. The best effort approach to security (for most common distros) will simply consists of ignoring such an error and retry without RESOLVE_MAYEXEC. However, a fully controlled system may which to error out if such an inconsistency is detected. Changes since v1: * Set __FMODE_EXEC when using O_MAYEXEC to make this information available through the new fanotify/FAN_OPEN_EXEC event (suggested by Jan Kara and Matthew Bobrowski). --- fs/open.c | 6 ++++++ include/linux/fcntl.h | 2 +- include/linux/fs.h | 2 ++ include/uapi/linux/openat2.h | 6 ++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/open.c b/fs/open.c index 719b320ede52..ca5a145761a2 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1029,6 +1029,12 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op) if (flags & __O_SYNC) flags |= O_DSYNC; + /* Checks execution permissions on open. */ + if (how->resolve & RESOLVE_MAYEXEC) { + acc_mode |= MAY_OPENEXEC; + flags |= __FMODE_EXEC; + } + op->open_flag = flags; /* O_TRUNC implies we need access checks for write permissions */ diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h index 7bcdcf4f6ab2..a37e213220ad 100644 --- a/include/linux/fcntl.h +++ b/include/linux/fcntl.h @@ -19,7 +19,7 @@ /* List of all valid flags for the how->resolve argument: */ #define VALID_RESOLVE_FLAGS \ (RESOLVE_NO_XDEV | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_SYMLINKS | \ - RESOLVE_BENEATH | RESOLVE_IN_ROOT) + RESOLVE_BENEATH | RESOLVE_IN_ROOT | RESOLVE_MAYEXEC) /* List of all open_how "versions". */ #define OPEN_HOW_SIZE_VER0 24 /* sizeof first published struct */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 4f6f59b4f22a..f5be4be7c01d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -101,6 +101,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, #define MAY_CHDIR 0x00000040 /* called from RCU mode, don't block */ #define MAY_NOT_BLOCK 0x00000080 +/* the inode is opened with RESOLVE_MAYEXEC */ +#define MAY_OPENEXEC 0x00000100 /* * flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond diff --git a/include/uapi/linux/openat2.h b/include/uapi/linux/openat2.h index 58b1eb711360..86ed0a2321c3 100644 --- a/include/uapi/linux/openat2.h +++ b/include/uapi/linux/openat2.h @@ -35,5 +35,11 @@ struct open_how { #define RESOLVE_IN_ROOT 0x10 /* Make all jumps to "/" and ".." be scoped inside the dirfd (similar to chroot(2)). */ +#define RESOLVE_MAYEXEC 0x20 /* Code execution from the target file is + intended, checks such permission. A + simple policy can be enforced + system-wide as explained in + Documentation/admin-guide/sysctl/fs.rst + */ #endif /* _UAPI_LINUX_OPENAT2_H */ -- 2.26.2