[RFC PATCH] lsm,selinux: introduce LSM_ATTR_UNSHARE and wire it up for SELinux
Stephen Smalley
stephen.smalley.work at gmail.com
Thu Sep 11 14:00:56 UTC 2025
On Thu, Sep 4, 2025 at 10:41 AM Stephen Smalley
<stephen.smalley.work at gmail.com> wrote:
>
> On Wed, Sep 3, 2025 at 3:28 PM Stephen Smalley
> <stephen.smalley.work at gmail.com> wrote:
> >
> > In the hopes of nudging the conversation in [1] in a more focused
> > direction with a goal of getting SELinux namespaces upstreamed, this
> > RFC provides a starting point for a concrete discussion. This is RFC
> > only and has only been build-tested thus far.
> >
> > This defines a new LSM_ATTR_UNSHARE attribute for the
> > lsm_set_self_attr(2) system call and wires it up for SELinux to invoke
> > the underlying function for unsharing the SELinux namespace. As with
> > the selinuxfs interface, this immediately unshares the SELinux
> > namespace of the current process just like an unshare(2) system call
> > would do for other namespaces. I have not yet explored the
> > alternatives of deferring the unshare to the next unshare(2),
> > clone(2), or execve(2) call and would want to first confirm that doing
> > so does not introduce any issues in the kernel or make it harder to
> > integrate with existing container runtimes.
> >
> > Differences between this syscall interface and the selinuxfs interface
> > that need discussion before moving forward:
> >
> > 1. The syscall interface does not currently check any Linux capability
> > or DAC permissions, whereas the selinuxfs interface can only be set by
> > uid-0 or CAP_DAC_OVERRIDE processes. We need to decide what if any
> > capability or DAC check should apply to this syscall interface and if
> > any, add the checks to either the LSM framework code or to the SELinux
> > hook function.
> >
> > Pros: Checking a capability or DAC permissions prevents misuse of this
> > interface by unprivileged processes, particularly on systems with
> > policies that do not yet define any of the new SELinux permissions
> > introduced for controlling this operation. This is a potential concern
> > on Linux distributions that do not tightly coordinate kernel updates
> > with policy updates (or where users may choose to deploy upstream
> > kernels on their own), but not on Android.
> >
> > Cons: Checking a capability or DAC permissions requires any process
> > that uses this facility to have the corresponding capability or
> > permissions, which might otherwise be unnecessary and create
> > additional risks. This is less likely if we use a capability already
> > required by container runtimes and similar components that might
> > leverage this facility for unsharing SELinux namespaces.
> >
> > 2. The syscall interface checks a new SELinux unshare_selinuxns
> > permission in the process2 class between the task SID and itself,
> > similar to other checks for setting process attributes. This means
> > that:
> > allow domain self:process2 *; -or-
> > allow domain self:process2 ~anything-other-than-unshare_selinuxns; -or-
> > allow domain self:process2 unshare_selinuxns;
> > would allow a process to unshare its SELinux namespace.
> >
> > The selinuxfs interface checks a new unshare permission in the
> > security class between the task SID and the security initial SID,
> > likewise similar to other checks for setting selinuxfs attributes.
> > This means that:
> > allow domain security_t:security *; -or-
> > allow domain security_t:security ~anything-other-than-unshare; -or-
> > allow domain security_t:security unshare;
> > would allow a process to unshare its SELinux namespace.
> >
> > Technically, the selinuxfs interface also currently requires open and
> > write access to the selinuxfs node; hence:
> > allow domain security_t:file { open write };
> > is also required for the selinuxfs interface.
> >
> > We need to decide what we want the SELinux check(s) to be for the
> > syscall and whether it should be more like the former (process
> > attributes) or more like the latter (security policy settings). Note
> > that the permission name itself is unimportant here and only differs
> > because it seemed less evident in the process2 class that we are
> > talking about a SELinux namespace otherwise.
> >
> > Regardless, either form of allow rule can be prohibited in policies
> > via neverallow rules on systems that enforce their usage
> > (e.g. Android, not necessarily on Linux distributions).
> >
> > 3. The selinuxfs interface currently offers more functionality than I
> > have implemented here for the sycall interface, including:
> >
> > a) the ability to read the selinuxfs node to see if your namespace has
> > been unshared, which should be easily implementable via
> > lsm_get_self_attr(2). However, questions remain as to when that
> > should return 1 versus 0 (currently returns 1 whenever your namespace
> > is NOT the initial SELinux namespace, useful for the testsuite to
> > detect it is in a child, but could instead be reset to 0 by a
> > subsequent policy load to indicate completion of the setup of the
> > namespace, thus hiding from child processes that they are in a child
> > namespace once its policy has been loaded).
> >
> > b) the abilities to get and set the maximum number of SELinux
> > namespaces (via a /sys/fs/selinux/maxns node) and to get and set the
> > maximum depth for SELinux namespaces (via a /sys/fs/selinux/maxnsdepth
> > node). These could be left in selinuxfs or migrated to some other LSM
> > management APIs since they are global in scope, not per-process
> > attributes.
> >
> > Signed-off-by: Stephen Smalley <stephen.smalley.work at gmail.com>
Gentle ping on this RFC, happy to update and re-submit whenever.
> > ---
> > include/uapi/linux/lsm.h | 1 +
> > security/selinux/hooks.c | 8 ++++++++
> > security/selinux/include/classmap.h | 4 +++-
> > 3 files changed, 12 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h
> > index 938593dfd5da..fb1b4a8aa639 100644
> > --- a/include/uapi/linux/lsm.h
> > +++ b/include/uapi/linux/lsm.h
> > @@ -83,6 +83,7 @@ struct lsm_ctx {
> > #define LSM_ATTR_KEYCREATE 103
> > #define LSM_ATTR_PREV 104
> > #define LSM_ATTR_SOCKCREATE 105
> > +#define LSM_ATTR_UNSHARE 106
> >
> > /*
> > * LSM_FLAG_XXX definitions identify special handling instructions
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index c544b3e2fd5c..11b0b3c5b74a 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -6812,6 +6812,10 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size)
> > error = avc_has_perm(state, mysid, mysid, SECCLASS_PROCESS,
> > PROCESS__SETCURRENT, NULL);
> > break;
> > + case LSM_ATTR_UNSHARE:
> > + error = avc_has_perm(state, mysid, mysid, SECCLASS_PROCESS,
>
> Ignore the obvious typo here (should be SECCLASS_PROCESS2 above). Will
> be fixed before submission. Otherwise, the RFC remains the same.
>
> > + PROCESS2__UNSHARE_SELINUXNS, NULL);
> > + break;
> > default:
> > error = -EOPNOTSUPP;
> > break;
> > @@ -6923,6 +6927,10 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size)
> > }
> >
> > tsec->sid = sid;
> > + } else if (attr == LSM_ATTR_UNSHARE) {
> > + error = selinux_state_create(new);
> > + if (error)
> > + goto abort_change;
> > } else {
> > error = -EINVAL;
> > goto abort_change;
> > diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
> > index be52ebb6b94a..07fe316308cd 100644
> > --- a/security/selinux/include/classmap.h
> > +++ b/security/selinux/include/classmap.h
> > @@ -60,7 +60,9 @@ const struct security_class_mapping secclass_map[] = {
> > "siginh", "setrlimit", "rlimitinh", "dyntransition",
> > "setcurrent", "execmem", "execstack", "execheap",
> > "setkeycreate", "setsockcreate", "getrlimit", NULL } },
> > - { "process2", { "nnp_transition", "nosuid_transition", NULL } },
> > + { "process2",
> > + { "nnp_transition", "nosuid_transition", "unshare_selinuxns",
> > + NULL } },
> > { "system",
> > { "ipc_info", "syslog_read", "syslog_mod", "syslog_console",
> > "module_request", "module_load", "firmware_load",
> > --
> > 2.51.0
> >
More information about the Linux-security-module-archive
mailing list