SELinux Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v2 0/6] Harden userfaultfd
@ 2020-02-11 22:55 Daniel Colascione
  2020-02-11 22:55 ` [PATCH v2 1/6] Add a new flags-accepting interface for anonymous inodes Daniel Colascione
                   ` (8 more replies)
  0 siblings, 9 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-11 22:55 UTC (permalink / raw)
  To: dancol, timmurray, nosh, nnk, lokeshgidra, linux-kernel,
	linux-api, selinux

Userfaultfd in unprivileged contexts could be potentially very
useful. We'd like to harden userfaultfd to make such unprivileged use
less risky. This patch series allows SELinux to manage userfaultfd
file descriptors and allows administrators to limit userfaultfd to
servicing user-mode faults, increasing the difficulty of using
userfaultfd in exploit chains invoking delaying kernel faults.

A new anon_inodes interface allows callers to opt into SELinux
management of anonymous file objects. In this mode, anon_inodes
creates new ephemeral inodes for anonymous file objects instead of
reusing a singleton dummy inode. A new LSM hook gives security modules
an opportunity to configure and veto these ephemeral inodes.

Existing anon_inodes users must opt into the new functionality.

Daniel Colascione (6):
  Add a new flags-accepting interface for anonymous inodes
  Add a concept of a "secure" anonymous file
  Teach SELinux about a new userfaultfd class
  Wire UFFD up to SELinux
  Let userfaultfd opt out of handling kernel-mode faults
  Add a new sysctl for limiting userfaultfd to user mode faults

 Documentation/admin-guide/sysctl/vm.rst | 13 ++++
 fs/anon_inodes.c                        | 89 +++++++++++++++++--------
 fs/userfaultfd.c                        | 29 ++++++--
 include/linux/anon_inodes.h             | 27 ++++++--
 include/linux/lsm_hooks.h               |  8 +++
 include/linux/security.h                |  2 +
 include/linux/userfaultfd_k.h           |  3 +
 include/uapi/linux/userfaultfd.h        |  9 +++
 kernel/sysctl.c                         |  9 +++
 security/security.c                     |  8 +++
 security/selinux/hooks.c                | 68 +++++++++++++++++++
 security/selinux/include/classmap.h     |  2 +
 12 files changed, 229 insertions(+), 38 deletions(-)

-- 
2.25.0.225.g125e21ebc7-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v2 1/6] Add a new flags-accepting interface for anonymous inodes
  2020-02-11 22:55 [PATCH v2 0/6] Harden userfaultfd Daniel Colascione
@ 2020-02-11 22:55 ` Daniel Colascione
  2020-02-12 16:37   ` Stephen Smalley
  2020-02-11 22:55 ` [PATCH v2 2/6] Add a concept of a "secure" anonymous file Daniel Colascione
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-02-11 22:55 UTC (permalink / raw)
  To: dancol, timmurray, nosh, nnk, lokeshgidra, linux-kernel,
	linux-api, selinux

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 <dancol@google.com>
---
 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 */
 
-- 
2.25.0.225.g125e21ebc7-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v2 2/6] Add a concept of a "secure" anonymous file
  2020-02-11 22:55 [PATCH v2 0/6] Harden userfaultfd Daniel Colascione
  2020-02-11 22:55 ` [PATCH v2 1/6] Add a new flags-accepting interface for anonymous inodes Daniel Colascione
@ 2020-02-11 22:55 ` Daniel Colascione
  2020-02-12 16:49   ` Stephen Smalley
  2020-02-14 22:13   ` kbuild test robot
  2020-02-11 22:55 ` [PATCH v2 3/6] Teach SELinux about a new userfaultfd class Daniel Colascione
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-11 22:55 UTC (permalink / raw)
  To: dancol, timmurray, nosh, nnk, lokeshgidra, linux-kernel,
	linux-api, selinux

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 <dancol@google.com>
---
 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)
-- 
2.25.0.225.g125e21ebc7-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v2 3/6] Teach SELinux about a new userfaultfd class
  2020-02-11 22:55 [PATCH v2 0/6] Harden userfaultfd Daniel Colascione
  2020-02-11 22:55 ` [PATCH v2 1/6] Add a new flags-accepting interface for anonymous inodes Daniel Colascione
  2020-02-11 22:55 ` [PATCH v2 2/6] Add a concept of a "secure" anonymous file Daniel Colascione
@ 2020-02-11 22:55 ` Daniel Colascione
  2020-02-12 17:05   ` Stephen Smalley
  2020-02-11 22:55 ` [PATCH v2 4/6] Wire UFFD up to SELinux Daniel Colascione
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-02-11 22:55 UTC (permalink / raw)
  To: dancol, timmurray, nosh, nnk, lokeshgidra, linux-kernel,
	linux-api, selinux

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 <dancol@google.com>
---
 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 <linux/fsnotify.h>
 #include <linux/fanotify.h>
 
+#ifdef CONFIG_USERFAULTFD
+#include <linux/userfaultfd_k.h>
+#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 }
   };
 
-- 
2.25.0.225.g125e21ebc7-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v2 4/6] Wire UFFD up to SELinux
  2020-02-11 22:55 [PATCH v2 0/6] Harden userfaultfd Daniel Colascione
                   ` (2 preceding siblings ...)
  2020-02-11 22:55 ` [PATCH v2 3/6] Teach SELinux about a new userfaultfd class Daniel Colascione
@ 2020-02-11 22:55 ` Daniel Colascione
  2020-02-11 22:55 ` [PATCH v2 5/6] Let userfaultfd opt out of handling kernel-mode faults Daniel Colascione
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-11 22:55 UTC (permalink / raw)
  To: dancol, timmurray, nosh, nnk, lokeshgidra, linux-kernel,
	linux-api, selinux

This change gives userfaultfd file descriptors a real security
context, allowing policy to act on them.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 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);
-- 
2.25.0.225.g125e21ebc7-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v2 5/6] Let userfaultfd opt out of handling kernel-mode faults
  2020-02-11 22:55 [PATCH v2 0/6] Harden userfaultfd Daniel Colascione
                   ` (3 preceding siblings ...)
  2020-02-11 22:55 ` [PATCH v2 4/6] Wire UFFD up to SELinux Daniel Colascione
@ 2020-02-11 22:55 ` Daniel Colascione
  2020-02-11 22:55 ` [PATCH v2 6/6] Add a new sysctl for limiting userfaultfd to user mode faults Daniel Colascione
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-11 22:55 UTC (permalink / raw)
  To: dancol, timmurray, nosh, nnk, lokeshgidra, linux-kernel,
	linux-api, selinux

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 <dancol@google.com>
---
 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 */
-- 
2.25.0.225.g125e21ebc7-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v2 6/6] Add a new sysctl for limiting userfaultfd to user mode faults
  2020-02-11 22:55 [PATCH v2 0/6] Harden userfaultfd Daniel Colascione
                   ` (4 preceding siblings ...)
  2020-02-11 22:55 ` [PATCH v2 5/6] Let userfaultfd opt out of handling kernel-mode faults Daniel Colascione
@ 2020-02-11 22:55 ` Daniel Colascione
  2020-02-11 23:13 ` [PATCH v2 0/6] Harden userfaultfd Casey Schaufler
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-11 22:55 UTC (permalink / raw)
  To: dancol, timmurray, nosh, nnk, lokeshgidra, linux-kernel,
	linux-api, selinux

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 <dancol@google.com>
---
 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 <linux/hugetlb.h>
 
 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
 	{ }
 };
-- 
2.25.0.225.g125e21ebc7-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-11 22:55 [PATCH v2 0/6] Harden userfaultfd Daniel Colascione
                   ` (5 preceding siblings ...)
  2020-02-11 22:55 ` [PATCH v2 6/6] Add a new sysctl for limiting userfaultfd to user mode faults Daniel Colascione
@ 2020-02-11 23:13 ` Casey Schaufler
  2020-02-11 23:27   ` Daniel Colascione
  2020-02-12  7:50 ` Kees Cook
  2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  8 siblings, 1 reply; 75+ messages in thread
From: Casey Schaufler @ 2020-02-11 23:13 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, nosh, nnk, lokeshgidra,
	linux-kernel, linux-api, selinux
  Cc: Casey Schaufler

On 2/11/2020 2:55 PM, Daniel Colascione wrote:
> Userfaultfd in unprivileged contexts could be potentially very
> useful. We'd like to harden userfaultfd to make such unprivileged use
> less risky. This patch series allows SELinux to manage userfaultfd
> file descriptors and allows administrators to limit userfaultfd to
> servicing user-mode faults, increasing the difficulty of using
> userfaultfd in exploit chains invoking delaying kernel faults.
>
> A new anon_inodes interface allows callers to opt into SELinux
> management of anonymous file objects. In this mode, anon_inodes
> creates new ephemeral inodes for anonymous file objects instead of
> reusing a singleton dummy inode. A new LSM hook gives security modules
> an opportunity to configure and veto these ephemeral inodes.
>
> Existing anon_inodes users must opt into the new functionality.
>
> Daniel Colascione (6):
>   Add a new flags-accepting interface for anonymous inodes
>   Add a concept of a "secure" anonymous file
>   Teach SELinux about a new userfaultfd class
>   Wire UFFD up to SELinux
>   Let userfaultfd opt out of handling kernel-mode faults
>   Add a new sysctl for limiting userfaultfd to user mode faults

This must be posted to the linux Security Module list
<linux-security-module@vger.kernel.org>

>
>  Documentation/admin-guide/sysctl/vm.rst | 13 ++++
>  fs/anon_inodes.c                        | 89 +++++++++++++++++--------
>  fs/userfaultfd.c                        | 29 ++++++--
>  include/linux/anon_inodes.h             | 27 ++++++--
>  include/linux/lsm_hooks.h               |  8 +++
>  include/linux/security.h                |  2 +
>  include/linux/userfaultfd_k.h           |  3 +
>  include/uapi/linux/userfaultfd.h        |  9 +++
>  kernel/sysctl.c                         |  9 +++
>  security/security.c                     |  8 +++
>  security/selinux/hooks.c                | 68 +++++++++++++++++++
>  security/selinux/include/classmap.h     |  2 +
>  12 files changed, 229 insertions(+), 38 deletions(-)
>

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-11 23:13 ` [PATCH v2 0/6] Harden userfaultfd Casey Schaufler
@ 2020-02-11 23:27   ` Daniel Colascione
  2020-02-12 16:09     ` Stephen Smalley
  2020-02-21 17:56     ` James Morris
  0 siblings, 2 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-11 23:27 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux, LSM List

On Tue, Feb 11, 2020 at 3:13 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>
> On 2/11/2020 2:55 PM, Daniel Colascione wrote:
> > Userfaultfd in unprivileged contexts could be potentially very
> > useful. We'd like to harden userfaultfd to make such unprivileged use
> > less risky. This patch series allows SELinux to manage userfaultfd
> > file descriptors and allows administrators to limit userfaultfd to
> > servicing user-mode faults, increasing the difficulty of using
> > userfaultfd in exploit chains invoking delaying kernel faults.
> >
> > A new anon_inodes interface allows callers to opt into SELinux
> > management of anonymous file objects. In this mode, anon_inodes
> > creates new ephemeral inodes for anonymous file objects instead of
> > reusing a singleton dummy inode. A new LSM hook gives security modules
> > an opportunity to configure and veto these ephemeral inodes.
> >
> > Existing anon_inodes users must opt into the new functionality.
> >
> > Daniel Colascione (6):
> >   Add a new flags-accepting interface for anonymous inodes
> >   Add a concept of a "secure" anonymous file
> >   Teach SELinux about a new userfaultfd class
> >   Wire UFFD up to SELinux
> >   Let userfaultfd opt out of handling kernel-mode faults
> >   Add a new sysctl for limiting userfaultfd to user mode faults
>
> This must be posted to the linux Security Module list
> <linux-security-module@vger.kernel.org>

Added. I thought selinux@ was sufficient.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-11 22:55 [PATCH v2 0/6] Harden userfaultfd Daniel Colascione
                   ` (6 preceding siblings ...)
  2020-02-11 23:13 ` [PATCH v2 0/6] Harden userfaultfd Casey Schaufler
@ 2020-02-12  7:50 ` Kees Cook
  2020-02-12 16:54   ` Jann Horn
  2020-02-12 17:12   ` Daniel Colascione
  2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  8 siblings, 2 replies; 75+ messages in thread
From: Kees Cook @ 2020-02-12  7:50 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: timmurray, nosh, nnk, lokeshgidra, linux-kernel, linux-api,
	selinux, Andrea Arcangeli, Mike Rapoport, Peter Xu, Jann Horn,
	linux-security-module

Hi!

Firstly, thanks for working on this! It's been on my TODO list for a
while. :)

Casey already recommended including the LSM list to CC (since this is a
new LSM -- there are many LSMs). Additionally, the series should
probably be sent _to_ the userfaultfd maintainers:
	Andrea Arcangeli <aarcange@redhat.com>
	Mike Rapoport <rppt@linux.ibm.com>
and I'd also CC a couple other people that have done recent work:
	Peter Xu <peterx@redhat.com>
	Jann Horn <jannh@google.com>

More notes below...

On Tue, Feb 11, 2020 at 02:55:41PM -0800, Daniel Colascione wrote:
> Userfaultfd in unprivileged contexts could be potentially very
> useful. We'd like to harden userfaultfd to make such unprivileged use
> less risky. This patch series allows SELinux to manage userfaultfd
> file descriptors and allows administrators to limit userfaultfd to
> servicing user-mode faults, increasing the difficulty of using
> userfaultfd in exploit chains invoking delaying kernel faults.

I actually think these are two very different goals and likely the
series could be split into two for them. One is LSM hooking of
userfaultfd and the SELinux attachment, and the other is the user-mode
fault restrictions. And they would likely go via separate trees (LSM
through James's LSM tree, and probably akpm's -mm tree for the sysctl).

> A new anon_inodes interface allows callers to opt into SELinux
> management of anonymous file objects. In this mode, anon_inodes
> creates new ephemeral inodes for anonymous file objects instead of
> reusing a singleton dummy inode. A new LSM hook gives security modules
> an opportunity to configure and veto these ephemeral inodes.
> 
> Existing anon_inodes users must opt into the new functionality.
> 
> Daniel Colascione (6):
>   Add a new flags-accepting interface for anonymous inodes
>   Add a concept of a "secure" anonymous file
>   Teach SELinux about a new userfaultfd class
>   Wire UFFD up to SELinux

The above is the first "series"... I don't have much opinion about it,
though I do like the idea of making userfaultfd visible to the LSM.

>   Let userfaultfd opt out of handling kernel-mode faults
>   Add a new sysctl for limiting userfaultfd to user mode faults

Now this I'm very interested in. Can you go into more detail about two
things:

- What is the threat being solved? (I understand the threat, but detailing
  it in the commit log is important for people who don't know it. Existing
  commit cefdca0a86be517bc390fc4541e3674b8e7803b0 gets into some of the
  details already, but I'd like to see reference to external sources like
  https://duasynt.com/blog/linux-kernel-heap-spray)

- Why is this needed in addition to the existing vm.unprivileged_userfaultfd
  sysctl? (And should this maybe just be another setting for that
  sysctl, like "2"?)

As to the mechanics of the change, I'm not sure I like the idea of adding
a UAPI flag for this. Why not just retain the permission check done at
open() and if kernelmode faults aren't allowed, ignore them? This would
require no changes to existing programs and gains the desired defense.
(And, I think, the sysctl value could be bumped to "2" as that's a
better default state -- does qemu actually need kernelmode traps?)

Thanks again for the patches!

-Kees

> 
>  Documentation/admin-guide/sysctl/vm.rst | 13 ++++
>  fs/anon_inodes.c                        | 89 +++++++++++++++++--------
>  fs/userfaultfd.c                        | 29 ++++++--
>  include/linux/anon_inodes.h             | 27 ++++++--
>  include/linux/lsm_hooks.h               |  8 +++
>  include/linux/security.h                |  2 +
>  include/linux/userfaultfd_k.h           |  3 +
>  include/uapi/linux/userfaultfd.h        |  9 +++
>  kernel/sysctl.c                         |  9 +++
>  security/security.c                     |  8 +++
>  security/selinux/hooks.c                | 68 +++++++++++++++++++
>  security/selinux/include/classmap.h     |  2 +
>  12 files changed, 229 insertions(+), 38 deletions(-)
> 
> -- 
> 2.25.0.225.g125e21ebc7-goog
> 

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-11 23:27   ` Daniel Colascione
@ 2020-02-12 16:09     ` Stephen Smalley
  2020-02-21 17:56     ` James Morris
  1 sibling, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-02-12 16:09 UTC (permalink / raw)
  To: Daniel Colascione, Casey Schaufler
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux, LSM List

On 2/11/20 6:27 PM, Daniel Colascione wrote:
> On Tue, Feb 11, 2020 at 3:13 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>>
>> On 2/11/2020 2:55 PM, Daniel Colascione wrote:
>>> Userfaultfd in unprivileged contexts could be potentially very
>>> useful. We'd like to harden userfaultfd to make such unprivileged use
>>> less risky. This patch series allows SELinux to manage userfaultfd
>>> file descriptors and allows administrators to limit userfaultfd to
>>> servicing user-mode faults, increasing the difficulty of using
>>> userfaultfd in exploit chains invoking delaying kernel faults.
>>>
>>> A new anon_inodes interface allows callers to opt into SELinux
>>> management of anonymous file objects. In this mode, anon_inodes
>>> creates new ephemeral inodes for anonymous file objects instead of
>>> reusing a singleton dummy inode. A new LSM hook gives security modules
>>> an opportunity to configure and veto these ephemeral inodes.
>>>
>>> Existing anon_inodes users must opt into the new functionality.
>>>
>>> Daniel Colascione (6):
>>>    Add a new flags-accepting interface for anonymous inodes
>>>    Add a concept of a "secure" anonymous file
>>>    Teach SELinux about a new userfaultfd class
>>>    Wire UFFD up to SELinux
>>>    Let userfaultfd opt out of handling kernel-mode faults
>>>    Add a new sysctl for limiting userfaultfd to user mode faults
>>
>> This must be posted to the linux Security Module list
>> <linux-security-module@vger.kernel.org>
> 
> Added. I thought selinux@ was sufficient.

scripts/get_maintainer.pl can be helpful in identifying relevant lists 
and maintainers for each patch.  I don't use its output blindly as it 
tends to over-approximate but since your patches span the VFS, LSM 
framework, and selinux, you do need to include relevant 
maintainers/lists for each.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 1/6] Add a new flags-accepting interface for anonymous inodes
  2020-02-11 22:55 ` [PATCH v2 1/6] Add a new flags-accepting interface for anonymous inodes Daniel Colascione
@ 2020-02-12 16:37   ` Stephen Smalley
  2020-02-12 17:23     ` Daniel Colascione
  0 siblings, 1 reply; 75+ messages in thread
From: Stephen Smalley @ 2020-02-12 16:37 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, nosh, nnk, lokeshgidra,
	linux-kernel, linux-api, selinux

On 2/11/20 5:55 PM, Daniel Colascione wrote:
> 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 <dancol@google.com>

(please add linux-fsdevel, viro to cc on future versions of this patch 
since this is a VFS change)

> ---
>   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

Not going to bikeshed on names but anon_inode_getfile_flags or _secure 
or something would be more descriptive.

>    *
>    * @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*

Do we really envision ever needing more than one new flag here?  If not, 
then making it a bool secure parameter or encoding it as an 
unused/ignored flag bit in the existing flags argument would seem 
preferable.

In some cases, we actually want the "anon inode" to inherit the security 
context of a related inode (e.g. ioctls on /dev/kvm can create anon 
inodes representing VMs, vCPUs, etc and further ioctls are performed on 
those inodes), in which case we may need the caller to pass in the 
related inode as well.

>    *
> - * 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);

Not sure this is how it is normally done (i.e. one patch to just 
introduce an extended interface but disallow all use of it, then a 
separate patch to introduce the first use).  Would recommend combining; 
otherwise reviewers can't see how it will be used without looking at both.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 2/6] Add a concept of a "secure" anonymous file
  2020-02-11 22:55 ` [PATCH v2 2/6] Add a concept of a "secure" anonymous file Daniel Colascione
@ 2020-02-12 16:49   ` Stephen Smalley
  2020-02-14 22:13   ` kbuild test robot
  1 sibling, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-02-12 16:49 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, nosh, nnk, lokeshgidra,
	linux-kernel, linux-api, selinux

On 2/11/20 5:55 PM, Daniel Colascione wrote:
> 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 <dancol@google.com>

(please add linux-fsdevel, viro, linux-security-module, 
jmorris@namei.org, serge@hallyn.com to cc on future versions of this 
patch since it is a VFS and a LSM change)

> --- > 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.

Please document the parameters for the hook as well.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-12  7:50 ` Kees Cook
@ 2020-02-12 16:54   ` Jann Horn
  2020-02-12 17:14     ` Peter Xu
  2020-02-12 17:12   ` Daniel Colascione
  1 sibling, 1 reply; 75+ messages in thread
From: Jann Horn @ 2020-02-12 16:54 UTC (permalink / raw)
  To: Kees Cook
  Cc: Daniel Colascione, Tim Murray, Nosh Minwalla, Nick Kralevich,
	Lokesh Gidra, kernel list, Linux API, SElinux list,
	Andrea Arcangeli, Mike Rapoport, Peter Xu, linux-security-module

On Wed, Feb 12, 2020 at 8:51 AM Kees Cook <keescook@chromium.org> wrote:
> On Tue, Feb 11, 2020 at 02:55:41PM -0800, Daniel Colascione wrote:
> >   Let userfaultfd opt out of handling kernel-mode faults
> >   Add a new sysctl for limiting userfaultfd to user mode faults
>
> Now this I'm very interested in. Can you go into more detail about two
> things:
[...]
> - Why is this needed in addition to the existing vm.unprivileged_userfaultfd
>   sysctl? (And should this maybe just be another setting for that
>   sysctl, like "2"?)
>
> As to the mechanics of the change, I'm not sure I like the idea of adding
> a UAPI flag for this. Why not just retain the permission check done at
> open() and if kernelmode faults aren't allowed, ignore them? This would
> require no changes to existing programs and gains the desired defense.
> (And, I think, the sysctl value could be bumped to "2" as that's a
> better default state -- does qemu actually need kernelmode traps?)

I think this might be necessary for I/O emulation? As in, if before
getting migrated, the guest writes some data into a buffer, then the
guest gets migrated, and then while the postcopy migration stuff is
still running, the guest tells QEMU to write that data from
guest-physical memory to disk or whatever; I think in that case, QEMU
will do something like a pwrite() syscall where the userspace pointer
points into the memory area containing guest-physical memory, which
would return -EFAULT if userfaultfd was restricted to userspace
accesses.

This was described in this old presentation about why userfaultfd is
better than a SIGSEGV handler:
https://drive.google.com/file/d/0BzyAwvVlQckeSzlCSDFmRHVybzQ/view
(slide 6) (recording at https://youtu.be/pC8cWWRVSPw?t=463)

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 3/6] Teach SELinux about a new userfaultfd class
  2020-02-11 22:55 ` [PATCH v2 3/6] Teach SELinux about a new userfaultfd class Daniel Colascione
@ 2020-02-12 17:05   ` Stephen Smalley
  2020-02-12 17:19     ` Daniel Colascione
  0 siblings, 1 reply; 75+ messages in thread
From: Stephen Smalley @ 2020-02-12 17:05 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, nosh, nnk, lokeshgidra,
	linux-kernel, linux-api, selinux

On 2/11/20 5:55 PM, Daniel Colascione wrote:
> 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 <dancol@google.com>

(please add linux-fsdevel and viro to the cc for future versions of this 
patch since it changes the VFS)

> ---
> 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
> @@ -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;

Seems like this is precluded by the caller and would be a bug?  If 
needed at all, take it to the security_inode_init_security_anon() so it 
doesn't have to be repeated in each security module.

> +
> +	/*
> +	 * We shouldn't be creating secure anonymous inodes before LSM
> +	 * initialization completes.
> +	 */
> +	if (unlikely(!selinux_state.initialized))
> +		return -EBUSY;

I don't think this is viable; any arbitrary actions are possible before 
policy is loaded, and a Linux distro can be brought up fully with 
SELinux enabled and no policy loaded.  You'll just need to have a 
default behavior prior to initialization.

> +
> +	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);

I think the kernel discourages overuse of BUG_ON/BUG/...

> +
> +#ifdef CONFIG_USERFAULTFD
> +	if (fops == &userfaultfd_fops)
> +		isec->sclass = SECCLASS_UFFD;
> +#endif

Not sure we want or need to introduce a new security class for each user 
of anonymous inodes since the permissions should be the same as for 
file.  Also not sure we want to be testing fops for each such case.  We 
were looking at possibly leveraging the name as a key and using 
security_transition_sid() to generate a distinct SID/context/type for 
the inode via type_transition rules in policy.  We have some WIP along 
those lines.

> +
> +	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;

This doesn't generalize for other users of anonymous inodes, e.g. the 
/dev/kvm case where we'd rather inherit the SID and class from the 
original /dev/kvm inode itself.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-12  7:50 ` Kees Cook
  2020-02-12 16:54   ` Jann Horn
@ 2020-02-12 17:12   ` Daniel Colascione
  1 sibling, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-12 17:12 UTC (permalink / raw)
  To: Kees Cook
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux, Andrea Arcangeli,
	Mike Rapoport, Peter Xu, Jann Horn, LSM List

Thanks for taking a look and for the fast reply!

On Tue, Feb 11, 2020 at 11:51 PM Kees Cook <keescook@chromium.org> wrote:
>
> Hi!
>
> Firstly, thanks for working on this! It's been on my TODO list for a
> while. :)
>
> Casey already recommended including the LSM list to CC (since this is a
> new LSM -- there are many LSMs). Additionally, the series should
> probably be sent _to_ the userfaultfd maintainers:
>         Andrea Arcangeli <aarcange@redhat.com>
>         Mike Rapoport <rppt@linux.ibm.com>
> and I'd also CC a couple other people that have done recent work:
>         Peter Xu <peterx@redhat.com>
>         Jann Horn <jannh@google.com>
>
> More notes below...

In general, in the event that a patch series doesn't include all
needed parties on the to-line, what's the right way to fix the
situation without spamming everyone and forking the thread? In this
case, since I'm splitting the patch series anyway, I can just expand
the to-line in the reroll.

> On Tue, Feb 11, 2020 at 02:55:41PM -0800, Daniel Colascione wrote:
> > Userfaultfd in unprivileged contexts could be potentially very
> > useful. We'd like to harden userfaultfd to make such unprivileged use
> > less risky. This patch series allows SELinux to manage userfaultfd
> > file descriptors and allows administrators to limit userfaultfd to
> > servicing user-mode faults, increasing the difficulty of using
> > userfaultfd in exploit chains invoking delaying kernel faults.
>
> I actually think these are two very different goals and likely the
> series could be split into two for them. One is LSM hooking of
> userfaultfd and the SELinux attachment, and the other is the user-mode
> fault restrictions. And they would likely go via separate trees (LSM
> through James's LSM tree, and probably akpm's -mm tree for the sysctl).
>
> > A new anon_inodes interface allows callers to opt into SELinux
> > management of anonymous file objects. In this mode, anon_inodes
> > creates new ephemeral inodes for anonymous file objects instead of
> > reusing a singleton dummy inode. A new LSM hook gives security modules
> > an opportunity to configure and veto these ephemeral inodes.
> >
> > Existing anon_inodes users must opt into the new functionality.
> >
> > Daniel Colascione (6):
> >   Add a new flags-accepting interface for anonymous inodes
> >   Add a concept of a "secure" anonymous file
> >   Teach SELinux about a new userfaultfd class
> >   Wire UFFD up to SELinux
>
> The above is the first "series"... I don't have much opinion about it,
> though I do like the idea of making userfaultfd visible to the LSM.

Yeah. The interesting part there is the anon_inodes API change. I'll
split that half of the series out.

