linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christian Brauner <christian.brauner@ubuntu.com>
To: Stefan Berger <stefanb@linux.ibm.com>
Cc: linux-integrity@vger.kernel.org, zohar@linux.ibm.com,
	serge@hallyn.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
Subject: Re: [PATCH v5 13/16] ima: Move some IMA policy and filesystem related variables into ima_namespace
Date: Fri, 10 Dec 2021 12:32:44 +0100	[thread overview]
Message-ID: <20211210113244.odv2ibrifz2jzft5@wittgenstein> (raw)
In-Reply-To: <0ab33fbc-8438-27b6-ff4c-0321bfc73855@linux.ibm.com>

On Thu, Dec 09, 2021 at 07:57:02PM -0500, Stefan Berger wrote:
> 
> On 12/9/21 14:11, Christian Brauner wrote:
> > 
> >  From 1f03dc427c583d5e9ebc9ebe9de77c3c535bbebe Mon Sep 17 00:00:00 2001
> > From: Christian Brauner <christian.brauner@ubuntu.com>
> > Date: Thu, 9 Dec 2021 20:07:02 +0100
> > Subject: [PATCH] !!!! HERE BE DRAGONS - UNTESTED !!!!
> > 
> > ---
> >   security/integrity/ima/ima_fs.c | 43 +++++++++++++++++++++++++++++----
> >   1 file changed, 38 insertions(+), 5 deletions(-)
> > 
> > diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
> > index 583462b29cb5..d5b302b925b8 100644
> > --- a/security/integrity/ima/ima_fs.c
> > +++ b/security/integrity/ima/ima_fs.c
> > @@ -317,10 +317,14 @@ static ssize_t ima_read_policy(char *path)
> >   static ssize_t ima_write_policy(struct file *file, const char __user *buf,
> >   				size_t datalen, loff_t *ppos)
> >   {
> > -	struct ima_namespace *ns = get_current_ns();
> > +	struct ima_namespace *ns;
> > +	struct user_namespace *user_ns;
> >   	char *data;
> >   	ssize_t result;
> > +	user_ns = ima_filp_private(filp);
> > +	ns = user_ns->ima_ns
> > +
> >   	if (datalen >= PAGE_SIZE)
> >   		datalen = PAGE_SIZE - 1;
> > @@ -373,26 +377,51 @@ static const struct seq_operations ima_policy_seqops = {
> >   };
> >   #endif
> > +static struct user_namespace *ima_filp_private(struct file *filp)
> > +{
> > +	if (!(filp->f_flags & O_WRONLY)) {
> > +#ifdef CONFIG_IMA_READ_POLICY
> > +		struct seq_file *seq;
> > +
> > +		seq = filp->private_data;
> > +		return seq->private;
> > +#endif
> > +	}
> > +	return filp->private_data;
> > +}
> > +
> >   /*
> >    * ima_open_policy: sequentialize access to the policy file
> >    */
> >   static int ima_open_policy(struct inode *inode, struct file *filp)
> >   {
> > -	struct ima_namespace *ns = get_current_ns();
> > +	struct user_namespace *user_ns = current_user_ns();
> 
> 
> Do we have to take a reference on the user namespace assuming one can open
> the file, pass the fd down the hierarchy, and then the user namespace with
> the opened file goes away? Or is there anything else that keeps the user
> namespace alive?

No, we don't. When ima_policy_open() is called we do current_user_ns()
but that will be guaranteed to be identical to filp->f_cred->user_ns.
And f_cred is a reference that has been taken when the vfs allocated a
struct file for this .open call so won't go away until the last fput.

My proposal is also too complicated, I think.
(The booster is giving me the same side-effects as my second shot so
this looks like two good days of fever and headache. So I'll use that as
an excuse. :))

Your patch series as it stands has a bit of a security issue with those
get_current_ns() calls across differnet file/seq_file operations.

You have to make an architectural decision, I think. I see two sensible
options:
1. The relevant ima_ns that .open/.read/.write operate on is always taken
   to be the ima_ns of the filesystem's userns, i.e.
   sb->s_user_ns->ima_ns.
   This - but I'm not an ima person - makes the most sense to me and the
   semantics are straightforward. If I write to a file to alter some
   policy then I expect the ima namespace of the user namespace to be
   affected that the securityfs instance was mounted in.
2. The relevant ima_ns that .open/.read/.write operate on is always
   taken to be the one of the opener. I don't really like that as that
   gets weird if for some complicated reason the caller is not located
   in the userns the filesystem was mounted in (weird mount propagation
   scenario or sm). It also feels strange to operate on an ima_ns that's
   different from s_user_ns->ima_ns in a securityfs instance.

So I think I would propose you do sm:

From 6c8018f14f22e7bc2255dcebab96f9b8c39a8459 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner@ubuntu.com>
Date: Fri, 10 Dec 2021 10:31:27 +0100
Subject: [PATCH 1/2] !!!! HERE BE DRAGONS - COMPLETELY UNTESTED !!!!

The relevant ima_ns that .open/.read/.write operate on is always taken to be
the ima_ns of the filesystem's userns, i.e.  sb->s_user_ns->ima_ns. This - but
I'm not an ima person - makes the most sense to me and the semantics are
straightforward. If I write to a file to alter some policy then I expect the
ima namespace of the user namespace to be affected that the securityfs instance
was mounted in.
---
 security/integrity/ima/ima_fs.c     | 30 ++++++++++++++++++-----------
 security/integrity/ima/ima_policy.c |  8 ++++++--
 2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 778983fd9a73..95b7b9ec2a76 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -49,7 +49,8 @@ static ssize_t ima_show_htable_violations(struct file *filp,
 					  char __user *buf,
 					  size_t count, loff_t *ppos)
 {
-	struct ima_namespace *ns = get_current_ns();
+	struct user_namespace *user_ns = filp->f_path.mnt->mnt_sb->s_user_ns;
+	struct ima_namespace *ns = user_ns->ima_ns;
 
 	return ima_show_htable_value(buf, count, ppos, &ns->ima_htable.violations);
 }
@@ -63,7 +64,8 @@ static ssize_t ima_show_measurements_count(struct file *filp,
 					   char __user *buf,
 					   size_t count, loff_t *ppos)
 {
-	struct ima_namespace *ns = get_current_ns();
+	struct user_namespace *user_ns = filp->f_path.mnt->mnt_sb->s_user_ns;
+	struct ima_namespace *ns = user_ns->ima_ns;
 
 	return ima_show_htable_value(buf, count, ppos, &ns->ima_htable.len);
 }
@@ -76,7 +78,9 @@ static const struct file_operations ima_measurements_count_ops = {
 /* returns pointer to hlist_node */
 static void *ima_measurements_start(struct seq_file *m, loff_t *pos)
 {
-	struct ima_namespace *ns = get_current_ns();
+	const struct file *filp = m->file;
+	struct user_namespace *user_ns = filp->f_path.mnt->mnt_sb->s_user_ns;
+	struct ima_namespace *ns = user_ns->ima_ns;
 	loff_t l = *pos;
 	struct ima_queue_entry *qe;
 
@@ -94,7 +98,9 @@ static void *ima_measurements_start(struct seq_file *m, loff_t *pos)
 
 static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	struct ima_namespace *ns = get_current_ns();
+	const struct file *filp = m->file;
+	struct user_namespace *user_ns = filp->f_path.mnt->mnt_sb->s_user_ns;
+	struct ima_namespace *ns = user_ns->ima_ns;
 	struct ima_queue_entry *qe = v;
 
 	/* lock protects when reading beyond last element
@@ -273,9 +279,8 @@ static const struct file_operations ima_ascii_measurements_ops = {
 	.release = seq_release,
 };
 
-static ssize_t ima_read_policy(char *path)
+static ssize_t ima_read_policy(struct ima_namespace *ns, char *path)
 {
-	struct ima_namespace *ns = get_current_ns();
 	void *data = NULL;
 	char *datap;
 	size_t size;
@@ -317,7 +322,8 @@ static ssize_t ima_read_policy(char *path)
 static ssize_t ima_write_policy(struct file *file, const char __user *buf,
 				size_t datalen, loff_t *ppos)
 {
-	struct ima_namespace *ns = get_current_ns();
+	struct user_namespace *user_ns = file->f_path.mnt->mnt_sb->s_user_ns;
+	struct ima_namespace *ns = user_ns->ima_ns;
 	char *data;
 	ssize_t result;
 
@@ -340,7 +346,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
 		goto out_free;
 
 	if (data[0] == '/') {
-		result = ima_read_policy(data);
+		result = ima_read_policy(ns, data);
 	} else if (ima_appraise & IMA_APPRAISE_POLICY) {
 		pr_err("signed policy file (specified as an absolute pathname) required\n");
 		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
@@ -378,7 +384,8 @@ static const struct seq_operations ima_policy_seqops = {
  */
 static int ima_open_policy(struct inode *inode, struct file *filp)
 {
-	struct ima_namespace *ns = get_current_ns();
+	struct user_namespace *user_ns = inode->i_sb->s_user_ns;
+	struct ima_namespace *ns = user_ns->ima_ns;
 
 	if (!(filp->f_flags & O_WRONLY)) {
 #ifndef	CONFIG_IMA_READ_POLICY
@@ -386,7 +393,7 @@ static int ima_open_policy(struct inode *inode, struct file *filp)
 #else
 		if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
 			return -EACCES;
-		if (!mac_admin_ns_capable(ns->user_ns))
+		if (!mac_admin_ns_capable(user_ns))
 			return -EPERM;
 		return seq_open(filp, &ima_policy_seqops);
 #endif
@@ -405,7 +412,8 @@ static int ima_open_policy(struct inode *inode, struct file *filp)
  */
 static int ima_release_policy(struct inode *inode, struct file *file)
 {
-	struct ima_namespace *ns = get_current_ns();
+	struct user_namespace *user_ns = inode->i_sb->s_user_ns;
+	struct ima_namespace *ns = user_ns->ima_ns;
 	const char *cause = ns->valid_policy ? "completed" : "failed";
 
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 747dca6131d6..41e5f17ec44d 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -1908,7 +1908,9 @@ static const char *const mask_tokens[] = {
 
 void *ima_policy_start(struct seq_file *m, loff_t *pos)
 {
-	struct ima_namespace *ns = get_current_ns();
+	const struct file *filp = m->file;
+	struct user_namespace *user_ns = filp->f_path.mnt->mnt_sb->user_ns;
+	struct ima_namespace *ns = user_ns->ima_ns;
 	loff_t l = *pos;
 	struct ima_rule_entry *entry;
 	struct list_head *ima_rules_tmp;
@@ -1928,7 +1930,9 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos)
 void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos)
 {
 	struct ima_rule_entry *entry = v;
-	struct ima_namespace *ns = get_current_ns();
+	const struct file *filp = m->file;
+	struct user_namespace *user_ns = filp->f_path.mnt->mnt_sb->user_ns;
+	struct ima_namespace *ns = user_ns->ima_ns;
 
 	rcu_read_lock();
 	entry = list_entry_rcu(entry->list.next, struct ima_rule_entry, list);
-- 
2.30.2

From ecf25d6b2b5895005d4103169bdb55d970e7a865 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner@ubuntu.com>
Date: Fri, 10 Dec 2021 11:56:25 +0100
Subject: [PATCH 2/2] !!!! HERE BE DRAGONS - COMPLETELY UNTESTED !!!!

securityfs: don't allow mounting from outside the filesystem's userns

If we ever need to allow that we should revisit the semantics.
---
 security/inode.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/security/inode.c b/security/inode.c
index eaccba7017d9..71f9634228f3 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -43,7 +43,10 @@ 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;
+	int error = -EINVAL;
+
+	if (WARN_ON(ns != current_user_ns()))
+		return error;
 
 	error = simple_fill_super(sb, SECURITYFS_MAGIC, files);
 	if (error)
-- 
2.30.2


  reply	other threads:[~2021-12-10 11:32 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-08 22:18 [PATCH v5 00/16] ima: Namespace IMA with audit support in IMA-ns Stefan Berger
2021-12-08 22:18 ` [PATCH v5 01/16] ima: Add IMA namespace support Stefan Berger
2021-12-08 22:18 ` [PATCH v5 02/16] ima: Define ns_status for storing namespaced iint data Stefan Berger
2021-12-08 22:18 ` [PATCH v5 03/16] ima: Namespace audit status flags Stefan Berger
2021-12-08 22:18 ` [PATCH v5 04/16] ima: Move delayed work queue and variables into ima_namespace Stefan Berger
2021-12-09 13:11   ` Christian Brauner
2021-12-09 15:09     ` Stefan Berger
2021-12-08 22:18 ` [PATCH v5 05/16] ima: Move IMA's keys queue related " Stefan Berger
2021-12-08 22:18 ` [PATCH v5 06/16] ima: Move policy " Stefan Berger
2021-12-08 22:18 ` [PATCH v5 07/16] ima: Move ima_htable " Stefan Berger
2021-12-08 22:18 ` [PATCH v5 08/16] ima: Move measurement list related variables " Stefan Berger
2021-12-08 22:18 ` [PATCH v5 09/16] ima: Only accept AUDIT rules for IMA non-init_ima_ns namespaces for now Stefan Berger
2021-12-08 22:18 ` [PATCH v5 10/16] ima: Implement hierarchical processing of file accesses Stefan Berger
2021-12-08 22:18 ` [PATCH v5 11/16] securityfs: Only use simple_pin_fs/simple_release_fs for init_user_ns Stefan Berger
2021-12-08 22:18 ` [PATCH v5 12/16] securityfs: Extend securityfs with namespacing support Stefan Berger
2021-12-08 22:18 ` [PATCH v5 13/16] ima: Move some IMA policy and filesystem related variables into ima_namespace Stefan Berger
2021-12-09 19:11   ` Christian Brauner
2021-12-09 20:42     ` Stefan Berger
2021-12-10  0:57     ` Stefan Berger
2021-12-10 11:32       ` Christian Brauner [this message]
2021-12-10 13:57         ` Stefan Berger
2021-12-10 14:21           ` James Bottomley
2021-12-11  9:50           ` Christian Brauner
2021-12-11 10:45             ` Christian Brauner
2021-12-13 15:33             ` Stefan Berger
2021-12-13 15:50               ` Christian Brauner
2021-12-13 16:03                 ` Christian Brauner
2021-12-13 16:25                 ` Stefan Berger
2021-12-13 16:37                   ` Christian Brauner
2021-12-13 16:40                 ` Christian Brauner
2021-12-10 20:08         ` Stefan Berger
2021-12-11  8:46           ` Christian Brauner
2021-12-08 22:18 ` [PATCH v5 14/16] ima: Use mac_admin_ns_capable() to check corresponding capability Stefan Berger
2021-12-09  7:22   ` Denis Semakin
2021-12-09 13:23     ` James Bottomley
2021-12-09  8:09   ` Denis Semakin
2021-12-11 15:02     ` Serge E. Hallyn
2021-12-11 15:38       ` Stefan Berger
2021-12-11 16:00         ` James Bottomley
2021-12-08 22:18 ` [PATCH v5 15/16] ima: Move dentries into ima_namespace Stefan Berger
2021-12-09 14:34   ` Christian Brauner
2021-12-09 14:37     ` Christian Brauner
2021-12-09 14:41       ` Christian Brauner
2021-12-09 15:00         ` Stefan Berger
2021-12-09 15:47           ` Christian Brauner
2021-12-09 15:30       ` James Bottomley
2021-12-09 19:38         ` James Bottomley
2021-12-09 20:13           ` Stefan Berger
2021-12-10 11:49           ` Christian Brauner
2021-12-10 12:09             ` Mimi Zohar
2021-12-10 12:40               ` Stefan Berger
2021-12-10 13:02                 ` Mimi Zohar
2021-12-10 14:17                   ` Stefan Berger
2021-12-10 14:26                     ` James Bottomley
2021-12-10 15:26                       ` Mimi Zohar
2021-12-10 15:32                         ` Stefan Berger
2021-12-10 15:48                           ` Mimi Zohar
2021-12-10 16:40                             ` Stefan Berger
2021-12-10 12:40               ` James Bottomley
2021-12-10 12:54                 ` Mimi Zohar
2021-12-12 14:13             ` James Bottomley
2021-12-13 11:25               ` Christian Brauner
2021-12-08 22:18 ` [PATCH v5 16/16] ima: Setup securityfs for IMA namespace Stefan Berger

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=20211210113244.odv2ibrifz2jzft5@wittgenstein \
    --to=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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).