exec: Add SELinuxContext configuration item
authorMichael Scherer <misc@zarb.org>
Thu, 6 Feb 2014 09:05:16 +0000 (10:05 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 10 Feb 2014 12:18:16 +0000 (13:18 +0100)
This permit to let system administrators decide of the domain of a service.
This can be used with templated units to have each service in a diffĂ©rent
domain ( for example, a per customer database, using MLS or anything ),
or can be used to force a non selinux enabled system (jvm, erlang, etc)
to start in a different domain for each service.

man/systemd.exec.xml
src/core/dbus-execute.c
src/core/execute.c
src/core/execute.h
src/core/load-fragment-gperf.gperf.m4
src/shared/exit-status.c
src/shared/exit-status.h

index 7eaf52b..4281c03 100644 (file)
                         </varlistentry>
 
                         <varlistentry>
+                                <term><varname>SELinuxContext=</varname></term>
+
+                                <listitem><para>Set the SELinux context of the
+                                executed process. If set, this will override the
+                                automated domain transition. However, the policy
+                                still need to autorize the transition. See
+                                <citerefentry><refentrytitle>setexeccon</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+                                for details.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><varname>IgnoreSIGPIPE=</varname></term>
 
                                 <listitem><para>Takes a boolean
index 4236b98..db16990 100644 (file)
@@ -419,6 +419,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("SELinuxContext", "s", NULL, offsetof(ExecContext, selinux_context), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SystemCallFilter", "au", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
index 91e4352..c02c768 100644 (file)
 #include <security/pam_appl.h>
 #endif
 
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#endif
+
 #include "execute.h"
 #include "strv.h"
 #include "macro.h"
@@ -1564,6 +1568,20 @@ int exec_spawn(ExecCommand *command,
                                         goto fail_child;
                                 }
                         }
+#ifdef HAVE_SELINUX
+                        if (context->selinux_context) {
+                                err = security_check_context(context->selinux_context);
+                                if (err < 0) {
+                                        r = EXIT_SELINUX_CONTEXT;
+                                        goto fail_child;
+                                }
+                                err = setexeccon(context->selinux_context);
+                                if (err < 0) {
+                                        r = EXIT_SELINUX_CONTEXT;
+                                        goto fail_child;
+                                }
+                        }
+#endif
                 }
 
                 err = build_environment(context, n_fds, watchdog_usec, home, username, shell, &our_env);
@@ -1722,6 +1740,9 @@ void exec_context_done(ExecContext *c) {
         free(c->utmp_id);
         c->utmp_id = NULL;
 
+        free(c->selinux_context);
+        c->selinux_context = NULL;
+
         free(c->syscall_filter);
         c->syscall_filter = NULL;
 }
@@ -2091,6 +2112,12 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
                 fprintf(f,
                         "%sUtmpIdentifier: %s\n",
                         prefix, c->utmp_id);
+
+        if (c->selinux_context)
+                fprintf(f,
+                        "%sSELinuxContext: %s\n",
+                        prefix, c->selinux_context);
+
 }
 
 void exec_status_start(ExecStatus *s, pid_t pid) {
index 4851152..be811a9 100644 (file)
@@ -133,6 +133,8 @@ struct ExecContext {
 
         char *utmp_id;
 
+        char *selinux_context;
+
         char **read_write_dirs, **read_only_dirs, **inaccessible_dirs;
         unsigned long mount_flags;
 
index 59b2a64..7d40578 100644 (file)
@@ -76,7 +76,8 @@ $1.MountFlags,                   config_parse_exec_mount_flags,      0,
 $1.TCPWrapName,                  config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.tcpwrap_name)
 $1.PAMName,                      config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.pam_name)
 $1.IgnoreSIGPIPE,                config_parse_bool,                  0,                             offsetof($1, exec_context.ignore_sigpipe)
-$1.UtmpIdentifier,               config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.utmp_id)'
+$1.UtmpIdentifier,               config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.utmp_id)
+$1.SELinuxContext,               config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.selinux_context)'
 )m4_dnl
 m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
 `$1.SendSIGKILL,                 config_parse_bool,                  0,                             offsetof($1, kill_context.send_sigkill)
index ef2d63f..70789f5 100644 (file)
@@ -130,6 +130,9 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
 
                 case EXIT_SECCOMP:
                         return "SECCOMP";
+
+                case EXIT_SELINUX_CONTEXT:
+                        return "SELINUX_CONTEXT";
                 }
         }
 
index 1ecf9d5..e84bfe3 100644 (file)
@@ -67,7 +67,8 @@ typedef enum ExitStatus {
         EXIT_NETWORK,
         EXIT_NAMESPACE,
         EXIT_NO_NEW_PRIVILEGES,
-        EXIT_SECCOMP
+        EXIT_SECCOMP,
+        EXIT_SELINUX_CONTEXT
 } ExitStatus;
 
 typedef enum ExitStatusLevel {