> >   Let userfaultfd opt out of handling kernel-mode faults
> >   Add a new sysctl for limiting userfaultfd to user mode faults
>
> Now this I'm very interested in. Can you go into more detail about two
> things:
>
> - What is the threat being solved? (I understand the threat, but detailing
>   it in the commit log is important for people who don't know it. Existing
>   commit cefdca0a86be517bc390fc4541e3674b8e7803b0 gets into some of the
>   details already, but I'd like to see reference to external sources like
>   https://duasynt.com/blog/linux-kernel-heap-spray)

Sure. I can add a reference to that and a more general discussion of
how delaying kernel fault handling can broaden race windows for other
exploits.

> - Why is this needed in addition to the existing vm.unprivileged_userfaultfd
>   sysctl? (And should this maybe just be another setting for that
>   sysctl, like "2"?)

We want to use UFFD for a new garbage collector in Android, and we
want unprivileged processes to be able to use this new garbage
collector. Giving them CAP_SYS_PTRACE is dangerous.

> As to the mechanics of the change, I'm not sure I like the idea of adding
> a UAPI flag for this. Why not just retain the permission check done at
> open() and if kernelmode faults aren't allowed, ignore them? This would
> require no changes to existing programs and gains the desired defense.

As Jann mentions below, it's a matter of the kernel's contractual
obligation to userspace. Right now, userfaultfd(2) either succeeds or
it fails with one of the enumerated error codes. You're proposing
having the userfaultfd(2) succeed but return a file descriptor that
doesn't do the job the kernel promised it would do. If we were to
adopt your proposal, an application would see UFFD succeed, then see
unexpeced EFAULTs from system calls, which would probably cause the
application to malfunctioning in exciting ways. An explicit "sorry, I
can't do that" error code is better: an application that gets an error
code from userfaultfd(2) can fall back to something else, but an
application that silently gets an underfeatured UFFD doesn't know
anything is wrong until it's too late. The additional flag preserves
the UFFD contract and gives applications a way to probe for feature
support.

> (And, I think, the sysctl value could be bumped to "2" as that's a
> better default state -- does qemu actually need kernelmode traps?)

I prefer a default of one for regular systems because I don't want to
make experimentation with novel ways to use UFFD more difficult, and a
default of two would require users go out of their way to handle user
faults, and few will. For a more constrained system like Android, two
is fine.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-12 16:54   ` Jann Horn
@ 2020-02-12 17:14     ` Peter Xu
  2020-02-12 19:41       ` Andrea Arcangeli
  0 siblings, 1 reply; 75+ messages in thread
From: Peter Xu @ 2020-02-12 17:14 UTC (permalink / raw)
  To: Jann Horn
  Cc: Kees Cook, Daniel Colascione, Tim Murray, Nosh Minwalla,
	Nick Kralevich, Lokesh Gidra, kernel list, Linux API,
	SElinux list, Andrea Arcangeli, Mike Rapoport,
	linux-security-module

On Wed, Feb 12, 2020 at 05:54:35PM +0100, Jann Horn wrote:
> On Wed, Feb 12, 2020 at 8:51 AM Kees Cook <keescook@chromium.org> wrote:
> > On Tue, Feb 11, 2020 at 02:55:41PM -0800, Daniel Colascione wrote:
> > >   Let userfaultfd opt out of handling kernel-mode faults
> > >   Add a new sysctl for limiting userfaultfd to user mode faults
> >
> > Now this I'm very interested in. Can you go into more detail about two
> > things:
> [...]
> > - Why is this needed in addition to the existing vm.unprivileged_userfaultfd
> >   sysctl? (And should this maybe just be another setting for that
> >   sysctl, like "2"?)
> >
> > As to the mechanics of the change, I'm not sure I like the idea of adding
> > a UAPI flag for this. Why not just retain the permission check done at
> > open() and if kernelmode faults aren't allowed, ignore them? This would
> > require no changes to existing programs and gains the desired defense.
> > (And, I think, the sysctl value could be bumped to "2" as that's a
> > better default state -- does qemu actually need kernelmode traps?)
> 
> I think this might be necessary for I/O emulation? As in, if before
> getting migrated, the guest writes some data into a buffer, then the
> guest gets migrated, and then while the postcopy migration stuff is
> still running, the guest tells QEMU to write that data from
> guest-physical memory to disk or whatever; I think in that case, QEMU
> will do something like a pwrite() syscall where the userspace pointer
> points into the memory area containing guest-physical memory, which
> would return -EFAULT if userfaultfd was restricted to userspace
> accesses.
> 
> This was described in this old presentation about why userfaultfd is
> better than a SIGSEGV handler:
> https://drive.google.com/file/d/0BzyAwvVlQckeSzlCSDFmRHVybzQ/view
> (slide 6) (recording at https://youtu.be/pC8cWWRVSPw?t=463)

Right. AFAICT QEMU uses it far more than disk IOs.  A guest page can
be accessed by any kernel component on the destination host during a
postcopy procedure.  It can be as simple as when a vcpu writes to a
missing guest page which still resides on the source host, then KVM
will get a page fault and trap into userfaultfd asking for that page.
The same thing happens to other modules like vhost, etc., as long as a
missing guest page is touched by a kernel module.

Thanks,

-- 
Peter Xu


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 3/6] Teach SELinux about a new userfaultfd class
  2020-02-12 17:05   ` Stephen Smalley
@ 2020-02-12 17:19     ` Daniel Colascione
  2020-02-12 18:04       ` Stephen Smalley
  0 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-02-12 17:19 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux

Thanks for taking a look.

On Wed, Feb 12, 2020 at 9:04 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>
> On 2/11/20 5:55 PM, Daniel Colascione wrote:
> > 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 <dancol@google.com>
>
> (please add linux-fsdevel and viro to the cc for future versions of this
> patch since it changes the VFS)
>
> > ---
> > 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
> > @@ -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;
>
> Seems like this is precluded by the caller and would be a bug?  If
> needed at all, take it to the security_inode_init_security_anon() so it
> doesn't have to be repeated in each security module.
>
> > +
> > +     /*
> > +      * We shouldn't be creating secure anonymous inodes before LSM
> > +      * initialization completes.
> > +      */
> > +     if (unlikely(!selinux_state.initialized))
> > +             return -EBUSY;
>
> I don't think this is viable; any arbitrary actions are possible before
> policy is loaded, and a Linux distro can be brought up fully with
> SELinux enabled and no policy loaded.  You'll just need to have a
> default behavior prior to initialization.

We'd have to fail open then, I think, and return an S_PRIVATE inode
(the regular anon inode).

> > +
> > +     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);
>
> I think the kernel discourages overuse of BUG_ON/BUG/...

I'm not sure what counts as overuse.

> > +
> > +#ifdef CONFIG_USERFAULTFD
> > +     if (fops == &userfaultfd_fops)
> > +             isec->sclass = SECCLASS_UFFD;
> > +#endif
>
> Not sure we want or need to introduce a new security class for each user
> of anonymous inodes since the permissions should be the same as for
> file.

The purpose of this change is to apply special policy to userfaultfd
FDs in particular. Isn't having a UFFD security class the best way to
go about that? (There's no path.) Am I missing something?

> Also not sure we want to be testing fops for each such case.

I was also thinking of just providing some kind of context string
(maybe the name), which might be friendlier to modules, but the loose
coupling kind of scares me, and for this particular application, since
UFFD is always in the core and never in a module, checking the fops
seems a bit more robust and doesn't hurt anything.

> We
> were looking at possibly leveraging the name as a key and using
> security_transition_sid() to generate a distinct SID/context/type for
> the inode via type_transition rules in policy.  We have some WIP along
> those lines.

Where? Any chance it would be ready soon? I'd rather not hold up this
work for a more general mechanism.

> > +
> > +     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;
>
> This doesn't generalize for other users of anonymous inodes, e.g. the
> /dev/kvm case where we'd rather inherit the SID and class from the
> original /dev/kvm inode itself.

I think someone mentioned on the first version of this patch that we
could make it more flexible if the need arose. If we do want to do it
now, we could have the anon_inode security hook accept a "parent" or
"context" inode that modules could inspect for the purposes of forming
the new inode's SID. Does that make sense to you?

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 1/6] Add a new flags-accepting interface for anonymous inodes
  2020-02-12 16:37   ` Stephen Smalley
@ 2020-02-12 17:23     ` Daniel Colascione
  0 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-12 17:23 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux

Thanks again for the review.

On Wed, Feb 12, 2020 at 8:36 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>
> On 2/11/20 5:55 PM, Daniel Colascione wrote:
> > 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 <dancol@google.com>
>
> (please add linux-fsdevel, viro to cc on future versions of this patch
> since this is a VFS change)
>
> > ---
> >   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
>
> Not going to bikeshed on names but anon_inode_getfile_flags or _secure
> or something would be more descriptive.

_flags is fine, but I think _secure is overfitting.

> >    *
> >    * @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*
>
> Do we really envision ever needing more than one new flag here?  If not,
> then making it a bool secure parameter or encoding it as an
> unused/ignored flag bit in the existing flags argument would seem
> preferable.

A bool and a flag is the same as far as the machine is concerned with
respect to argument passing, and I find the flag much more descriptive
than a bare "true" or a "false" scattered at call sites. Besides, a
flags argument could lead to less churn later.

> In some cases, we actually want the "anon inode" to inherit the security
> context of a related inode (e.g. ioctls on /dev/kvm can create anon
> inodes representing VMs, vCPUs, etc and further ioctls are performed on
> those inodes), in which case we may need the caller to pass in the
> related inode as well.

See my other reply on this subject. Passing an optional related inode
seems like a decent approach here.

> >    *
> > - * 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);
>
> Not sure this is how it is normally done (i.e. one patch to just
> introduce an extended interface but disallow all use of it, then a
> separate patch to introduce the first use).  Would recommend combining;
> otherwise reviewers can't see how it will be used without looking at both.

All things being equal, finer-grained patches are better: they allow
for easier bisection. But I don't feel strongly one way or the other
here, so let's see what other reviewers say.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 3/6] Teach SELinux about a new userfaultfd class
  2020-02-12 17:19     ` Daniel Colascione
@ 2020-02-12 18:04       ` Stephen Smalley
  2020-02-12 18:59         ` Stephen Smalley
  0 siblings, 1 reply; 75+ messages in thread
From: Stephen Smalley @ 2020-02-12 18:04 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux

On 2/12/20 12:19 PM, Daniel Colascione wrote:
> Thanks for taking a look.
> 
> On Wed, Feb 12, 2020 at 9:04 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>>
>> On 2/11/20 5:55 PM, Daniel Colascione wrote:
>>> 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 <dancol@google.com>
>>
>> (please add linux-fsdevel and viro to the cc for future versions of this
>> patch since it changes the VFS)
>>
>>> ---
>>> 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
>>> @@ -2915,6 +2919,69 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>>> +
>>> +     /*
>>> +      * We shouldn't be creating secure anonymous inodes before LSM
>>> +      * initialization completes.
>>> +      */
>>> +     if (unlikely(!selinux_state.initialized))
>>> +             return -EBUSY;
>>
>> I don't think this is viable; any arbitrary actions are possible before
>> policy is loaded, and a Linux distro can be brought up fully with
>> SELinux enabled and no policy loaded.  You'll just need to have a
>> default behavior prior to initialization.
> 
> We'd have to fail open then, I think, and return an S_PRIVATE inode
> (the regular anon inode).

Not sure why.  You aren't doing anything in the hook that actually 
relies on selinux_state.initialized being set (i.e. nothing requires a 
policy).  The avc_has_perm() call will just succeed until a policy is 
loaded.  So if these inodes are created prior to policy load, they will 
get assigned the task SID (which would be the kernel SID prior to policy 
load or first exec or write to /proc/self/attr/current afterward) and 
UFFD class (in your current code), be permitted, and then once policy is 
loaded any further access will get checked against the kernel SID.

>>> +     /*
>>> +      * 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);
>>
>> I think the kernel discourages overuse of BUG_ON/BUG/...
> 
> I'm not sure what counts as overuse.

Me either (not my rule) but I'm pretty sure this counts or you'd see a 
lot more of these kinds of BUG_ON() checks throughout.  Try to reserve 
them for really critical cases.

>>> +
>>> +#ifdef CONFIG_USERFAULTFD
>>> +     if (fops == &userfaultfd_fops)
>>> +             isec->sclass = SECCLASS_UFFD;
>>> +#endif
>>
>> Not sure we want or need to introduce a new security class for each user
>> of anonymous inodes since the permissions should be the same as for
>> file.
> 
> The purpose of this change is to apply special policy to userfaultfd
> FDs in particular. Isn't having a UFFD security class the best way to
> go about that? (There's no path.) Am I missing something?

It is probably the simplest approach; it just doesn't generalize to all 
users of anonymous inodes. We can distinguish them in one of two ways: 
use a different class like you did (requires a code change every time we 
add a new one and yet another duplicate of the file class) or use a 
different SID/context/type. The latter could be achieved by calling 
security_transition_sid() with the provided name wrapped in a qstr and 
specifying type_transition rules on the name.  Then policy could define 
derived types for each domain, ala
type_transition init self:file "[userfaultfd]" init_userfaultfd;
type_transition untrusted_app self:file "[userfaultfd]" 
untrusted_app_userfaultfd;
...

>> Also not sure we want to be testing fops for each such case.
> 
> I was also thinking of just providing some kind of context string
> (maybe the name), which might be friendlier to modules, but the loose
> coupling kind of scares me, and for this particular application, since
> UFFD is always in the core and never in a module, checking the fops
> seems a bit more robust and doesn't hurt anything.

Yes, not sure how the vfs folks feel about either coupling (the 
name-based one or the fops-based one).  Neither seems great.

>> We
>> were looking at possibly leveraging the name as a key and using
>> security_transition_sid() to generate a distinct SID/context/type for
>> the inode via type_transition rules in policy.  We have some WIP along
>> those lines.
> 
> Where? Any chance it would be ready soon? I'd rather not hold up this
> work for a more general mechanism.

Hopefully will have a patch available soon.  But not saying this 
necessarily has to wait either.

>>> +     /*
>>> +      * Always give secure anonymous inodes the sid of the
>>> +      * creating task.
>>> +      */
>>> +
>>> +     isec->sid = tsec->sid;
>>
>> This doesn't generalize for other users of anonymous inodes, e.g. the
>> /dev/kvm case where we'd rather inherit the SID and class from the
>> original /dev/kvm inode itself.
> 
> I think someone mentioned on the first version of this patch that we
> could make it more flexible if the need arose. If we do want to do it
> now, we could have the anon_inode security hook accept a "parent" or
> "context" inode that modules could inspect for the purposes of forming
> the new inode's SID. Does that make sense to you?

Yes, that's the approach in our current WIP, except we call it a 
"related" inode since it isn't necessarily connected to the anon inode 
in any vfs sense.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 3/6] Teach SELinux about a new userfaultfd class
  2020-02-12 18:04       ` Stephen Smalley
@ 2020-02-12 18:59         ` Stephen Smalley
  2020-02-12 19:04           ` Daniel Colascione
  0 siblings, 1 reply; 75+ messages in thread
From: Stephen Smalley @ 2020-02-12 18:59 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux

On 2/12/20 1:04 PM, Stephen Smalley wrote:
> On 2/12/20 12:19 PM, Daniel Colascione wrote:
>> Thanks for taking a look.
>>
>> On Wed, Feb 12, 2020 at 9:04 AM Stephen Smalley <sds@tycho.nsa.gov> 
>> wrote:
>>>
>>> On 2/11/20 5:55 PM, Daniel Colascione wrote:
>>>> 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 <dancol@google.com>
>>>
>>> (please add linux-fsdevel and viro to the cc for future versions of this
>>> patch since it changes the VFS)
>>>
>>>> ---
>>>> 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
>>>> @@ -2915,6 +2919,69 @@ static int selinux_inode_init_security(struct 
>>>> inode *inode, struct inode *dir,
>>>> +
>>>> +     /*
>>>> +      * We shouldn't be creating secure anonymous inodes before LSM
>>>> +      * initialization completes.
>>>> +      */
>>>> +     if (unlikely(!selinux_state.initialized))
>>>> +             return -EBUSY;
>>>
>>> I don't think this is viable; any arbitrary actions are possible before
>>> policy is loaded, and a Linux distro can be brought up fully with
>>> SELinux enabled and no policy loaded.  You'll just need to have a
>>> default behavior prior to initialization.
>>
>> We'd have to fail open then, I think, and return an S_PRIVATE inode
>> (the regular anon inode).
> 
> Not sure why.  You aren't doing anything in the hook that actually 
> relies on selinux_state.initialized being set (i.e. nothing requires a 
> policy).  The avc_has_perm() call will just succeed until a policy is 
> loaded.  So if these inodes are created prior to policy load, they will 
> get assigned the task SID (which would be the kernel SID prior to policy 
> load or first exec or write to /proc/self/attr/current afterward) and 
> UFFD class (in your current code), be permitted, and then once policy is 
> loaded any further access will get checked against the kernel SID.
> 
>>>> +     /*
>>>> +      * 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);
>>>
>>> I think the kernel discourages overuse of BUG_ON/BUG/...
>>
>> I'm not sure what counts as overuse.
> 
> Me either (not my rule) but I'm pretty sure this counts or you'd see a 
> lot more of these kinds of BUG_ON() checks throughout.  Try to reserve 
> them for really critical cases.
> 
>>>> +
>>>> +#ifdef CONFIG_USERFAULTFD
>>>> +     if (fops == &userfaultfd_fops)
>>>> +             isec->sclass = SECCLASS_UFFD;
>>>> +#endif
>>>
>>> Not sure we want or need to introduce a new security class for each user
>>> of anonymous inodes since the permissions should be the same as for
>>> file.
>>
>> The purpose of this change is to apply special policy to userfaultfd
>> FDs in particular. Isn't having a UFFD security class the best way to
>> go about that? (There's no path.) Am I missing something?
> 
> It is probably the simplest approach; it just doesn't generalize to all 
> users of anonymous inodes. We can distinguish them in one of two ways: 
> use a different class like you did (requires a code change every time we 
> add a new one and yet another duplicate of the file class) or use a 
> different SID/context/type. The latter could be achieved by calling 
> security_transition_sid() with the provided name wrapped in a qstr and 
> specifying type_transition rules on the name.  Then policy could define 
> derived types for each domain, ala
> type_transition init self:file "[userfaultfd]" init_userfaultfd;
> type_transition untrusted_app self:file "[userfaultfd]" 
> untrusted_app_userfaultfd;
> ...
> 
>>> Also not sure we want to be testing fops for each such case.
>>
>> I was also thinking of just providing some kind of context string
>> (maybe the name), which might be friendlier to modules, but the loose
>> coupling kind of scares me, and for this particular application, since
>> UFFD is always in the core and never in a module, checking the fops
>> seems a bit more robust and doesn't hurt anything.
> 
> Yes, not sure how the vfs folks feel about either coupling (the 
> name-based one or the fops-based one).  Neither seems great.
> 
>>> We
>>> were looking at possibly leveraging the name as a key and using
>>> security_transition_sid() to generate a distinct SID/context/type for
>>> the inode via type_transition rules in policy.  We have some WIP along
>>> those lines.
>>
>> Where? Any chance it would be ready soon? I'd rather not hold up this
>> work for a more general mechanism.
> 
> Hopefully will have a patch available soon.  But not saying this 
> necessarily has to wait either.
> 
>>>> +     /*
>>>> +      * Always give secure anonymous inodes the sid of the
>>>> +      * creating task.
>>>> +      */
>>>> +
>>>> +     isec->sid = tsec->sid;
>>>
>>> This doesn't generalize for other users of anonymous inodes, e.g. the
>>> /dev/kvm case where we'd rather inherit the SID and class from the
>>> original /dev/kvm inode itself.
>>
>> I think someone mentioned on the first version of this patch that we
>> could make it more flexible if the need arose. If we do want to do it
>> now, we could have the anon_inode security hook accept a "parent" or
>> "context" inode that modules could inspect for the purposes of forming
>> the new inode's SID. Does that make sense to you?
> 
> Yes, that's the approach in our current WIP, except we call it a 
> "related" inode since it isn't necessarily connected to the anon inode 
> in any vfs sense.

The other key difference in our WIP approach is that we assumed that we 
couldn't mandate allocating a separate anon inode for each of these fds 
and we wanted to cover all anonymous inodes (not opt-in), so we are 
storing the SID/class pair as additional fields in the 
file_security_struct and have modified file_has_perm() and others to 
look there for anonymous inodes.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 3/6] Teach SELinux about a new userfaultfd class
  2020-02-12 18:59         ` Stephen Smalley
@ 2020-02-12 19:04           ` Daniel Colascione
  2020-02-12 19:11             ` Stephen Smalley
  0 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-02-12 19:04 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux

On Wed, Feb 12, 2020 at 10:59 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>
> On 2/12/20 1:04 PM, Stephen Smalley wrote:
> > On 2/12/20 12:19 PM, Daniel Colascione wrote:
> >> Thanks for taking a look.
> >>
> >> On Wed, Feb 12, 2020 at 9:04 AM Stephen Smalley <sds@tycho.nsa.gov>
> >> wrote:
> >>>
> >>> On 2/11/20 5:55 PM, Daniel Colascione wrote:
> >>>> 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 <dancol@google.com>
> >>>
> >>> (please add linux-fsdevel and viro to the cc for future versions of this
> >>> patch since it changes the VFS)
> >>>
> >>>> ---
> >>>> 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
> >>>> @@ -2915,6 +2919,69 @@ static int selinux_inode_init_security(struct
> >>>> inode *inode, struct inode *dir,
> >>>> +
> >>>> +     /*
> >>>> +      * We shouldn't be creating secure anonymous inodes before LSM
> >>>> +      * initialization completes.
> >>>> +      */
> >>>> +     if (unlikely(!selinux_state.initialized))
> >>>> +             return -EBUSY;
> >>>
> >>> I don't think this is viable; any arbitrary actions are possible before
> >>> policy is loaded, and a Linux distro can be brought up fully with
> >>> SELinux enabled and no policy loaded.  You'll just need to have a
> >>> default behavior prior to initialization.
> >>
> >> We'd have to fail open then, I think, and return an S_PRIVATE inode
> >> (the regular anon inode).
> >
> > Not sure why.  You aren't doing anything in the hook that actually
> > relies on selinux_state.initialized being set (i.e. nothing requires a
> > policy).  The avc_has_perm() call will just succeed until a policy is
> > loaded.  So if these inodes are created prior to policy load, they will
> > get assigned the task SID (which would be the kernel SID prior to policy
> > load or first exec or write to /proc/self/attr/current afterward) and
> > UFFD class (in your current code), be permitted, and then once policy is
> > loaded any further access will get checked against the kernel SID.
> >
> >>>> +     /*
> >>>> +      * 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);
> >>>
> >>> I think the kernel discourages overuse of BUG_ON/BUG/...
> >>
> >> I'm not sure what counts as overuse.
> >
> > Me either (not my rule) but I'm pretty sure this counts or you'd see a
> > lot more of these kinds of BUG_ON() checks throughout.  Try to reserve
> > them for really critical cases.
> >
> >>>> +
> >>>> +#ifdef CONFIG_USERFAULTFD
> >>>> +     if (fops == &userfaultfd_fops)
> >>>> +             isec->sclass = SECCLASS_UFFD;
> >>>> +#endif
> >>>
> >>> Not sure we want or need to introduce a new security class for each user
> >>> of anonymous inodes since the permissions should be the same as for
> >>> file.
> >>
> >> The purpose of this change is to apply special policy to userfaultfd
> >> FDs in particular. Isn't having a UFFD security class the best way to
> >> go about that? (There's no path.) Am I missing something?
> >
> > It is probably the simplest approach; it just doesn't generalize to all
> > users of anonymous inodes. We can distinguish them in one of two ways:
> > use a different class like you did (requires a code change every time we
> > add a new one and yet another duplicate of the file class) or use a
> > different SID/context/type. The latter could be achieved by calling
> > security_transition_sid() with the provided name wrapped in a qstr and
> > specifying type_transition rules on the name.  Then policy could define
> > derived types for each domain, ala
> > type_transition init self:file "[userfaultfd]" init_userfaultfd;
> > type_transition untrusted_app self:file "[userfaultfd]"
> > untrusted_app_userfaultfd;
> > ...
> >
> >>> Also not sure we want to be testing fops for each such case.
> >>
> >> I was also thinking of just providing some kind of context string
> >> (maybe the name), which might be friendlier to modules, but the loose
> >> coupling kind of scares me, and for this particular application, since
> >> UFFD is always in the core and never in a module, checking the fops
> >> seems a bit more robust and doesn't hurt anything.
> >
> > Yes, not sure how the vfs folks feel about either coupling (the
> > name-based one or the fops-based one).  Neither seems great.
> >
> >>> We
> >>> were looking at possibly leveraging the name as a key and using
> >>> security_transition_sid() to generate a distinct SID/context/type for
> >>> the inode via type_transition rules in policy.  We have some WIP along
> >>> those lines.
> >>
> >> Where? Any chance it would be ready soon? I'd rather not hold up this
> >> work for a more general mechanism.
> >
> > Hopefully will have a patch available soon.  But not saying this
> > necessarily has to wait either.
> >
> >>>> +     /*
> >>>> +      * Always give secure anonymous inodes the sid of the
> >>>> +      * creating task.
> >>>> +      */
> >>>> +
> >>>> +     isec->sid = tsec->sid;
> >>>
> >>> This doesn't generalize for other users of anonymous inodes, e.g. the
> >>> /dev/kvm case where we'd rather inherit the SID and class from the
> >>> original /dev/kvm inode itself.
> >>
> >> I think someone mentioned on the first version of this patch that we
> >> could make it more flexible if the need arose. If we do want to do it
> >> now, we could have the anon_inode security hook accept a "parent" or
> >> "context" inode that modules could inspect for the purposes of forming
> >> the new inode's SID. Does that make sense to you?
> >
> > Yes, that's the approach in our current WIP, except we call it a
> > "related" inode since it isn't necessarily connected to the anon inode
> > in any vfs sense.
>
> The other key difference in our WIP approach is that we assumed that we
> couldn't mandate allocating a separate anon inode for each of these fds
> and we wanted to cover all anonymous inodes (not opt-in), so we are
> storing the SID/class pair as additional fields in the
> file_security_struct and have modified file_has_perm() and others to
> look there for anonymous inodes.

A separate inode seems like the simpler approach for now, because it
means that we have fewer places to check for security information ---
and it's not as if an inode is particularly expensive. We can always
switch later.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 3/6] Teach SELinux about a new userfaultfd class
  2020-02-12 19:04           ` Daniel Colascione
@ 2020-02-12 19:11             ` Stephen Smalley
  2020-02-12 19:13               ` Daniel Colascione
  2020-02-12 19:17               ` Stephen Smalley
  0 siblings, 2 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-02-12 19:11 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux

On 2/12/20 2:04 PM, Daniel Colascione wrote:
> On Wed, Feb 12, 2020 at 10:59 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>>
>> On 2/12/20 1:04 PM, Stephen Smalley wrote:
>>> On 2/12/20 12:19 PM, Daniel Colascione wrote:
>>>> Thanks for taking a look.
>>>>
>>>> On Wed, Feb 12, 2020 at 9:04 AM Stephen Smalley <sds@tycho.nsa.gov>
>>>> wrote:
>>>>>
>>>>> On 2/11/20 5:55 PM, Daniel Colascione wrote:
>>>>>> 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 <dancol@google.com>
>>>>>
>>>>> (please add linux-fsdevel and viro to the cc for future versions of this
>>>>> patch since it changes the VFS)
>>>>>
>>>>>> ---
>>>>>> 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
>>>>>> @@ -2915,6 +2919,69 @@ static int selinux_inode_init_security(struct
>>>>>> inode *inode, struct inode *dir,
>>>>>> +
>>>>>> +     /*
>>>>>> +      * We shouldn't be creating secure anonymous inodes before LSM
>>>>>> +      * initialization completes.
>>>>>> +      */
>>>>>> +     if (unlikely(!selinux_state.initialized))
>>>>>> +             return -EBUSY;
>>>>>
>>>>> I don't think this is viable; any arbitrary actions are possible before
>>>>> policy is loaded, and a Linux distro can be brought up fully with
>>>>> SELinux enabled and no policy loaded.  You'll just need to have a
>>>>> default behavior prior to initialization.
>>>>
>>>> We'd have to fail open then, I think, and return an S_PRIVATE inode
>>>> (the regular anon inode).
>>>
>>> Not sure why.  You aren't doing anything in the hook that actually
>>> relies on selinux_state.initialized being set (i.e. nothing requires a
>>> policy).  The avc_has_perm() call will just succeed until a policy is
>>> loaded.  So if these inodes are created prior to policy load, they will
>>> get assigned the task SID (which would be the kernel SID prior to policy
>>> load or first exec or write to /proc/self/attr/current afterward) and
>>> UFFD class (in your current code), be permitted, and then once policy is
>>> loaded any further access will get checked against the kernel SID.
>>>
>>>>>> +     /*
>>>>>> +      * 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);
>>>>>
>>>>> I think the kernel discourages overuse of BUG_ON/BUG/...
>>>>
>>>> I'm not sure what counts as overuse.
>>>
>>> Me either (not my rule) but I'm pretty sure this counts or you'd see a
>>> lot more of these kinds of BUG_ON() checks throughout.  Try to reserve
>>> them for really critical cases.
>>>
>>>>>> +
>>>>>> +#ifdef CONFIG_USERFAULTFD
>>>>>> +     if (fops == &userfaultfd_fops)
>>>>>> +             isec->sclass = SECCLASS_UFFD;
>>>>>> +#endif
>>>>>
>>>>> Not sure we want or need to introduce a new security class for each user
>>>>> of anonymous inodes since the permissions should be the same as for
>>>>> file.
>>>>
>>>> The purpose of this change is to apply special policy to userfaultfd
>>>> FDs in particular. Isn't having a UFFD security class the best way to
>>>> go about that? (There's no path.) Am I missing something?
>>>
>>> It is probably the simplest approach; it just doesn't generalize to all
>>> users of anonymous inodes. We can distinguish them in one of two ways:
>>> use a different class like you did (requires a code change every time we
>>> add a new one and yet another duplicate of the file class) or use a
>>> different SID/context/type. The latter could be achieved by calling
>>> security_transition_sid() with the provided name wrapped in a qstr and
>>> specifying type_transition rules on the name.  Then policy could define
>>> derived types for each domain, ala
>>> type_transition init self:file "[userfaultfd]" init_userfaultfd;
>>> type_transition untrusted_app self:file "[userfaultfd]"
>>> untrusted_app_userfaultfd;
>>> ...
>>>
>>>>> Also not sure we want to be testing fops for each such case.
>>>>
>>>> I was also thinking of just providing some kind of context string
>>>> (maybe the name), which might be friendlier to modules, but the loose
>>>> coupling kind of scares me, and for this particular application, since
>>>> UFFD is always in the core and never in a module, checking the fops
>>>> seems a bit more robust and doesn't hurt anything.
>>>
>>> Yes, not sure how the vfs folks feel about either coupling (the
>>> name-based one or the fops-based one).  Neither seems great.
>>>
>>>>> We
>>>>> were looking at possibly leveraging the name as a key and using
>>>>> security_transition_sid() to generate a distinct SID/context/type for
>>>>> the inode via type_transition rules in policy.  We have some WIP along
>>>>> those lines.
>>>>
>>>> Where? Any chance it would be ready soon? I'd rather not hold up this
>>>> work for a more general mechanism.
>>>
>>> Hopefully will have a patch available soon.  But not saying this
>>> necessarily has to wait either.
>>>
>>>>>> +     /*
>>>>>> +      * Always give secure anonymous inodes the sid of the
>>>>>> +      * creating task.
>>>>>> +      */
>>>>>> +
>>>>>> +     isec->sid = tsec->sid;
>>>>>
>>>>> This doesn't generalize for other users of anonymous inodes, e.g. the
>>>>> /dev/kvm case where we'd rather inherit the SID and class from the
>>>>> original /dev/kvm inode itself.
>>>>
>>>> I think someone mentioned on the first version of this patch that we
>>>> could make it more flexible if the need arose. If we do want to do it
>>>> now, we could have the anon_inode security hook accept a "parent" or
>>>> "context" inode that modules could inspect for the purposes of forming
>>>> the new inode's SID. Does that make sense to you?
>>>
>>> Yes, that's the approach in our current WIP, except we call it a
>>> "related" inode since it isn't necessarily connected to the anon inode
>>> in any vfs sense.
>>
>> The other key difference in our WIP approach is that we assumed that we
>> couldn't mandate allocating a separate anon inode for each of these fds
>> and we wanted to cover all anonymous inodes (not opt-in), so we are
>> storing the SID/class pair as additional fields in the
>> file_security_struct and have modified file_has_perm() and others to
>> look there for anonymous inodes.
> 
> A separate inode seems like the simpler approach for now, because it
> means that we have fewer places to check for security information ---
> and it's not as if an inode is particularly expensive. We can always
> switch later.

We'd prefer having a separate inode if possible but didn't think that 
would fly with the vfs folks, especially if we try to apply this to all 
anonymous inodes. It might be ok for userfaultfd usage as a specific 
case but there is a reason why anonymous inodes were introduced and 
creating a separate inode each time defeats that purpose IIUC.  It will 
be interesting to see how they respond.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 3/6] Teach SELinux about a new userfaultfd class
  2020-02-12 19:11             ` Stephen Smalley
