netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stephen Smalley <stephen.smalley.work@gmail.com>
To: selinux@vger.kernel.org
Cc: paul@paul-moore.com, omosnace@redhat.com, netdev@vger.kernel.org,
	Stephen Smalley <stephen.smalley.work@gmail.com>
Subject: [PATCH v3 12/42] selinux: refactor selinux_state_create()
Date: Tue, 20 May 2025 07:59:10 -0400	[thread overview]
Message-ID: <20250520120000.25501-14-stephen.smalley.work@gmail.com> (raw)
In-Reply-To: <20250520120000.25501-2-stephen.smalley.work@gmail.com>

Refactor selinux_state_create() to be more like create_user_ns()
after which it was originally modeled. In particular, pass in
a single cred argument and update the cred SELinux blob with
the new state. This makes the reference counting situation
clearer with regard to the old state / parent reference and
simplifies the callers.

Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
---
 security/selinux/hooks.c            | 79 ++++++++++++++++++++---------
 security/selinux/include/security.h |  3 +-
 security/selinux/selinuxfs.c        | 10 +---
 3 files changed, 57 insertions(+), 35 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b2efe6b1e566..83846fdaa3ad 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -204,22 +204,6 @@ static int selinux_lsm_notifier_avc_callback(u32 event)
 	return 0;
 }
 
-struct selinux_state *init_selinux_state;
-
-/*
- * initialise the security for the init task
- */
-static void cred_init_security(void)
-{
-	struct task_security_struct *tsec;
-
-	/* NOTE: the lsm framework zeros out the buffer on allocation */
-
-	tsec = selinux_cred(unrcu_pointer(current->real_cred));
-	tsec->osid = tsec->sid = tsec->avdcache.sid = SECINITSID_KERNEL;
-	tsec->state = get_selinux_state(init_selinux_state);
-}
-
 /*
  * get the security ID of a set of credentials
  */
@@ -7811,9 +7795,10 @@ unsigned int selinux_maxnsdepth = CONFIG_SECURITY_SELINUX_MAXNSDEPTH;
 
 static atomic_t selinux_nsnum = ATOMIC_INIT(0);
 
