selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 1/2] nspawn: add --selinux-namespace option to unshare SELinux namespace
@ 2025-09-19 12:21 Stephen Smalley
  2025-09-19 12:21 ` [RFC PATCH 2/2] systemd: perform SELinux initialization again in a " Stephen Smalley
  0 siblings, 1 reply; 4+ messages in thread
From: Stephen Smalley @ 2025-09-19 12:21 UTC (permalink / raw)
  To: selinux; +Cc: Stephen Smalley

RFC only, this demonstrates how to use the selinux_unshare(3) API
added to libselinux by
https://lore.kernel.org/selinux/20250918135118.9896-2-stephen.smalley.work@gmail.com/

and integrates it into systemd-nspawn to support launching containers
with their own SELinux namespace.

Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
---
 src/nspawn/nspawn.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 2dcab7d379..9c4bcb7688 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -138,6 +138,7 @@ static char *arg_machine = NULL;     /* The name used by the host to refer to th
 static char *arg_hostname = NULL;    /* The name the payload sees by default */
 static const char *arg_selinux_context = NULL;
 static const char *arg_selinux_apifs_context = NULL;
+static bool arg_selinux_namespace = false;
 static char *arg_slice = NULL;
 static bool arg_private_network; /* initialized depending on arg_privileged in run() */
 static bool arg_read_only = false;
@@ -422,6 +423,7 @@ static int help(void) {
                "  -L --selinux-apifs-context=SECLABEL\n"
                "                            Set the SELinux security context to be used by\n"
                "                            API/tmpfs file systems in the container\n"
+               "     --selinux-namespace    Unshare SELinux namespace\n"
                "\n%3$sResources:%4$s\n"
                "     --rlimit=NAME=LIMIT    Set a resource limit for the payload\n"
                "     --oom-score-adjust=VALUE\n"
@@ -639,6 +641,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_OVERLAY,
                 ARG_OVERLAY_RO,
                 ARG_INACCESSIBLE,
+                ARG_SELINUX_NAMESPACE,
                 ARG_SHARE_SYSTEM,
                 ARG_REGISTER,
                 ARG_KEEP_UNIT,
@@ -714,6 +717,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "setenv",                 required_argument, NULL, 'E'                        },
                 { "selinux-context",        required_argument, NULL, 'Z'                        },
                 { "selinux-apifs-context",  required_argument, NULL, 'L'                        },
+                { "selinux-namespace",      no_argument,       NULL, ARG_SELINUX_NAMESPACE      },
                 { "quiet",                  no_argument,       NULL, 'q'                        },
                 { "share-system",           no_argument,       NULL, ARG_SHARE_SYSTEM           }, /* not documented */
                 { "register",               required_argument, NULL, ARG_REGISTER               },
@@ -986,6 +990,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_selinux_apifs_context = optarg;
                         break;
 
+                case ARG_SELINUX_NAMESPACE:
+                        arg_selinux_namespace = true;
+                        break;
+
                 case ARG_READ_ONLY:
                         arg_read_only = true;
                         arg_settings_mask |= SETTING_READ_ONLY;
@@ -3257,6 +3265,7 @@ static int inner_child(
                 NULL, /* NOTIFY_SOCKET */
                 NULL, /* CREDENTIALS_DIRECTORY */
                 NULL, /* LANG */
+                NULL, /* SELINUXNS */
                 NULL
         };
         const char *exec_target;
@@ -3468,6 +3477,9 @@ static int inner_child(
         if (arg_selinux_context)
                 if (setexeccon(arg_selinux_context) < 0)
                         return log_error_errno(errno, "setexeccon(\"%s\") failed: %m", arg_selinux_context);
+        if (arg_selinux_namespace)
+                if (selinux_unshare() < 0)
+                        return log_error_errno(errno, "selinux_unshare() failed: %m");
 #endif
 
         /* Make sure we keep the caps across the uid/gid dropping, so that we can retain some selected caps
@@ -3545,6 +3557,15 @@ static int inner_child(
                 n_env++;
         }
 
+#if HAVE_SELINUX
+        if (arg_selinux_namespace) {
+                envp[n_env] = strdup("SELINUXNS=1");
+                if (!envp[n_env])
+                        return log_oom();
+                n_env++;
+        }
+#endif
+
         env_use = strv_env_merge(envp, os_release_pairs, arg_setenv);
         if (!env_use)
                 return log_oom();
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-09-19 12:40 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-19 12:21 [RFC PATCH 1/2] nspawn: add --selinux-namespace option to unshare SELinux namespace Stephen Smalley
2025-09-19 12:21 ` [RFC PATCH 2/2] systemd: perform SELinux initialization again in a " Stephen Smalley
2025-09-19 12:36   ` Christian Göttsche
2025-09-19 12:40     ` Stephen Smalley

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).