@ 2020-02-12 19:13               ` Daniel Colascione
  2020-02-12 19:17               ` Stephen Smalley
  1 sibling, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-12 19:13 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux

On Wed, Feb 12, 2020 at 11:10 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>
> On 2/12/20 2:04 PM, Daniel Colascione wrote:
> > On Wed, Feb 12, 2020 at 10:59 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> >>
> >> On 2/12/20 1:04 PM, Stephen Smalley wrote:
> >>> On 2/12/20 12:19 PM, Daniel Colascione wrote:
> >>>> Thanks for taking a look.
> >>>>
> >>>> On Wed, Feb 12, 2020 at 9:04 AM Stephen Smalley <sds@tycho.nsa.gov>
> >>>> wrote:
> >>>>>
> >>>>> On 2/11/20 5:55 PM, Daniel Colascione wrote:
> >>>>>> 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 <dancol@google.com>
> >>>>>
> >>>>> (please add linux-fsdevel and viro to the cc for future versions of this
> >>>>> patch since it changes the VFS)
> >>>>>
> >>>>>> ---
> >>>>>> 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
> >>>>>> @@ -2915,6 +2919,69 @@ static int selinux_inode_init_security(struct
> >>>>>> inode *inode, struct inode *dir,
> >>>>>> +
> >>>>>> +     /*
> >>>>>> +      * We shouldn't be creating secure anonymous inodes before LSM
> >>>>>> +      * initialization completes.
> >>>>>> +      */
> >>>>>> +     if (unlikely(!selinux_state.initialized))
> >>>>>> +             return -EBUSY;
> >>>>>
> >>>>> I don't think this is viable; any arbitrary actions are possible before
> >>>>> policy is loaded, and a Linux distro can be brought up fully with
> >>>>> SELinux enabled and no policy loaded.  You'll just need to have a
> >>>>> default behavior prior to initialization.
> >>>>
> >>>> We'd have to fail open then, I think, and return an S_PRIVATE inode
> >>>> (the regular anon inode).
> >>>
> >>> Not sure why.  You aren't doing anything in the hook that actually
> >>> relies on selinux_state.initialized being set (i.e. nothing requires a
> >>> policy).  The avc_has_perm() call will just succeed until a policy is
> >>> loaded.  So if these inodes are created prior to policy load, they will
> >>> get assigned the task SID (which would be the kernel SID prior to policy
> >>> load or first exec or write to /proc/self/attr/current afterward) and
> >>> UFFD class (in your current code), be permitted, and then once policy is
> >>> loaded any further access will get checked against the kernel SID.
> >>>
> >>>>>> +     /*
> >>>>>> +      * 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);
> >>>>>
> >>>>> I think the kernel discourages overuse of BUG_ON/BUG/...
> >>>>
> >>>> I'm not sure what counts as overuse.
> >>>
> >>> Me either (not my rule) but I'm pretty sure this counts or you'd see a
> >>> lot more of these kinds of BUG_ON() checks throughout.  Try to reserve
> >>> them for really critical cases.
> >>>
> >>>>>> +
> >>>>>> +#ifdef CONFIG_USERFAULTFD
> >>>>>> +     if (fops == &userfaultfd_fops)
> >>>>>> +             isec->sclass = SECCLASS_UFFD;
> >>>>>> +#endif
> >>>>>
> >>>>> Not sure we want or need to introduce a new security class for each user
> >>>>> of anonymous inodes since the permissions should be the same as for
> >>>>> file.
> >>>>
> >>>> The purpose of this change is to apply special policy to userfaultfd
> >>>> FDs in particular. Isn't having a UFFD security class the best way to
> >>>> go about that? (There's no path.) Am I missing something?
> >>>
> >>> It is probably the simplest approach; it just doesn't generalize to all
> >>> users of anonymous inodes. We can distinguish them in one of two ways:
> >>> use a different class like you did (requires a code change every time we
> >>> add a new one and yet another duplicate of the file class) or use a
> >>> different SID/context/type. The latter could be achieved by calling
> >>> security_transition_sid() with the provided name wrapped in a qstr and
> >>> specifying type_transition rules on the name.  Then policy could define
> >>> derived types for each domain, ala
> >>> type_transition init self:file "[userfaultfd]" init_userfaultfd;
> >>> type_transition untrusted_app self:file "[userfaultfd]"
> >>> untrusted_app_userfaultfd;
> >>> ...
> >>>
> >>>>> Also not sure we want to be testing fops for each such case.
> >>>>
> >>>> I was also thinking of just providing some kind of context string
> >>>> (maybe the name), which might be friendlier to modules, but the loose
> >>>> coupling kind of scares me, and for this particular application, since
> >>>> UFFD is always in the core and never in a module, checking the fops
> >>>> seems a bit more robust and doesn't hurt anything.
> >>>
> >>> Yes, not sure how the vfs folks feel about either coupling (the
> >>> name-based one or the fops-based one).  Neither seems great.
> >>>
> >>>>> We
> >>>>> were looking at possibly leveraging the name as a key and using
> >>>>> security_transition_sid() to generate a distinct SID/context/type for
> >>>>> the inode via type_transition rules in policy.  We have some WIP along
> >>>>> those lines.
> >>>>
> >>>> Where? Any chance it would be ready soon? I'd rather not hold up this
> >>>> work for a more general mechanism.
> >>>
> >>> Hopefully will have a patch available soon.  But not saying this
> >>> necessarily has to wait either.
> >>>
> >>>>>> +     /*
> >>>>>> +      * Always give secure anonymous inodes the sid of the
> >>>>>> +      * creating task.
> >>>>>> +      */
> >>>>>> +
> >>>>>> +     isec->sid = tsec->sid;
> >>>>>
> >>>>> This doesn't generalize for other users of anonymous inodes, e.g. the
> >>>>> /dev/kvm case where we'd rather inherit the SID and class from the
> >>>>> original /dev/kvm inode itself.
> >>>>
> >>>> I think someone mentioned on the first version of this patch that we
> >>>> could make it more flexible if the need arose. If we do want to do it
> >>>> now, we could have the anon_inode security hook accept a "parent" or
> >>>> "context" inode that modules could inspect for the purposes of forming
> >>>> the new inode's SID. Does that make sense to you?
> >>>
> >>> Yes, that's the approach in our current WIP, except we call it a
> >>> "related" inode since it isn't necessarily connected to the anon inode
> >>> in any vfs sense.
> >>
> >> The other key difference in our WIP approach is that we assumed that we
> >> couldn't mandate allocating a separate anon inode for each of these fds
> >> and we wanted to cover all anonymous inodes (not opt-in), so we are
> >> storing the SID/class pair as additional fields in the
> >> file_security_struct and have modified file_has_perm() and others to
> >> look there for anonymous inodes.
> >
> > A separate inode seems like the simpler approach for now, because it
> > means that we have fewer places to check for security information ---
> > and it's not as if an inode is particularly expensive. We can always
> > switch later.
>
> We'd prefer having a separate inode if possible but didn't think that
> would fly with the vfs folks,

Let's ask them.

> especially if we try to apply this to all
> anonymous inodes.

For the moment, we're not.

> It might be ok for userfaultfd usage as a specific
> case but there is a reason why anonymous inodes were introduced and
> creating a separate inode each time defeats that purpose IIUC.  It will
> be interesting to see how they respond.

Sort of. Anonymous inodes also free other parts of the kernel from
having to deal with special-purpose filesystems (like pipefs) on which
to hang custom inodes. It's just a generic "just give me an inode and
I don't care about the filesystem" feature, and if we actually get a
new inode each time, we still do the job. Pipe seems to be good with
creating inodes each time.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 3/6] Teach SELinux about a new userfaultfd class
  2020-02-12 19:11             ` Stephen Smalley
  2020-02-12 19:13               ` Daniel Colascione
@ 2020-02-12 19:17               ` Stephen Smalley
  1 sibling, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-02-12 19:17 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: Tim Murray, Nosh Minwalla, Nick Kralevich, Lokesh Gidra,
	linux-kernel, Linux API, selinux

On 2/12/20 2:11 PM, Stephen Smalley wrote:
> On 2/12/20 2:04 PM, Daniel Colascione wrote:
>> On Wed, Feb 12, 2020 at 10:59 AM Stephen Smalley <sds@tycho.nsa.gov> 
>> wrote:
>>>
>>> On 2/12/20 1:04 PM, Stephen Smalley wrote:
>>>> On 2/12/20 12:19 PM, Daniel Colascione wrote:
>>>>> Thanks for taking a look.
>>>>>
>>>>> On Wed, Feb 12, 2020 at 9:04 AM Stephen Smalley <sds@tycho.nsa.gov>
>>>>> wrote:
>>>>>>
>>>>>> On 2/11/20 5:55 PM, Daniel Colascione wrote:
>>>>>>> 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 <dancol@google.com>
>>>>>>
>>>>>> (please add linux-fsdevel and viro to the cc for future versions 
>>>>>> of this
>>>>>> patch since it changes the VFS)
>>>>>>
>>>>>>> ---
>>>>>>> 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
>>>>>>> @@ -2915,6 +2919,69 @@ static int selinux_inode_init_security(struct
>>>>>>> inode *inode, struct inode *dir,
>>>>>>> +
>>>>>>> +     /*
>>>>>>> +      * We shouldn't be creating secure anonymous inodes before LSM
>>>>>>> +      * initialization completes.
>>>>>>> +      */
>>>>>>> +     if (unlikely(!selinux_state.initialized))
>>>>>>> +             return -EBUSY;
>>>>>>
>>>>>> I don't think this is viable; any arbitrary actions are possible 
>>>>>> before
>>>>>> policy is loaded, and a Linux distro can be brought up fully with
>>>>>> SELinux enabled and no policy loaded.  You'll just need to have a
>>>>>> default behavior prior to initialization.
>>>>>
>>>>> We'd have to fail open then, I think, and return an S_PRIVATE inode
>>>>> (the regular anon inode).
>>>>
>>>> Not sure why.  You aren't doing anything in the hook that actually
>>>> relies on selinux_state.initialized being set (i.e. nothing requires a
>>>> policy).  The avc_has_perm() call will just succeed until a policy is
>>>> loaded.  So if these inodes are created prior to policy load, they will
>>>> get assigned the task SID (which would be the kernel SID prior to 
>>>> policy
>>>> load or first exec or write to /proc/self/attr/current afterward) and
>>>> UFFD class (in your current code), be permitted, and then once 
>>>> policy is
>>>> loaded any further access will get checked against the kernel SID.
>>>>
>>>>>>> +     /*
>>>>>>> +      * 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);
>>>>>>
>>>>>> I think the kernel discourages overuse of BUG_ON/BUG/...
>>>>>
>>>>> I'm not sure what counts as overuse.
>>>>
>>>> Me either (not my rule) but I'm pretty sure this counts or you'd see a
>>>> lot more of these kinds of BUG_ON() checks throughout.  Try to reserve
>>>> them for really critical cases.
>>>>
>>>>>>> +
>>>>>>> +#ifdef CONFIG_USERFAULTFD
>>>>>>> +     if (fops == &userfaultfd_fops)
>>>>>>> +             isec->sclass = SECCLASS_UFFD;
>>>>>>> +#endif
>>>>>>
>>>>>> Not sure we want or need to introduce a new security class for 
>>>>>> each user
>>>>>> of anonymous inodes since the permissions should be the same as for
>>>>>> file.
>>>>>
>>>>> The purpose of this change is to apply special policy to userfaultfd
>>>>> FDs in particular. Isn't having a UFFD security class the best way to
>>>>> go about that? (There's no path.) Am I missing something?
>>>>
>>>> It is probably the simplest approach; it just doesn't generalize to all
>>>> users of anonymous inodes. We can distinguish them in one of two ways:
>>>> use a different class like you did (requires a code change every 
>>>> time we
>>>> add a new one and yet another duplicate of the file class) or use a
>>>> different SID/context/type. The latter could be achieved by calling
>>>> security_transition_sid() with the provided name wrapped in a qstr and
>>>> specifying type_transition rules on the name.  Then policy could define
>>>> derived types for each domain, ala
>>>> type_transition init self:file "[userfaultfd]" init_userfaultfd;
>>>> type_transition untrusted_app self:file "[userfaultfd]"
>>>> untrusted_app_userfaultfd;
>>>> ...
>>>>
>>>>>> Also not sure we want to be testing fops for each such case.
>>>>>
>>>>> I was also thinking of just providing some kind of context string
>>>>> (maybe the name), which might be friendlier to modules, but the loose
>>>>> coupling kind of scares me, and for this particular application, since
>>>>> UFFD is always in the core and never in a module, checking the fops
>>>>> seems a bit more robust and doesn't hurt anything.
>>>>
>>>> Yes, not sure how the vfs folks feel about either coupling (the
>>>> name-based one or the fops-based one).  Neither seems great.
>>>>
>>>>>> We
>>>>>> were looking at possibly leveraging the name as a key and using
>>>>>> security_transition_sid() to generate a distinct SID/context/type for
>>>>>> the inode via type_transition rules in policy.  We have some WIP 
>>>>>> along
>>>>>> those lines.
>>>>>
>>>>> Where? Any chance it would be ready soon? I'd rather not hold up this
>>>>> work for a more general mechanism.
>>>>
>>>> Hopefully will have a patch available soon.  But not saying this
>>>> necessarily has to wait either.
>>>>
>>>>>>> +     /*
>>>>>>> +      * Always give secure anonymous inodes the sid of the
>>>>>>> +      * creating task.
>>>>>>> +      */
>>>>>>> +
>>>>>>> +     isec->sid = tsec->sid;
>>>>>>
>>>>>> This doesn't generalize for other users of anonymous inodes, e.g. the
>>>>>> /dev/kvm case where we'd rather inherit the SID and class from the
>>>>>> original /dev/kvm inode itself.
>>>>>
>>>>> I think someone mentioned on the first version of this patch that we
>>>>> could make it more flexible if the need arose. If we do want to do it
>>>>> now, we could have the anon_inode security hook accept a "parent" or
>>>>> "context" inode that modules could inspect for the purposes of forming
>>>>> the new inode's SID. Does that make sense to you?
>>>>
>>>> Yes, that's the approach in our current WIP, except we call it a
>>>> "related" inode since it isn't necessarily connected to the anon inode
>>>> in any vfs sense.
>>>
>>> The other key difference in our WIP approach is that we assumed that we
>>> couldn't mandate allocating a separate anon inode for each of these fds
>>> and we wanted to cover all anonymous inodes (not opt-in), so we are
>>> storing the SID/class pair as additional fields in the
>>> file_security_struct and have modified file_has_perm() and others to
>>> look there for anonymous inodes.
>>
>> A separate inode seems like the simpler approach for now, because it
>> means that we have fewer places to check for security information ---
>> and it's not as if an inode is particularly expensive. We can always
>> switch later.
> 
> We'd prefer having a separate inode if possible but didn't think that 
> would fly with the vfs folks, especially if we try to apply this to all 
> anonymous inodes. It might be ok for userfaultfd usage as a specific 
> case but there is a reason why anonymous inodes were introduced and 
> creating a separate inode each time defeats that purpose IIUC.  It will 
> be interesting to see how they respond.

I suppose an optimization of your approach could be to only allocate a 
new anon inode if there isn't already one that has the same security 
info (SID/class pair in the SELinux case).

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-12 17:14     ` Peter Xu
@ 2020-02-12 19:41       ` Andrea Arcangeli
  2020-02-12 20:04         ` Daniel Colascione
  0 siblings, 1 reply; 75+ messages in thread
From: Andrea Arcangeli @ 2020-02-12 19:41 UTC (permalink / raw)
  To: Peter Xu
  Cc: Jann Horn, Kees Cook, Daniel Colascione, Tim Murray,
	Nosh Minwalla, Nick Kralevich, Lokesh Gidra, kernel list,
	Linux API, SElinux list, Mike Rapoport, linux-security-module

Hello everyone,

On Wed, Feb 12, 2020 at 12:14:16PM -0500, Peter Xu wrote:
> Right. AFAICT QEMU uses it far more than disk IOs.  A guest page can
> be accessed by any kernel component on the destination host during a
> postcopy procedure.  It can be as simple as when a vcpu writes to a
> missing guest page which still resides on the source host, then KVM
> will get a page fault and trap into userfaultfd asking for that page.
> The same thing happens to other modules like vhost, etc., as long as a
> missing guest page is touched by a kernel module.

Correct.

How does the android garbage collection work to make sure there cannot
be kernel faults on the missing memory?

If I understood correctly (I didn't have much time to review sorry)
what's proposed with regard to limiting uffd events from kernel
faults, the only use case I know that could deal with it is the
UFFD_FEATURE_SIGBUS but that's not normal userfaultfd: that's also the
only feature required from uffd to implement a pure malloc library in
userland that never takes the mmap sem for writing to implement
userland mremap/mmap/munmap lib calls (as those will convert to
UFFDIO_ZEROPAGE and MADV_DONTNEED internally to the lib and there will
be always a single vma). We just need to extend UFFDIO_ZEROPAGE to map
the THP zeropage to make this future pure-uffd malloc lib perform
better.

On the other end I'm also planning a mremap_vma_merge userland syscall
that will merge fragmented vmas.

Currently once you have a nice heap all contiguous but with small
objects and you free the fragments you can't build THP anymore even if
you make the memory virtually contiguous again by calling mremap. That
just build up a ton of vmas slowing down the app forever and also
preventing THP collapsing ever again.

mremap_vma_merge will require no new kernel feature, but it
fundamentally must be able to handle kernel faults. If databases
starts to use that, how can you enable this feature without breaking
random apps then?

So it'd be a feature usable only by one user (Android) perhaps? And
only until you start defragging the vmas of small objects?

Thanks,
Andrea


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-12 19:41       ` Andrea Arcangeli
@ 2020-02-12 20:04         ` Daniel Colascione
  2020-02-12 23:41           ` Andrea Arcangeli
  0 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-02-12 20:04 UTC (permalink / raw)
  To: Andrea Arcangeli
  Cc: Peter Xu, Jann Horn, Kees Cook, Tim Murray, Nosh Minwalla,
	Nick Kralevich, Lokesh Gidra, kernel list, Linux API,
	SElinux list, Mike Rapoport, linux-security-module

On Wed, Feb 12, 2020 at 11:41 AM Andrea Arcangeli <aarcange@redhat.com> wrote:
>
> Hello everyone,
>
> On Wed, Feb 12, 2020 at 12:14:16PM -0500, Peter Xu wrote:
> > Right. AFAICT QEMU uses it far more than disk IOs.  A guest page can
> > be accessed by any kernel component on the destination host during a
> > postcopy procedure.  It can be as simple as when a vcpu writes to a
> > missing guest page which still resides on the source host, then KVM
> > will get a page fault and trap into userfaultfd asking for that page.
> > The same thing happens to other modules like vhost, etc., as long as a
> > missing guest page is touched by a kernel module.
>
> Correct.
>
> How does the android garbage collection work to make sure there cannot
> be kernel faults on the missing memory?

We don't pass pointers to the heap into system calls. (Big primitive
arrays, ByteBuffer, etc. are allocated off the regular heap.)

> If I understood correctly (I didn't have much time to review sorry)
> what's proposed with regard to limiting uffd events from kernel
> faults,

I don't understand what you mean. The purpose of preventing UFFD from
handling kernel faults is exploit mitigation.

> the only use case I know that could deal with it is the
> UFFD_FEATURE_SIGBUS but that's not normal userfaultfd: that's also the
> only feature required from uffd to implement a pure malloc library in
> userland that never takes the mmap sem for writing to implement
> userland mremap/mmap/munmap lib calls (as those will convert to
> UFFDIO_ZEROPAGE and MADV_DONTNEED internally to the lib and there will
> be always a single vma). We just need to extend UFFDIO_ZEROPAGE to map
> the THP zeropage to make this future pure-uffd malloc lib perform
> better.

The key requirement here is the ability to prevent unprivileged
processes from using UFFD to widen kernel exploit windows by
preventing UFFD from taking kernel faults. Forcing unprivileged
processes to use UFFD only with UFFD_FEATURE_SIGBUS would satisfy this
requirement, but it's much less flexible and unnecessarily couples two
features.

> On the other end I'm also planning a mremap_vma_merge userland syscall
> that will merge fragmented vmas.

This is probably a separate discussion, but does that operation really
need to be a system call? Historically, userspace has operated mostly
on page ranges and not VMAs per se, and the kernel has been free to
merge and split VMAs as needed for its internal purposes. This
approach has serious negative side effects (like making munmap
fallible: see [1]), but it is what it is.

[1] https://lore.kernel.org/linux-mm/CAKOZuetOD6MkGPVvYFLj5RXh200FaDyu3sQqZviVRhTFFS3fjA@mail.gmail.com/

> Currently once you have a nice heap all contiguous but with small
> objects and you free the fragments you can't build THP anymore even if
> you make the memory virtually contiguous again by calling mremap. That
> just build up a ton of vmas slowing down the app forever and also
> preventing THP collapsing ever again.

Shouldn't the THP background kthread take care of merging VMAs?

> mremap_vma_merge will require no new kernel feature, but it
> fundamentally must be able to handle kernel faults. If databases
> starts to use that, how can you enable this feature without breaking
> random apps then?

Presumably, those apps wouldn't issue the system call on address
ranges managed with a non-kernel-fault UFFD.

> So it'd be a feature usable only by one user (Android) perhaps? And
> only until you start defragging the vmas of small objects?

We shouldn't be fragmenting at all, either at the memory level or the
VMA level. The GC is a moving collector, and we don't punch holes in
the heap.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-12 20:04         ` Daniel Colascione
@ 2020-02-12 23:41           ` Andrea Arcangeli
  0 siblings, 0 replies; 75+ messages in thread
From: Andrea Arcangeli @ 2020-02-12 23:41 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: Peter Xu, Jann Horn, Kees Cook, Tim Murray, Nosh Minwalla,
	Nick Kralevich, Lokesh Gidra, kernel list, Linux API,
	SElinux list, Mike Rapoport, linux-security-module

Hi Daniel,

On Wed, Feb 12, 2020 at 12:04:39PM -0800, Daniel Colascione wrote:
> We don't pass pointers to the heap into system calls. (Big primitive
> arrays, ByteBuffer, etc. are allocated off the regular heap.)

That sounds pretty restrictive, I wonder what you gain by enforcing
that invariant or if it just happened incidentally for some other
reason?  Do you need to copy that memory every time if you need to do
I/O on it? Are you sure this won't need to change any time soon to
increase performance?

> I don't understand what you mean. The purpose of preventing UFFD from
> handling kernel faults is exploit mitigation.

That part was clear. What wasn't clear is what the new feature
does exactly and what it blocks, because it's all about blocking or
how does it make things more secure?

> The key requirement here is the ability to prevent unprivileged
> processes from using UFFD to widen kernel exploit windows by
> preventing UFFD from taking kernel faults. Forcing unprivileged
> processes to use UFFD only with UFFD_FEATURE_SIGBUS would satisfy this
> requirement, but it's much less flexible and unnecessarily couples two
> features.

I mentioned it in case you could use something like that model.

> > On the other end I'm also planning a mremap_vma_merge userland syscall
> > that will merge fragmented vmas.
> 
> This is probably a separate discussion, but does that operation really
> need to be a system call? Historically, userspace has operated mostly

mremap_vma_merge was not intended as a system call, if implemented as
a system call it wouldn't use uffd.

> on page ranges and not VMAs per se, and the kernel has been free to

Userland doesn't need to know anything.. unless it wants to optimize.

The userland can know full well if it does certain mremap operations
and puts its ranges virtually contiguous in a non linear way, so that
the kernel cannot merge the vmas.

> merge and split VMAs as needed for its internal purposes. This
> approach has serious negative side effects (like making munmap
> fallible: see [1]), but it is what it is.
> 
> [1] https://lore.kernel.org/linux-mm/CAKOZuetOD6MkGPVvYFLj5RXh200FaDyu3sQqZviVRhTFFS3fjA@mail.gmail.com/

The fact it's fallible is a secondary concern here. Even if you make
it unlimited, if it grows it slowdown everything and also prevents THP
to be collapsed. Even the scalability of the mmap_sem worsens.

> > Currently once you have a nice heap all contiguous but with small
> > objects and you free the fragments you can't build THP anymore even if
> > you make the memory virtually contiguous again by calling mremap. That
> > just build up a ton of vmas slowing down the app forever and also
> > preventing THP collapsing ever again.
> 
> Shouldn't the THP background kthread take care of merging VMAs?

The solution can't depend on any THP feature, because the buildup of
vmas is a scalability issue and a performance regression over time
even if THP is not configured in the kernel. However once that's
solved THP also gets naturally optimized.

What should happen (in my view) is just the simplest solution that can
defrag and forcefully merge the vmas without having to stop or restart
the app.

> Presumably, those apps wouldn't issue the system call on address
> ranges managed with a non-kernel-fault UFFD.

So the new security feature won't have to block kernel faults on those
apps and they can run side by side with the blocked app?

> We shouldn't be fragmenting at all, either at the memory level or the
> VMA level. The GC is a moving collector, and we don't punch holes in
> the heap.

That sounds good.

Thanks,
Andrea


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH 0/3] SELinux support for anonymous inodes and UFFD
  2020-02-11 22:55 [PATCH v2 0/6] Harden userfaultfd Daniel Colascione
                   ` (7 preceding siblings ...)
  2020-02-12  7:50 ` Kees Cook
@ 2020-02-14  3:26 ` Daniel Colascione
  2020-02-14  3:26   ` [PATCH 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
                     ` (7 more replies)
  8 siblings, 8 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-14  3:26 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra
  Cc: Daniel Colascione

Userfaultfd in unprivileged contexts could be potentially very
useful. We'd like to harden userfaultfd to make such unprivileged use
less risky. This patch series allows SELinux to manage userfaultfd
file descriptors and in the future, other kinds of
anonymous-inode-based file descriptor.  SELinux policy authors can
apply policy types to anonymous inodes by providing name-based
transition rules keyed off the anonymous inode internal name (
"[userfaultfd]" in the case of userfaultfd(2) file descriptors) and
applying policy to the new SIDs thus produced.

Inside the kernel, a pair of new anon_inodes interface,
anon_inode_getfile_secure and anon_inode_getfd_secure, allow callers
to opt into this SELinux management. In this new "secure" mode,
anon_inodes creates new ephemeral inodes for anonymous file objects
instead of reusing the normal anon_inodes singleton dummy inode. A new
LSM hook gives security modules an opportunity to configure and veto
these ephemeral inodes.

This patch series is one of two fork of [1] and is an
alternative to [2].

The primary difference between the two patch series is that this
partch series creates a unique inode for each "secure" anonymous
inode, while the other patch series ([2]) continues using the
singleton dummy anonymous inode and adds a way to attach SELinux
security information directly to file objects.

I prefer the approach in this patch series because 1) it's a smaller
patch than [2], and 2) it produces a more regular security
architecture: in this patch series, secure anonymous inodes aren't
S_PRIVATE and they maintain the SELinux property that the label for a
file is in its inode. We do need an additional inode per anonymous
file, but per-struct-file inode creation doesn't seem to be a problem
for pipes and sockets.

The previous version of this feature ([1]) created a new SELinux
security class for userfaultfd file descriptors. This version adopts
the generic transition-based approach of [2].

This patch series also differs from [2] in that it doesn't affect all
anonymous inodes right away --- instead requiring anon_inodes callers
to opt in --- but this difference isn't one of basic approach. The
important question to resolve is whether we should be creating new
inodes or enhancing per-file data.

[1] https://lore.kernel.org/lkml/20200211225547.235083-1-dancol@google.com/
[2] https://lore.kernel.org/linux-fsdevel/20200213194157.5877-1-sds@tycho.nsa.gov/

Daniel Colascione (3):
  Add a new LSM-supporting anonymous inode interface
  Teach SELinux about anonymous inodes
  Wire UFFD up to SELinux

 fs/anon_inodes.c            | 196 ++++++++++++++++++++++++++++--------
 fs/userfaultfd.c            |  34 +++++--
 include/linux/anon_inodes.h |  13 +++
 include/linux/lsm_hooks.h   |   9 ++
 include/linux/security.h    |   4 +
 security/security.c         |  10 ++
 security/selinux/hooks.c    |  57 +++++++++++
 7 files changed, 274 insertions(+), 49 deletions(-)

