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,
horms@kernel.org,
Stephen Smalley <stephen.smalley.work@gmail.com>
Subject: [PATCH v7 09/42] selinux: init inode from nearest initialized namespace
Date: Thu, 14 Aug 2025 09:26:00 -0400 [thread overview]
Message-ID: <20250814132637.1659-10-stephen.smalley.work@gmail.com> (raw)
In-Reply-To: <20250814132637.1659-1-stephen.smalley.work@gmail.com>
Previously inode_doinit_with_dentry() was only checking sbsec->flags
to see if it should defer the inode security blob initialization,
which was fine when there was only a single SELinux state/namespace
since that could only be set if the state was initialized. However,
with the introduction of SELinux namespaces, the superblock could be
initialized in the parent (or other ancestor) namespace but the
current namespace may not yet be initialized (i.e. the namespace was
unshared but no policy has yet been loaded into it). Check for this
case, and if uninitialized, find the nearest ancestor SELinux
namespace that is initialized and use it instead. In the case where
the init SELinux namespace was never initialized (i.e. no policy
loaded on the host), then defer initialization of the inode.
Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
---
security/selinux/hooks.c | 45 +++++++++++++++++------------
security/selinux/include/security.h | 6 ++--
2 files changed, 30 insertions(+), 21 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3135378e9229..65d9762b992a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1347,10 +1347,9 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
return SECCLASS_SOCKET;
}
-static int selinux_genfs_get_sid(struct dentry *dentry,
- u16 tclass,
- u16 flags,
- u32 *sid)
+static int selinux_genfs_get_sid(struct selinux_state *state,
+ struct dentry *dentry, u16 tclass,
+ u16 flags, u32 *sid)
{
int rc;
struct super_block *sb = dentry->d_sb;
@@ -1373,8 +1372,8 @@ static int selinux_genfs_get_sid(struct dentry *dentry,
path++;
}
}
- rc = security_genfs_sid(current_selinux_state, sb->s_type->name,
- path, tclass, sid);
+ rc = security_genfs_sid(state, sb->s_type->name, path,
+ tclass, sid);
if (rc == -ENOENT) {
/* No match in policy, mark as unlabeled. */
*sid = SECINITSID_UNLABELED;
@@ -1385,7 +1384,9 @@ static int selinux_genfs_get_sid(struct dentry *dentry,
return rc;
}
-static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
+static int inode_doinit_use_xattr(struct selinux_state *state,
+ struct inode *inode,
+ struct dentry *dentry,
u32 def_sid, u32 *sid)
{
#define INITCONTEXTLEN 255
@@ -1428,8 +1429,8 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
return 0;
}
- rc = security_context_to_sid_default(current_selinux_state, context, rc,
- sid, def_sid, GFP_NOFS);
+ rc = security_context_to_sid_default(state, context, rc, sid,
+ def_sid, GFP_NOFS);
if (rc) {
char *dev = inode->i_sb->s_id;
unsigned long ino = inode->i_ino;
@@ -1449,6 +1450,7 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
/* The inode's security attributes must be initialized before first use. */
static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
{
+ struct selinux_state *state = current_selinux_state;
struct superblock_security_struct *sbsec = NULL;
struct inode_security_struct *isec = selinux_inode(inode);
u32 task_sid, sid = 0;
@@ -1466,8 +1468,14 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
if (isec->sclass == SECCLASS_FILE)
isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ /*
+ * Find an initialized state to use.
+ */
+ while (state && !selinux_initialized(state))
+ state = state->parent;
+
sbsec = selinux_superblock(inode->i_sb);
- if (!(sbsec->flags & SE_SBINITIALIZED)) {
+ if (!state || !(sbsec->flags & SE_SBINITIALIZED)) {
/* Defer initialization until selinux_complete_init,
after the initial policy is loaded and the security
server is ready to handle calls. */
@@ -1524,8 +1532,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
goto out_invalid;
}
- rc = inode_doinit_use_xattr(inode, dentry, sbsec->def_sid,
- &sid);
+ rc = inode_doinit_use_xattr(state, inode, dentry,
+ sbsec->def_sid, &sid);
dput(dentry);
if (rc)
goto out;
@@ -1538,8 +1546,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
sid = sbsec->sid;
/* Try to obtain a transition SID. */
- rc = security_transition_sid(current_selinux_state, task_sid, sid,
- sclass, NULL, &sid);
+ rc = security_transition_sid(state, task_sid, sid, sclass,
+ NULL, &sid);
if (rc)
goto out;
break;
@@ -1552,7 +1560,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
if ((sbsec->flags & SE_SBGENFS) &&
(!S_ISLNK(inode->i_mode) ||
- selinux_policycap_genfs_seclabel_symlinks())) {
+ selinux_policycap_genfs_seclabel_symlinks(state))) {
/* We must have a dentry to determine the label on
* procfs inodes */
if (opt_dentry) {
@@ -1579,7 +1587,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
*/
if (!dentry)
goto out_invalid;
- rc = selinux_genfs_get_sid(dentry, sclass,
+ rc = selinux_genfs_get_sid(state, dentry, sclass,
sbsec->flags, &sid);
if (rc) {
dput(dentry);
@@ -1588,8 +1596,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
if ((sbsec->flags & SE_SBGENFS_XATTR) &&
(inode->i_opflags & IOP_XATTR)) {
- rc = inode_doinit_use_xattr(inode, dentry,
- sid, &sid);
+ rc = inode_doinit_use_xattr(state, inode,
+ dentry, sid,
+ &sid);
if (rc) {
dput(dentry);
goto out;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 329b1fe48057..c4a0766aa24e 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -261,11 +261,11 @@ static inline bool selinux_policycap_nnp_nosuid_transition(void)
->policycap[POLICYDB_CAP_NNP_NOSUID_TRANSITION]);
}
-static inline bool selinux_policycap_genfs_seclabel_symlinks(void)
+static inline bool
+selinux_policycap_genfs_seclabel_symlinks(struct selinux_state *state)
{
return READ_ONCE(
- current_selinux_state
- ->policycap[POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS]);
+ state->policycap[POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS]);
}
static inline bool selinux_policycap_ioctl_skip_cloexec(void)
--
2.50.1
next prev parent reply other threads:[~2025-08-14 13:27 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-14 13:25 [PATCH v7 00/42] SELinux namespace support Stephen Smalley
2025-08-14 13:25 ` [PATCH v7 01/42] selinux: restore passing of selinux_state Stephen Smalley
2025-08-14 13:25 ` [PATCH v7 02/42] selinux: introduce current_selinux_state Stephen Smalley
2025-08-14 13:25 ` [PATCH v7 03/42] selinux: support multiple selinuxfs instances Stephen Smalley
2025-08-14 13:25 ` [PATCH v7 04/42] selinux: dynamically allocate selinux namespace Stephen Smalley
2025-08-14 13:25 ` [PATCH v7 05/42] netstate,selinux: create the selinux netlink socket per network namespace Stephen Smalley
2025-08-14 13:25 ` [PATCH v7 06/42] selinux: limit selinux netlink notifications to init namespace Stephen Smalley
2025-08-14 13:25 ` [PATCH v7 07/42] selinux: support per-task/cred selinux namespace Stephen Smalley
2025-08-14 13:25 ` [PATCH v7 08/42] selinux: introduce cred_selinux_state() and use it Stephen Smalley
2025-08-14 13:26 ` Stephen Smalley [this message]
2025-08-14 13:26 ` [PATCH v7 10/42] selinux: add a selinuxfs interface to unshare selinux namespace Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 11/42] selinux: add limits for SELinux namespaces Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 12/42] selinux: exempt creation of init SELinux namespace from limits Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 13/42] selinux: refactor selinux_state_create() Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 14/42] selinux: allow userspace to detect non-init SELinux namespace Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 15/42] selinuxfs: restrict write operations to the same selinux namespace Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 16/42] selinux: introduce a global SID table Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 17/42] selinux: wrap security server interfaces to use the " Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 18/42] selinux: introduce a Kconfig option for SELinux namespaces Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 19/42] selinux: eliminate global SID table if !CONFIG_SECURITY_SELINUX_NS Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 20/42] selinux: maintain a small cache in the global SID table Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 21/42] selinux: update hook functions to use correct selinux namespace Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 22/42] selinux: introduce cred_task_has_perm() Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 23/42] selinux: introduce cred_has_extended_perms() Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 24/42] selinux: introduce cred_self_has_perm() Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 25/42] selinux: introduce cred_has_perm() Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 26/42] selinux: introduce cred_ssid_has_perm() and cred_other_has_perm() Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 27/42] selinux: introduce task_obj_has_perm() Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 28/42] selinux: update bprm hooks for selinux namespaces Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 29/42] selinux: add kerneldoc to new permission checking functions Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 30/42] selinux: convert selinux_file_send_sigiotask() to namespace-aware helper Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 31/42] selinux: rename cred_has_perm*() to cred_tsid_has_perm*() Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 32/42] selinux: update cred_tsid_has_perm_noaudit() to return the combined avd Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 33/42] selinux: convert additional checks to cred_ssid_has_perm() Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 34/42] selinux: introduce selinux_state_has_perm() Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 35/42] selinux: annotate selinuxfs permission checks Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 36/42] selinux: annotate process transition " Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 37/42] selinux: convert xfrm and netlabel " Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 38/42] selinux: switch selinux_lsm_setattr() checks to current namespace Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 39/42] selinux: make open_perms namespace-aware Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 40/42] selinux: split cred_ssid_has_perm() into two cases Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 41/42] selinux: convert nlmsg_sock_has_extended_perms() to namespace-aware Stephen Smalley
2025-08-14 13:26 ` [PATCH v7 42/42] selinux: disallow writes to /sys/fs/selinux/user in non-init namespaces 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=20250814132637.1659-10-stephen.smalley.work@gmail.com \
--to=stephen.smalley.work@gmail.com \
--cc=horms@kernel.org \
--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).