-int selinux_state_create(struct selinux_state *parent,
-			 struct selinux_state **state)
+int selinux_state_create(const struct cred *cred)
 {
+	struct task_security_struct *tsec = selinux_cred(cred);
+	struct selinux_state *parent = tsec->state;
 	struct selinux_state *newstate;
 	int rc;
 
@@ -7838,13 +7823,40 @@ int selinux_state_create(struct selinux_state *parent,
 		goto err;
 
 	if (parent) {
-		newstate->parent = get_selinux_state(parent);
+		/*
+		 * The reference to the new state replaces the reference
+		 * to the old state (parent) in the cred security blob;
+		 * hence, we do not need to use get_selinux_state() below
+		 * to increment the parent reference count.
+		 */
+		newstate->parent = parent;
 		newstate->depth = parent->depth + 1;
 	}
 
 	atomic_inc(&selinux_nsnum);
 
-	*state = newstate;
+	/*
+	 * Set the new namespace.
+	 * The reference count was initialized to 1 and
+	 * this is that reference.
+	 */
+	tsec->state = newstate;
+
+	/* Reset the SIDs for the new namespace. */
+	if (parent)
+		tsec->osid = tsec->sid = tsec->avdcache.sid = SECINITSID_INIT;
+	tsec->exec_sid = tsec->create_sid = tsec->keycreate_sid =
+		tsec->sockcreate_sid = SECSID_NULL;
+
+	/*
+	 * Save the credential in the parent namespace
+	 * for later use in checks in that namespace.
+	 */
+	if (parent) {
+		put_cred(tsec->parent_cred);
+		tsec->parent_cred = get_current_cred();
+	}
+
 	return 0;
 err:
 	kfree(newstate);
@@ -7873,16 +7885,35 @@ void __put_selinux_state(struct selinux_state *state)
 	schedule_work(&state->work);
 }
 
+struct selinux_state *init_selinux_state;
+
 static __init int selinux_init(void)
 {
+	const struct cred *cred = unrcu_pointer(current->real_cred);
+	struct task_security_struct *tsec = selinux_cred(cred);
+
 	pr_info("SELinux:  Initializing.\n");
 
-	if (selinux_state_create(NULL, &init_selinux_state))
+	/*
+	 * Initialize the first cred with the kernel SID and
+	 * NULL state since selinux_state_create() expects
+	 * these two fields to be set. The rest is handled by
+	 * selinux_state_create(), which will update the state
+	 * field to refer to the new state and set the parent
+	 * pointer to the old state value (NULL).
+	 */
+	tsec->osid = tsec->sid = tsec->avdcache.sid = SECINITSID_KERNEL;
+	tsec->state = NULL;
+	if (selinux_state_create(cred))
 		panic("SELinux: Could not create initial namespace\n");
-	enforcing_set(init_selinux_state, selinux_enforcing_boot);
 
-	/* Set the security state for the initial task. */
-	cred_init_security();
+	/*
+	 * Save a reference to the initial SELinux namespace
+	 * for use in various other functions.
+	 */
+	init_selinux_state = get_selinux_state(tsec->state);
+
+	enforcing_set(init_selinux_state, selinux_enforcing_boot);
 
 	default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
 	if (!default_noexec)
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index cb1c9095cffd..9802099e2f56 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -116,8 +116,7 @@ struct selinux_state {
 extern struct selinux_state *init_selinux_state;
 
 extern unsigned int selinux_maxns, selinux_maxnsdepth;
-int selinux_state_create(struct selinux_state *parent,
-			 struct selinux_state **state);
+int selinux_state_create(const struct cred *cred);
 void __put_selinux_state(struct selinux_state *state);
 
 void selinux_policy_free(struct selinux_policy __rcu *policy);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index b64730bb6596..c7e74229d2e3 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -325,8 +325,6 @@ static ssize_t sel_write_unshare(struct file *file, const char __user *buf,
 				 size_t count, loff_t *ppos)
 
 {
-	struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
-	struct selinux_state *state = fsi->state;
 	char *page;
 	ssize_t length;
 	bool set;
@@ -355,22 +353,16 @@ static ssize_t sel_write_unshare(struct file *file, const char __user *buf,
 
 	if (set) {
 		struct cred *cred = prepare_creds();
-		struct task_security_struct *tsec;
 
 		if (!cred) {
 			length = -ENOMEM;
 			goto out;
 		}
-		tsec = selinux_cred(cred);
-		if (selinux_state_create(state, &tsec->state)) {
+		if (selinux_state_create(cred)) {
 			abort_creds(cred);
 			length = -ENOMEM;
 			goto out;
 		}
-		tsec->osid = tsec->sid = SECINITSID_INIT;
-		tsec->exec_sid = tsec->create_sid = tsec->keycreate_sid =
-			tsec->sockcreate_sid = SECSID_NULL;
-		tsec->parent_cred = get_current_cred();
 		commit_creds(cred);
 	}
 
-- 
2.49.0


  parent reply	other threads:[~2025-05-20 12:01 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-20 11:58 [PATCH v3 00/42] SELinux namespace support Stephen Smalley
2025-05-20 11:58 ` [PATCH v3 01/42] selinux: restore passing of selinux_state Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 02/42] selinux: introduce current_selinux_state Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 03/42] selinux: support multiple selinuxfs instances Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 04/42] selinux: dynamically allocate selinux namespace Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 05/42] netstate,selinux: create the selinux netlink socket per network namespace Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 06/42] selinux: limit selinux netlink notifications to init namespace Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 07/42] selinux: support per-task/cred selinux namespace Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 08/42] selinux: introduce cred_selinux_state() and use it Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 09/42] selinux: add a selinuxfs interface to unshare selinux namespace Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 10/42] selinux: add limits for SELinux namespaces Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 11/42] selinux: exempt creation of init SELinux namespace from limits Stephen Smalley
2025-05-20 11:59 ` Stephen Smalley [this message]
2025-05-20 11:59 ` [PATCH v3 13/42] selinux: allow userspace to detect non-init SELinux namespace Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 14/42] selinuxfs: restrict write operations to the same selinux namespace Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 15/42] selinux: introduce a global SID table Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 16/42] selinux: wrap security server interfaces to use the " Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 17/42] selinux: introduce a Kconfig option for SELinux namespaces Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 18/42] selinux: eliminate global SID table if !CONFIG_SECURITY_SELINUX_NS Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 19/42] selinux: maintain a small cache in the global SID table Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 20/42] selinux: update hook functions to use correct selinux namespace Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 21/42] selinux: introduce cred_task_has_perm() Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 22/42] selinux: introduce cred_has_extended_perms() Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 23/42] selinux: introduce cred_self_has_perm() Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 24/42] selinux: introduce cred_has_perm() Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 25/42] selinux: introduce cred_ssid_has_perm() and cred_other_has_perm() Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 26/42] selinux: introduce task_obj_perm() Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 27/42] selinux: update bprm hooks for selinux namespaces Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 28/42] selinux: add kerneldoc to new permission checking functions Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 29/42] selinux: convert selinux_file_send_sigiotask() to namespace-aware helper Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 30/42] selinux: rename cred_has_perm*() to cred_tsid_has_perm*() Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 31/42] selinux: update cred_tsid_has_perm_noaudit() to return the combined avd Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 32/42] selinux: convert additional checks to cred_ssid_has_perm() Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 33/42] selinux: introduce selinux_state_has_perm() Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 34/42] selinux: annotate selinuxfs permission checks Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 35/42] selinux: annotate process transition " Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 36/42] selinux: convert xfrm and netlabel " Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 37/42] selinux: switch selinux_lsm_setattr() checks to current namespace Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 38/42] selinux: make open_perms namespace-aware Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 39/42] selinux: split cred_ssid_has_perm() into two cases Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 40/42] selinux: disallow writes to /sys/fs/selinux/user in non-init namespaces Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 41/42] selinux: convert nlmsg_sock_has_extended_perms() to namespace-aware Stephen Smalley
2025-05-20 11:59 ` [PATCH v3 42/42] selinux: init inode from nearest initialized namespace Stephen Smalley

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=20250520120000.25501-14-stephen.smalley.work@gmail.com \
    --to=stephen.smalley.work@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=omosnace@redhat.com \
    --cc=paul@paul-moore.com \
    --cc=selinux@vger.kernel.org \
    /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).