-- 
2.25.0.265.gbab2e86ba0-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH 1/3] Add a new LSM-supporting anonymous inode interface
  2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
@ 2020-02-14  3:26   ` Daniel Colascione
  2020-02-14  3:26   ` [PATCH 2/3] Teach SELinux about anonymous inodes Daniel Colascione
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-14  3:26 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra
  Cc: Daniel Colascione

This change adds two new functions, anon_inode_getfile_secure and
anon_inode_getfd_secure, that create anonymous-node files with
individual non-S_PRIVATE inodes to which security modules can apply
policy. Existing callers continue using the original singleton-inode
kind of anonymous-inode file. We can transition anonymous inode users
to the new kind of anonymous inode in individual patches for the sake
of bisection and review.

The new functions accept an optional context_inode parameter that
callers can use to provide additional contextual information to
security modules, e.g., indicating that one anonymous struct file is a
logical child of another, allowing a security model to propagate
security information from one to the other.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 fs/anon_inodes.c            | 196 ++++++++++++++++++++++++++++--------
 fs/userfaultfd.c            |   4 +-
 include/linux/anon_inodes.h |  13 +++
 include/linux/lsm_hooks.h   |   9 ++
 include/linux/security.h    |   4 +
 security/security.c         |  10 ++
 6 files changed, 191 insertions(+), 45 deletions(-)

diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 89714308c25b..114a04fc1db4 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -55,75 +55,135 @@ static struct file_system_type anon_inode_fs_type = {
 	.kill_sb	= kill_anon_super,
 };
 
-/**
- * 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
- *
- * @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
- *
- * Creates a new file by hooking it on a single 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.
- */
-struct file *anon_inode_getfile(const char *name,
-				const struct file_operations *fops,
-				void *priv, int flags)
+static struct inode *anon_inode_make_secure_inode(
+	const char *name,
+	const struct inode *context_inode,
+	const struct file_operations *fops)
+{
+	struct inode *inode;
+	const struct qstr qname = QSTR_INIT(name, strlen(name));
+	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, &qname, fops, context_inode);
+	if (error) {
+		iput(inode);
+		return ERR_PTR(error);
+	}
+	return inode;
+}
+
+struct file *_anon_inode_getfile(const char *name,
+				 const struct file_operations *fops,
+				 void *priv, int flags,
+				 const struct inode *context_inode,
+				 bool secure)
 {
+	struct inode *inode;
 	struct file *file;
 
-	if (IS_ERR(anon_inode_inode))
-		return ERR_PTR(-ENODEV);
+	if (secure) {
+		inode =	anon_inode_make_secure_inode(
+			name, context_inode, 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))
-		return ERR_PTR(-ENOENT);
+	if (fops->owner && !try_module_get(fops->owner)) {
+		file = ERR_PTR(-ENOENT);
+		goto err;
+	}
 
-	/*
-	 * 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,
+	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);
 
 /**
- * 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_getfile_secure - creates a new file instance by hooking
+ *                             it up to a new anonymous inode and a
+ *                             dentry that describe the "class" of the
+ *                             file.  Make it possible to use security
+ *                             modules to control access to the
+ *                             new 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 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_secure() will have distinct inodes, avoiding
+ * code duplication for the file/inode/dentry setup.  Returns the
+ * newly created file* or an error pointer.
+ */
+struct file *anon_inode_getfile_secure(const char *name,
+				       const struct file_operations *fops,
+				       void *priv, int flags,
+				       const struct inode *context_inode)
+{
+	return _anon_inode_getfile(
+		name, fops, priv, flags, context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile_secure);
+
+/**
+ * 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.
+ *
+ * @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 for the file
  *
- * 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_getfd() will share a single inode,
+ * 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 new descriptor or an error code.
+ * setup.  Returns the newly created file* or an error pointer.
  */
-int anon_inode_getfd(const char *name, const struct file_operations *fops,
-		     void *priv, int flags)
+struct file *anon_inode_getfile(const char *name,
+				const struct file_operations *fops,
+				void *priv, int flags)
+{
+	return _anon_inode_getfile(name, fops, priv, flags, NULL, false);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile);
+
+static int _anon_inode_getfd(const char *name,
+			     const struct file_operations *fops,
+			     void *priv, int flags,
+			     const struct inode *context_inode,
+			     bool secure)
 {
 	int error, fd;
 	struct file *file;
@@ -133,7 +193,8 @@ 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_getfile(name, fops, priv, flags, context_inode,
+				   secure);
 	if (IS_ERR(file)) {
 		error = PTR_ERR(file);
 		goto err_put_unused_fd;
@@ -146,6 +207,57 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
 	put_unused_fd(fd);
 	return error;
 }
+
+/**
+ * anon_inode_getfd_secure - creates a new file instance by hooking it
+ *                           up to a new anonymous inode and a dentry
+ *                           that describe the "class" of the file.
+ *                           Make it possible to use security modules
+ *                           to control access to the new 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
+ *
+ * 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_secure() will have distinct inodes, avoiding
+ * code duplication for the file/inode/dentry setup.  Returns a newly
+ * created file descriptor or an error code.
+ */
+int anon_inode_getfd_secure(const char *name, const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode)
+{
+	return _anon_inode_getfd(name, fops, priv, flags,
+				 context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfd_secure);
+
+/**
+ * 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
+ *
+ * @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
+ *
+ * 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 use the same singleton inode, reducing
+ * memory use and avoiding code duplication for the file/inode/dentry
+ * setup.  Returns a newly created file descriptor or an error code.
+ */
+int anon_inode_getfd(const char *name, const struct file_operations *fops,
+		     void *priv, int flags)
+{
+	return _anon_inode_getfd(name, fops, priv, flags, NULL, false);
+}
 EXPORT_SYMBOL_GPL(anon_inode_getfd);
 
 static int __init anon_inode_init(void)
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/anon_inodes.h b/include/linux/anon_inodes.h
index d0d7d96261ad..67bd85d92dca 100644
--- a/include/linux/anon_inodes.h
+++ b/include/linux/anon_inodes.h
@@ -10,12 +10,25 @@
 #define _LINUX_ANON_INODES_H
 
 struct file_operations;
+struct inode;
+
+struct file *anon_inode_getfile_secure(const char *name,
+				       const struct file_operations *fops,
+				       void *priv, int flags,
+				       const struct inode *context_inode);
 
 struct file *anon_inode_getfile(const char *name,
 				const struct file_operations *fops,
 				void *priv, int flags);
+
+int anon_inode_getfd_secure(const char *name,
+			    const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode);
+
 int anon_inode_getfd(const char *name, const struct file_operations *fops,
 		     void *priv, int flags);
 
+
 #endif /* _LINUX_ANON_INODES_H */
 
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 20d8cf194fb7..de5d37e388df 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,10 @@ 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 struct qstr *name,
+					const struct file_operations *fops,
+					const struct inode *context_inode);
 	int (*inode_create)(struct inode *dir, struct dentry *dentry,
 				umode_t mode);
 	int (*inode_link)(struct dentry *old_dentry, struct inode *dir,
@@ -1884,6 +1892,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..8ea76af0be7a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -320,6 +320,10 @@ 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 struct qstr *name,
+				      const struct file_operations *fops,
+				      const struct inode *context_inode);
 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..d06f3969c030 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1033,6 +1033,16 @@ 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 struct qstr *name,
+				  const struct file_operations *fops,
+				  const struct inode *context_inode)
+{
+	return call_int_hook(inode_init_security_anon, 0, inode, name,
+			     fops, context_inode);
+}
+
 int security_old_inode_init_security(struct inode *inode, struct inode *dir,
 				     const struct qstr *qstr, const char **name,
 				     void **value, size_t *len)
-- 
2.25.0.265.gbab2e86ba0-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH 2/3] Teach SELinux about anonymous inodes
  2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  2020-02-14  3:26   ` [PATCH 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
@ 2020-02-14  3:26   ` Daniel Colascione
  2020-02-14 16:39     ` Stephen Smalley
  2020-02-14  3:26   ` [PATCH 3/3] Wire UFFD up to SELinux Daniel Colascione
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-02-14  3:26 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra
  Cc: Daniel Colascione

This change uses the anon_inodes and LSM infrastructure introduced in
the previous patch to give SELinux the ability to control
anonymous-inode files that are created using the new _secure()
anon_inodes functions.

A SELinux policy author detects and controls these anonymous inodes by
adding a name-based type_transition rule that assigns a new security
type to anonymous-inode files created in some domain. The name used
for the name-based transition is the name associated with the
anonymous inode for file listings --- e.g., "[userfaultfd]" or
"[perf_event]".

Example:

type uffd_t;
type_transition sysadm_t sysadm_t : file uffd_t "[userfaultfd]";
allow sysadm_t uffd_t:file { create };

(The next patch in this series is necessary for making userfaultfd
support this new interface.  The example above is just
for exposition.)

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 security/selinux/hooks.c | 57 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1659b59fb5d7..6de0892620b3 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2915,6 +2915,62 @@ 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 struct qstr *name,
+					    const struct file_operations *fops,
+					    const struct inode *context_inode)
+{
+	const struct task_security_struct *tsec = selinux_cred(current_cred());
+	struct common_audit_data ad;
+	struct inode_security_struct *isec;
+	int rc;
+
+	if (unlikely(IS_PRIVATE(inode)))
+		return 0;
+
+	if (unlikely(!selinux_state.initialized))
+		return 0;
+
+	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.
+	 */
+
+	if (context_inode) {
+		struct inode_security_struct *context_isec =
+			selinux_inode(context_inode);
+		if (IS_ERR(context_isec))
+			return PTR_ERR(context_isec);
+		isec->sid = context_isec->sid;
+	} else {
+		rc = security_transition_sid(
+			&selinux_state, tsec->sid, tsec->sid,
+			SECCLASS_FILE, name, &isec->sid);
+		if (rc)
+			return rc;
+	}
+
+	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 +6979,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),
-- 
2.25.0.265.gbab2e86ba0-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH 3/3] Wire UFFD up to SELinux
  2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  2020-02-14  3:26   ` [PATCH 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
  2020-02-14  3:26   ` [PATCH 2/3] Teach SELinux about anonymous inodes Daniel Colascione
@ 2020-02-14  3:26   ` Daniel Colascione
  2020-03-25 23:02   ` [PATCH v2 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-02-14  3:26 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra
  Cc: Daniel Colascione

This change gives userfaultfd file descriptors a real security
context, allowing policy to act on them.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 fs/userfaultfd.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 07b0f6e03849..06e92697aba4 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -76,6 +76,8 @@ struct userfaultfd_ctx {
 	bool mmap_changing;
 	/* mm with one ore more vmas attached to this userfaultfd_ctx */
 	struct mm_struct *mm;
+	/* The inode that owns this context --- not a strong reference.  */
+	const struct inode *owner;
 };
 
 struct userfaultfd_fork_ctx {
@@ -1020,8 +1022,10 @@ static int resolve_userfault_fork(struct userfaultfd_ctx *ctx,
 {
 	int fd;
 
-	fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, new,
-			      O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS));
+	fd = anon_inode_getfd_secure(
+		"[userfaultfd]", &userfaultfd_fops, new,
+		O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS),
+		ctx->owner);
 	if (fd < 0)
 		return fd;
 
@@ -1943,6 +1947,7 @@ static void init_once_userfaultfd_ctx(void *mem)
 
 SYSCALL_DEFINE1(userfaultfd, int, flags)
 {
+	struct file *file;
 	struct userfaultfd_ctx *ctx;
 	int fd;
 
@@ -1972,8 +1977,25 @@ 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));
+	file = anon_inode_getfile_secure(
+		"[userfaultfd]", &userfaultfd_fops, ctx,
+		O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS),
+		NULL);
+	if (IS_ERR(file)) {
+		fd = PTR_ERR(file);
+		goto out;
+	}
+
+	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
+	if (fd < 0) {
+		fput(file);
+		goto out;
+	}
+
+	ctx->owner = file_inode(file);
+	fd_install(fd, file);
+
+out:
 	if (fd < 0) {
 		mmdrop(ctx->mm);
 		kmem_cache_free(userfaultfd_ctx_cachep, ctx);
-- 
2.25.0.265.gbab2e86ba0-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 2/3] Teach SELinux about anonymous inodes
  2020-02-14  3:26   ` [PATCH 2/3] Teach SELinux about anonymous inodes Daniel Colascione
@ 2020-02-14 16:39     ` Stephen Smalley
  2020-02-14 17:21       ` Daniel Colascione
  0 siblings, 1 reply; 75+ messages in thread
From: Stephen Smalley @ 2020-02-14 16:39 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, selinux, linux-security-module,
	linux-fsdevel, linux-kernel, kvm, viro, paul, nnk, lokeshgidra

On 2/13/20 10:26 PM, Daniel Colascione wrote:
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 1659b59fb5d7..6de0892620b3 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2915,6 +2915,62 @@ 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 struct qstr *name,
> +					    const struct file_operations *fops,
> +					    const struct inode *context_inode)
> +{
> +	const struct task_security_struct *tsec = selinux_cred(current_cred());
> +	struct common_audit_data ad;
> +	struct inode_security_struct *isec;
> +	int rc;
> +
> +	if (unlikely(IS_PRIVATE(inode)))
> +		return 0;

This is not possible since the caller clears S_PRIVATE before calling 
and it would be a bug to call the hook on an inode that was intended to 
be private, so we shouldn't check it here.

> +
> +	if (unlikely(!selinux_state.initialized))
> +		return 0;

Are we doing this to defer initialization until selinux_complete_init() 
- that's normally why we bail in the !initialized case?  Not entirely 
sure what will happen in such a situation since we won't have the 
context_inode or the allocating task information at that time, so we 
certainly won't get the same result - probably they would all be labeled 
with whatever anon_inodefs is assigned via genfscon or 
SECINITSID_UNLABELED by default.  If we instead just drop this test and 
proceed, we'll inherit the context inode SID if specified or we'll call 
security_transition_sid(), which in the !initialized case will just 
return the tsid i.e. tsec->sid, so it will be labeled with the creating 
task SID (SECINITSID_KERNEL prior to initialization).  Then the 
avc_has_perm() call will pass because everything gets allowed until 
initialization. So you could drop this check and userfaultfds created 
before policy load would get the kernel SID, or you can keep it and they 
will get the unlabeled SID.  Preference?

> +
> +	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.
> +	 */
> +
> +	if (context_inode) {
> +		struct inode_security_struct *context_isec =
> +			selinux_inode(context_inode);
> +		if (IS_ERR(context_isec))
> +			return PTR_ERR(context_isec);

This isn't possible AFAICT so you don't need to test for it or handle 
it.  In fact, even the test for NULL in selinux_inode() is bogus and 
should get dropped AFAICT; we always allocate an inode security blob 
even before policy load so it would be a bug if we ever had a NULL there.

> +		isec->sid = context_isec->sid;
> +	} else {
> +		rc = security_transition_sid(
> +			&selinux_state, tsec->sid, tsec->sid,
> +			SECCLASS_FILE, name, &isec->sid);
> +		if (rc)
> +			return rc;
> +	}

Since you switched to using security_transition_sid(), you are not using 
the fops parameter anymore nor comparing with userfaultfd_fops, so you 
could drop the parameter from the hook and leave the latter static in 
the first patch.
That's assuming you are ok with having to define these type_transition 
rules for the userfaultfd case instead of having your own separate 
security class.  Wondering how many different anon inode names/classes 
there are in the kernel today and how much they change over time; for a 
small, relatively stable set, separate classes might be ok; for a large, 
dynamic set, type transitions should scale better.  We might still need 
to create a mapping table in SELinux from the names to some stable 
identifier for the policy lookup if we can't rely on the names being stable.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 2/3] Teach SELinux about anonymous inodes
  2020-02-14 16:39     ` Stephen Smalley
@ 2020-02-14 17:21       ` Daniel Colascione
  2020-02-14 18:02         ` Stephen Smalley
  0 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-02-14 17:21 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Tim Murray, SElinux list, LSM List, Linux FS Devel, linux-kernel,
	kvm, Al Viro, paul, Nick Kralevich, Lokesh Gidra

On Fri, Feb 14, 2020 at 8:38 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>
> On 2/13/20 10:26 PM, Daniel Colascione wrote:
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 1659b59fb5d7..6de0892620b3 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -2915,6 +2915,62 @@ 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 struct qstr *name,
> > +                                         const struct file_operations *fops,
> > +                                         const struct inode *context_inode)
> > +{
> > +     const struct task_security_struct *tsec = selinux_cred(current_cred());
> > +     struct common_audit_data ad;
> > +     struct inode_security_struct *isec;
> > +     int rc;
> > +
> > +     if (unlikely(IS_PRIVATE(inode)))
> > +             return 0;
>
> This is not possible since the caller clears S_PRIVATE before calling
> and it would be a bug to call the hook on an inode that was intended to
> be private, so we shouldn't check it here.
>
> > +
> > +     if (unlikely(!selinux_state.initialized))
> > +             return 0;
>
> Are we doing this to defer initialization until selinux_complete_init()
> - that's normally why we bail in the !initialized case?  Not entirely
> sure what will happen in such a situation since we won't have the
> context_inode or the allocating task information at that time, so we
> certainly won't get the same result - probably they would all be labeled
> with whatever anon_inodefs is assigned via genfscon or
> SECINITSID_UNLABELED by default.
> If we instead just drop this test and
> proceed, we'll inherit the context inode SID if specified or we'll call
> security_transition_sid(), which in the !initialized case will just
> return the tsid i.e. tsec->sid, so it will be labeled with the creating
> task SID (SECINITSID_KERNEL prior to initialization).  Then the
> avc_has_perm() call will pass because everything gets allowed until
> initialization. So you could drop this check and userfaultfds created
> before policy load would get the kernel SID, or you can keep it and they
> will get the unlabeled SID.  Preference?

The kernel SID seems safer. Thanks for the explanation!

> > +
> > +     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.
> > +      */
> > +
> > +     if (context_inode) {
> > +             struct inode_security_struct *context_isec =
> > +                     selinux_inode(context_inode);
> > +             if (IS_ERR(context_isec))
> > +                     return PTR_ERR(context_isec);
>
> This isn't possible AFAICT so you don't need to test for it or handle
> it.  In fact, even the test for NULL in selinux_inode() is bogus and
> should get dropped AFAICT; we always allocate an inode security blob
> even before policy load so it would be a bug if we ever had a NULL there.

Thanks. Will fix.

> > +             isec->sid = context_isec->sid;
> > +     } else {
> > +             rc = security_transition_sid(
> > +                     &selinux_state, tsec->sid, tsec->sid,
> > +                     SECCLASS_FILE, name, &isec->sid);
> > +             if (rc)
> > +                     return rc;
> > +     }
>
> Since you switched to using security_transition_sid(), you are not using
> the fops parameter anymore nor comparing with userfaultfd_fops, so you
> could drop the parameter from the hook and leave the latter static in
> the first patch.

That's true, but I figured different LSMs might want different rules
that depend on the fops. I'm also okay with removing this parameter
for now, since we're not using it.

> That's assuming you are ok with having to define these type_transition
> rules for the userfaultfd case instead of having your own separate
> security class.  Wondering how many different anon inode names/classes
> there are in the kernel today and how much they change over time; for a
> small, relatively stable set, separate classes might be ok; for a large,
> dynamic set, type transitions should scale better.

I think we can get away without a class per anonymous-inode-type. I do
wonder whether we need a class for all anonymous inodes, though: if we
just give them the file class and use the anon inode type name for the
type_transition rule, isn't it possible that the type_transition rule
might also fire for plain files with the same names in the last path
component and the same originating sid? (Maybe I'm not understanding
type_transition rules properly.) Using a class to encompass all
anonymous inodes would address this problem (assuming the problem
exists in the first place).

> We might still need
> to create a mapping table in SELinux from the names to some stable
> identifier for the policy lookup if we can't rely on the names being stable.

Sure. The anonymous inode type names have historically been stable,
though, so maybe we can just use the names from anon_inodes directly
for now and then add some kind of remapping if we want to change those
names in the core, remaping to the old name for SELinux
type_transition purposes.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 2/3] Teach SELinux about anonymous inodes
  2020-02-14 17:21       ` Daniel Colascione
@ 2020-02-14 18:02         ` Stephen Smalley
  2020-02-14 18:08           ` Stephen Smalley
  0 siblings, 1 reply; 75+ messages in thread
From: Stephen Smalley @ 2020-02-14 18:02 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: Tim Murray, SElinux list, LSM List, Linux FS Devel, linux-kernel,
	kvm, Al Viro, paul, Nick Kralevich, Lokesh Gidra

On 2/14/20 12:21 PM, Daniel Colascione wrote:
> On Fri, Feb 14, 2020 at 8:38 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>> That's assuming you are ok with having to define these type_transition
>> rules for the userfaultfd case instead of having your own separate
>> security class.  Wondering how many different anon inode names/classes
>> there are in the kernel today and how much they change over time; for a
>> small, relatively stable set, separate classes might be ok; for a large,
>> dynamic set, type transitions should scale better.
> 
> I think we can get away without a class per anonymous-inode-type. I do
> wonder whether we need a class for all anonymous inodes, though: if we
> just give them the file class and use the anon inode type name for the
> type_transition rule, isn't it possible that the type_transition rule
> might also fire for plain files with the same names in the last path
> component and the same originating sid? (Maybe I'm not understanding
> type_transition rules properly.) Using a class to encompass all
> anonymous inodes would address this problem (assuming the problem
> exists in the first place).

It shouldn't fire for non-anon inodes because on a (non-anon) file 
creation, security_transition_sid() is passed the parent directory SID 
as the second argument and we only assign task SIDs to /proc/pid 
directories, which don't support (userspace) file creation anyway.

However, in the absence of a matching type_transition rule, we'll end up 
defaulting to the task SID on the anon inode, and without a separate 
class we won't be able to distinguish it from a /proc/pid inode.  So 
that might justify a separate anoninode or similar class.

This however reminded me that for the context_inode case, we not only 
want to inherit the SID but also the sclass from the context_inode. 
That is so that anon inodes created via device node ioctls inherit the 
same SID/class pair as the device node and a single allowx rule can 
govern all ioctl commands on that device.









^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 2/3] Teach SELinux about anonymous inodes
  2020-02-14 18:02         ` Stephen Smalley
@ 2020-02-14 18:08           ` Stephen Smalley
  2020-02-14 20:24             ` Stephen Smalley
  0 siblings, 1 reply; 75+ messages in thread
From: Stephen Smalley @ 2020-02-14 18:08 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: Tim Murray, SElinux list, LSM List, Linux FS Devel, linux-kernel,
	kvm, Al Viro, paul, Nick Kralevich, Lokesh Gidra,
	Jeffrey Vander Stoep

On 2/14/20 1:02 PM, Stephen Smalley wrote:
> It shouldn't fire for non-anon inodes because on a (non-anon) file 
> creation, security_transition_sid() is passed the parent directory SID 
> as the second argument and we only assign task SIDs to /proc/pid 
> directories, which don't support (userspace) file creation anyway.
> 
> However, in the absence of a matching type_transition rule, we'll end up 
> defaulting to the task SID on the anon inode, and without a separate 
> class we won't be able to distinguish it from a /proc/pid inode.  So 
> that might justify a separate anoninode or similar class.
> 
> This however reminded me that for the context_inode case, we not only 
> want to inherit the SID but also the sclass from the context_inode. That 
> is so that anon inodes created via device node ioctls inherit the same 
> SID/class pair as the device node and a single allowx rule can govern 
> all ioctl commands on that device.

At least that's the way our patch worked with the /dev/kvm example. 
However, if we are introducing a separate anoninode class for the 
type_transition case, maybe we should apply that to all anon inodes 
regardless of how they are labeled (based on context_inode or 
transition) and then we'd need to write two allowx rules, one for ioctls 
on the original device node and one for those on anon inodes created 
from it.  Not sure how Android wants to handle that as the original 
developer and primary user of SELinux ioctl whitelisting.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 2/3] Teach SELinux about anonymous inodes
  2020-02-14 18:08           ` Stephen Smalley
@ 2020-02-14 20:24             ` Stephen Smalley
  0 siblings, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-02-14 20:24 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: Tim Murray, SElinux list, LSM List, Linux FS Devel, linux-kernel,
	kvm, Al Viro, paul, Nick Kralevich, Lokesh Gidra,
	Jeffrey Vander Stoep

On 2/14/20 1:08 PM, Stephen Smalley wrote:
> On 2/14/20 1:02 PM, Stephen Smalley wrote:
>> It shouldn't fire for non-anon inodes because on a (non-anon) file 
>> creation, security_transition_sid() is passed the parent directory SID 
>> as the second argument and we only assign task SIDs to /proc/pid 
>> directories, which don't support (userspace) file creation anyway.
>>
>> However, in the absence of a matching type_transition rule, we'll end 
>> up defaulting to the task SID on the anon inode, and without a 
>> separate class we won't be able to distinguish it from a /proc/pid 
>> inode.  So that might justify a separate anoninode or similar class.
>>
>> This however reminded me that for the context_inode case, we not only 
>> want to inherit the SID but also the sclass from the context_inode. 
>> That is so that anon inodes created via device node ioctls inherit the 
>> same SID/class pair as the device node and a single allowx rule can 
>> govern all ioctl commands on that device.
> 
> At least that's the way our patch worked with the /dev/kvm example. 
> However, if we are introducing a separate anoninode class for the 
> type_transition case, maybe we should apply that to all anon inodes 
> regardless of how they are labeled (based on context_inode or 
> transition) and then we'd need to write two allowx rules, one for ioctls 
> on the original device node and one for those on anon inodes created 
> from it.  Not sure how Android wants to handle that as the original 
> developer and primary user of SELinux ioctl whitelisting.

I would tentatively argue for inheriting both sclass and SID from the 
context_inode for the sake of sane policy writing.  In the userfaultfd 
case, that will still end up using the new SECCLASS_ANONINODE or 
whatever since the sclass will be initially set to that value for the 
transition SID case and then inherited on fork.  But for /dev/kvm, it 
would be the class from the /dev/kvm inode, i.e. SECCLASS_CHR_FILE.


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 2/6] Add a concept of a "secure" anonymous file
  2020-02-11 22:55 ` [PATCH v2 2/6] Add a concept of a "secure" anonymous file Daniel Colascione
  2020-02-12 16:49   ` Stephen Smalley
@ 2020-02-14 22:13   ` kbuild test robot
  1 sibling, 0 replies; 75+ messages in thread
From: kbuild test robot @ 2020-02-14 22:13 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: kbuild-all, dancol, timmurray, nosh, nnk, lokeshgidra,
	linux-kernel, linux-api, selinux


[-- Attachment #1: Type: text/plain, Size: 2082 bytes --]

Hi Daniel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on pcmoore-selinux/next]
[also build test ERROR on security/next-testing linux/master linus/master v5.6-rc1 next-20200214]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Daniel-Colascione/Harden-userfaultfd/20200215-034039
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git next
config: i386-tinyconfig (attached as .config)
compiler: gcc-7 (Debian 7.5.0-4) 7.5.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   fs/anon_inodes.c: In function 'anon_inode_make_secure_inode':
>> fs/anon_inodes.c:67:10: error: implicit declaration of function 'security_inode_init_security_anon'; did you mean 'security_inode_init_security'? [-Werror=implicit-function-declaration]
     error = security_inode_init_security_anon(inode, name, fops);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             security_inode_init_security
   cc1: some warnings being treated as errors

vim +67 fs/anon_inodes.c

    57	
    58	struct inode *anon_inode_make_secure_inode(const char *name,
    59						   const struct file_operations *fops)
    60	{
    61		struct inode *inode;
    62		int error;
    63		inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
    64		if (IS_ERR(inode))
    65			return ERR_PTR(PTR_ERR(inode));
    66		inode->i_flags &= ~S_PRIVATE;
  > 67		error =	security_inode_init_security_anon(inode, name, fops);
    68		if (error) {
    69			iput(inode);
    70			return ERR_PTR(error);
    71		}
    72		return inode;
    73	}
    74	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 7239 bytes --]

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 0/6] Harden userfaultfd
  2020-02-11 23:27   ` Daniel Colascione
  2020-02-12 16:09     ` Stephen Smalley
@ 2020-02-21 17:56     ` James Morris
  1 sibling, 0 replies; 75+ messages in thread
From: James Morris @ 2020-02-21 17:56 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: Casey Schaufler, Tim Murray, Nosh Minwalla, Nick Kralevich,
	Lokesh Gidra, linux-kernel, Linux API, selinux, LSM List

On Tue, 11 Feb 2020, Daniel Colascione wrote:

> > This must be posted to the linux Security Module list
> > <linux-security-module@vger.kernel.org>
> 
> Added. I thought selinux@ was sufficient.
> 

Please cc: me on these patches.

-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v2 0/3] SELinux support for anonymous inodes and UFFD
  2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
                     ` (2 preceding siblings ...)
  2020-02-14  3:26   ` [PATCH 3/3] Wire UFFD up to SELinux Daniel Colascione
