All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stefan Berger <stefanb@linux.vnet.ibm.com>
To: linux-integrity@vger.kernel.org
Cc: zohar@linux.ibm.com, serge@hallyn.com,
	christian.brauner@ubuntu.com, containers@lists.linux.dev,
	dmitry.kasatkin@gmail.com, ebiederm@xmission.com,
	krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com,
	mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com,
	puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com,
	linux-kernel@vger.kernel.org, paul@paul-moore.com,
	rgb@redhat.com, linux-security-module@vger.kernel.org,
	jmorris@namei.org, Stefan Berger <stefanb@linux.ibm.com>,
	James Bottomley <James.Bottomley@HansenPartnership.com>
Subject: [PATCH v8 01/19] securityfs: Extend securityfs with namespacing support
Date: Tue,  4 Jan 2022 12:03:58 -0500	[thread overview]
Message-ID: <20220104170416.1923685-2-stefanb@linux.vnet.ibm.com> (raw)
In-Reply-To: <20220104170416.1923685-1-stefanb@linux.vnet.ibm.com>

From: Stefan Berger <stefanb@linux.ibm.com>

To prepare for virtualization of SecurityFS, use simple_pin_fs and
simpe_release_fs only when init_user_ns is active.

Extend 'securityfs' for support of IMA namespacing so that each
IMA (user) namespace can have its own front-end for showing the currently
active policy, the measurement list, number of violations and so on.

Enable multiple instances of securityfs by keying each instance with a
pointer to the user namespace it belongs to.

Drop the additional dentry reference to enable simple cleanup of dentries
upon umount. Now the dentries do not need to be explicitly freed anymore
but we can just rely on d_genocide() and the dcache shrinker to do all
the required work.

Prevent mounting of an instance of securityfs in another user namespace
than it belongs to. Also, prevent accesses to files and directories by
a user namespace that it not either the user namespace it belongs to
or an ancestor of the user namespace that the instance of securityfs
belongs to. Do not prevent access if securityfs was bind-mounted and the
init_user_ns is the owning user namespace.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 security/inode.c | 75 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 63 insertions(+), 12 deletions(-)

diff --git a/security/inode.c b/security/inode.c
index 6c326939750d..e525ba960063 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -21,9 +21,37 @@
 #include <linux/security.h>
 #include <linux/lsm_hooks.h>
 #include <linux/magic.h>
+#include <linux/user_namespace.h>
 
