From patchwork Tue Feb 11 22:55:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Colascione X-Patchwork-Id: 11377081 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6791F138D for ; Tue, 11 Feb 2020 22:56:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3D6E22086A for ; Tue, 11 Feb 2020 22:56:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="FsDNRUzD" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727199AbgBKW4O (ORCPT ); Tue, 11 Feb 2020 17:56:14 -0500 Received: from mail-pf1-f201.google.com ([209.85.210.201]:46025 "EHLO mail-pf1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727795AbgBKW4N (ORCPT ); Tue, 11 Feb 2020 17:56:13 -0500 Received: by mail-pf1-f201.google.com with SMTP id x21so142945pfp.12 for ; Tue, 11 Feb 2020 14:56:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to; bh=a5LVi1czvjYTZRG10VC6YoW8AwFWVMSQpGq5Mo0ccJ0=; b=FsDNRUzDMerRb2TiLxdKBMsmNiW13dSthG+fFckRF863dwlpRI7H85zTW/Odu8uzvZ miE/DDwEZEVqFEIom+y0eIxg+bsVgZVr07yV4hHwFrEpx1guNPkyKNUaV9h4BVYGgPHj e5wK+JrX4G9SmuqMqc9rWPU1LMdhrkdXqSlvIgrOgFLp7Gqpgncf730gU8PXmDgJldTK aK2MxfzkLOgU54VEHwWsiuEtx72LKdLkM1e3wfsuOHYVHH7r2lJtf0hxQjCHkKS0ZeVk sy7gQRYbnVjN04xMTVjvvOstiTRY+ffCQYOgiYgKrdFHaxesYfFFoKY8/ihqGLQJn5gn PH0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to; bh=a5LVi1czvjYTZRG10VC6YoW8AwFWVMSQpGq5Mo0ccJ0=; b=XUvnbZg2tidDNkNYNcFC6n2/lo8Txnwao8r9FD/ItAeNX1jp1lMSRWoYCkXZb/f5gQ rGz1ewBPOPpYpP5W6oq+6Ne6OqmkKvHrQYk41BRcxeTS68Us9xH9DTBjOx928nefgE1L Qrf/VSj2HpGExPm5EmYnJQoibo9DKc7l0dypVlOgbHyPcHm9lnzJ49stUR2fG3RWr71N /LifqZ1YBeYXcTa3+WpNsDS38tspYVkSEGtrLqMv44gqy/fhDEymdUCGymm82EGhXkVj eo9MwiU13k5K7LKacytQ2FTgL9JoAiJPulbFWTFc8Y73z9cIkKxRRy/vSKyGfDqjQ0ir dGcw== X-Gm-Message-State: APjAAAWDM6RLIi0IHy3wSOY6JStXpEDVhyBa9Dw9Ct9CbXifHdOQLg/u Pbr2FUNMZ+5b9xCr289Cex/toiy2x/o= X-Google-Smtp-Source: APXvYqx/rUFYd8FJL3Cg2ZzHJgT4z7nus3aoD8U2JtQsG2gf1M1/LsybhvCS0PgNIvsvHx6K7XcdaqubiKo= X-Received: by 2002:a63:7701:: with SMTP id s1mr9794118pgc.271.1581461771648; Tue, 11 Feb 2020 14:56:11 -0800 (PST) Date: Tue, 11 Feb 2020 14:55:42 -0800 In-Reply-To: <20200211225547.235083-1-dancol@google.com> Message-Id: <20200211225547.235083-2-dancol@google.com> Mime-Version: 1.0 References: <20200211225547.235083-1-dancol@google.com> X-Mailer: git-send-email 2.25.0.225.g125e21ebc7-goog Subject: [PATCH v2 1/6] Add a new flags-accepting interface for anonymous inodes From: Daniel Colascione To: dancol@google.com, timmurray@google.com, nosh@google.com, nnk@google.com, lokeshgidra@google.com, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, selinux@vger.kernel.org Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org Add functions forwarding from the old names to the new ones so we don't need to change any callers. Signed-off-by: Daniel Colascione --- fs/anon_inodes.c | 62 ++++++++++++++++++++++--------------- include/linux/anon_inodes.h | 27 +++++++++++++--- 2 files changed, 59 insertions(+), 30 deletions(-) diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 89714308c25b..caa36019afca 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -56,60 +56,71 @@ static struct file_system_type anon_inode_fs_type = { }; /** - * anon_inode_getfile - creates a new file instance by hooking it up to an - * anonymous inode, and a dentry that describe the "class" - * of the file + * anon_inode_getfile2 - creates a new file instance by hooking it up to + * an anonymous inode, and a dentry that describe + * the "class" of the file * * @name: [in] name of the "class" of the new file * @fops: [in] file operations for the new file * @priv: [in] private data for the new file (will be file's private_data) - * @flags: [in] flags + * @flags: [in] flags for the file + * @anon_inode_flags: [in] flags for anon_inode* * - * Creates a new file by hooking it on a single inode. This is useful for files + * Creates a new file by hooking it on an unspecified inode. This is useful for files * that do not need to have a full-fledged inode in order to operate correctly. * All the files created with anon_inode_getfile() will share a single inode, * hence saving memory and avoiding code duplication for the file/inode/dentry * setup. Returns the newly created file* or an error pointer. + * + * anon_inode_flags must be zero. */ -struct file *anon_inode_getfile(const char *name, - const struct file_operations *fops, - void *priv, int flags) +struct file *anon_inode_getfile2(const char *name, + const struct file_operations *fops, + void *priv, int flags, int anon_inode_flags) { + struct inode *inode; struct file *file; - if (IS_ERR(anon_inode_inode)) - return ERR_PTR(-ENODEV); - - if (fops->owner && !try_module_get(fops->owner)) - return ERR_PTR(-ENOENT); + if (anon_inode_flags) + return ERR_PTR(-EINVAL); + inode = anon_inode_inode; + if (IS_ERR(inode)) + return ERR_PTR(-ENODEV); /* - * We know the anon_inode inode count is always greater than zero, - * so ihold() is safe. + * We know the anon_inode inode count is always + * greater than zero, so ihold() is safe. */ - ihold(anon_inode_inode); - file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name, + ihold(inode); + + if (fops->owner && !try_module_get(fops->owner)) { + file = ERR_PTR(-ENOENT); + goto err; + } + + file = alloc_file_pseudo(inode, anon_inode_mnt, name, flags & (O_ACCMODE | O_NONBLOCK), fops); if (IS_ERR(file)) goto err; - file->f_mapping = anon_inode_inode->i_mapping; + file->f_mapping = inode->i_mapping; file->private_data = priv; return file; err: - iput(anon_inode_inode); + iput(inode); module_put(fops->owner); return file; } EXPORT_SYMBOL_GPL(anon_inode_getfile); +EXPORT_SYMBOL_GPL(anon_inode_getfile2); /** - * anon_inode_getfd - creates a new file instance by hooking it up to an - * anonymous inode, and a dentry that describe the "class" - * of the file + * anon_inode_getfd2 - creates a new file instance by hooking it up to an + * anonymous inode, and a dentry that describe the "class" + * of the file * * @name: [in] name of the "class" of the new file * @fops: [in] file operations for the new file @@ -122,8 +133,8 @@ EXPORT_SYMBOL_GPL(anon_inode_getfile); * hence saving memory and avoiding code duplication for the file/inode/dentry * setup. Returns new descriptor or an error code. */ -int anon_inode_getfd(const char *name, const struct file_operations *fops, - void *priv, int flags) +int anon_inode_getfd2(const char *name, const struct file_operations *fops, + void *priv, int flags, int anon_inode_flags) { int error, fd; struct file *file; @@ -133,7 +144,7 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops, return error; fd = error; - file = anon_inode_getfile(name, fops, priv, flags); + file = anon_inode_getfile2(name, fops, priv, flags, anon_inode_flags); if (IS_ERR(file)) { error = PTR_ERR(file); goto err_put_unused_fd; @@ -147,6 +158,7 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops, return error; } EXPORT_SYMBOL_GPL(anon_inode_getfd); +EXPORT_SYMBOL_GPL(anon_inode_getfd2); static int __init anon_inode_init(void) { diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h index d0d7d96261ad..10699462dcb1 100644 --- a/include/linux/anon_inodes.h +++ b/include/linux/anon_inodes.h @@ -11,11 +11,28 @@ struct file_operations; -struct file *anon_inode_getfile(const char *name, - const struct file_operations *fops, - void *priv, int flags); -int anon_inode_getfd(const char *name, const struct file_operations *fops, - void *priv, int flags); +#define ANON_INODE_SECURE 1 + +struct file *anon_inode_getfile2(const char *name, + const struct file_operations *fops, + void *priv, int flags, int anon_inode_flags); +int anon_inode_getfd2(const char *name, const struct file_operations *fops, + void *priv, int flags, int anon_inode_flags); + +static inline int anon_inode_getfd(const char *name, + const struct file_operations *fops, + void *priv, int flags) +{ + return anon_inode_getfd2(name, fops, priv, flags, 0); +} + +static inline struct file *anon_inode_getfile(const char *name, + const struct file_operations *fops, + void *priv, int flags) +{ + return anon_inode_getfile2(name, fops, priv, flags, 0); +} + #endif /* _LINUX_ANON_INODES_H */ From patchwork Tue Feb 11 22:55:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Colascione X-Patchwork-Id: 11377091 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AD1631580 for ; Tue, 11 Feb 2020 22:56:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8351420842 for ; Tue, 11 Feb 2020 22:56:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="WfyYSNDP" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727690AbgBKW4i (ORCPT ); Tue, 11 Feb 2020 17:56:38 -0500 Received: from mail-pj1-f74.google.com ([209.85.216.74]:60182 "EHLO mail-pj1-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727798AbgBKW4Q (ORCPT ); Tue, 11 Feb 2020 17:56:16 -0500 Received: by mail-pj1-f74.google.com with SMTP id e4so30324pjj.9 for ; Tue, 11 Feb 2020 14:56:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to; bh=SfqbTtIZ891t7TDE9ou6HfiwogoYL0L+vInmvzqifsw=; b=WfyYSNDPN67RlUiW7x9XkianhYsJOBw/+w3G/mDYOLSvddwfe6D+t/ixXuvoc+wr/l Bz5hewdVukRwZ+dkHapInvhSRuw4keyjs8m2id82QO+o58jzCFe8LAw1b6CztNsELJWZ fualBZEutVuaJyL6SViqeDpn6v+eP545tu4qZ1H1kmVlhiJqpaOUEnxEOWDv3jQyc8y6 40XY0SpJ8MlJgm0IkmJIcgbnhTAn1GdPNt6o+wXWaNF0+krC2gYLUngwMdRnjly24uis Ps09LZegEIx5tkwacAba3KtVqx9AYa/bKa+bslSYOAq58Q9NSnziLbYRP2FjqM6hHAbB voTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to; bh=SfqbTtIZ891t7TDE9ou6HfiwogoYL0L+vInmvzqifsw=; b=TV2Gc6Lk1ZoZs/qYGs0NWTORfbr3tZLeL7CBzWpBLISMjXTWnFVieclBa24eoV75ed H13NthCrJjXWUfqZL435WNrWo4HOPTr6ztdqD1T8hZVdRT6+mnZKEEIuA6EGw3ke7VcQ s5p+hhTmgRu50dBP4+kZ1hte1STO1L/CC36JiR38Gys13Iylhry1JzCcjQTJ66NSi1aL PJQK8VjdbN7GqmdubCzOGQl3ixpHuz7TfzS0+FqQiTQrq+R1yVSubNlzJ6D0Qvn5vgN6 HudoJ4+IFCwzhS/S8AEiD2B8y7vB0bdVTSNM9zEMQgIaS+qCpDyI2ofxEdXM7YLC6iJi mEmQ== X-Gm-Message-State: APjAAAVEUeaHjK9KxVool6tuM0pVmiMLbredxGBHNn4qCabYS/saZGTr yE24GRNdto2+3mAvOfWJ51HE4g7/hIk= X-Google-Smtp-Source: APXvYqxcOZR72yGyDyJvUedgz3YRRybV+KpcT1SSXjtHbgMmPun7x8fbFMkY5AOwdjKTmF9bxkn/7qXoxf0= X-Received: by 2002:a63:502:: with SMTP id 2mr9605820pgf.364.1581461774275; Tue, 11 Feb 2020 14:56:14 -0800 (PST) Date: Tue, 11 Feb 2020 14:55:43 -0800 In-Reply-To: <20200211225547.235083-1-dancol@google.com> Message-Id: <20200211225547.235083-3-dancol@google.com> Mime-Version: 1.0 References: <20200211225547.235083-1-dancol@google.com> X-Mailer: git-send-email 2.25.0.225.g125e21ebc7-goog Subject: [PATCH v2 2/6] Add a concept of a "secure" anonymous file From: Daniel Colascione To: dancol@google.com, timmurray@google.com, nosh@google.com, nnk@google.com, lokeshgidra@google.com, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, selinux@vger.kernel.org Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org A secure anonymous file is one we hooked up to its own inode (as opposed to the shared inode we use for non-secure anonymous files). A new selinux hook gives security modules a chance to initialize, label, and veto the creation of these secure anonymous files. Security modules had limit ability to interact with non-secure anonymous files due to all of these files sharing a single inode. Signed-off-by: Daniel Colascione Reported-by: kbuild test robot --- fs/anon_inodes.c | 45 ++++++++++++++++++++++++++++++--------- include/linux/lsm_hooks.h | 8 +++++++ include/linux/security.h | 2 ++ security/security.c | 8 +++++++ 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index caa36019afca..d68d76523ad3 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -55,6 +55,23 @@ static struct file_system_type anon_inode_fs_type = { .kill_sb = kill_anon_super, }; +struct inode *anon_inode_make_secure_inode(const char *name, + const struct file_operations *fops) +{ + struct inode *inode; + int error; + inode = alloc_anon_inode(anon_inode_mnt->mnt_sb); + if (IS_ERR(inode)) + return ERR_PTR(PTR_ERR(inode)); + inode->i_flags &= ~S_PRIVATE; + error = security_inode_init_security_anon(inode, name, fops); + if (error) { + iput(inode); + return ERR_PTR(error); + } + return inode; +} + /** * anon_inode_getfile2 - creates a new file instance by hooking it up to * an anonymous inode, and a dentry that describe @@ -72,7 +89,9 @@ static struct file_system_type anon_inode_fs_type = { * hence saving memory and avoiding code duplication for the file/inode/dentry * setup. Returns the newly created file* or an error pointer. * - * anon_inode_flags must be zero. + * If anon_inode_flags contains ANON_INODE_SECURE, create a new inode + * and enable security checks for it. Otherwise, attach a new file to + * a singleton placeholder inode with security checks disabled. */ struct file *anon_inode_getfile2(const char *name, const struct file_operations *fops, @@ -81,17 +100,23 @@ struct file *anon_inode_getfile2(const char *name, struct inode *inode; struct file *file; - if (anon_inode_flags) + if (anon_inode_flags & ~ANON_INODE_SECURE) return ERR_PTR(-EINVAL); - inode = anon_inode_inode; - if (IS_ERR(inode)) - return ERR_PTR(-ENODEV); - /* - * We know the anon_inode inode count is always - * greater than zero, so ihold() is safe. - */ - ihold(inode); + if (anon_inode_flags & ANON_INODE_SECURE) { + inode = anon_inode_make_secure_inode(name, fops); + if (IS_ERR(inode)) + return ERR_PTR(PTR_ERR(inode)); + } else { + inode = anon_inode_inode; + if (IS_ERR(inode)) + return ERR_PTR(-ENODEV); + /* + * We know the anon_inode inode count is always + * greater than zero, so ihold() is safe. + */ + ihold(inode); + } if (fops->owner && !try_module_get(fops->owner)) { file = ERR_PTR(-ENOENT); diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 20d8cf194fb7..ba208ce5711d 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -215,6 +215,10 @@ * Returns 0 if @name and @value have been successfully set, * -EOPNOTSUPP if no security attribute is needed, or * -ENOMEM on memory allocation failure. + * @inode_init_security_anon: + * Set up a secure anonymous inode. + * Returns 0 on success. Returns -EPERM if the security module denies + * the creation of this inode. * @inode_create: * Check permission to create a regular file. * @dir contains inode structure of the parent of the new file. @@ -1552,6 +1556,9 @@ union security_list_options { const struct qstr *qstr, const char **name, void **value, size_t *len); + int (*inode_init_security_anon)(struct inode *inode, + const char *name, + const struct file_operations *fops); int (*inode_create)(struct inode *dir, struct dentry *dentry, umode_t mode); int (*inode_link)(struct dentry *old_dentry, struct inode *dir, @@ -1884,6 +1891,7 @@ struct security_hook_heads { struct hlist_head inode_alloc_security; struct hlist_head inode_free_security; struct hlist_head inode_init_security; + struct hlist_head inode_init_security_anon; struct hlist_head inode_create; struct hlist_head inode_link; struct hlist_head inode_unlink; diff --git a/include/linux/security.h b/include/linux/security.h index 64b19f050343..8625b647dd0b 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -320,6 +320,8 @@ void security_inode_free(struct inode *inode); int security_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, initxattrs initxattrs, void *fs_data); +int security_inode_init_security_anon(struct inode *inode, const char *name, + const struct file_operations *fops); int security_old_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, const char **name, void **value, size_t *len); diff --git a/security/security.c b/security/security.c index 565bc9b67276..78dc6096b30f 100644 --- a/security/security.c +++ b/security/security.c @@ -1033,6 +1033,14 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, } EXPORT_SYMBOL(security_inode_init_security); +int +security_inode_init_security_anon(struct inode *inode, + const char *name, + const struct file_operations *fops) +{ + return call_int_hook(inode_init_security_anon, 0, inode, name, fops); +} + int security_old_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, const char **name, void **value, size_t *len) From patchwork Tue Feb 11 22:55:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Colascione X-Patchwork-Id: 11377083 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7A9A6138D for ; Tue, 11 Feb 2020 22:56:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4FE4A20714 for ; Tue, 11 Feb 2020 22:56:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gxgroxdp" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727836AbgBKW4S (ORCPT ); Tue, 11 Feb 2020 17:56:18 -0500 Received: from mail-pl1-f202.google.com ([209.85.214.202]:34371 "EHLO mail-pl1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727797AbgBKW4R (ORCPT ); Tue, 11 Feb 2020 17:56:17 -0500 Received: by mail-pl1-f202.google.com with SMTP id j8so26060plk.1 for ; Tue, 11 Feb 2020 14:56:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to; bh=vHcKO3QArnYrq5IS1lBB+LSw7l3zk+6PTDFMKlLqjVY=; b=gxgroxdpy5apY+CiXlDvZ3ykbKxa6+DwISy7zYL64iaChm9WJXkU2eLLN7um5g8isj BOhtMjfkisilUoD1Djqg2bvSgeeDHdBVCYxg2Ut2KaCKn2bl6700QGsUZD+HoyobtI+E WiwDPOQmNQpSTpbyT6EdUAc4+QZV3rZA5o/dXf4j8wiHg3U3a3pxbBgMQ/16RGiBTBTX ajTB2PSHjdqaBEHWdmpxBJKkTVtdeF+C8Tvar0wr/jL0Ka+18+lZ9tN2a3pflblIv5vq vVR55P8bXSH7XwmnU+/GxqhJ/TP+Ku/aEAUmTpRXwSmZwzNylmwgsWmfUyDmDQEZkrFf wfOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to; bh=vHcKO3QArnYrq5IS1lBB+LSw7l3zk+6PTDFMKlLqjVY=; b=oNpFUyUGvnBYAjwGdFUlvF58utYRkPSz+5eRIT5WuBLrzZfYqaxGJOob/I7qfFwOt+ YMSHN3zZKSRcGLb6/s5Bc0ECae5JzzC2fnuun9VDLH95BqFjIoH/On7wcMqc7g6jO5o0 iWBs/kHBVor90AN42OZmFBwR+ZejGb83sHiuCw5RHW6kiLqm7bIq8SeEFMJMFUQL1hqE VyHxIwr0H4wLQJ1h0M9frLottU6JHgMQQJyQLxlYQV/HR8vqMLlFLfX1eXgexG1tJtvK 6UKD85Fgeedj7ICvfAJ8/+4j01jA19aZCVt0HzBKE8pspic6y7jo9aOYYYtuPiFY3cuW oaig== X-Gm-Message-State: APjAAAXpk9rk/5X5ZhA7J39ihlp9FJpaKPSW6ETGN6bqs68j5DFOYdbI 7KisT/a5AlJ2LlJRa1zWjCGVLrsb7tw= X-Google-Smtp-Source: APXvYqzJIL6WHUsPALso0TDvxO22ttnZWGbNBfpf2ul38VP3YBkBW8QGBonli8y5cLEtZ7ZHBcRd9HxSwbo= X-Received: by 2002:a63:594a:: with SMTP id j10mr9436698pgm.227.1581461776754; Tue, 11 Feb 2020 14:56:16 -0800 (PST) Date: Tue, 11 Feb 2020 14:55:44 -0800 In-Reply-To: <20200211225547.235083-1-dancol@google.com> Message-Id: <20200211225547.235083-4-dancol@google.com> Mime-Version: 1.0 References: <20200211225547.235083-1-dancol@google.com> X-Mailer: git-send-email 2.25.0.225.g125e21ebc7-goog Subject: [PATCH v2 3/6] Teach SELinux about a new userfaultfd class From: Daniel Colascione To: dancol@google.com, timmurray@google.com, nosh@google.com, nnk@google.com, lokeshgidra@google.com, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, selinux@vger.kernel.org Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org Use the secure anonymous inode LSM hook we just added to let SELinux policy place restrictions on userfaultfd use. The create operation applies to processes creating new instances of these file objects; transfer between processes is covered by restrictions on read, write, and ioctl access already checked inside selinux_file_receive. Signed-off-by: Daniel Colascione --- fs/userfaultfd.c | 4 +- include/linux/userfaultfd_k.h | 2 + security/selinux/hooks.c | 68 +++++++++++++++++++++++++++++ security/selinux/include/classmap.h | 2 + 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 37df7c9eedb1..07b0f6e03849 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -1014,8 +1014,6 @@ static __poll_t userfaultfd_poll(struct file *file, poll_table *wait) } } -static const struct file_operations userfaultfd_fops; - static int resolve_userfault_fork(struct userfaultfd_ctx *ctx, struct userfaultfd_ctx *new, struct uffd_msg *msg) @@ -1920,7 +1918,7 @@ static void userfaultfd_show_fdinfo(struct seq_file *m, struct file *f) } #endif -static const struct file_operations userfaultfd_fops = { +const struct file_operations userfaultfd_fops = { #ifdef CONFIG_PROC_FS .show_fdinfo = userfaultfd_show_fdinfo, #endif diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h index ac9d71e24b81..549c8b0cca52 100644 --- a/include/linux/userfaultfd_k.h +++ b/include/linux/userfaultfd_k.h @@ -30,6 +30,8 @@ extern int sysctl_unprivileged_userfaultfd; +extern const struct file_operations userfaultfd_fops; + extern vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason); extern ssize_t mcopy_atomic(struct mm_struct *dst_mm, unsigned long dst_start, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1659b59fb5d7..e178f6f40e93 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -92,6 +92,10 @@ #include #include +#ifdef CONFIG_USERFAULTFD +#include +#endif + #include "avc.h" #include "objsec.h" #include "netif.h" @@ -2915,6 +2919,69 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, return 0; } +static int selinux_inode_init_security_anon(struct inode *inode, + const char *name, + const struct file_operations *fops) +{ + const struct task_security_struct *tsec = selinux_cred(current_cred()); + struct common_audit_data ad; + struct inode_security_struct *isec; + + if (unlikely(IS_PRIVATE(inode))) + return 0; + + /* + * We shouldn't be creating secure anonymous inodes before LSM + * initialization completes. + */ + if (unlikely(!selinux_state.initialized)) + return -EBUSY; + + isec = selinux_inode(inode); + + /* + * We only get here once per ephemeral inode. The inode has + * been initialized via inode_alloc_security but is otherwise + * untouched, so check that the state is as + * inode_alloc_security left it. + */ + BUG_ON(isec->initialized != LABEL_INVALID); + BUG_ON(isec->sclass != SECCLASS_FILE); + +#ifdef CONFIG_USERFAULTFD + if (fops == &userfaultfd_fops) + isec->sclass = SECCLASS_UFFD; +#endif + + if (isec->sclass == SECCLASS_FILE) { + printk(KERN_WARNING "refusing to create secure anonymous inode " + "of unknown type"); + return -EOPNOTSUPP; + } + /* + * Always give secure anonymous inodes the sid of the + * creating task. + */ + + isec->sid = tsec->sid; + isec->initialized = LABEL_INITIALIZED; + + /* + * Now that we've initialized security, check whether we're + * allowed to actually create this type of anonymous inode. + */ + + ad.type = LSM_AUDIT_DATA_INODE; + ad.u.inode = inode; + + return avc_has_perm(&selinux_state, + tsec->sid, + isec->sid, + isec->sclass, + FILE__CREATE, + &ad); +} + static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode) { return may_create(dir, dentry, SECCLASS_FILE); @@ -6923,6 +6990,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security), LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security), + LSM_HOOK_INIT(inode_init_security_anon, selinux_inode_init_security_anon), LSM_HOOK_INIT(inode_create, selinux_inode_create), LSM_HOOK_INIT(inode_link, selinux_inode_link), LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink), diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 986f3ac14282..6d4f9ebf2017 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -248,6 +248,8 @@ struct security_class_mapping secclass_map[] = { {"open", "cpu", "kernel", "tracepoint", "read", "write"} }, { "lockdown", { "integrity", "confidentiality", NULL } }, + { "uffd", + { COMMON_FILE_PERMS, NULL } }, { NULL } }; From patchwork Tue Feb 11 22:55:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Colascione X-Patchwork-Id: 11377089 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 44C1E138D for ; Tue, 11 Feb 2020 22:56:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 23B882073C for ; Tue, 11 Feb 2020 22:56:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="umSesbTG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727860AbgBKW4W (ORCPT ); Tue, 11 Feb 2020 17:56:22 -0500 Received: from mail-qt1-f202.google.com ([209.85.160.202]:56881 "EHLO mail-qt1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727858AbgBKW4U (ORCPT ); Tue, 11 Feb 2020 17:56:20 -0500 Received: by mail-qt1-f202.google.com with SMTP id c22so7702383qtn.23 for ; Tue, 11 Feb 2020 14:56:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to; bh=/wUiaE4lRYXVr4XT55eq69Fhu4cwbqd4vz3JObgWLSw=; b=umSesbTGPsu+nvuQqZ8fY1eTSikUabPzN6xXg7xZJNBVLypMGXMDDOtJRe0wHcws/7 KVx131mQiaayMu32w+j2ucPHb9I5Eb8itpDFy9EHwUOdRgdnnhnKXgs7u72L/EpOwS2f JvJl3PKDTd9Y1naPldNOTFfg9IraAiaHTbUmM5seXxpMlK9aTnTnuqYp3Ud/ljRBeBkc WuPfeFuw2yoyip+1AA+8LQghHTNqWGHBzKnlUmuoOyGwGYsCIsIDAnf0JEf3eQDlIhI2 yKiZaipNfTJ1ATmOxT4/Zj07VxlViiwp1X4wBvuGy6Hc65x02f0NtCx8qf1iy1MOde2k odTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to; bh=/wUiaE4lRYXVr4XT55eq69Fhu4cwbqd4vz3JObgWLSw=; b=K7OG/k8XPCrNm2dUI7vPka1X/tYKA6UapLvsv5HzOtrIhbaTnf7KBu47Sy96+MvMcP Z0k7Iuw6ypX8RjVTEgCao1eoionFMtyr66+Ft2GoWIk/Knn1Gcy0zT3MFr6nF5t5j5So SHr76hkTjy/ZpgRHkW5NtI5WF4qDg3664JcAoA01Oi4FhHVln+0Slex0rLx7OFm5pR9M Xpvvv2d70daUlcCeBoyvacJMR1zCLdvgpH+5obNvkJ1XPbi7s5MIt/n7dNW2ZXMBYYF4 3b7ZeJA1kp3uh5z/AqQ3qZoav8VQIIbSx7+5hUtsxr9eKljJyBa6RVcBI/+XOtfS2lkl Gieg== X-Gm-Message-State: APjAAAXOkYpCZCXOk3JSyNK6KrtSVuBmguDca7wxrZcOBOFJ2txg4+YH 9wMdHeflSkzFhji6DqiWtranUbaHbj4= X-Google-Smtp-Source: APXvYqyZXCjauD7MRkh/uIhajsG5EI06HCT6AH+BThgzhc0Md1s+7ziwiBW5p3VuX5RjLJnrFmjTcG1OTEs= X-Received: by 2002:ac8:34b2:: with SMTP id w47mr16528854qtb.142.1581461779511; Tue, 11 Feb 2020 14:56:19 -0800 (PST) Date: Tue, 11 Feb 2020 14:55:45 -0800 In-Reply-To: <20200211225547.235083-1-dancol@google.com> Message-Id: <20200211225547.235083-5-dancol@google.com> Mime-Version: 1.0 References: <20200211225547.235083-1-dancol@google.com> X-Mailer: git-send-email 2.25.0.225.g125e21ebc7-goog Subject: [PATCH v2 4/6] Wire UFFD up to SELinux From: Daniel Colascione To: dancol@google.com, timmurray@google.com, nosh@google.com, nnk@google.com, lokeshgidra@google.com, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, selinux@vger.kernel.org Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org This change gives userfaultfd file descriptors a real security context, allowing policy to act on them. Signed-off-by: Daniel Colascione --- fs/userfaultfd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 07b0f6e03849..11227b94a5a7 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -1020,6 +1020,8 @@ static int resolve_userfault_fork(struct userfaultfd_ctx *ctx, { int fd; + /* Regular inode here is okay: only CAP_SYS_PTRACE callers + * can monitor forks. */ fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, new, O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS)); if (fd < 0) @@ -1972,8 +1974,9 @@ SYSCALL_DEFINE1(userfaultfd, int, flags) /* prevent the mm struct to be freed */ mmgrab(ctx->mm); - fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, ctx, - O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS)); + fd = anon_inode_getfd2("[userfaultfd]", &userfaultfd_fops, ctx, + O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS), + ANON_INODE_SECURE); if (fd < 0) { mmdrop(ctx->mm); kmem_cache_free(userfaultfd_ctx_cachep, ctx); From patchwork Tue Feb 11 22:55:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Colascione X-Patchwork-Id: 11377087 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2D4681580 for ; Tue, 11 Feb 2020 22:56:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0C79B2082F for ; Tue, 11 Feb 2020 22:56:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="WeWDMgIw" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727897AbgBKW4Y (ORCPT ); Tue, 11 Feb 2020 17:56:24 -0500 Received: from mail-pf1-f202.google.com ([209.85.210.202]:57230 "EHLO mail-pf1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727883AbgBKW4X (ORCPT ); Tue, 11 Feb 2020 17:56:23 -0500 Received: by mail-pf1-f202.google.com with SMTP id r29so127386pfl.23 for ; Tue, 11 Feb 2020 14:56:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to; bh=zuajClpY4n8pjVJyU4VcQsX18SP0Y8Sji2fDd6chARE=; b=WeWDMgIwDwbj7/AXWD1nXsQn6GX/nkkwQPg4D8SaZzdpux/IoFOYqW+cPEdoZXKA+z KeyUCv3fQ3BRHWHWuuiFxseX9APuVA3h8PGUbRZUh0l3He+njmrEg5cSm/IGa4tv+6Tm I50x1iyZueTqfd07v6Uq2TOxUr049ueKUeUSlpfmn1QnCWByi3jR0lnGyH60rSEo5Ri9 +r05f2myW4dtsdTS2k9fi5i5grbiS2UUw7IMdRJU2i1ST+/XyzYGRpXwXW2Y5w0D9TbP fsD2J9d+UsZnC4Cc7LQtwcEX9aAg8yO14OPMXom6LPmXosZmilC9gWbzfXSkRwxCCAPx 85QQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to; bh=zuajClpY4n8pjVJyU4VcQsX18SP0Y8Sji2fDd6chARE=; b=AZI7jNxgbkgbLnFLCTc9zBANvv68DNHJc0pomkDycJbO7t3Db85abmopOKdC6w1+nH 1TAipdjy8CBVMZ6/jjlsjv+MKvIr2/GggvtU3ADNW/YNGRpFI6Qzhh/GCL40GaKss9Ri Ww0bq/Arg5rO8VG54u304zGETGYy7n1uDX6jtULQTtpGp5fGFrBHRjvWPQo74TusJtJi 9B/lhPxP2MIYuGGaNBmhFWTpD+k+2slsDkdpXM4rJ1ewl8eTGoFnJKN/1Q1dhc6ynAtg 8LW1Pya4hA/KYqKi1wnMevS0vBZx6Q/6jRiJf0KZqI7AYx9uD4tFkXdEbckE8gKbj7Gu Y8xQ== X-Gm-Message-State: APjAAAXT16w1K9ga+5YJ0JwMh11W5aXdfBfX+CwEzxGFlyZkD9TihkQc 5DSkmD//OdtuCvyJiq2fR611evZLemg= X-Google-Smtp-Source: APXvYqxGjLt1U5Fk+LSI+2JB0pVm97WGbcPVZqZFDRBBOx6SwjGavrdX+xsJLI7S/No1RnNsl9FHCebL6nw= X-Received: by 2002:a63:4525:: with SMTP id s37mr9086010pga.418.1581461781964; Tue, 11 Feb 2020 14:56:21 -0800 (PST) Date: Tue, 11 Feb 2020 14:55:46 -0800 In-Reply-To: <20200211225547.235083-1-dancol@google.com> Message-Id: <20200211225547.235083-6-dancol@google.com> Mime-Version: 1.0 References: <20200211225547.235083-1-dancol@google.com> X-Mailer: git-send-email 2.25.0.225.g125e21ebc7-goog Subject: [PATCH v2 5/6] Let userfaultfd opt out of handling kernel-mode faults From: Daniel Colascione To: dancol@google.com, timmurray@google.com, nosh@google.com, nnk@google.com, lokeshgidra@google.com, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, selinux@vger.kernel.org Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org userfaultfd handles page faults from both user and kernel code. Add a new UFFD_USER_MODE_ONLY flag for userfaultfd(2) that makes the resulting userfaultfd object refuse to handle faults from kernel mode, treating these faults as if SIGBUS were always raised, causing the kernel code to fail with EFAULT. A future patch adds a knob allowing administrators to give some processes the ability to create userfaultfd file objects only if they pass UFFD_USER_MODE_ONLY, reducing the likelihood that these processes will exploit userfaultfd's ability to delay kernel page faults to open timing windows for future exploits. Signed-off-by: Daniel Colascione --- fs/userfaultfd.c | 7 ++++++- include/uapi/linux/userfaultfd.h | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 11227b94a5a7..47825a804d63 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -389,6 +389,9 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason) if (ctx->features & UFFD_FEATURE_SIGBUS) goto out; + if ((vmf->flags & FAULT_FLAG_USER) == 0 && + ctx->flags & UFFD_USER_MODE_ONLY) + goto out; /* * If it's already released don't get it. This avoids to loop @@ -1945,6 +1948,7 @@ static void init_once_userfaultfd_ctx(void *mem) SYSCALL_DEFINE1(userfaultfd, int, flags) { + static const int uffd_flags = UFFD_USER_MODE_ONLY; struct userfaultfd_ctx *ctx; int fd; @@ -1954,10 +1958,11 @@ SYSCALL_DEFINE1(userfaultfd, int, flags) BUG_ON(!current->mm); /* Check the UFFD_* constants for consistency. */ + BUILD_BUG_ON(uffd_flags & UFFD_SHARED_FCNTL_FLAGS); BUILD_BUG_ON(UFFD_CLOEXEC != O_CLOEXEC); BUILD_BUG_ON(UFFD_NONBLOCK != O_NONBLOCK); - if (flags & ~UFFD_SHARED_FCNTL_FLAGS) + if (flags & ~(UFFD_SHARED_FCNTL_FLAGS | uffd_flags)) return -EINVAL; ctx = kmem_cache_alloc(userfaultfd_ctx_cachep, GFP_KERNEL); diff --git a/include/uapi/linux/userfaultfd.h b/include/uapi/linux/userfaultfd.h index 48f1a7c2f1f0..fe3565eae617 100644 --- a/include/uapi/linux/userfaultfd.h +++ b/include/uapi/linux/userfaultfd.h @@ -231,4 +231,13 @@ struct uffdio_zeropage { __s64 zeropage; }; +/* + * Flags for the userfaultfd(2) system call itself. + */ + +/* + * Create a userfaultfd that can handle page faults only in user mode. + */ +#define UFFD_USER_MODE_ONLY 1 + #endif /* _LINUX_USERFAULTFD_H */ From patchwork Tue Feb 11 22:55:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Colascione X-Patchwork-Id: 11377085 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 84C7214E3 for ; Tue, 11 Feb 2020 22:56:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5B5C02073C for ; Tue, 11 Feb 2020 22:56:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="dcDpEH7Z" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727858AbgBKW40 (ORCPT ); Tue, 11 Feb 2020 17:56:26 -0500 Received: from mail-yw1-f74.google.com ([209.85.161.74]:34773 "EHLO mail-yw1-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727906AbgBKW40 (ORCPT ); Tue, 11 Feb 2020 17:56:26 -0500 Received: by mail-yw1-f74.google.com with SMTP id o1so313295ywl.1 for ; Tue, 11 Feb 2020 14:56:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to; bh=aOL9U/iY2dMKzhjMVeVV6Ai5vMkOfKpOd0BcDILMuYA=; b=dcDpEH7ZN45igP4l8mc9PLVcF4M9BgFDWIlzqYNPFVHD6Z9a751NvNdASr+aSkxqGo hQ1XpwVZvmIanE1Ex5O04cjcsPkuZVxJAfOCqRqyiPxgoy1ysb6uxY3UGdHfafMSX1MU fTeN9/ZqOmoZXeHp5x+PY060mJJ/fE8HJF+tBMze97Qu/dFQrzoasWRUYb2tXGqKUKYo bChRMEJPWxfwTZKUbB2x5blZWDc93pOqsuHp/kZZCSWvmA/er+k58DSej0RKcNcSDyRM DcPDwp14VI4GIRj2OGVYPhefz4RsPm7OZMkVfFDpukpkiDh+ff0A61+ElYpQWuqcMJRW mJrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to; bh=aOL9U/iY2dMKzhjMVeVV6Ai5vMkOfKpOd0BcDILMuYA=; b=iiLKveWr0gPysUSt+gyuWrs50sCcyxCYuIiF06+5AJsULtD8o1YC/+/ZF54J4OUZoa S81f3faNGSbuXukpsU374uVNbH80sQwD8XdKpGt8KIpi4AwPLSUIb9WDE3z2+44tk7Fc sNN9+WKmB0Qm44VZ6VubPD9YsZw3VJqL+KabKCjJUSdxPmzlwawODOnmQdD1yVWuAuN0 iWQmFqwP2jdmZ0NRjvyVb0uzO5KRdc6cFhzz6qiJ10XxOftogEiCCUQo6EgD30efG55G l30ONRDCkoCSLVXuth1Wrdopx1IjwoJamzEyGmzioYduQBdd9BJEYklIxB3D8JkbWbhE 0olA== X-Gm-Message-State: APjAAAWHeUvc5l/h2xHR3H8rQs2K4WKqRf95xwbA1bzRWwhj5cxG+gjr STjg8PQQJOTf/s7KyLlHWnfbTTa/mnU= X-Google-Smtp-Source: APXvYqzllhiKHdQpM4uPNwyqX+Good3/YFtj2svIu2Spz84zHU9aLEFd2AKu32ak6wuV1+Ian4qkJ4nZyhg= X-Received: by 2002:a0d:e2d1:: with SMTP id l200mr7607645ywe.122.1581461784825; Tue, 11 Feb 2020 14:56:24 -0800 (PST) Date: Tue, 11 Feb 2020 14:55:47 -0800 In-Reply-To: <20200211225547.235083-1-dancol@google.com> Message-Id: <20200211225547.235083-7-dancol@google.com> Mime-Version: 1.0 References: <20200211225547.235083-1-dancol@google.com> X-Mailer: git-send-email 2.25.0.225.g125e21ebc7-goog Subject: [PATCH v2 6/6] Add a new sysctl for limiting userfaultfd to user mode faults From: Daniel Colascione To: dancol@google.com, timmurray@google.com, nosh@google.com, nnk@google.com, lokeshgidra@google.com, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, selinux@vger.kernel.org Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org Add a new sysctl knob unprivileged_userfaultfd_user_mode_only. This sysctl can be set to either zero or one. When zero (the default) the system lets all users call userfaultfd with or without UFFD_USER_MODE_ONLY, modulo other access controls. When unprivileged_userfaultfd_user_mode_only is set to one, users without CAP_SYS_PTRACE must pass UFFD_USER_MODE_ONLY to userfaultfd or the API will fail with EPERM. This facility allows administrators to reduce the likelihood that an attacker with access to userfaultfd can delay faulting kernel code to widen timing windows for other exploits. Signed-off-by: Daniel Colascione --- Documentation/admin-guide/sysctl/vm.rst | 13 +++++++++++++ fs/userfaultfd.c | 11 ++++++++++- include/linux/userfaultfd_k.h | 1 + kernel/sysctl.c | 9 +++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst index 64aeee1009ca..1f416aff68b9 100644 --- a/Documentation/admin-guide/sysctl/vm.rst +++ b/Documentation/admin-guide/sysctl/vm.rst @@ -847,6 +847,19 @@ privileged users (with SYS_CAP_PTRACE capability). The default value is 1. +unprivileged_userfaultfd_user_mode_only +======================================== + +This flag controls whether unprivileged users can use the userfaultfd +system calls to handle page faults in kernel mode. If set to zero, +userfaultfd works with or without UFFD_USER_MODE_ONLY, modulo +unprivileged_userfaultfd above. If set to one, users without +SYS_CAP_PTRACE must pass UFFD_USER_MODE_ONLY in order for userfaultfd +to succeed. Prohibiting use of userfaultfd for handling faults from +kernel mode may make certain vulnerabilities more difficult +to exploit. + +The default value is 0. user_reserve_kbytes =================== diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 47825a804d63..d39bdf177f8c 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -29,6 +29,7 @@ #include int sysctl_unprivileged_userfaultfd __read_mostly = 1; +int sysctl_unprivileged_userfaultfd_user_mode_only __read_mostly = 0; static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly; @@ -1951,8 +1952,16 @@ SYSCALL_DEFINE1(userfaultfd, int, flags) static const int uffd_flags = UFFD_USER_MODE_ONLY; struct userfaultfd_ctx *ctx; int fd; + bool need_cap_check = false; - if (!sysctl_unprivileged_userfaultfd && !capable(CAP_SYS_PTRACE)) + if (!sysctl_unprivileged_userfaultfd) + need_cap_check = true; + + if (sysctl_unprivileged_userfaultfd_user_mode_only && + (flags & UFFD_USER_MODE_ONLY) == 0) + need_cap_check = true; + + if (need_cap_check && !capable(CAP_SYS_PTRACE)) return -EPERM; BUG_ON(!current->mm); diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h index 549c8b0cca52..efe14abb2dc8 100644 --- a/include/linux/userfaultfd_k.h +++ b/include/linux/userfaultfd_k.h @@ -29,6 +29,7 @@ #define UFFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS) extern int sysctl_unprivileged_userfaultfd; +extern int sysctl_unprivileged_userfaultfd_user_mode_only; extern const struct file_operations userfaultfd_fops; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index d396aaaf19a3..0650063c3741 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1740,6 +1740,15 @@ static struct ctl_table vm_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, }, + { + .procname = "unprivileged_userfaultfd_user_mode_only", + .data = &sysctl_unprivileged_userfaultfd_user_mode_only, + .maxlen = sizeof(sysctl_unprivileged_userfaultfd_user_mode_only), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, #endif { } };