@ 2020-03-25 23:02   ` Daniel Colascione
  2020-03-25 23:02   ` [PATCH v2 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-03-25 23:02 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra
  Cc: Daniel Colascione

Userfaultfd in unprivileged contexts could be potentially very
useful. We'd like to harden userfaultfd to make such unprivileged use
less risky. This patch series allows SELinux to manage userfaultfd
file descriptors and in the future, other kinds of
anonymous-inode-based file descriptor.  SELinux policy authors can
apply policy types to anonymous inodes by providing name-based
transition rules keyed off the anonymous inode internal name (
"[userfaultfd]" in the case of userfaultfd(2) file descriptors) and
applying policy to the new SIDs thus produced.

Inside the kernel, a pair of new anon_inodes interface,
anon_inode_getfile_secure and anon_inode_getfd_secure, allow callers
to opt into this SELinux management. In this new "secure" mode,
anon_inodes creates new ephemeral inodes for anonymous file objects
instead of reusing the normal anon_inodes singleton dummy inode. A new
LSM hook gives security modules an opportunity to configure and veto
these ephemeral inodes.

This patch series is one of two fork of [1] and is an
alternative to [2].

The primary difference between the two patch series is that this
partch series creates a unique inode for each "secure" anonymous
inode, while the other patch series ([2]) continues using the
singleton dummy anonymous inode and adds a way to attach SELinux
security information directly to file objects.

I prefer the approach in this patch series because 1) it's a smaller
patch than [2], and 2) it produces a more regular security
architecture: in this patch series, secure anonymous inodes aren't
S_PRIVATE and they maintain the SELinux property that the label for a
file is in its inode. We do need an additional inode per anonymous
file, but per-struct-file inode creation doesn't seem to be a problem
for pipes and sockets.

The previous version of this feature ([1]) created a new SELinux
security class for userfaultfd file descriptors. This version adopts
the generic transition-based approach of [2].

This patch series also differs from [2] in that it doesn't affect all
anonymous inodes right away --- instead requiring anon_inodes callers
to opt in --- but this difference isn't one of basic approach. The
important question to resolve is whether we should be creating new
inodes or enhancing per-file data.

Changes from the first version of the patch:

  - Removed some error checks
  - Defined a new anon_inode SELinux class to resolve the
    ambiguity in [3]
  - Inherit sclass as well as descriptor from context inode

[1] https://lore.kernel.org/lkml/20200211225547.235083-1-dancol@google.com/
[2] https://lore.kernel.org/linux-fsdevel/20200213194157.5877-1-sds@tycho.nsa.gov/
[3] https://lore.kernel.org/lkml/23f725ca-5b5a-5938-fcc8-5bbbfc9ba9bc@tycho.nsa.gov/

Daniel Colascione (3):
  Add a new LSM-supporting anonymous inode interface
  Teach SELinux about anonymous inodes
  Wire UFFD up to SELinux

 fs/anon_inodes.c                    | 196 ++++++++++++++++++++++------
 fs/userfaultfd.c                    |  30 ++++-
 include/linux/anon_inodes.h         |  13 ++
 include/linux/lsm_hooks.h           |   9 ++
 include/linux/security.h            |   4 +
 security/security.c                 |  10 ++
 security/selinux/hooks.c            |  54 ++++++++
 security/selinux/include/classmap.h |   2 +
 8 files changed, 272 insertions(+), 46 deletions(-)

-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v2 1/3] Add a new LSM-supporting anonymous inode interface
  2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
                     ` (3 preceding siblings ...)
  2020-03-25 23:02   ` [PATCH v2 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
@ 2020-03-25 23:02   ` Daniel Colascione
  2020-03-26 13:53     ` Stephen Smalley
  2020-03-25 23:02   ` [PATCH v2 2/3] Teach SELinux about anonymous inodes Daniel Colascione
                     ` (2 subsequent siblings)
  7 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-03-25 23:02 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra
  Cc: Daniel Colascione

This change adds two new functions, anon_inode_getfile_secure and
anon_inode_getfd_secure, that create anonymous-node files with
individual non-S_PRIVATE inodes to which security modules can apply
policy. Existing callers continue using the original singleton-inode
kind of anonymous-inode file. We can transition anonymous inode users
to the new kind of anonymous inode in individual patches for the sake
of bisection and review.

The new functions accept an optional context_inode parameter that
callers can use to provide additional contextual information to
security modules, e.g., indicating that one anonymous struct file is a
logical child of another, allowing a security model to propagate
security information from one to the other.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 fs/anon_inodes.c            | 196 ++++++++++++++++++++++++++++--------
 fs/userfaultfd.c            |   4 +-
 include/linux/anon_inodes.h |  13 +++
 include/linux/lsm_hooks.h   |   9 ++
 include/linux/security.h    |   4 +
 security/security.c         |  10 ++
 6 files changed, 191 insertions(+), 45 deletions(-)

diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 89714308c25b..114a04fc1db4 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -55,75 +55,135 @@ static struct file_system_type anon_inode_fs_type = {
 	.kill_sb	= kill_anon_super,
 };
 
-/**
- * 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
- *
- * @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
- *
- * Creates a new file by hooking it on a single 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.
- */
-struct file *anon_inode_getfile(const char *name,
-				const struct file_operations *fops,
-				void *priv, int flags)
+static struct inode *anon_inode_make_secure_inode(
+	const char *name,
+	const struct inode *context_inode,
+	const struct file_operations *fops)
+{
+	struct inode *inode;
+	const struct qstr qname = QSTR_INIT(name, strlen(name));
+	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, &qname, fops, context_inode);
+	if (error) {
+		iput(inode);
+		return ERR_PTR(error);
+	}
+	return inode;
+}
+
+struct file *_anon_inode_getfile(const char *name,
+				 const struct file_operations *fops,
+				 void *priv, int flags,
+				 const struct inode *context_inode,
+				 bool secure)
 {
+	struct inode *inode;
 	struct file *file;
 
-	if (IS_ERR(anon_inode_inode))
-		return ERR_PTR(-ENODEV);
+	if (secure) {
+		inode =	anon_inode_make_secure_inode(
+			name, context_inode, 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))
-		return ERR_PTR(-ENOENT);
+	if (fops->owner && !try_module_get(fops->owner)) {
+		file = ERR_PTR(-ENOENT);
+		goto err;
+	}
 
-	/*
-	 * 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,
+	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);
 
 /**
- * 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_getfile_secure - creates a new file instance by hooking
+ *                             it up to a new anonymous inode and a
+ *                             dentry that describe the "class" of the
+ *                             file.  Make it possible to use security
+ *                             modules to control access to the
+ *                             new 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 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_secure() will have distinct inodes, avoiding
+ * code duplication for the file/inode/dentry setup.  Returns the
+ * newly created file* or an error pointer.
+ */
+struct file *anon_inode_getfile_secure(const char *name,
+				       const struct file_operations *fops,
+				       void *priv, int flags,
+				       const struct inode *context_inode)
+{
+	return _anon_inode_getfile(
+		name, fops, priv, flags, context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile_secure);
+
+/**
+ * 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.
+ *
+ * @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 for the file
  *
- * 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_getfd() will share a single inode,
+ * 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 new descriptor or an error code.
+ * setup.  Returns the newly created file* or an error pointer.
  */
-int anon_inode_getfd(const char *name, const struct file_operations *fops,
-		     void *priv, int flags)
+struct file *anon_inode_getfile(const char *name,
+				const struct file_operations *fops,
+				void *priv, int flags)
+{
+	return _anon_inode_getfile(name, fops, priv, flags, NULL, false);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile);
+
+static int _anon_inode_getfd(const char *name,
+			     const struct file_operations *fops,
+			     void *priv, int flags,
+			     const struct inode *context_inode,
+			     bool secure)
 {
 	int error, fd;
 	struct file *file;
@@ -133,7 +193,8 @@ 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_getfile(name, fops, priv, flags, context_inode,
+				   secure);
 	if (IS_ERR(file)) {
 		error = PTR_ERR(file);
 		goto err_put_unused_fd;
@@ -146,6 +207,57 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
 	put_unused_fd(fd);
 	return error;
 }
+
+/**
+ * anon_inode_getfd_secure - creates a new file instance by hooking it
+ *                           up to a new anonymous inode and a dentry
+ *                           that describe the "class" of the file.
+ *                           Make it possible to use security modules
+ *                           to control access to the new 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
+ *
+ * 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_secure() will have distinct inodes, avoiding
+ * code duplication for the file/inode/dentry setup.  Returns a newly
+ * created file descriptor or an error code.
+ */
+int anon_inode_getfd_secure(const char *name, const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode)
+{
+	return _anon_inode_getfd(name, fops, priv, flags,
+				 context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfd_secure);
+
+/**
+ * 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
+ *
+ * @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
+ *
+ * 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 use the same singleton inode, reducing
+ * memory use and avoiding code duplication for the file/inode/dentry
+ * setup.  Returns a newly created file descriptor or an error code.
+ */
+int anon_inode_getfd(const char *name, const struct file_operations *fops,
+		     void *priv, int flags)
+{
+	return _anon_inode_getfd(name, fops, priv, flags, NULL, false);
+}
 EXPORT_SYMBOL_GPL(anon_inode_getfd);
 
 static int __init anon_inode_init(void)
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/anon_inodes.h b/include/linux/anon_inodes.h
index d0d7d96261ad..67bd85d92dca 100644
--- a/include/linux/anon_inodes.h
+++ b/include/linux/anon_inodes.h
@@ -10,12 +10,25 @@
 #define _LINUX_ANON_INODES_H
 
 struct file_operations;
+struct inode;
+
+struct file *anon_inode_getfile_secure(const char *name,
+				       const struct file_operations *fops,
+				       void *priv, int flags,
+				       const struct inode *context_inode);
 
 struct file *anon_inode_getfile(const char *name,
 				const struct file_operations *fops,
 				void *priv, int flags);
+
+int anon_inode_getfd_secure(const char *name,
+			    const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode);
+
 int anon_inode_getfd(const char *name, const struct file_operations *fops,
 		     void *priv, int flags);
 
+
 #endif /* _LINUX_ANON_INODES_H */
 
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 20d8cf194fb7..de5d37e388df 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,10 @@ 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 struct qstr *name,
+					const struct file_operations *fops,
+					const struct inode *context_inode);
 	int (*inode_create)(struct inode *dir, struct dentry *dentry,
 				umode_t mode);
 	int (*inode_link)(struct dentry *old_dentry, struct inode *dir,
@@ -1884,6 +1892,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..8ea76af0be7a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -320,6 +320,10 @@ 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 struct qstr *name,
+				      const struct file_operations *fops,
+				      const struct inode *context_inode);
 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..d06f3969c030 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1033,6 +1033,16 @@ 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 struct qstr *name,
+				  const struct file_operations *fops,
+				  const struct inode *context_inode)
+{
+	return call_int_hook(inode_init_security_anon, 0, inode, name,
+			     fops, context_inode);
+}
+
 int security_old_inode_init_security(struct inode *inode, struct inode *dir,
 				     const struct qstr *qstr, const char **name,
 				     void **value, size_t *len)
-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v2 2/3] Teach SELinux about anonymous inodes
  2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
                     ` (4 preceding siblings ...)
  2020-03-25 23:02   ` [PATCH v2 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
@ 2020-03-25 23:02   ` Daniel Colascione
  2020-03-26 13:58     ` Stephen Smalley
  2020-03-26 17:37     ` Stephen Smalley
  2020-03-25 23:02   ` [PATCH v2 3/3] Wire UFFD up to SELinux Daniel Colascione
  2020-03-26 18:14   ` [PATCH v3 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  7 siblings, 2 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-03-25 23:02 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra
  Cc: Daniel Colascione

This change uses the anon_inodes and LSM infrastructure introduced in
the previous patch to give SELinux the ability to control
anonymous-inode files that are created using the new _secure()
anon_inodes functions.

A SELinux policy author detects and controls these anonymous inodes by
adding a name-based type_transition rule that assigns a new security
type to anonymous-inode files created in some domain. The name used
for the name-based transition is the name associated with the
anonymous inode for file listings --- e.g., "[userfaultfd]" or
"[perf_event]".

Example:

type uffd_t;
type_transition sysadm_t sysadm_t : file uffd_t "[userfaultfd]";
allow sysadm_t uffd_t:file { create };

(The next patch in this series is necessary for making userfaultfd
support this new interface.  The example above is just
for exposition.)

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 security/selinux/hooks.c            | 54 +++++++++++++++++++++++++++++
 security/selinux/include/classmap.h |  2 ++
 2 files changed, 56 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1659b59fb5d7..b9eb45c2e4e5 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2915,6 +2915,59 @@ 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 struct qstr *name,
+					    const struct file_operations *fops,
+					    const struct inode *context_inode)
+{
+	const struct task_security_struct *tsec = selinux_cred(current_cred());
+	struct common_audit_data ad;
+	struct inode_security_struct *isec;
+	int rc;
+
+	if (unlikely(!selinux_state.initialized))
+		return 0;
+
+	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.
+	 */
+
+	if (context_inode) {
+		struct inode_security_struct *context_isec =
+			selinux_inode(context_inode);
+		isec->sclass = context_isec->sclass;
+		isec->sid = context_isec->sid;
+	} else {
+		isec->sclass = SECCLASS_ANON_INODE;
+		rc = security_transition_sid(
+			&selinux_state, tsec->sid, tsec->sid,
+			SECCLASS_FILE, name, &isec->sid);
+		if (rc)
+			return rc;
+	}
+
+	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 +6976,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..263750b6aaac 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 } },
+	{ "anon_inode",
+	  { COMMON_FILE_PERMS, NULL } },
 	{ NULL }
   };
 
-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v2 3/3] Wire UFFD up to SELinux
  2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
                     ` (5 preceding siblings ...)
  2020-03-25 23:02   ` [PATCH v2 2/3] Teach SELinux about anonymous inodes Daniel Colascione
@ 2020-03-25 23:02   ` Daniel Colascione
  2020-03-25 23:49     ` Casey Schaufler
  2020-03-26 18:14   ` [PATCH v3 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  7 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-03-25 23:02 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra
  Cc: Daniel Colascione

This change gives userfaultfd file descriptors a real security
context, allowing policy to act on them.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 fs/userfaultfd.c | 34 +++++++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 07b0f6e03849..78ff5d898733 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -76,6 +76,8 @@ struct userfaultfd_ctx {
 	bool mmap_changing;
 	/* mm with one ore more vmas attached to this userfaultfd_ctx */
 	struct mm_struct *mm;
+	/* The inode that owns this context --- not a strong reference.  */
+	const struct inode *owner;
 };
 
 struct userfaultfd_fork_ctx {
@@ -1014,14 +1016,18 @@ 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)
 {
 	int fd;
 
-	fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, new,
-			      O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS));
+	fd = anon_inode_getfd_secure(
+		"[userfaultfd]", &userfaultfd_fops, new,
+		O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS),
+		ctx->owner);
 	if (fd < 0)
 		return fd;
 
@@ -1918,7 +1924,7 @@ static void userfaultfd_show_fdinfo(struct seq_file *m, struct file *f)
 }
 #endif
 
-const struct file_operations userfaultfd_fops = {
+static const struct file_operations userfaultfd_fops = {
 #ifdef CONFIG_PROC_FS
 	.show_fdinfo	= userfaultfd_show_fdinfo,
 #endif
@@ -1943,6 +1949,7 @@ static void init_once_userfaultfd_ctx(void *mem)
 
 SYSCALL_DEFINE1(userfaultfd, int, flags)
 {
+	struct file *file;
 	struct userfaultfd_ctx *ctx;
 	int fd;
 
@@ -1972,8 +1979,25 @@ 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));
+	file = anon_inode_getfile_secure(
+		"[userfaultfd]", &userfaultfd_fops, ctx,
+		O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS),
+		NULL);
+	if (IS_ERR(file)) {
+		fd = PTR_ERR(file);
+		goto out;
+	}
+
+	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
+	if (fd < 0) {
+		fput(file);
+		goto out;
+	}
+
+	ctx->owner = file_inode(file);
+	fd_install(fd, file);
+
+out:
 	if (fd < 0) {
 		mmdrop(ctx->mm);
 		kmem_cache_free(userfaultfd_ctx_cachep, ctx);
-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 3/3] Wire UFFD up to SELinux
  2020-03-25 23:02   ` [PATCH v2 3/3] Wire UFFD up to SELinux Daniel Colascione
@ 2020-03-25 23:49     ` Casey Schaufler
  0 siblings, 0 replies; 75+ messages in thread
From: Casey Schaufler @ 2020-03-25 23:49 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, selinux, linux-security-module,
	linux-fsdevel, linux-kernel, kvm, viro, paul, nnk, sds,
	lokeshgidra, Casey Schaufler

On 3/25/2020 4:02 PM, Daniel Colascione wrote:
> This change gives userfaultfd file descriptors a real security
> context, allowing policy to act on them.

You should change the title to "Wire UFFD up to secure anon inodes".
This code should support any LSM that wants to control anon inodes.
If it doesn't, it isn't correct.

All references to SELinux behavior (i.e. assigning a "security context")
should be restricted to the SELinux specific bits of the patch set. You
should be describing how any LSM can use this, not just the LSM you've
targeted.

>
> Signed-off-by: Daniel Colascione <dancol@google.com>
> ---
>  fs/userfaultfd.c | 34 +++++++++++++++++++++++++++++-----
>  1 file changed, 29 insertions(+), 5 deletions(-)
>
> diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
> index 07b0f6e03849..78ff5d898733 100644
> --- a/fs/userfaultfd.c
> +++ b/fs/userfaultfd.c
> @@ -76,6 +76,8 @@ struct userfaultfd_ctx {
>  	bool mmap_changing;
>  	/* mm with one ore more vmas attached to this userfaultfd_ctx */
>  	struct mm_struct *mm;
> +	/* The inode that owns this context --- not a strong reference.  */
> +	const struct inode *owner;
>  };
>  
>  struct userfaultfd_fork_ctx {
> @@ -1014,14 +1016,18 @@ 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)
>  {
>  	int fd;
>  
> -	fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, new,
> -			      O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS));
> +	fd = anon_inode_getfd_secure(
> +		"[userfaultfd]", &userfaultfd_fops, new,
> +		O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS),
> +		ctx->owner);
>  	if (fd < 0)
>  		return fd;
>  
> @@ -1918,7 +1924,7 @@ static void userfaultfd_show_fdinfo(struct seq_file *m, struct file *f)
>  }
>  #endif
>  
> -const struct file_operations userfaultfd_fops = {
> +static const struct file_operations userfaultfd_fops = {
>  #ifdef CONFIG_PROC_FS
>  	.show_fdinfo	= userfaultfd_show_fdinfo,
>  #endif
> @@ -1943,6 +1949,7 @@ static void init_once_userfaultfd_ctx(void *mem)
>  
>  SYSCALL_DEFINE1(userfaultfd, int, flags)
>  {
> +	struct file *file;
>  	struct userfaultfd_ctx *ctx;
>  	int fd;
>  
> @@ -1972,8 +1979,25 @@ 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));
> +	file = anon_inode_getfile_secure(
> +		"[userfaultfd]", &userfaultfd_fops, ctx,
> +		O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS),
> +		NULL);
> +	if (IS_ERR(file)) {
> +		fd = PTR_ERR(file);
> +		goto out;
> +	}
> +
> +	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
> +	if (fd < 0) {
> +		fput(file);
> +		goto out;
> +	}
> +
> +	ctx->owner = file_inode(file);
> +	fd_install(fd, file);
> +
> +out:
>  	if (fd < 0) {
>  		mmdrop(ctx->mm);
>  		kmem_cache_free(userfaultfd_ctx_cachep, ctx);


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 1/3] Add a new LSM-supporting anonymous inode interface
  2020-03-25 23:02   ` [PATCH v2 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
@ 2020-03-26 13:53     ` Stephen Smalley
  0 siblings, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-03-26 13:53 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, selinux, linux-security-module,
	linux-fsdevel, linux-kernel, kvm, viro, paul, nnk, lokeshgidra,
	James Morris

On 3/25/20 7:02 PM, Daniel Colascione wrote:
> This change adds two new functions, anon_inode_getfile_secure and
> anon_inode_getfd_secure, that create anonymous-node files with
> individual non-S_PRIVATE inodes to which security modules can apply
> policy. Existing callers continue using the original singleton-inode
> kind of anonymous-inode file. We can transition anonymous inode users
> to the new kind of anonymous inode in individual patches for the sake
> of bisection and review.
> 
> The new functions accept an optional context_inode parameter that
> callers can use to provide additional contextual information to
> security modules, e.g., indicating that one anonymous struct file is a
> logical child of another, allowing a security model to propagate
> security information from one to the other.
> 
> Signed-off-by: Daniel Colascione <dancol@google.com>
> ---

> diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
> index 89714308c25b..114a04fc1db4 100644
> --- a/fs/anon_inodes.c
> +++ b/fs/anon_inodes.c
> @@ -55,75 +55,135 @@ static struct file_system_type anon_inode_fs_type = {
>   	.kill_sb	= kill_anon_super,
>   };
>   
> -/**
> - * 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
> - *
> - * @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
> - *
> - * Creates a new file by hooking it on a single 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.
> - */
> -struct file *anon_inode_getfile(const char *name,
> -				const struct file_operations *fops,
> -				void *priv, int flags)
> +static struct inode *anon_inode_make_secure_inode(
> +	const char *name,
> +	const struct inode *context_inode,
> +	const struct file_operations *fops)
> +{
> +	struct inode *inode;
> +	const struct qstr qname = QSTR_INIT(name, strlen(name));
> +	int error;
> +
> +	inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
> +	if (IS_ERR(inode))
> +		return ERR_PTR(PTR_ERR(inode));

Just return inode here?

> +	inode->i_flags &= ~S_PRIVATE;
> +	error =	security_inode_init_security_anon(
> +		inode, &qname, fops, context_inode);

Would drop fops argument to the security hook until we have an actual 
user of it; one can always add it later.


> 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

These changes can be dropped entirely AFAICT.

> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 20d8cf194fb7..de5d37e388df 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.

I'd favor describing the arguments (@name, @context_inode) too.

>    * @inode_create:
>    *	Check permission to create a regular file.
>    *	@dir contains inode structure of the parent of the new file.
> @@ -1552,6 +1556,10 @@ 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 struct qstr *name,
> +					const struct file_operations *fops,
> +					const struct inode *context_inode);
>   	int (*inode_create)(struct inode *dir, struct dentry *dentry,

Can drop the fops argument.

> diff --git a/include/linux/security.h b/include/linux/security.h
> index 64b19f050343..8ea76af0be7a 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -320,6 +320,10 @@ 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 struct qstr *name,
> +				      const struct file_operations *fops,
> +				      const struct inode *context_inode);

Ditto

> diff --git a/security/security.c b/security/security.c
> index 565bc9b67276..d06f3969c030 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1033,6 +1033,16 @@ 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 struct qstr *name,
> +				  const struct file_operations *fops,
> +				  const struct inode *context_inode)
> +{
> +	return call_int_hook(inode_init_security_anon, 0, inode, name,
> +			     fops, context_inode);
> +}
> +

And again.



^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 2/3] Teach SELinux about anonymous inodes
  2020-03-25 23:02   ` [PATCH v2 2/3] Teach SELinux about anonymous inodes Daniel Colascione
@ 2020-03-26 13:58     ` Stephen Smalley
  2020-03-26 17:59       ` Daniel Colascione
  2020-03-26 17:37     ` Stephen Smalley
  1 sibling, 1 reply; 75+ messages in thread
From: Stephen Smalley @ 2020-03-26 13:58 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, selinux, linux-security-module,
	linux-fsdevel, linux-kernel, kvm, viro, paul, nnk, lokeshgidra

On 3/25/20 7:02 PM, Daniel Colascione wrote:
> This change uses the anon_inodes and LSM infrastructure introduced in
> the previous patch to give SELinux the ability to control
> anonymous-inode files that are created using the new _secure()
> anon_inodes functions.
> 
> A SELinux policy author detects and controls these anonymous inodes by
> adding a name-based type_transition rule that assigns a new security
> type to anonymous-inode files created in some domain. The name used
> for the name-based transition is the name associated with the
> anonymous inode for file listings --- e.g., "[userfaultfd]" or
> "[perf_event]".
> 
> Example:
> 
> type uffd_t;
> type_transition sysadm_t sysadm_t : file uffd_t "[userfaultfd]";
> allow sysadm_t uffd_t:file { create };
> 
> (The next patch in this series is necessary for making userfaultfd
> support this new interface.  The example above is just
> for exposition.)
> 
> Signed-off-by: Daniel Colascione <dancol@google.com>
> ---
>   security/selinux/hooks.c            | 54 +++++++++++++++++++++++++++++
>   security/selinux/include/classmap.h |  2 ++
>   2 files changed, 56 insertions(+)
> 
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 1659b59fb5d7..b9eb45c2e4e5 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2915,6 +2915,59 @@ 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 struct qstr *name,
> +					    const struct file_operations *fops,
> +					    const struct inode *context_inode)
> +{
> +	const struct task_security_struct *tsec = selinux_cred(current_cred());
> +	struct common_audit_data ad;
> +	struct inode_security_struct *isec;
> +	int rc;
> +
> +	if (unlikely(!selinux_state.initialized))
> +		return 0;

This leaves secure anon inodes created before first policy load with the 
unlabeled SID rather than defaulting to the SID of the creating task 
(kernel SID in that situation).  Is that what you want?  Alternatively 
you can just remove this test and let it proceed; nothing should be 
break and the anon inodes will get the kernel SID.

> +
> +	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.
> +	 */
> +
> +	if (context_inode) {
> +		struct inode_security_struct *context_isec =
> +			selinux_inode(context_inode);
> +		isec->sclass = context_isec->sclass;
> +		isec->sid = context_isec->sid;
> +	} else {
> +		isec->sclass = SECCLASS_ANON_INODE;
> +		rc = security_transition_sid(
> +			&selinux_state, tsec->sid, tsec->sid,
> +			SECCLASS_FILE, name, &isec->sid);
> +		if (rc)
> +			return rc;
> +	}
> +
> +	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 +6976,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..263750b6aaac 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 } },
> +	{ "anon_inode",
> +	  { COMMON_FILE_PERMS, NULL } },
>   	{ NULL }
>     };
>   
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 2/3] Teach SELinux about anonymous inodes
  2020-03-25 23:02   ` [PATCH v2 2/3] Teach SELinux about anonymous inodes Daniel Colascione
  2020-03-26 13:58     ` Stephen Smalley
@ 2020-03-26 17:37     ` Stephen Smalley
  1 sibling, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-03-26 17:37 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, selinux, linux-security-module,
	linux-fsdevel, linux-kernel, kvm, viro, paul, nnk, lokeshgidra

On 3/25/20 7:02 PM, Daniel Colascione wrote:
> This change uses the anon_inodes and LSM infrastructure introduced in
> the previous patch to give SELinux the ability to control
> anonymous-inode files that are created using the new _secure()
> anon_inodes functions.
> 
> A SELinux policy author detects and controls these anonymous inodes by
> adding a name-based type_transition rule that assigns a new security
> type to anonymous-inode files created in some domain. The name used
> for the name-based transition is the name associated with the
> anonymous inode for file listings --- e.g., "[userfaultfd]" or
> "[perf_event]".
> 
> Example:
> 
> type uffd_t;
> type_transition sysadm_t sysadm_t : file uffd_t "[userfaultfd]";
> allow sysadm_t uffd_t:file { create };

These should use :anon_inode rather than :file since the class is no 
longer file.

> 
> (The next patch in this series is necessary for making userfaultfd
> support this new interface.  The example above is just
> for exposition.)
> 
> Signed-off-by: Daniel Colascione <dancol@google.com>
> ---
>   security/selinux/hooks.c            | 54 +++++++++++++++++++++++++++++
>   security/selinux/include/classmap.h |  2 ++
>   2 files changed, 56 insertions(+)
> 
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 1659b59fb5d7..b9eb45c2e4e5 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2915,6 +2915,59 @@ 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 struct qstr *name,
> +					    const struct file_operations *fops,
> +					    const struct inode *context_inode)
> +{
> +	const struct task_security_struct *tsec = selinux_cred(current_cred());
> +	struct common_audit_data ad;
> +	struct inode_security_struct *isec;
> +	int rc;
> +
> +	if (unlikely(!selinux_state.initialized))
> +		return 0;
> +
> +	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.
> +	 */
> +
> +	if (context_inode) {
> +		struct inode_security_struct *context_isec =
> +			selinux_inode(context_inode);
> +		isec->sclass = context_isec->sclass;
> +		isec->sid = context_isec->sid;
> +	} else {
> +		isec->sclass = SECCLASS_ANON_INODE;
> +		rc = security_transition_sid(
> +			&selinux_state, tsec->sid, tsec->sid,
> +			SECCLASS_FILE, name, &isec->sid);

You should use isec->sclass == SECCLASS_ANON_INODE instead of 
SECCLASS_FILE here.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v2 2/3] Teach SELinux about anonymous inodes
  2020-03-26 13:58     ` Stephen Smalley