-static struct vfsmount *mount;
-static int mount_count;
+static struct vfsmount *init_securityfs_mount;
+static int init_securityfs_mount_count;
+
+static int securityfs_permission(struct user_namespace *mnt_userns,
+				 struct inode *inode, int mask)
+{
+	int err;
+
+	err = generic_permission(&init_user_ns, inode, mask);
+	if (!err) {
+		/* Unless bind-mounted, deny access if current_user_ns() is not
+		 * ancestor.
+		 */
+		if (inode->i_sb->s_user_ns != &init_user_ns &&
+		    !in_userns(current_user_ns(), inode->i_sb->s_user_ns))
+			err = -EACCES;
+	}
+
+	return err;
+}
+
+static const struct inode_operations securityfs_dir_inode_operations = {
+	.permission	= securityfs_permission,
+	.lookup		= simple_lookup,
+};
+
+static const struct inode_operations securityfs_file_inode_operations = {
+	.permission	= securityfs_permission,
+};
 
 static void securityfs_free_inode(struct inode *inode)
 {
@@ -40,20 +68,25 @@ static const struct super_operations securityfs_super_operations = {
 static int securityfs_fill_super(struct super_block *sb, struct fs_context *fc)
 {
 	static const struct tree_descr files[] = {{""}};
+	struct user_namespace *ns = fc->user_ns;
 	int error;
 
+	if (WARN_ON(ns != current_user_ns()))
+		return -EINVAL;
+
 	error = simple_fill_super(sb, SECURITYFS_MAGIC, files);
 	if (error)
 		return error;
 
 	sb->s_op = &securityfs_super_operations;
+	sb->s_root->d_inode->i_op = &securityfs_dir_inode_operations;
 
 	return 0;
 }
 
 static int securityfs_get_tree(struct fs_context *fc)
 {
-	return get_tree_single(fc, securityfs_fill_super);
+	return get_tree_keyed(fc, securityfs_fill_super, fc->user_ns);
 }
 
 static const struct fs_context_operations securityfs_context_ops = {
@@ -71,6 +104,7 @@ static struct file_system_type fs_type = {
 	.name =		"securityfs",
 	.init_fs_context = securityfs_init_fs_context,
 	.kill_sb =	kill_litter_super,
+	.fs_flags =	FS_USERNS_MOUNT,
 };
 
 /**
@@ -109,6 +143,7 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
 					const struct file_operations *fops,
 					const struct inode_operations *iops)
 {
+	struct user_namespace *ns = current_user_ns();
 	struct dentry *dentry;
 	struct inode *dir, *inode;
 	int error;
@@ -118,12 +153,19 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
 
 	pr_debug("securityfs: creating file '%s'\n",name);
 
-	error = simple_pin_fs(&fs_type, &mount, &mount_count);
-	if (error)
-		return ERR_PTR(error);
+	if (ns == &init_user_ns) {
+		error = simple_pin_fs(&fs_type, &init_securityfs_mount,
+				      &init_securityfs_mount_count);
+		if (error)
+			return ERR_PTR(error);
+	}
 
-	if (!parent)
-		parent = mount->mnt_root;
+	if (!parent) {
+		if (ns == &init_user_ns)
+			parent = init_securityfs_mount->mnt_root;
+		else
+			return ERR_PTR(-EINVAL);
+	}
 
 	dir = d_inode(parent);
 
@@ -148,7 +190,7 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
 	inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
 	inode->i_private = data;
 	if (S_ISDIR(mode)) {
-		inode->i_op = &simple_dir_inode_operations;
+		inode->i_op = &securityfs_dir_inode_operations;
 		inode->i_fop = &simple_dir_operations;
 		inc_nlink(inode);
 		inc_nlink(dir);
@@ -156,10 +198,10 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
 		inode->i_op = iops ? iops : &simple_symlink_inode_operations;
 		inode->i_link = data;
 	} else {
+		inode->i_op = &securityfs_file_inode_operations;
 		inode->i_fop = fops;
 	}
 	d_instantiate(dentry, inode);
-	dget(dentry);
 	inode_unlock(dir);
 	return dentry;
 
@@ -168,7 +210,9 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
 	dentry = ERR_PTR(error);
 out:
 	inode_unlock(dir);
-	simple_release_fs(&mount, &mount_count);
+	if (ns == &init_user_ns)
+		simple_release_fs(&init_securityfs_mount,
+				  &init_securityfs_mount_count);
 	return dentry;
 }
 
@@ -294,22 +338,29 @@ EXPORT_SYMBOL_GPL(securityfs_create_symlink);
  */
 void securityfs_remove(struct dentry *dentry)
 {
+	struct user_namespace *ns;
 	struct inode *dir;
 
 	if (!dentry || IS_ERR(dentry))
 		return;
 
+	ns = dentry->d_sb->s_user_ns;
+
 	dir = d_inode(dentry->d_parent);
 	inode_lock(dir);
 	if (simple_positive(dentry)) {
+		dget(dentry);
 		if (d_is_dir(dentry))
 			simple_rmdir(dir, dentry);
 		else
 			simple_unlink(dir, dentry);
+		d_delete(dentry);
 		dput(dentry);
 	}
 	inode_unlock(dir);
-	simple_release_fs(&mount, &mount_count);
+	if (ns == &init_user_ns)
+		simple_release_fs(&init_securityfs_mount,
+				  &init_securityfs_mount_count);
 }
 EXPORT_SYMBOL_GPL(securityfs_remove);
 
-- 
2.31.1


  reply	other threads:[~2022-01-04 17:04 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-04 17:03 [PATCH v8 00/19] ima: Namespace IMA with audit support in IMA-ns Stefan Berger
2022-01-04 17:03 ` Stefan Berger [this message]
2022-01-05  3:58   ` [PATCH v8 01/19] securityfs: Extend securityfs with namespacing support Al Viro
2022-01-05 10:18     ` Christian Brauner
2022-01-11 12:16       ` Mimi Zohar
2022-01-11 14:12         ` Christian Brauner
2022-01-04 17:03 ` [PATCH v8 02/19] ima: Define ima_namespace structure and implement basic functions Stefan Berger
2022-01-04 17:04 ` [PATCH v8 03/19] ima: Move policy related variables into ima_namespace Stefan Berger
2022-01-13 20:26   ` Mimi Zohar
2022-01-14 10:48     ` Christian Brauner
2022-01-19 13:32     ` Stefan Berger
2022-01-04 17:04 ` [PATCH v8 04/19] ima: Move ima_htable " Stefan Berger
2022-01-04 17:04 ` [PATCH v8 05/19] ima: Move measurement list related variables " Stefan Berger
2022-01-13 20:27   ` Mimi Zohar
2022-01-19 12:23     ` Stefan Berger
2022-01-04 17:04 ` [PATCH v8 06/19] ima: Move some IMA policy and filesystem " Stefan Berger
2022-01-04 17:04 ` [PATCH v8 07/19] ima: Move dentry into ima_namespace and others onto stack Stefan Berger
2022-01-13 20:28   ` Mimi Zohar
2022-01-18 20:12     ` Stefan Berger
2022-01-18 20:42       ` Mimi Zohar
2022-01-18 20:54         ` Stefan Berger
2022-01-04 17:04 ` [PATCH v8 08/19] ima: Use mac_admin_ns_capable() to check corresponding capability Stefan Berger
2022-01-05 20:55   ` kernel test robot
2022-01-05 20:55     ` kernel test robot
2022-01-13 20:28   ` Mimi Zohar
2022-01-04 17:04 ` [PATCH v8 09/19] ima: Only accept AUDIT rules for non-init_ima_ns namespaces for now Stefan Berger
2022-01-04 17:04 ` [PATCH v8 10/19] ima: Implement hierarchical processing of file accesses Stefan Berger
2022-01-14 11:21   ` Christian Brauner
2022-01-18 18:25     ` Stefan Berger
2022-01-04 17:04 ` [PATCH v8 11/19] ima: Implement ima_free_policy_rules() for freeing of an ima_namespace Stefan Berger
2022-01-04 17:04 ` [PATCH v8 12/19] userns: Add pointer to ima_namespace to user_namespace Stefan Berger
2022-01-04 17:04 ` [PATCH v8 13/19] ima: Add functions for creation and freeing of an ima_namespace Stefan Berger
2022-01-14 11:43   ` Christian Brauner
2022-01-04 17:04 ` [PATCH v8 14/19] integrity/ima: Define ns_status for storing namespaced iint data Stefan Berger
2022-01-04 17:04 ` [PATCH v8 15/19] ima: Namespace audit status flags Stefan Berger
2022-01-04 17:04 ` [PATCH v8 16/19] ima: Enable re-auditing of modified files Stefan Berger
2022-01-05 15:21   ` Stefan Berger
2022-01-04 17:04 ` [PATCH v8 17/19] ima: Setup securityfs for IMA namespace Stefan Berger
2022-01-04 17:04 ` [PATCH v8 18/19] ima: Show owning user namespace's uid and gid when displaying policy Stefan Berger
2022-01-14 13:45   ` Christian Brauner
2022-01-18 16:31     ` Stefan Berger
2022-01-19  9:23       ` Christian Brauner
2022-01-04 17:04 ` [PATCH v8 19/19] ima: Enable IMA namespaces Stefan Berger
2022-01-14 12:05   ` Christian Brauner
2022-01-18 17:53     ` Stefan Berger
2022-01-14 14:45   ` Christian Brauner
2022-01-18 18:09     ` Stefan Berger
2022-01-19  9:46       ` Christian Brauner
2022-01-19 12:45         ` Stefan Berger
2022-01-19 13:03           ` Christian Brauner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220104170416.1923685-2-stefanb@linux.vnet.ibm.com \
    --to=stefanb@linux.vnet.ibm.com \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=christian.brauner@ubuntu.com \
    --cc=containers@lists.linux.dev \
    --cc=dmitry.kasatkin@gmail.com \
    --cc=ebiederm@xmission.com \
    --cc=jamjoom@us.ibm.com \
    --cc=jejb@linux.ibm.com \
    --cc=jmorris@namei.org \
    --cc=krzysztof.struczynski@huawei.com \
    --cc=lhinds@redhat.com \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=lsturman@redhat.com \
    --cc=mpeters@redhat.com \
    --cc=paul@paul-moore.com \
    --cc=puiterwi@redhat.com \
    --cc=rgb@redhat.com \
    --cc=roberto.sassu@huawei.com \
    --cc=serge@hallyn.com \
    --cc=stefanb@linux.ibm.com \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.