@ 2020-03-26 17:59       ` Daniel Colascione
  0 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-03-26 17:59 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Tim Murray, SElinux list, LSM List, Linux FS Devel, linux-kernel,
	kvm, Al Viro, Paul Moore, Nick Kralevich, Lokesh Gidra

Thanks for taking a look!

On Thu, Mar 26, 2020 at 6:57 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>
> On 3/25/20 7:02 PM, Daniel Colascione wrote:
> > This change uses the anon_inodes and LSM infrastructure introduced in
> > the previous patch to give SELinux the ability to control
> > anonymous-inode files that are created using the new _secure()
> > anon_inodes functions.
> >
> > A SELinux policy author detects and controls these anonymous inodes by
> > adding a name-based type_transition rule that assigns a new security
> > type to anonymous-inode files created in some domain. The name used
> > for the name-based transition is the name associated with the
> > anonymous inode for file listings --- e.g., "[userfaultfd]" or
> > "[perf_event]".
> >
> > Example:
> >
> > type uffd_t;
> > type_transition sysadm_t sysadm_t : file uffd_t "[userfaultfd]";
> > allow sysadm_t uffd_t:file { create };

Oops. Will fix.

> > (The next patch in this series is necessary for making userfaultfd
> > support this new interface.  The example above is just
> > for exposition.)
> >
> > Signed-off-by: Daniel Colascione <dancol@google.com>
> > ---
> >   security/selinux/hooks.c            | 54 +++++++++++++++++++++++++++++
> >   security/selinux/include/classmap.h |  2 ++
> >   2 files changed, 56 insertions(+)
> >
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 1659b59fb5d7..b9eb45c2e4e5 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -2915,6 +2915,59 @@ 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 struct qstr *name,
> > +                                         const struct file_operations *fops,
> > +                                         const struct inode *context_inode)
> > +{
> > +     const struct task_security_struct *tsec = selinux_cred(current_cred());
> > +     struct common_audit_data ad;
> > +     struct inode_security_struct *isec;
> > +     int rc;
> > +
> > +     if (unlikely(!selinux_state.initialized))
> > +             return 0;
>
> This leaves secure anon inodes created before first policy load with the
> unlabeled SID rather than defaulting to the SID of the creating task
> (kernel SID in that situation).  Is that what you want?  Alternatively
> you can just remove this test and let it proceed; nothing should be
> break and the anon inodes will get the kernel SID.

We talked about this decision on the last thread [1], and I think you
mentioned that either the unlabeled or the kernel SID approach would
be defensible. Using the unlabeled SID seems more "honest" to me than
using the kernel SID: the unlabeled SID says "we don't know", while
using kernel SID would be making an affirmative claim that the
anonymous inode belongs to the kernel, and claim wouldn't be true.
That's why I'm leaning toward the unlabeled approach right now.

[1] https://lore.kernel.org/lkml/9ca03838-8686-0007-0971-ee63bf5031da@tycho.nsa.gov/

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v3 0/3] SELinux support for anonymous inodes and UFFD
  2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
                     ` (6 preceding siblings ...)
  2020-03-25 23:02   ` [PATCH v2 3/3] Wire UFFD up to SELinux Daniel Colascione
@ 2020-03-26 18:14   ` Daniel Colascione
  2020-03-26 18:14     ` [PATCH v3 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
                       ` (3 more replies)
  7 siblings, 4 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-03-26 18:14 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

Userfaultfd in unprivileged contexts could be potentially very
useful. We'd like to harden userfaultfd to make such unprivileged use
less risky. This patch series allows SELinux to manage userfaultfd
file descriptors and in the future, other kinds of
anonymous-inode-based file descriptor.  SELinux policy authors can
apply policy types to anonymous inodes by providing name-based
transition rules keyed off the anonymous inode internal name (
"[userfaultfd]" in the case of userfaultfd(2) file descriptors) and
applying policy to the new SIDs thus produced.

Inside the kernel, a pair of new anon_inodes interface,
anon_inode_getfile_secure and anon_inode_getfd_secure, allow callers
to opt into this SELinux management. In this new "secure" mode,
anon_inodes creates new ephemeral inodes for anonymous file objects
instead of reusing the normal anon_inodes singleton dummy inode. A new
LSM hook gives security modules an opportunity to configure and veto
these ephemeral inodes.

This patch series is one of two fork of [1] and is an
alternative to [2].

The primary difference between the two patch series is that this
partch series creates a unique inode for each "secure" anonymous
inode, while the other patch series ([2]) continues using the
singleton dummy anonymous inode and adds a way to attach SELinux
security information directly to file objects.

I prefer the approach in this patch series because 1) it's a smaller
patch than [2], and 2) it produces a more regular security
architecture: in this patch series, secure anonymous inodes aren't
S_PRIVATE and they maintain the SELinux property that the label for a
file is in its inode. We do need an additional inode per anonymous
file, but per-struct-file inode creation doesn't seem to be a problem
for pipes and sockets.

The previous version of this feature ([1]) created a new SELinux
security class for userfaultfd file descriptors. This version adopts
the generic transition-based approach of [2].

This patch series also differs from [2] in that it doesn't affect all
anonymous inodes right away --- instead requiring anon_inodes callers
to opt in --- but this difference isn't one of basic approach. The
important question to resolve is whether we should be creating new
inodes or enhancing per-file data.

Changes from the first version of the patch:

  - Removed some error checks
  - Defined a new anon_inode SELinux class to resolve the
    ambiguity in [3]
  - Inherit sclass as well as descriptor from context inode

Changes from the second version of the patch:

  - Fixed example policy in the commit message to reflect the use of
    the new anon_inode class.

[1] https://lore.kernel.org/lkml/20200211225547.235083-1-dancol@google.com/
[2] https://lore.kernel.org/linux-fsdevel/20200213194157.5877-1-sds@tycho.nsa.gov/
[3] https://lore.kernel.org/lkml/23f725ca-5b5a-5938-fcc8-5bbbfc9ba9bc@tycho.nsa.gov/

Daniel Colascione (3):
  Add a new LSM-supporting anonymous inode interface
  Teach SELinux about anonymous inodes
  Wire UFFD up to SELinux

 fs/anon_inodes.c                    | 196 ++++++++++++++++++++++------
 fs/userfaultfd.c                    |  30 ++++-
 include/linux/anon_inodes.h         |  13 ++
 include/linux/lsm_hooks.h           |   9 ++
 include/linux/security.h            |   4 +
 security/security.c                 |  10 ++
 security/selinux/hooks.c            |  54 ++++++++
 security/selinux/include/classmap.h |   2 +
 8 files changed, 272 insertions(+), 46 deletions(-)

-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v3 1/3] Add a new LSM-supporting anonymous inode interface
  2020-03-26 18:14   ` [PATCH v3 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
@ 2020-03-26 18:14     ` Daniel Colascione
  2020-03-26 19:00       ` Stephen Smalley
  2020-03-26 18:14     ` [PATCH v3 2/3] Teach SELinux about anonymous inodes Daniel Colascione
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-03-26 18:14 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

This change adds two new functions, anon_inode_getfile_secure and
anon_inode_getfd_secure, that create anonymous-node files with
individual non-S_PRIVATE inodes to which security modules can apply
policy. Existing callers continue using the original singleton-inode
kind of anonymous-inode file. We can transition anonymous inode users
to the new kind of anonymous inode in individual patches for the sake
of bisection and review.

The new functions accept an optional context_inode parameter that
callers can use to provide additional contextual information to
security modules, e.g., indicating that one anonymous struct file is a
logical child of another, allowing a security model to propagate
security information from one to the other.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 fs/anon_inodes.c            | 196 ++++++++++++++++++++++++++++--------
 fs/userfaultfd.c            |   4 +-
 include/linux/anon_inodes.h |  13 +++
 include/linux/lsm_hooks.h   |   9 ++
 include/linux/security.h    |   4 +
 security/security.c         |  10 ++
 6 files changed, 191 insertions(+), 45 deletions(-)

diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 89714308c25b..114a04fc1db4 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -55,75 +55,135 @@ static struct file_system_type anon_inode_fs_type = {
 	.kill_sb	= kill_anon_super,
 };
 
-/**
- * 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
- *
- * @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
- *
- * Creates a new file by hooking it on a single 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.
- */
-struct file *anon_inode_getfile(const char *name,
-				const struct file_operations *fops,
-				void *priv, int flags)
+static struct inode *anon_inode_make_secure_inode(
+	const char *name,
+	const struct inode *context_inode,
+	const struct file_operations *fops)
+{
+	struct inode *inode;
+	const struct qstr qname = QSTR_INIT(name, strlen(name));
+	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, &qname, fops, context_inode);
+	if (error) {
+		iput(inode);
+		return ERR_PTR(error);
+	}
+	return inode;
+}
+
+struct file *_anon_inode_getfile(const char *name,
+				 const struct file_operations *fops,
+				 void *priv, int flags,
+				 const struct inode *context_inode,
+				 bool secure)
 {
+	struct inode *inode;
 	struct file *file;
 
-	if (IS_ERR(anon_inode_inode))
-		return ERR_PTR(-ENODEV);
+	if (secure) {
+		inode =	anon_inode_make_secure_inode(
+			name, context_inode, 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))
-		return ERR_PTR(-ENOENT);
+	if (fops->owner && !try_module_get(fops->owner)) {
+		file = ERR_PTR(-ENOENT);
+		goto err;
+	}
 
-	/*
-	 * 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,
+	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);
 
 /**
- * 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_getfile_secure - creates a new file instance by hooking
+ *                             it up to a new anonymous inode and a
+ *                             dentry that describe the "class" of the
+ *                             file.  Make it possible to use security
+ *                             modules to control access to the
+ *                             new 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 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_secure() will have distinct inodes, avoiding
+ * code duplication for the file/inode/dentry setup.  Returns the
+ * newly created file* or an error pointer.
+ */
+struct file *anon_inode_getfile_secure(const char *name,
+				       const struct file_operations *fops,
+				       void *priv, int flags,
+				       const struct inode *context_inode)
+{
+	return _anon_inode_getfile(
+		name, fops, priv, flags, context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile_secure);
+
+/**
+ * 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.
+ *
+ * @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 for the file
  *
- * 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_getfd() will share a single inode,
+ * 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 new descriptor or an error code.
+ * setup.  Returns the newly created file* or an error pointer.
  */
-int anon_inode_getfd(const char *name, const struct file_operations *fops,
-		     void *priv, int flags)
+struct file *anon_inode_getfile(const char *name,
+				const struct file_operations *fops,
+				void *priv, int flags)
+{
+	return _anon_inode_getfile(name, fops, priv, flags, NULL, false);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile);
+
+static int _anon_inode_getfd(const char *name,
+			     const struct file_operations *fops,
+			     void *priv, int flags,
+			     const struct inode *context_inode,
+			     bool secure)
 {
 	int error, fd;
 	struct file *file;
@@ -133,7 +193,8 @@ 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_getfile(name, fops, priv, flags, context_inode,
+				   secure);
 	if (IS_ERR(file)) {
 		error = PTR_ERR(file);
 		goto err_put_unused_fd;
@@ -146,6 +207,57 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
 	put_unused_fd(fd);
 	return error;
 }
+
+/**
+ * anon_inode_getfd_secure - creates a new file instance by hooking it
+ *                           up to a new anonymous inode and a dentry
+ *                           that describe the "class" of the file.
+ *                           Make it possible to use security modules
+ *                           to control access to the new 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
+ *
+ * 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_secure() will have distinct inodes, avoiding
+ * code duplication for the file/inode/dentry setup.  Returns a newly
+ * created file descriptor or an error code.
+ */
+int anon_inode_getfd_secure(const char *name, const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode)
+{
+	return _anon_inode_getfd(name, fops, priv, flags,
+				 context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfd_secure);
+
+/**
+ * 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
+ *
+ * @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
+ *
+ * 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 use the same singleton inode, reducing
+ * memory use and avoiding code duplication for the file/inode/dentry
+ * setup.  Returns a newly created file descriptor or an error code.
+ */
+int anon_inode_getfd(const char *name, const struct file_operations *fops,
+		     void *priv, int flags)
+{
+	return _anon_inode_getfd(name, fops, priv, flags, NULL, false);
+}
 EXPORT_SYMBOL_GPL(anon_inode_getfd);
 
 static int __init anon_inode_init(void)
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/anon_inodes.h b/include/linux/anon_inodes.h
index d0d7d96261ad..67bd85d92dca 100644
--- a/include/linux/anon_inodes.h
+++ b/include/linux/anon_inodes.h
@@ -10,12 +10,25 @@
 #define _LINUX_ANON_INODES_H
 
 struct file_operations;
+struct inode;
+
+struct file *anon_inode_getfile_secure(const char *name,
+				       const struct file_operations *fops,
+				       void *priv, int flags,
+				       const struct inode *context_inode);
 
 struct file *anon_inode_getfile(const char *name,
 				const struct file_operations *fops,
 				void *priv, int flags);
+
+int anon_inode_getfd_secure(const char *name,
+			    const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode);
+
 int anon_inode_getfd(const char *name, const struct file_operations *fops,
 		     void *priv, int flags);
 
+
 #endif /* _LINUX_ANON_INODES_H */
 
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 20d8cf194fb7..de5d37e388df 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,10 @@ 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 struct qstr *name,
+					const struct file_operations *fops,
+					const struct inode *context_inode);
 	int (*inode_create)(struct inode *dir, struct dentry *dentry,
 				umode_t mode);
 	int (*inode_link)(struct dentry *old_dentry, struct inode *dir,
@@ -1884,6 +1892,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..8ea76af0be7a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -320,6 +320,10 @@ 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 struct qstr *name,
+				      const struct file_operations *fops,
+				      const struct inode *context_inode);
 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..d06f3969c030 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1033,6 +1033,16 @@ 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 struct qstr *name,
+				  const struct file_operations *fops,
+				  const struct inode *context_inode)
+{
+	return call_int_hook(inode_init_security_anon, 0, inode, name,
+			     fops, context_inode);
+}
+
 int security_old_inode_init_security(struct inode *inode, struct inode *dir,
 				     const struct qstr *qstr, const char **name,
 				     void **value, size_t *len)
-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v3 2/3] Teach SELinux about anonymous inodes
  2020-03-26 18:14   ` [PATCH v3 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  2020-03-26 18:14     ` [PATCH v3 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
@ 2020-03-26 18:14     ` Daniel Colascione
  2020-03-26 19:02       ` Stephen Smalley
  2020-03-26 18:14     ` [PATCH v3 3/3] Wire UFFD up to SELinux Daniel Colascione
  2020-03-26 20:06     ` [PATCH v4 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  3 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-03-26 18:14 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

This change uses the anon_inodes and LSM infrastructure introduced in
the previous patch to give SELinux the ability to control
anonymous-inode files that are created using the new _secure()
anon_inodes functions.

A SELinux policy author detects and controls these anonymous inodes by
adding a name-based type_transition rule that assigns a new security
type to anonymous-inode files created in some domain. The name used
for the name-based transition is the name associated with the
anonymous inode for file listings --- e.g., "[userfaultfd]" or
"[perf_event]".

Example:

type uffd_t;
type_transition sysadm_t sysadm_t : anon_inode uffd_t "[userfaultfd]";
allow sysadm_t uffd_t:anon_inode { create };

(The next patch in this series is necessary for making userfaultfd
support this new interface.  The example above is just
for exposition.)

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 security/selinux/hooks.c            | 54 +++++++++++++++++++++++++++++
 security/selinux/include/classmap.h |  2 ++
 2 files changed, 56 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1659b59fb5d7..b9eb45c2e4e5 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2915,6 +2915,59 @@ 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 struct qstr *name,
+					    const struct file_operations *fops,
+					    const struct inode *context_inode)
+{
+	const struct task_security_struct *tsec = selinux_cred(current_cred());
+	struct common_audit_data ad;
+	struct inode_security_struct *isec;
+	int rc;
+
+	if (unlikely(!selinux_state.initialized))
+		return 0;
+
+	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.
+	 */
+
+	if (context_inode) {
+		struct inode_security_struct *context_isec =
+			selinux_inode(context_inode);
+		isec->sclass = context_isec->sclass;
+		isec->sid = context_isec->sid;
+	} else {
+		isec->sclass = SECCLASS_ANON_INODE;
+		rc = security_transition_sid(
+			&selinux_state, tsec->sid, tsec->sid,
+			SECCLASS_FILE, name, &isec->sid);
+		if (rc)
+			return rc;
+	}
+
+	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 +6976,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..263750b6aaac 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 } },
+	{ "anon_inode",
+	  { COMMON_FILE_PERMS, NULL } },
 	{ NULL }
   };
 
-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v3 3/3] Wire UFFD up to SELinux
  2020-03-26 18:14   ` [PATCH v3 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  2020-03-26 18:14     ` [PATCH v3 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
  2020-03-26 18:14     ` [PATCH v3 2/3] Teach SELinux about anonymous inodes Daniel Colascione
@ 2020-03-26 18:14     ` Daniel Colascione
  2020-03-26 20:06     ` [PATCH v4 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  3 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-03-26 18:14 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

This change gives userfaultfd file descriptors a real security
context, allowing policy to act on them.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 fs/userfaultfd.c | 34 +++++++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 07b0f6e03849..78ff5d898733 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -76,6 +76,8 @@ struct userfaultfd_ctx {
 	bool mmap_changing;
 	/* mm with one ore more vmas attached to this userfaultfd_ctx */
 	struct mm_struct *mm;
+	/* The inode that owns this context --- not a strong reference.  */
+	const struct inode *owner;
 };
 
 struct userfaultfd_fork_ctx {
@@ -1014,14 +1016,18 @@ 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)
 {
 	int fd;
 
-	fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, new,
-			      O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS));
+	fd = anon_inode_getfd_secure(
+		"[userfaultfd]", &userfaultfd_fops, new,
+		O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS),
+		ctx->owner);
 	if (fd < 0)
 		return fd;
 
@@ -1918,7 +1924,7 @@ static void userfaultfd_show_fdinfo(struct seq_file *m, struct file *f)
 }
 #endif
 
-const struct file_operations userfaultfd_fops = {
+static const struct file_operations userfaultfd_fops = {
 #ifdef CONFIG_PROC_FS
 	.show_fdinfo	= userfaultfd_show_fdinfo,
 #endif
@@ -1943,6 +1949,7 @@ static void init_once_userfaultfd_ctx(void *mem)
 
 SYSCALL_DEFINE1(userfaultfd, int, flags)
 {
+	struct file *file;
 	struct userfaultfd_ctx *ctx;
 	int fd;
 
@@ -1972,8 +1979,25 @@ 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));
+	file = anon_inode_getfile_secure(
+		"[userfaultfd]", &userfaultfd_fops, ctx,
+		O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS),
+		NULL);
+	if (IS_ERR(file)) {
+		fd = PTR_ERR(file);
+		goto out;
+	}
+
+	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
+	if (fd < 0) {
+		fput(file);
+		goto out;
+	}
+
+	ctx->owner = file_inode(file);
+	fd_install(fd, file);
+
+out:
 	if (fd < 0) {
 		mmdrop(ctx->mm);
 		kmem_cache_free(userfaultfd_ctx_cachep, ctx);
-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v3 1/3] Add a new LSM-supporting anonymous inode interface
  2020-03-26 18:14     ` [PATCH v3 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
@ 2020-03-26 19:00       ` Stephen Smalley
  0 siblings, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-03-26 19:00 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, selinux, linux-security-module,
	linux-fsdevel, linux-kernel, kvm, viro, paul, nnk, lokeshgidra,
	jmorris

On 3/26/20 2:14 PM, Daniel Colascione wrote:
> This change adds two new functions, anon_inode_getfile_secure and
> anon_inode_getfd_secure, that create anonymous-node files with
> individual non-S_PRIVATE inodes to which security modules can apply
> policy. Existing callers continue using the original singleton-inode
> kind of anonymous-inode file. We can transition anonymous inode users
> to the new kind of anonymous inode in individual patches for the sake
> of bisection and review.
> 
> The new functions accept an optional context_inode parameter that
> callers can use to provide additional contextual information to
> security modules, e.g., indicating that one anonymous struct file is a
> logical child of another, allowing a security model to propagate
> security information from one to the other.
> 
> Signed-off-by: Daniel Colascione <dancol@google.com>
> ---

Repeating verbatim what I said on v2 of patch 1/3.

> diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
> index 89714308c25b..114a04fc1db4 100644
> --- a/fs/anon_inodes.c
> +++ b/fs/anon_inodes.c
> @@ -55,75 +55,135 @@ static struct file_system_type anon_inode_fs_type = {
>   	.kill_sb	= kill_anon_super,
>   };
>   
> -/**
> - * 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
> - *
> - * @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
> - *
> - * Creates a new file by hooking it on a single 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.
> - */
> -struct file *anon_inode_getfile(const char *name,
> -				const struct file_operations *fops,
> -				void *priv, int flags)
> +static struct inode *anon_inode_make_secure_inode(
> +	const char *name,
> +	const struct inode *context_inode,
> +	const struct file_operations *fops)
> +{
> +	struct inode *inode;
> +	const struct qstr qname = QSTR_INIT(name, strlen(name));
> +	int error;
> +
> +	inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
> +	if (IS_ERR(inode))
> +		return ERR_PTR(PTR_ERR(inode));

Just return inode here ?

> +	inode->i_flags &= ~S_PRIVATE;
> +	error =	security_inode_init_security_anon(
> +		inode, &qname, fops, context_inode);

Would drop fops argument until we have a real user for it; we can always 
add it later.

> 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

These changes are unnecessary for this patch and reverted by patch 3, so 
drop them here.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v3 2/3] Teach SELinux about anonymous inodes
  2020-03-26 18:14     ` [PATCH v3 2/3] Teach SELinux about anonymous inodes Daniel Colascione
@ 2020-03-26 19:02       ` Stephen Smalley
  0 siblings, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-03-26 19:02 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, selinux, linux-security-module,
	linux-fsdevel, linux-kernel, kvm, viro, paul, nnk, lokeshgidra,
	jmorris

On 3/26/20 2:14 PM, Daniel Colascione wrote:
> This change uses the anon_inodes and LSM infrastructure introduced in
> the previous patch to give SELinux the ability to control
> anonymous-inode files that are created using the new _secure()
> anon_inodes functions.
> 
> A SELinux policy author detects and controls these anonymous inodes by
> adding a name-based type_transition rule that assigns a new security
> type to anonymous-inode files created in some domain. The name used
> for the name-based transition is the name associated with the
> anonymous inode for file listings --- e.g., "[userfaultfd]" or
> "[perf_event]".
> 
> Example:
> 
> type uffd_t;
> type_transition sysadm_t sysadm_t : anon_inode uffd_t "[userfaultfd]";
> allow sysadm_t uffd_t:anon_inode { create };
> 
> (The next patch in this series is necessary for making userfaultfd
> support this new interface.  The example above is just
> for exposition.)
> 
> Signed-off-by: Daniel Colascione <dancol@google.com>
> ---
>   security/selinux/hooks.c            | 54 +++++++++++++++++++++++++++++
>   security/selinux/include/classmap.h |  2 ++
>   2 files changed, 56 insertions(+)
> 
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 1659b59fb5d7..b9eb45c2e4e5 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2915,6 +2915,59 @@ 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 struct qstr *name,
> +					    const struct file_operations *fops,
> +					    const struct inode *context_inode)
> +{
> +	const struct task_security_struct *tsec = selinux_cred(current_cred());
> +	struct common_audit_data ad;
> +	struct inode_security_struct *isec;
> +	int rc;
> +
> +	if (unlikely(!selinux_state.initialized))
> +		return 0;
> +
> +	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.
> +	 */
> +
> +	if (context_inode) {
> +		struct inode_security_struct *context_isec =
> +			selinux_inode(context_inode);
> +		isec->sclass = context_isec->sclass;
> +		isec->sid = context_isec->sid;
> +	} else {
> +		isec->sclass = SECCLASS_ANON_INODE;
> +		rc = security_transition_sid(
> +			&selinux_state, tsec->sid, tsec->sid,
> +			SECCLASS_FILE, name, &isec->sid);

I guess you missed the 2nd comment in my reply to v2 of this patch:
You should use isec->sclass aka SECCLASS_ANON_INODE instead of 
SECCLASS_FILE here.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v4 0/3] SELinux support for anonymous inodes and UFFD
  2020-03-26 18:14   ` [PATCH v3 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
                       ` (2 preceding siblings ...)
  2020-03-26 18:14     ` [PATCH v3 3/3] Wire UFFD up to SELinux Daniel Colascione
@ 2020-03-26 20:06     ` Daniel Colascione
  2020-03-26 20:06       ` [PATCH v4 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
                         ` (3 more replies)
  3 siblings, 4 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-03-26 20:06 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

Userfaultfd in unprivileged contexts could be potentially very
useful. We'd like to harden userfaultfd to make such unprivileged use
less risky. This patch series allows SELinux to manage userfaultfd
file descriptors and in the future, other kinds of
anonymous-inode-based file descriptor.  SELinux policy authors can
apply policy types to anonymous inodes by providing name-based
transition rules keyed off the anonymous inode internal name (
"[userfaultfd]" in the case of userfaultfd(2) file descriptors) and
applying policy to the new SIDs thus produced.

Inside the kernel, a pair of new anon_inodes interface,
anon_inode_getfile_secure and anon_inode_getfd_secure, allow callers
to opt into this SELinux management. In this new "secure" mode,
anon_inodes creates new ephemeral inodes for anonymous file objects
instead of reusing the normal anon_inodes singleton dummy inode. A new
LSM hook gives security modules an opportunity to configure and veto
these ephemeral inodes.

This patch series is one of two fork of [1] and is an
alternative to [2].

The primary difference between the two patch series is that this
partch series creates a unique inode for each "secure" anonymous
inode, while the other patch series ([2]) continues using the
singleton dummy anonymous inode and adds a way to attach SELinux
security information directly to file objects.

I prefer the approach in this patch series because 1) it's a smaller
patch than [2], and 2) it produces a more regular security
architecture: in this patch series, secure anonymous inodes aren't
S_PRIVATE and they maintain the SELinux property that the label for a
file is in its inode. We do need an additional inode per anonymous
file, but per-struct-file inode creation doesn't seem to be a problem
for pipes and sockets.

The previous version of this feature ([1]) created a new SELinux
security class for userfaultfd file descriptors. This version adopts
the generic transition-based approach of [2].

This patch series also differs from [2] in that it doesn't affect all
anonymous inodes right away --- instead requiring anon_inodes callers
to opt in --- but this difference isn't one of basic approach. The
important question to resolve is whether we should be creating new
inodes or enhancing per-file data.

Changes from the first version of the patch:

  - Removed some error checks
  - Defined a new anon_inode SELinux class to resolve the
    ambiguity in [3]
  - Inherit sclass as well as descriptor from context inode

Changes from the second version of the patch:

  - Fixed example policy in the commit message to reflect the use of
    the new anon_inode class.

Changes from the third version of the patch:

  - Dropped the fops parameter to the LSM hook
  - Documented hook parameters
  - Fixed incorrect class used for SELinux transition
  - Removed stray UFFD changed early in the series
  - Removed a redundant ERR_PTR(PTR_ERR())

[1] https://lore.kernel.org/lkml/20200211225547.235083-1-dancol@google.com/
[2] https://lore.kernel.org/linux-fsdevel/20200213194157.5877-1-sds@tycho.nsa.gov/
[3] https://lore.kernel.org/lkml/23f725ca-5b5a-5938-fcc8-5bbbfc9ba9bc@tycho.nsa.gov/

Daniel Colascione (3):
  Add a new LSM-supporting anonymous inode interface
  Teach SELinux about anonymous inodes
  Wire UFFD up to SELinux

 fs/anon_inodes.c                    | 196 ++++++++++++++++++++++------
 fs/userfaultfd.c                    |  30 ++++-
 include/linux/anon_inodes.h         |  13 ++
 include/linux/lsm_hooks.h           |  11 ++
 include/linux/security.h            |   3 +
 security/security.c                 |   9 ++
 security/selinux/hooks.c            |  53 ++++++++
 security/selinux/include/classmap.h |   2 +
 8 files changed, 271 insertions(+), 46 deletions(-)

-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v4 1/3] Add a new LSM-supporting anonymous inode interface
  2020-03-26 20:06     ` [PATCH v4 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
@ 2020-03-26 20:06       ` Daniel Colascione
  2020-03-27 13:40         ` Stephen Smalley
  2020-03-26 20:06       ` [PATCH v4 2/3] Teach SELinux about anonymous inodes Daniel Colascione
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-03-26 20:06 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

This change adds two new functions, anon_inode_getfile_secure and
anon_inode_getfd_secure, that create anonymous-node files with
individual non-S_PRIVATE inodes to which security modules can apply
policy. Existing callers continue using the original singleton-inode
kind of anonymous-inode file. We can transition anonymous inode users
to the new kind of anonymous inode in individual patches for the sake
of bisection and review.

The new functions accept an optional context_inode parameter that
callers can use to provide additional contextual information to
security modules, e.g., indicating that one anonymous struct file is a
logical child of another, allowing a security model to propagate
security information from one to the other.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 fs/anon_inodes.c            | 196 ++++++++++++++++++++++++++++--------
 include/linux/anon_inodes.h |  13 +++
 include/linux/lsm_hooks.h   |  11 ++
 include/linux/security.h    |   3 +
 security/security.c         |   9 ++
 5 files changed, 190 insertions(+), 42 deletions(-)

diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 89714308c25b..024059e333dc 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -55,75 +55,135 @@ static struct file_system_type anon_inode_fs_type = {
 	.kill_sb	= kill_anon_super,
 };
 
-/**
- * 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
- *
- * @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
- *
- * Creates a new file by hooking it on a single 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.
- */
-struct file *anon_inode_getfile(const char *name,
-				const struct file_operations *fops,
-				void *priv, int flags)
+static struct inode *anon_inode_make_secure_inode(
+	const char *name,
+	const struct inode *context_inode,
+	const struct file_operations *fops)
+{
+	struct inode *inode;
+	const struct qstr qname = QSTR_INIT(name, strlen(name));
+	int error;
+
+	inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
+	if (IS_ERR(inode))
+		return inode;
+	inode->i_flags &= ~S_PRIVATE;
+	error =	security_inode_init_security_anon(
+		inode, &qname, context_inode);
+	if (error) {
+		iput(inode);
+		return ERR_PTR(error);
+	}
+	return inode;
+}
+
+struct file *_anon_inode_getfile(const char *name,
+				 const struct file_operations *fops,
+				 void *priv, int flags,
+				 const struct inode *context_inode,
+				 bool secure)
 {
+	struct inode *inode;
 	struct file *file;
 
-	if (IS_ERR(anon_inode_inode))
-		return ERR_PTR(-ENODEV);
+	if (secure) {
+		inode =	anon_inode_make_secure_inode(
+			name, context_inode, 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))
-		return ERR_PTR(-ENOENT);
+	if (fops->owner && !try_module_get(fops->owner)) {
+		file = ERR_PTR(-ENOENT);
+		goto err;
+	}
 
-	/*
-	 * 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,
+	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);
 
 /**
- * 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_getfile_secure - creates a new file instance by hooking
+ *                             it up to a new anonymous inode and a
+ *                             dentry that describe the "class" of the
+ *                             file.  Make it possible to use security
+ *                             modules to control access to the
+ *                             new 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 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_secure() will have distinct inodes, avoiding
+ * code duplication for the file/inode/dentry setup.  Returns the
+ * newly created file* or an error pointer.
+ */
+struct file *anon_inode_getfile_secure(const char *name,
+				       const struct file_operations *fops,
+				       void *priv, int flags,
+				       const struct inode *context_inode)
+{
+	return _anon_inode_getfile(
+		name, fops, priv, flags, context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile_secure);
+
+/**
+ * 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.
+ *
+ * @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 for the file
  *
- * 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_getfd() will share a single inode,
+ * 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 new descriptor or an error code.
+ * setup.  Returns the newly created file* or an error pointer.
  */
-int anon_inode_getfd(const char *name, const struct file_operations *fops,
-		     void *priv, int flags)
+struct file *anon_inode_getfile(const char *name,
+				const struct file_operations *fops,
+				void *priv, int flags)
+{
+	return _anon_inode_getfile(name, fops, priv, flags, NULL, false);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile);
+
+static int _anon_inode_getfd(const char *name,
+			     const struct file_operations *fops,
+			     void *priv, int flags,
+			     const struct inode *context_inode,
+			     bool secure)
 {
 	int error, fd;
 	struct file *file;
@@ -133,7 +193,8 @@ 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_getfile(name, fops, priv, flags, context_inode,
+				   secure);
 	if (IS_ERR(file)) {
 		error = PTR_ERR(file);
 		goto err_put_unused_fd;
@@ -146,6 +207,57 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
 	put_unused_fd(fd);
 	return error;
 }
+
+/**
+ * anon_inode_getfd_secure - creates a new file instance by hooking it
+ *                           up to a new anonymous inode and a dentry
+ *                           that describe the "class" of the file.
+ *                           Make it possible to use security modules
+ *                           to control access to the new 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
+ *
+ * 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_secure() will have distinct inodes, avoiding
+ * code duplication for the file/inode/dentry setup.  Returns a newly
+ * created file descriptor or an error code.
+ */
+int anon_inode_getfd_secure(const char *name, const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode)
+{
+	return _anon_inode_getfd(name, fops, priv, flags,
+				 context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfd_secure);
+
+/**
+ * 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
+ *
+ * @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
+ *
+ * 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 use the same singleton inode, reducing
+ * memory use and avoiding code duplication for the file/inode/dentry
+ * setup.  Returns a newly created file descriptor or an error code.
+ */
+int anon_inode_getfd(const char *name, const struct file_operations *fops,
+		     void *priv, int flags)
+{
+	return _anon_inode_getfd(name, fops, priv, flags, NULL, false);
+}
 EXPORT_SYMBOL_GPL(anon_inode_getfd);
 
 static int __init anon_inode_init(void)
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
index d0d7d96261ad..67bd85d92dca 100644
--- a/include/linux/anon_inodes.h
+++ b/include/linux/anon_inodes.h
@@ -10,12 +10,25 @@
 #define _LINUX_ANON_INODES_H
 
 struct file_operations;
+struct inode;
+
+struct file *anon_inode_getfile_secure(const char *name,
+				       const struct file_operations *fops,
+				       void *priv, int flags,
+				       const struct inode *context_inode);
 
 struct file *anon_inode_getfile(const char *name,
 				const struct file_operations *fops,
 				void *priv, int flags);
+
+int anon_inode_getfd_secure(const char *name,
+			    const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode);
+
 int anon_inode_getfd(const char *name, const struct file_operations *fops,
 		     void *priv, int flags);
 
+
 #endif /* _LINUX_ANON_INODES_H */
 
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 20d8cf194fb7..5434c1d285b2 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -215,6 +215,13 @@
  *	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.
+ *      @inode contains the inode structure
+ *      @name name of the anonymous inode class
+ *      @context_inode optional related 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 +1559,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 struct qstr *name,
+					const struct inode *context_inode);
 	int (*inode_create)(struct inode *dir, struct dentry *dentry,
 				umode_t mode);
 	int (*inode_link)(struct dentry *old_dentry, struct inode *dir,
@@ -1884,6 +1894,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..2108c3ce0666 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -320,6 +320,9 @@ 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 struct qstr *name,
+				      const struct inode *context_inode);
 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..70bfebada024 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1033,6 +1033,15 @@ 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 struct qstr *name,
+				  const struct inode *context_inode)
+{
+	return call_int_hook(inode_init_security_anon, 0, inode, name,
+			     context_inode);
+}
+
 int security_old_inode_init_security(struct inode *inode, struct inode *dir,
 				     const struct qstr *qstr, const char **name,
 				     void **value, size_t *len)
-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v4 2/3] Teach SELinux about anonymous inodes
  2020-03-26 20:06     ` [PATCH v4 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  2020-03-26 20:06       ` [PATCH v4 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
@ 2020-03-26 20:06       ` Daniel Colascione
  2020-03-27 13:41         ` Stephen Smalley
  2020-03-26 20:06       ` [PATCH v4 3/3] Wire UFFD up to SELinux Daniel Colascione
  2020-04-01 21:39       ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  3 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-03-26 20:06 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

This change uses the anon_inodes and LSM infrastructure introduced in
the previous patch to give SELinux the ability to control
anonymous-inode files that are created using the new _secure()
anon_inodes functions.

A SELinux policy author detects and controls these anonymous inodes by
adding a name-based type_transition rule that assigns a new security
type to anonymous-inode files created in some domain. The name used
for the name-based transition is the name associated with the
anonymous inode for file listings --- e.g., "[userfaultfd]" or
"[perf_event]".

Example:

type uffd_t;
type_transition sysadm_t sysadm_t : anon_inode uffd_t "[userfaultfd]";
allow sysadm_t uffd_t:anon_inode { create };

(The next patch in this series is necessary for making userfaultfd
support this new interface.  The example above is just
for exposition.)

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 security/selinux/hooks.c            | 53 +++++++++++++++++++++++++++++
 security/selinux/include/classmap.h |  2 ++
 2 files changed, 55 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1659b59fb5d7..6f7222d2e404 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2915,6 +2915,58 @@ 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 struct qstr *name,
+					    const struct inode *context_inode)
+{
+	const struct task_security_struct *tsec = selinux_cred(current_cred());
+	struct common_audit_data ad;
+	struct inode_security_struct *isec;
+	int rc;
+
+	if (unlikely(!selinux_state.initialized))
+		return 0;
+
+	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.
+	 */
+
+	if (context_inode) {
+		struct inode_security_struct *context_isec =
+			selinux_inode(context_inode);
+		isec->sclass = context_isec->sclass;
+		isec->sid = context_isec->sid;
+	} else {
+		isec->sclass = SECCLASS_ANON_INODE;
+		rc = security_transition_sid(
+			&selinux_state, tsec->sid, tsec->sid,
+			isec->sclass, name, &isec->sid);
+		if (rc)
+			return rc;
+	}
+
+	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 +6975,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..263750b6aaac 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 } },
+	{ "anon_inode",
+	  { COMMON_FILE_PERMS, NULL } },
 	{ NULL }
   };
 
-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v4 3/3] Wire UFFD up to SELinux
  2020-03-26 20:06     ` [PATCH v4 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  2020-03-26 20:06       ` [PATCH v4 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
  2020-03-26 20:06       ` [PATCH v4 2/3] Teach SELinux about anonymous inodes Daniel Colascione
@ 2020-03-26 20:06       ` Daniel Colascione
  2020-04-01 21:39       ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  3 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-03-26 20:06 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

This change gives userfaultfd file descriptors a real security
context, allowing policy to act on them.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 fs/userfaultfd.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 37df7c9eedb1..78ff5d898733 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -76,6 +76,8 @@ struct userfaultfd_ctx {
 	bool mmap_changing;
 	/* mm with one ore more vmas attached to this userfaultfd_ctx */
 	struct mm_struct *mm;
+	/* The inode that owns this context --- not a strong reference.  */
+	const struct inode *owner;
 };
 
 struct userfaultfd_fork_ctx {
@@ -1022,8 +1024,10 @@ static int resolve_userfault_fork(struct userfaultfd_ctx *ctx,
 {
 	int fd;
 
-	fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, new,
-			      O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS));
+	fd = anon_inode_getfd_secure(
+		"[userfaultfd]", &userfaultfd_fops, new,
+		O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS),
+		ctx->owner);
 	if (fd < 0)
 		return fd;
 
@@ -1945,6 +1949,7 @@ static void init_once_userfaultfd_ctx(void *mem)
 
 SYSCALL_DEFINE1(userfaultfd, int, flags)
 {
+	struct file *file;
 	struct userfaultfd_ctx *ctx;
 	int fd;
 
@@ -1974,8 +1979,25 @@ 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));
+	file = anon_inode_getfile_secure(
+		"[userfaultfd]", &userfaultfd_fops, ctx,
+		O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS),
+		NULL);
+	if (IS_ERR(file)) {
+		fd = PTR_ERR(file);
+		goto out;
+	}
+
+	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
+	if (fd < 0) {
+		fput(file);
+		goto out;
+	}
+
+	ctx->owner = file_inode(file);
+	fd_install(fd, file);
+
+out:
 	if (fd < 0) {
 		mmdrop(ctx->mm);
 		kmem_cache_free(userfaultfd_ctx_cachep, ctx);
-- 
2.25.1.696.g5e7596f4ac-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v4 1/3] Add a new LSM-supporting anonymous inode interface
  2020-03-26 20:06       ` [PATCH v4 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
@ 2020-03-27 13:40         ` Stephen Smalley
  0 siblings, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-03-27 13:40 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, selinux, linux-security-module,
	linux-fsdevel, linux-kernel, kvm, viro, paul, nnk, lokeshgidra,
	jmorris

On 3/26/20 4:06 PM, Daniel Colascione wrote:
> This change adds two new functions, anon_inode_getfile_secure and
> anon_inode_getfd_secure, that create anonymous-node files with
> individual non-S_PRIVATE inodes to which security modules can apply
> policy. Existing callers continue using the original singleton-inode
> kind of anonymous-inode file. We can transition anonymous inode users
> to the new kind of anonymous inode in individual patches for the sake
> of bisection and review.
> 
> The new functions accept an optional context_inode parameter that
> callers can use to provide additional contextual information to
> security modules, e.g., indicating that one anonymous struct file is a
> logical child of another, allowing a security model to propagate
> security information from one to the other.
> 
> Signed-off-by: Daniel Colascione <dancol@google.com>
> ---

> diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
> index 89714308c25b..024059e333dc 100644
> --- a/fs/anon_inodes.c
> +++ b/fs/anon_inodes.c
> @@ -55,75 +55,135 @@ static struct file_system_type anon_inode_fs_type = {
> +static struct inode *anon_inode_make_secure_inode(
> +	const char *name,
> +	const struct inode *context_inode,
> +	const struct file_operations *fops)

fops argument can be removed here too, unused now by this function.

>   /**
> - * 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_getfile_secure - creates a new file instance by hooking
> + *                             it up to a new anonymous inode and a
> + *                             dentry that describe the "class" of the
> + *                             file.  Make it possible to use security
> + *                             modules to control access to the
> + *                             new 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*

anon_inode_flags leftover from prior version of the patch, not an 
argument in the current code.  Likewise, the "for the file" addendum to 
the @flags argument description is a leftover and not needed.

 > + * 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_secure() will have distinct inodes, avoiding
 > + * code duplication for the file/inode/dentry setup.

The two preceding sentences directly contradict each other.

> +/**
> + * 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.

This would be identical to the original except for different word 
wrapping.  Probably a leftover from prior version of the patch where you 
were modifying the existing interface.  Recommend reverting such changes 
to minimize unnecessary noise in your diff and meke it easier to tell 
what changes are real.

> + *
> + * @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 for the file
>    *
> - * 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

Unnecessary difference here; this interface does use a single inode.

> @@ -146,6 +207,57 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
>   	put_unused_fd(fd);
>   	return error;
>   }
> +
> +/**
> + * anon_inode_getfd_secure - creates a new file instance by hooking it
> + *                           up to a new anonymous inode and a dentry
> + *                           that describe the "class" of the file.
> + *                           Make it possible to use security modules
> + *                           to control access to the new 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
> + *
 > + * 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_secure() will have distinct inodes, avoiding
 > + * code duplication for the file/inode/dentry setup.

The two preceding sentences contradict each other.


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v4 2/3] Teach SELinux about anonymous inodes
  2020-03-26 20:06       ` [PATCH v4 2/3] Teach SELinux about anonymous inodes Daniel Colascione
@ 2020-03-27 13:41         ` Stephen Smalley
  0 siblings, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-03-27 13:41 UTC (permalink / raw)
  To: Daniel Colascione, timmurray, selinux, linux-security-module,
	linux-fsdevel, linux-kernel, kvm, viro, paul, nnk, lokeshgidra,
	jmorris

On 3/26/20 4:06 PM, Daniel Colascione wrote:
> This change uses the anon_inodes and LSM infrastructure introduced in
> the previous patch to give SELinux the ability to control
> anonymous-inode files that are created using the new _secure()
> anon_inodes functions.
> 
> A SELinux policy author detects and controls these anonymous inodes by
> adding a name-based type_transition rule that assigns a new security
> type to anonymous-inode files created in some domain. The name used
> for the name-based transition is the name associated with the
> anonymous inode for file listings --- e.g., "[userfaultfd]" or
> "[perf_event]".
> 
> Example:
> 
> type uffd_t;
> type_transition sysadm_t sysadm_t : anon_inode uffd_t "[userfaultfd]";
> allow sysadm_t uffd_t:anon_inode { create };
> 
> (The next patch in this series is necessary for making userfaultfd
> support this new interface.  The example above is just
> for exposition.)
> 
> Signed-off-by: Daniel Colascione <dancol@google.com>

Acked-by: Stephen Smalley <sds@tycho.nsa.gov>


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-03-26 20:06     ` [PATCH v4 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
                         ` (2 preceding siblings ...)
  2020-03-26 20:06       ` [PATCH v4 3/3] Wire UFFD up to SELinux Daniel Colascione
@ 2020-04-01 21:39       ` Daniel Colascione
  2020-04-01 21:39         ` [PATCH v5 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
                           ` (3 more replies)
  3 siblings, 4 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-04-01 21:39 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

Userfaultfd in unprivileged contexts could be potentially very
useful. We'd like to harden userfaultfd to make such unprivileged use
less risky. This patch series allows SELinux to manage userfaultfd
file descriptors and in the future, other kinds of
anonymous-inode-based file descriptor.  SELinux policy authors can
apply policy types to anonymous inodes by providing name-based
transition rules keyed off the anonymous inode internal name (
"[userfaultfd]" in the case of userfaultfd(2) file descriptors) and
applying policy to the new SIDs thus produced.

Inside the kernel, a pair of new anon_inodes interface,
anon_inode_getfile_secure and anon_inode_getfd_secure, allow callers
to opt into this SELinux management. In this new "secure" mode,
anon_inodes creates new ephemeral inodes for anonymous file objects
instead of reusing the normal anon_inodes singleton dummy inode. A new
LSM hook gives security modules an opportunity to configure and veto
these ephemeral inodes.

This patch series is one of two fork of [1] and is an
alternative to [2].

The primary difference between the two patch series is that this
partch series creates a unique inode for each "secure" anonymous
inode, while the other patch series ([2]) continues using the
singleton dummy anonymous inode and adds a way to attach SELinux
security information directly to file objects.

I prefer the approach in this patch series because 1) it's a smaller
patch than [2], and 2) it produces a more regular security
architecture: in this patch series, secure anonymous inodes aren't
S_PRIVATE and they maintain the SELinux property that the label for a
file is in its inode. We do need an additional inode per anonymous
file, but per-struct-file inode creation doesn't seem to be a problem
for pipes and sockets.

The previous version of this feature ([1]) created a new SELinux
security class for userfaultfd file descriptors. This version adopts
the generic transition-based approach of [2].

This patch series also differs from [2] in that it doesn't affect all
anonymous inodes right away --- instead requiring anon_inodes callers
to opt in --- but this difference isn't one of basic approach. The
important question to resolve is whether we should be creating new
inodes or enhancing per-file data.

Changes from the first version of the patch:

  - Removed some error checks
  - Defined a new anon_inode SELinux class to resolve the
    ambiguity in [3]
  - Inherit sclass as well as descriptor from context inode

Changes from the second version of the patch:

  - Fixed example policy in the commit message to reflect the use of
    the new anon_inode class.

Changes from the third version of the patch:

  - Dropped the fops parameter to the LSM hook
  - Documented hook parameters
  - Fixed incorrect class used for SELinux transition
  - Removed stray UFFD changed early in the series
  - Removed a redundant ERR_PTR(PTR_ERR())

Changes from the fourth version of the patch:

  - Removed an unused parameter from an internal function
  - Fixed function documentation

[1] https://lore.kernel.org/lkml/20200211225547.235083-1-dancol@google.com/
[2] https://lore.kernel.org/linux-fsdevel/20200213194157.5877-1-sds@tycho.nsa.gov/
[3] https://lore.kernel.org/lkml/23f725ca-5b5a-5938-fcc8-5bbbfc9ba9bc@tycho.nsa.gov/

Daniel Colascione (3):
  Add a new LSM-supporting anonymous inode interface
  Teach SELinux about anonymous inodes
  Wire UFFD up to SELinux

 fs/anon_inodes.c                    | 191 ++++++++++++++++++++++------
 fs/userfaultfd.c                    |  30 ++++-
 include/linux/anon_inodes.h         |  13 ++
 include/linux/lsm_hooks.h           |  11 ++
 include/linux/security.h            |   3 +
 security/security.c                 |   9 ++
 security/selinux/hooks.c            |  53 ++++++++
 security/selinux/include/classmap.h |   2 +
 8 files changed, 267 insertions(+), 45 deletions(-)

-- 
2.26.0.rc2.310.g2932bb562d-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v5 1/3] Add a new LSM-supporting anonymous inode interface
  2020-04-01 21:39       ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
@ 2020-04-01 21:39         ` Daniel Colascione
  2020-05-07 16:02           ` James Morris
  2020-04-01 21:39         ` [PATCH v5 2/3] Teach SELinux about anonymous inodes Daniel Colascione
                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-04-01 21:39 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

This change adds two new functions, anon_inode_getfile_secure and
anon_inode_getfd_secure, that create anonymous-node files with
individual non-S_PRIVATE inodes to which security modules can apply
policy. Existing callers continue using the original singleton-inode
kind of anonymous-inode file. We can transition anonymous inode users
to the new kind of anonymous inode in individual patches for the sake
of bisection and review.

The new functions accept an optional context_inode parameter that
callers can use to provide additional contextual information to
security modules, e.g., indicating that one anonymous struct file is a
logical child of another, allowing a security model to propagate
security information from one to the other.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 fs/anon_inodes.c            | 191 ++++++++++++++++++++++++++++--------
 include/linux/anon_inodes.h |  13 +++
 include/linux/lsm_hooks.h   |  11 +++
 include/linux/security.h    |   3 +
 security/security.c         |   9 ++
 5 files changed, 186 insertions(+), 41 deletions(-)

diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 89714308c25b..f87f221167cf 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -55,61 +55,108 @@ static struct file_system_type anon_inode_fs_type = {
 	.kill_sb	= kill_anon_super,
 };
 
-/**
- * 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
- *
- * @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
- *
- * Creates a new file by hooking it on a single 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.
- */
-struct file *anon_inode_getfile(const char *name,
-				const struct file_operations *fops,
-				void *priv, int flags)
+static struct inode *anon_inode_make_secure_inode(
+	const char *name,
+	const struct inode *context_inode)
+{
+	struct inode *inode;
+	const struct qstr qname = QSTR_INIT(name, strlen(name));
+	int error;
+
+	inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
+	if (IS_ERR(inode))
+		return inode;
+	inode->i_flags &= ~S_PRIVATE;
+	error =	security_inode_init_security_anon(
+		inode, &qname, context_inode);
+	if (error) {
+		iput(inode);
+		return ERR_PTR(error);
+	}
+	return inode;
+}
+
+struct file *_anon_inode_getfile(const char *name,
+				 const struct file_operations *fops,
+				 void *priv, int flags,
+				 const struct inode *context_inode,
+				 bool secure)
 {
+	struct inode *inode;
 	struct file *file;
 
-	if (IS_ERR(anon_inode_inode))
-		return ERR_PTR(-ENODEV);
+	if (secure) {
+		inode =	anon_inode_make_secure_inode(
+			name, context_inode);
+		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))
-		return ERR_PTR(-ENOENT);
+	if (fops->owner && !try_module_get(fops->owner)) {
+		file = ERR_PTR(-ENOENT);
+		goto err;
+	}
 
-	/*
-	 * 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,
+	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);
 
 /**
- * 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_getfile_secure - creates a new file instance by hooking
+ *                             it up to a new anonymous inode and a
+ *                             dentry that describe the "class" of the
+ *                             file.  Make it possible to use security
+ *                             modules to control access to the
+ *                             new 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
+ *
+ * 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 filesystem
+ * to operate correctly.  All the files created with
+ * anon_inode_getfile_secure() will have distinct inodes, avoiding
+ * code duplication for the file/inode/dentry setup.  Returns the
+ * newly created file* or an error pointer.
+ */
+struct file *anon_inode_getfile_secure(const char *name,
+				       const struct file_operations *fops,
+				       void *priv, int flags,
+				       const struct inode *context_inode)
+{
+	return _anon_inode_getfile(
+		name, fops, priv, flags, context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile_secure);
+
+/**
+ * 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
  *
  * @name:    [in]    name of the "class" of the new file
  * @fops:    [in]    file operations for the new file
@@ -118,12 +165,23 @@ EXPORT_SYMBOL_GPL(anon_inode_getfile);
  *
  * Creates a new file by hooking it on a single 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_getfd() will share a single inode,
+ * 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 new descriptor or an error code.
+ * setup.  Returns the newly created file* or an error pointer.
  */
-int anon_inode_getfd(const char *name, const struct file_operations *fops,
-		     void *priv, int flags)
+struct file *anon_inode_getfile(const char *name,
+				const struct file_operations *fops,
+				void *priv, int flags)
+{
+	return _anon_inode_getfile(name, fops, priv, flags, NULL, false);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile);
+
+static int _anon_inode_getfd(const char *name,
+			     const struct file_operations *fops,
+			     void *priv, int flags,
+			     const struct inode *context_inode,
+			     bool secure)
 {
 	int error, fd;
 	struct file *file;
@@ -133,7 +191,8 @@ 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_getfile(name, fops, priv, flags, context_inode,
+				   secure);
 	if (IS_ERR(file)) {
 		error = PTR_ERR(file);
 		goto err_put_unused_fd;
@@ -146,6 +205,57 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
 	put_unused_fd(fd);
 	return error;
 }
+
+/**
+ * anon_inode_getfd_secure - creates a new file instance by hooking it
+ *                           up to a new anonymous inode and a dentry
+ *                           that describe the "class" of the file.
+ *                           Make it possible to use security modules
+ *                           to control access to the new 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
+ *
+ * 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 filesystem
+ * to operate correctly.  All the files created with
+ * anon_inode_getfile_secure() will have distinct inodes, avoiding
+ * code duplication for the file/inode/dentry setup.  Returns a newly
+ * created file descriptor or an error code.
+ */
+int anon_inode_getfd_secure(const char *name, const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode)
+{
+	return _anon_inode_getfd(name, fops, priv, flags,
+				 context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfd_secure);
+
+/**
+ * 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
+ *
+ * @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
+ *
+ * Creates a new file by hooking it on a single 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 use the same singleton inode, reducing
+ * memory use and avoiding code duplication for the file/inode/dentry
+ * setup.  Returns a newly created file descriptor or an error code.
+ */
+int anon_inode_getfd(const char *name, const struct file_operations *fops,
+		     void *priv, int flags)
+{
+	return _anon_inode_getfd(name, fops, priv, flags, NULL, false);
+}
 EXPORT_SYMBOL_GPL(anon_inode_getfd);
 
 static int __init anon_inode_init(void)
@@ -162,4 +272,3 @@ static int __init anon_inode_init(void)
 }
 
 fs_initcall(anon_inode_init);
-
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
index d0d7d96261ad..67bd85d92dca 100644
--- a/include/linux/anon_inodes.h
+++ b/include/linux/anon_inodes.h
@@ -10,12 +10,25 @@
 #define _LINUX_ANON_INODES_H
 
 struct file_operations;
+struct inode;
+
+struct file *anon_inode_getfile_secure(const char *name,
+				       const struct file_operations *fops,
+				       void *priv, int flags,
+				       const struct inode *context_inode);
 
 struct file *anon_inode_getfile(const char *name,
 				const struct file_operations *fops,
 				void *priv, int flags);
+
+int anon_inode_getfd_secure(const char *name,
+			    const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode);
+
 int anon_inode_getfd(const char *name, const struct file_operations *fops,
 		     void *priv, int flags);
 
+
 #endif /* _LINUX_ANON_INODES_H */
 
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 20d8cf194fb7..5434c1d285b2 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -215,6 +215,13 @@
  *	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.
+ *      @inode contains the inode structure
+ *      @name name of the anonymous inode class
+ *      @context_inode optional related 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 +1559,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 struct qstr *name,
+					const struct inode *context_inode);
 	int (*inode_create)(struct inode *dir, struct dentry *dentry,
 				umode_t mode);
 	int (*inode_link)(struct dentry *old_dentry, struct inode *dir,
@@ -1884,6 +1894,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..2108c3ce0666 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -320,6 +320,9 @@ 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 struct qstr *name,
+				      const struct inode *context_inode);
 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..70bfebada024 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1033,6 +1033,15 @@ 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 struct qstr *name,
+				  const struct inode *context_inode)
+{
+	return call_int_hook(inode_init_security_anon, 0, inode, name,
+			     context_inode);
+}
+
 int security_old_inode_init_security(struct inode *inode, struct inode *dir,
 				     const struct qstr *qstr, const char **name,
 				     void **value, size_t *len)
-- 
2.26.0.rc2.310.g2932bb562d-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v5 2/3] Teach SELinux about anonymous inodes
  2020-04-01 21:39       ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  2020-04-01 21:39         ` [PATCH v5 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
@ 2020-04-01 21:39         ` Daniel Colascione
  2020-04-01 21:39         ` [PATCH v5 3/3] Wire UFFD up to SELinux Daniel Colascione
  2020-04-13 13:29         ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  3 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-04-01 21:39 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

This change uses the anon_inodes and LSM infrastructure introduced in
the previous patch to give SELinux the ability to control
anonymous-inode files that are created using the new _secure()
anon_inodes functions.

A SELinux policy author detects and controls these anonymous inodes by
adding a name-based type_transition rule that assigns a new security
type to anonymous-inode files created in some domain. The name used
for the name-based transition is the name associated with the
anonymous inode for file listings --- e.g., "[userfaultfd]" or
"[perf_event]".

Example:

type uffd_t;
type_transition sysadm_t sysadm_t : anon_inode uffd_t "[userfaultfd]";
allow sysadm_t uffd_t:anon_inode { create };

(The next patch in this series is necessary for making userfaultfd
support this new interface.  The example above is just
for exposition.)

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 security/selinux/hooks.c            | 53 +++++++++++++++++++++++++++++
 security/selinux/include/classmap.h |  2 ++
 2 files changed, 55 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1659b59fb5d7..6f7222d2e404 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2915,6 +2915,58 @@ 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 struct qstr *name,
+					    const struct inode *context_inode)
+{
+	const struct task_security_struct *tsec = selinux_cred(current_cred());
+	struct common_audit_data ad;
+	struct inode_security_struct *isec;
+	int rc;
+
+	if (unlikely(!selinux_state.initialized))
+		return 0;
+
+	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.
+	 */
+
+	if (context_inode) {
+		struct inode_security_struct *context_isec =
+			selinux_inode(context_inode);
+		isec->sclass = context_isec->sclass;
+		isec->sid = context_isec->sid;
+	} else {
+		isec->sclass = SECCLASS_ANON_INODE;
+		rc = security_transition_sid(
+			&selinux_state, tsec->sid, tsec->sid,
+			isec->sclass, name, &isec->sid);
+		if (rc)
+			return rc;
+	}
+
+	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 +6975,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..263750b6aaac 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 } },
+	{ "anon_inode",
+	  { COMMON_FILE_PERMS, NULL } },
 	{ NULL }
   };
 
-- 
2.26.0.rc2.310.g2932bb562d-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH v5 3/3] Wire UFFD up to SELinux
  2020-04-01 21:39       ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  2020-04-01 21:39         ` [PATCH v5 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
  2020-04-01 21:39         ` [PATCH v5 2/3] Teach SELinux about anonymous inodes Daniel Colascione
@ 2020-04-01 21:39         ` Daniel Colascione
  2020-04-13 13:29         ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
  3 siblings, 0 replies; 75+ messages in thread
From: Daniel Colascione @ 2020-04-01 21:39 UTC (permalink / raw)
  To: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, viro, paul, nnk, sds, lokeshgidra, jmorris
  Cc: Daniel Colascione

This change gives userfaultfd file descriptors a real security
context, allowing policy to act on them.

Signed-off-by: Daniel Colascione <dancol@google.com>
---
 fs/userfaultfd.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 37df7c9eedb1..78ff5d898733 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -76,6 +76,8 @@ struct userfaultfd_ctx {
 	bool mmap_changing;
 	/* mm with one ore more vmas attached to this userfaultfd_ctx */
 	struct mm_struct *mm;
+	/* The inode that owns this context --- not a strong reference.  */
+	const struct inode *owner;
 };
 
 struct userfaultfd_fork_ctx {
@@ -1022,8 +1024,10 @@ static int resolve_userfault_fork(struct userfaultfd_ctx *ctx,
 {
 	int fd;
 
-	fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, new,
-			      O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS));
+	fd = anon_inode_getfd_secure(
+		"[userfaultfd]", &userfaultfd_fops, new,
+		O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS),
+		ctx->owner);
 	if (fd < 0)
 		return fd;
 
@@ -1945,6 +1949,7 @@ static void init_once_userfaultfd_ctx(void *mem)
 
 SYSCALL_DEFINE1(userfaultfd, int, flags)
 {
+	struct file *file;
 	struct userfaultfd_ctx *ctx;
 	int fd;
 
@@ -1974,8 +1979,25 @@ 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));
+	file = anon_inode_getfile_secure(
+		"[userfaultfd]", &userfaultfd_fops, ctx,
+		O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS),
+		NULL);
+	if (IS_ERR(file)) {
+		fd = PTR_ERR(file);
+		goto out;
+	}
+
+	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
+	if (fd < 0) {
+		fput(file);
+		goto out;
+	}
+
+	ctx->owner = file_inode(file);
+	fd_install(fd, file);
+
+out:
 	if (fd < 0) {
 		mmdrop(ctx->mm);
 		kmem_cache_free(userfaultfd_ctx_cachep, ctx);
-- 
2.26.0.rc2.310.g2932bb562d-goog


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-04-01 21:39       ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
                           ` (2 preceding siblings ...)
  2020-04-01 21:39         ` [PATCH v5 3/3] Wire UFFD up to SELinux Daniel Colascione
@ 2020-04-13 13:29         ` Daniel Colascione
  2020-04-22 16:55           ` James Morris
  3 siblings, 1 reply; 75+ messages in thread
From: Daniel Colascione @ 2020-04-13 13:29 UTC (permalink / raw)
  To: Tim Murray, SElinux list, LSM List, Linux FS Devel, linux-kernel,
	kvm, Al Viro, Paul Moore, Nick Kralevich, Stephen Smalley,
	Lokesh Gidra, jmorris

On Wed, Apr 1, 2020 at 2:39 PM Daniel Colascione <dancol@google.com> wrote:
>
> Changes from the fourth version of the patch:


Is there anything else that needs to be done before merging this patch series?

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-04-13 13:29         ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
@ 2020-04-22 16:55           ` James Morris
  2020-04-22 17:12             ` Casey Schaufler
  2020-04-27 17:15             ` Casey Schaufler
  0 siblings, 2 replies; 75+ messages in thread
From: James Morris @ 2020-04-22 16:55 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: Tim Murray, SElinux list, LSM List, Linux FS Devel, linux-kernel,
	kvm, Al Viro, Paul Moore, Nick Kralevich, Stephen Smalley,
	Lokesh Gidra, John Johansen, Casey Schaufler

On Mon, 13 Apr 2020, Daniel Colascione wrote:

> On Wed, Apr 1, 2020 at 2:39 PM Daniel Colascione <dancol@google.com> wrote:
> >
> > Changes from the fourth version of the patch:
> 
> 
> Is there anything else that needs to be done before merging this patch series?

The vfs changes need review and signoff from the vfs folk, the SELinux 
changes by either Paul or Stephen, and we also need signoff on the LSM 
hooks from other major LSM authors (Casey and John, at a minimum).


-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-04-22 16:55           ` James Morris
@ 2020-04-22 17:12             ` Casey Schaufler
  2020-04-23 22:24               ` Casey Schaufler
  2020-04-27 17:15             ` Casey Schaufler
  1 sibling, 1 reply; 75+ messages in thread
From: Casey Schaufler @ 2020-04-22 17:12 UTC (permalink / raw)
  To: James Morris, Daniel Colascione
  Cc: Tim Murray, SElinux list, LSM List, Linux FS Devel, linux-kernel,
	kvm, Al Viro, Paul Moore, Nick Kralevich, Stephen Smalley,
	Lokesh Gidra, John Johansen, Casey Schaufler

On 4/22/2020 9:55 AM, James Morris wrote:
> On Mon, 13 Apr 2020, Daniel Colascione wrote:
>
>> On Wed, Apr 1, 2020 at 2:39 PM Daniel Colascione <dancol@google.com> wrote:
>>> Changes from the fourth version of the patch:
>>
>> Is there anything else that needs to be done before merging this patch series?
> The vfs changes need review and signoff from the vfs folk, the SELinux 
> changes by either Paul or Stephen, and we also need signoff on the LSM 
> hooks from other major LSM authors (Casey and John, at a minimum).

I haven't had the opportunity to test this relative to Smack.
It's unclear whether the change would impact security modules that
don't provide hooks for it. I will bump my priority on this, but it's
still going to be a bit before I can get to it.


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-04-22 17:12             ` Casey Schaufler
@ 2020-04-23 22:24               ` Casey Schaufler
  2020-04-27 16:18                 ` Casey Schaufler
  0 siblings, 1 reply; 75+ messages in thread
From: Casey Schaufler @ 2020-04-23 22:24 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: James Morris, Tim Murray, SElinux list, LSM List, Linux FS Devel,
	linux-kernel, kvm, Al Viro, Paul Moore, Nick Kralevich,
	Stephen Smalley, Lokesh Gidra, John Johansen, Casey Schaufler

On 4/22/2020 10:12 AM, Casey Schaufler wrote:
> On 4/22/2020 9:55 AM, James Morris wrote:
>> On Mon, 13 Apr 2020, Daniel Colascione wrote:
>>
>>> On Wed, Apr 1, 2020 at 2:39 PM Daniel Colascione <dancol@google.com> wrote:
>>>> Changes from the fourth version of the patch:
>>> Is there anything else that needs to be done before merging this patch series?

Do you have a test case that exercises this feature?


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-04-23 22:24               ` Casey Schaufler
@ 2020-04-27 16:18                 ` Casey Schaufler
  2020-04-27 16:48                   ` Stephen Smalley
  0 siblings, 1 reply; 75+ messages in thread
From: Casey Schaufler @ 2020-04-27 16:18 UTC (permalink / raw)
  To: Daniel Colascione
  Cc: James Morris, Tim Murray, SElinux list, LSM List, Linux FS Devel,
	linux-kernel, kvm, Al Viro, Paul Moore, Nick Kralevich,
	Stephen Smalley, Lokesh Gidra, John Johansen, Casey Schaufler

On 4/23/2020 3:24 PM, Casey Schaufler wrote:
> On 4/22/2020 10:12 AM, Casey Schaufler wrote:
>> On 4/22/2020 9:55 AM, James Morris wrote:
>>> On Mon, 13 Apr 2020, Daniel Colascione wrote:
>>>
>>>> On Wed, Apr 1, 2020 at 2:39 PM Daniel Colascione <dancol@google.com> wrote:
>>>>> Changes from the fourth version of the patch:
>>>> Is there anything else that needs to be done before merging this patch series?
> Do you have a test case that exercises this feature?

I haven't heard anything back. What would cause this code to be executed?



^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-04-27 16:18                 ` Casey Schaufler
@ 2020-04-27 16:48                   ` Stephen Smalley
  2020-04-27 17:12                     ` Casey Schaufler
  2020-04-29 17:02                     ` Stephen Smalley
  0 siblings, 2 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-04-27 16:48 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Daniel Colascione, James Morris, Tim Murray, SElinux list,
	LSM List, Linux FS Devel, linux-kernel, kvm, Al Viro, Paul Moore,
	Nick Kralevich, Stephen Smalley, Lokesh Gidra, John Johansen

On Mon, Apr 27, 2020 at 12:19 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>
> On 4/23/2020 3:24 PM, Casey Schaufler wrote:
> > On 4/22/2020 10:12 AM, Casey Schaufler wrote:
> >> On 4/22/2020 9:55 AM, James Morris wrote:
> >>> On Mon, 13 Apr 2020, Daniel Colascione wrote:
> >>>
> >>>> On Wed, Apr 1, 2020 at 2:39 PM Daniel Colascione <dancol@google.com> wrote:
> >>>>> Changes from the fourth version of the patch:
> >>>> Is there anything else that needs to be done before merging this patch series?
> > Do you have a test case that exercises this feature?
>
> I haven't heard anything back. What would cause this code to be executed?

See https://lore.kernel.org/selinux/513f6230-1fb3-dbb5-5f75-53cd02b91b28@tycho.nsa.gov/
for example.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-04-27 16:48                   ` Stephen Smalley
@ 2020-04-27 17:12                     ` Casey Schaufler
  2020-04-29 17:02                     ` Stephen Smalley
  1 sibling, 0 replies; 75+ messages in thread
From: Casey Schaufler @ 2020-04-27 17:12 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Daniel Colascione, James Morris, Tim Murray, SElinux list,
	LSM List, Linux FS Devel, linux-kernel, kvm, Al Viro, Paul Moore,
	Nick Kralevich, Stephen Smalley, Lokesh Gidra, John Johansen

On 4/27/2020 9:48 AM, Stephen Smalley wrote:
> On Mon, Apr 27, 2020 at 12:19 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>> On 4/23/2020 3:24 PM, Casey Schaufler wrote:
>>> On 4/22/2020 10:12 AM, Casey Schaufler wrote:
>>>> On 4/22/2020 9:55 AM, James Morris wrote:
>>>>> On Mon, 13 Apr 2020, Daniel Colascione wrote:
>>>>>
>>>>>> On Wed, Apr 1, 2020 at 2:39 PM Daniel Colascione <dancol@google.com> wrote:
>>>>>>> Changes from the fourth version of the patch:
>>>>>> Is there anything else that needs to be done before merging this patch series?
>>> Do you have a test case that exercises this feature?
>> I haven't heard anything back. What would cause this code to be executed?
> See https://lore.kernel.org/selinux/513f6230-1fb3-dbb5-5f75-53cd02b91b28@tycho.nsa.gov/
> for example.

Great. Thanks, that's what I needed. I'll Ack the patch set.


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-04-22 16:55           ` James Morris
  2020-04-22 17:12             ` Casey Schaufler
@ 2020-04-27 17:15             ` Casey Schaufler
  2020-04-27 19:40               ` Stephen Smalley
  1 sibling, 1 reply; 75+ messages in thread
From: Casey Schaufler @ 2020-04-27 17:15 UTC (permalink / raw)
  To: James Morris, Daniel Colascione
  Cc: Tim Murray, SElinux list, LSM List, Linux FS Devel, linux-kernel,
	kvm, Al Viro, Paul Moore, Nick Kralevich, Stephen Smalley,
	Lokesh Gidra, John Johansen, Casey Schaufler

On 4/22/2020 9:55 AM, James Morris wrote:
> On Mon, 13 Apr 2020, Daniel Colascione wrote:
>
>> On Wed, Apr 1, 2020 at 2:39 PM Daniel Colascione <dancol@google.com> wrote:
>>> Changes from the fourth version of the patch:
>>
>> Is there anything else that needs to be done before merging this patch series?
> The vfs changes need review and signoff from the vfs folk, the SELinux 
> changes by either Paul or Stephen, and we also need signoff on the LSM 
> hooks from other major LSM authors (Casey and John, at a minimum).

You can add my

	Acked-by: Casey Schaufler <casey@schaufler-ca.com>

for this patchset.


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-04-27 17:15             ` Casey Schaufler
@ 2020-04-27 19:40               ` Stephen Smalley
  0 siblings, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-04-27 19:40 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: James Morris, Daniel Colascione, Tim Murray, SElinux list,
	LSM List, Linux FS Devel, linux-kernel, kvm, Al Viro, Paul Moore,
	Nick Kralevich, Stephen Smalley, Lokesh Gidra, John Johansen

On Mon, Apr 27, 2020 at 1:17 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>
> On 4/22/2020 9:55 AM, James Morris wrote:
> > On Mon, 13 Apr 2020, Daniel Colascione wrote:
> >
> >> On Wed, Apr 1, 2020 at 2:39 PM Daniel Colascione <dancol@google.com> wrote:
> >>> Changes from the fourth version of the patch:
> >>
> >> Is there anything else that needs to be done before merging this patch series?
> > The vfs changes need review and signoff from the vfs folk, the SELinux
> > changes by either Paul or Stephen, and we also need signoff on the LSM
> > hooks from other major LSM authors (Casey and John, at a minimum).
>
> You can add my
>
>         Acked-by: Casey Schaufler <casey@schaufler-ca.com>
>
> for this patchset.

This version of the series addresses all of my comments, so you can add my
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>

I don't know though how to get a response from the vfs folks; the
series has been posted repeatedly without any
response by them.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD
  2020-04-27 16:48                   ` Stephen Smalley
  2020-04-27 17:12                     ` Casey Schaufler
@ 2020-04-29 17:02                     ` Stephen Smalley
  1 sibling, 0 replies; 75+ messages in thread
From: Stephen Smalley @ 2020-04-29 17:02 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Daniel Colascione, James Morris, Tim Murray, SElinux list,
	LSM List, Linux FS Devel, linux-kernel, kvm, Al Viro, Paul Moore,
	Nick Kralevich, Stephen Smalley, Lokesh Gidra, John Johansen

On Mon, Apr 27, 2020 at 12:48 PM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
>
> On Mon, Apr 27, 2020 at 12:19 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> >
> > On 4/23/2020 3:24 PM, Casey Schaufler wrote:
> > > On 4/22/2020 10:12 AM, Casey Schaufler wrote:
> > >> On 4/22/2020 9:55 AM, James Morris wrote:
> > >>> On Mon, 13 Apr 2020, Daniel Colascione wrote:
> > >>>
> > >>>> On Wed, Apr 1, 2020 at 2:39 PM Daniel Colascione <dancol@google.com> wrote:
> > >>>>> Changes from the fourth version of the patch:
> > >>>> Is there anything else that needs to be done before merging this patch series?
> > > Do you have a test case that exercises this feature?
> >
> > I haven't heard anything back. What would cause this code to be executed?
>
> See https://lore.kernel.org/selinux/513f6230-1fb3-dbb5-5f75-53cd02b91b28@tycho.nsa.gov/
> for example.

NB The example cited above needs to be tweaked for changes in the
logic from the original RFC patch on which the example was
based.  In particular, the userfaultfd CIL policy needs to be updated
to define and use the new anon_inode class and to allow create
permission as follows.

$ cat userfaultfd.cil
(class anon_inode ())
(classcommon anon_inode file)
(classorder (unordered anon_inode))
(type uffd_t)
; Label the UFFD with uffd_t; this can be specialized per domain
(typetransition unconfined_t unconfined_t anon_inode "[userfaultfd]"   uffd_t)
(allow unconfined_t uffd_t (anon_inode (create)))
; Permit read() and ioctl() on the UFFD.
; Comment out if you want to test read or basic ioctl enforcement.
(allow unconfined_t uffd_t (anon_inode (read)))
(allow unconfined_t uffd_t (anon_inode (ioctl)))
; Uncomment one of the allowx lines below to test ioctl whitelisting.
; Currently the 1st one is uncommented; comment that out if trying another.
; None
(allowx unconfined_t uffd_t (ioctl anon_inode ((0x00))))
; UFFDIO_API
;(allowx unconfined_t uffd_t (ioctl anon_inode ((0xaa3f))))

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH v5 1/3] Add a new LSM-supporting anonymous inode interface
  2020-04-01 21:39         ` [PATCH v5 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
@ 2020-05-07 16:02           ` James Morris
  0 siblings, 0 replies; 75+ messages in thread
From: James Morris @ 2020-05-07 16:02 UTC (permalink / raw)
  To: Daniel Colascione, Al Viro, Andrew Morton
  Cc: timmurray, selinux, linux-security-module, linux-fsdevel,
	linux-kernel, kvm, Paul Moore, nnk, Stephen Smalley, lokeshgidra

On Wed, 1 Apr 2020, Daniel Colascione wrote:

> This change adds two new functions, anon_inode_getfile_secure and
> anon_inode_getfd_secure, that create anonymous-node files with
> individual non-S_PRIVATE inodes to which security modules can apply
> policy. Existing callers continue using the original singleton-inode
> kind of anonymous-inode file. We can transition anonymous inode users
> to the new kind of anonymous inode in individual patches for the sake
> of bisection and review.
> 
> The new functions accept an optional context_inode parameter that
> callers can use to provide additional contextual information to
> security modules, e.g., indicating that one anonymous struct file is a
> logical child of another, allowing a security model to propagate
> security information from one to the other.
> 
> Signed-off-by: Daniel Colascione <dancol@google.com>

Al, Andrew, wondering if you could look at these anon inode changes 
before we merge this?



> ---
>  fs/anon_inodes.c            | 191 ++++++++++++++++++++++++++++--------
>  include/linux/anon_inodes.h |  13 +++
>  include/linux/lsm_hooks.h   |  11 +++
>  include/linux/security.h    |   3 +
>  security/security.c         |   9 ++
>  5 files changed, 186 insertions(+), 41 deletions(-)
> 
> diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
> index 89714308c25b..f87f221167cf 100644
> --- a/fs/anon_inodes.c
> +++ b/fs/anon_inodes.c
> @@ -55,61 +55,108 @@ static struct file_system_type anon_inode_fs_type = {
>  	.kill_sb	= kill_anon_super,
>  };
>  
> -/**
> - * 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
> - *
> - * @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
> - *
> - * Creates a new file by hooking it on a single 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.
> - */
> -struct file *anon_inode_getfile(const char *name,
> -				const struct file_operations *fops,
> -				void *priv, int flags)
> +static struct inode *anon_inode_make_secure_inode(
> +	const char *name,
> +	const struct inode *context_inode)
> +{
> +	struct inode *inode;
> +	const struct qstr qname = QSTR_INIT(name, strlen(name));
> +	int error;
> +
> +	inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
> +	if (IS_ERR(inode))
> +		return inode;
> +	inode->i_flags &= ~S_PRIVATE;
> +	error =	security_inode_init_security_anon(
> +		inode, &qname, context_inode);
> +	if (error) {
> +		iput(inode);
> +		return ERR_PTR(error);
> +	}
> +	return inode;
> +}
> +
> +struct file *_anon_inode_getfile(const char *name,
> +				 const struct file_operations *fops,
> +				 void *priv, int flags,
> +				 const struct inode *context_inode,
> +				 bool secure)
>  {
> +	struct inode *inode;
>  	struct file *file;
>  
> -	if (IS_ERR(anon_inode_inode))
> -		return ERR_PTR(-ENODEV);
> +	if (secure) {
> +		inode =	anon_inode_make_secure_inode(
> +			name, context_inode);
> +		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))
> -		return ERR_PTR(-ENOENT);
> +	if (fops->owner && !try_module_get(fops->owner)) {
> +		file = ERR_PTR(-ENOENT);
> +		goto err;
> +	}
>  
> -	/*
> -	 * 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,
> +	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);
>  
>  /**
> - * 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_getfile_secure - creates a new file instance by hooking
> + *                             it up to a new anonymous inode and a
> + *                             dentry that describe the "class" of the
> + *                             file.  Make it possible to use security
> + *                             modules to control access to the
> + *                             new 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
> + *
> + * 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 filesystem
> + * to operate correctly.  All the files created with
> + * anon_inode_getfile_secure() will have distinct inodes, avoiding
> + * code duplication for the file/inode/dentry setup.  Returns the
> + * newly created file* or an error pointer.
> + */
> +struct file *anon_inode_getfile_secure(const char *name,
> +				       const struct file_operations *fops,
> +				       void *priv, int flags,
> +				       const struct inode *context_inode)
> +{
> +	return _anon_inode_getfile(
> +		name, fops, priv, flags, context_inode, true);
> +}
> +EXPORT_SYMBOL_GPL(anon_inode_getfile_secure);
> +
> +/**
> + * 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
>   *
>   * @name:    [in]    name of the "class" of the new file
>   * @fops:    [in]    file operations for the new file
> @@ -118,12 +165,23 @@ EXPORT_SYMBOL_GPL(anon_inode_getfile);
>   *
>   * Creates a new file by hooking it on a single 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_getfd() will share a single inode,
> + * 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 new descriptor or an error code.
> + * setup.  Returns the newly created file* or an error pointer.
>   */
> -int anon_inode_getfd(const char *name, const struct file_operations *fops,
> -		     void *priv, int flags)
> +struct file *anon_inode_getfile(const char *name,
> +				const struct file_operations *fops,
> +				void *priv, int flags)
> +{
> +	return _anon_inode_getfile(name, fops, priv, flags, NULL, false);
> +}
> +EXPORT_SYMBOL_GPL(anon_inode_getfile);
> +
> +static int _anon_inode_getfd(const char *name,
> +			     const struct file_operations *fops,
> +			     void *priv, int flags,
> +			     const struct inode *context_inode,
> +			     bool secure)
>  {
>  	int error, fd;
>  	struct file *file;
> @@ -133,7 +191,8 @@ 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_getfile(name, fops, priv, flags, context_inode,
> +				   secure);
>  	if (IS_ERR(file)) {
>  		error = PTR_ERR(file);
>  		goto err_put_unused_fd;
> @@ -146,6 +205,57 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
>  	put_unused_fd(fd);
>  	return error;
>  }
> +
> +/**
> + * anon_inode_getfd_secure - creates a new file instance by hooking it
> + *                           up to a new anonymous inode and a dentry
> + *                           that describe the "class" of the file.
> + *                           Make it possible to use security modules
> + *                           to control access to the new 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
> + *
> + * 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 filesystem
> + * to operate correctly.  All the files created with
> + * anon_inode_getfile_secure() will have distinct inodes, avoiding
> + * code duplication for the file/inode/dentry setup.  Returns a newly
> + * created file descriptor or an error code.
> + */
> +int anon_inode_getfd_secure(const char *name, const struct file_operations *fops,
> +			    void *priv, int flags,
> +			    const struct inode *context_inode)
> +{
> +	return _anon_inode_getfd(name, fops, priv, flags,
> +				 context_inode, true);
> +}
> +EXPORT_SYMBOL_GPL(anon_inode_getfd_secure);
> +
> +/**
> + * 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
> + *
> + * @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
> + *
> + * Creates a new file by hooking it on a single 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 use the same singleton inode, reducing
> + * memory use and avoiding code duplication for the file/inode/dentry
> + * setup.  Returns a newly created file descriptor or an error code.
> + */
> +int anon_inode_getfd(const char *name, const struct file_operations *fops,
> +		     void *priv, int flags)
> +{
> +	return _anon_inode_getfd(name, fops, priv, flags, NULL, false);
> +}
>  EXPORT_SYMBOL_GPL(anon_inode_getfd);
>  
>  static int __init anon_inode_init(void)
> @@ -162,4 +272,3 @@ static int __init anon_inode_init(void)
>  }
>  
>  fs_initcall(anon_inode_init);
> -
> diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
> index d0d7d96261ad..67bd85d92dca 100644
> --- a/include/linux/anon_inodes.h
> +++ b/include/linux/anon_inodes.h
> @@ -10,12 +10,25 @@
>  #define _LINUX_ANON_INODES_H
>  
>  struct file_operations;
> +struct inode;
> +
> +struct file *anon_inode_getfile_secure(const char *name,
> +				       const struct file_operations *fops,
> +				       void *priv, int flags,
> +				       const struct inode *context_inode);
>  
>  struct file *anon_inode_getfile(const char *name,
>  				const struct file_operations *fops,
>  				void *priv, int flags);
> +
> +int anon_inode_getfd_secure(const char *name,
> +			    const struct file_operations *fops,
> +			    void *priv, int flags,
> +			    const struct inode *context_inode);
> +
>  int anon_inode_getfd(const char *name, const struct file_operations *fops,
>  		     void *priv, int flags);
>  
> +
>  #endif /* _LINUX_ANON_INODES_H */
>  
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 20d8cf194fb7..5434c1d285b2 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -215,6 +215,13 @@
>   *	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.
> + *      @inode contains the inode structure
> + *      @name name of the anonymous inode class
> + *      @context_inode optional related 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 +1559,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 struct qstr *name,
> +					const struct inode *context_inode);
>  	int (*inode_create)(struct inode *dir, struct dentry *dentry,
>  				umode_t mode);
>  	int (*inode_link)(struct dentry *old_dentry, struct inode *dir,
> @@ -1884,6 +1894,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..2108c3ce0666 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -320,6 +320,9 @@ 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 struct qstr *name,
> +				      const struct inode *context_inode);
>  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..70bfebada024 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1033,6 +1033,15 @@ 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 struct qstr *name,
> +				  const struct inode *context_inode)
> +{
> +	return call_int_hook(inode_init_security_anon, 0, inode, name,
> +			     context_inode);
> +}
> +
>  int security_old_inode_init_security(struct inode *inode, struct inode *dir,
>  				     const struct qstr *qstr, const char **name,
>  				     void **value, size_t *len)
> 

-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 75+ messages in thread

end of thread, back to index

Thread overview: 75+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-11 22:55 [PATCH v2 0/6] Harden userfaultfd Daniel Colascione
2020-02-11 22:55 ` [PATCH v2 1/6] Add a new flags-accepting interface for anonymous inodes Daniel Colascione
2020-02-12 16:37   ` Stephen Smalley
2020-02-12 17:23     ` Daniel Colascione
2020-02-11 22:55 ` [PATCH v2 2/6] Add a concept of a "secure" anonymous file Daniel Colascione
2020-02-12 16:49   ` Stephen Smalley
2020-02-14 22:13   ` kbuild test robot
2020-02-11 22:55 ` [PATCH v2 3/6] Teach SELinux about a new userfaultfd class Daniel Colascione
2020-02-12 17:05   ` Stephen Smalley
2020-02-12 17:19     ` Daniel Colascione
2020-02-12 18:04       ` Stephen Smalley
2020-02-12 18:59         ` Stephen Smalley
2020-02-12 19:04           ` Daniel Colascione
2020-02-12 19:11             ` Stephen Smalley
2020-02-12 19:13               ` Daniel Colascione
2020-02-12 19:17               ` Stephen Smalley
2020-02-11 22:55 ` [PATCH v2 4/6] Wire UFFD up to SELinux Daniel Colascione
2020-02-11 22:55 ` [PATCH v2 5/6] Let userfaultfd opt out of handling kernel-mode faults Daniel Colascione
2020-02-11 22:55 ` [PATCH v2 6/6] Add a new sysctl for limiting userfaultfd to user mode faults Daniel Colascione
2020-02-11 23:13 ` [PATCH v2 0/6] Harden userfaultfd Casey Schaufler
2020-02-11 23:27   ` Daniel Colascione
2020-02-12 16:09     ` Stephen Smalley
2020-02-21 17:56     ` James Morris
2020-02-12  7:50 ` Kees Cook
2020-02-12 16:54   ` Jann Horn
2020-02-12 17:14     ` Peter Xu
2020-02-12 19:41       ` Andrea Arcangeli
2020-02-12 20:04         ` Daniel Colascione
2020-02-12 23:41           ` Andrea Arcangeli
2020-02-12 17:12   ` Daniel Colascione
2020-02-14  3:26 ` [PATCH 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
2020-02-14  3:26   ` [PATCH 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
2020-02-14  3:26   ` [PATCH 2/3] Teach SELinux about anonymous inodes Daniel Colascione
2020-02-14 16:39     ` Stephen Smalley
2020-02-14 17:21       ` Daniel Colascione
2020-02-14 18:02         ` Stephen Smalley
2020-02-14 18:08           ` Stephen Smalley
2020-02-14 20:24             ` Stephen Smalley
2020-02-14  3:26   ` [PATCH 3/3] Wire UFFD up to SELinux Daniel Colascione
2020-03-25 23:02   ` [PATCH v2 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
2020-03-25 23:02   ` [PATCH v2 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
2020-03-26 13:53     ` Stephen Smalley
2020-03-25 23:02   ` [PATCH v2 2/3] Teach SELinux about anonymous inodes Daniel Colascione
2020-03-26 13:58     ` Stephen Smalley
2020-03-26 17:59       ` Daniel Colascione
2020-03-26 17:37     ` Stephen Smalley
2020-03-25 23:02   ` [PATCH v2 3/3] Wire UFFD up to SELinux Daniel Colascione
2020-03-25 23:49     ` Casey Schaufler
2020-03-26 18:14   ` [PATCH v3 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
2020-03-26 18:14     ` [PATCH v3 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
2020-03-26 19:00       ` Stephen Smalley
2020-03-26 18:14     ` [PATCH v3 2/3] Teach SELinux about anonymous inodes Daniel Colascione
2020-03-26 19:02       ` Stephen Smalley
2020-03-26 18:14     ` [PATCH v3 3/3] Wire UFFD up to SELinux Daniel Colascione
2020-03-26 20:06     ` [PATCH v4 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
2020-03-26 20:06       ` [PATCH v4 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
2020-03-27 13:40         ` Stephen Smalley
2020-03-26 20:06       ` [PATCH v4 2/3] Teach SELinux about anonymous inodes Daniel Colascione
2020-03-27 13:41         ` Stephen Smalley
2020-03-26 20:06       ` [PATCH v4 3/3] Wire UFFD up to SELinux Daniel Colascione
2020-04-01 21:39       ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
2020-04-01 21:39         ` [PATCH v5 1/3] Add a new LSM-supporting anonymous inode interface Daniel Colascione
2020-05-07 16:02           ` James Morris
2020-04-01 21:39         ` [PATCH v5 2/3] Teach SELinux about anonymous inodes Daniel Colascione
2020-04-01 21:39         ` [PATCH v5 3/3] Wire UFFD up to SELinux Daniel Colascione
2020-04-13 13:29         ` [PATCH v5 0/3] SELinux support for anonymous inodes and UFFD Daniel Colascione
2020-04-22 16:55           ` James Morris
2020-04-22 17:12             ` Casey Schaufler
2020-04-23 22:24               ` Casey Schaufler
2020-04-27 16:18                 ` Casey Schaufler
2020-04-27 16:48                   ` Stephen Smalley
2020-04-27 17:12                     ` Casey Schaufler
2020-04-29 17:02                     ` Stephen Smalley
2020-04-27 17:15             ` Casey Schaufler
2020-04-27 19:40               ` Stephen Smalley

SELinux Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/selinux/0 selinux/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 selinux selinux/ https://lore.kernel.org/selinux \
		selinux@vger.kernel.org
	public-inbox-index selinux

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.selinux


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git