84b277
From d0a2b8832732d297321fddcad56872511ff212f2 Mon Sep 17 00:00:00 2001
84b277
From: Michael Scherer <misc@zarb.org>
84b277
Date: Thu, 6 Feb 2014 10:05:16 +0100
84b277
Subject: [PATCH] exec: Add SELinuxContext configuration item
84b277
MIME-Version: 1.0
84b277
Content-Type: text/plain; charset=UTF-8
84b277
Content-Transfer-Encoding: 8bit
84b277
84b277
This permit to let system administrators decide of the domain of a service.
84b277
This can be used with templated units to have each service in a différent
84b277
domain ( for example, a per customer database, using MLS or anything ),
84b277
or can be used to force a non selinux enabled system (jvm, erlang, etc)
84b277
to start in a different domain for each service.
84b277
84b277
Conflicts:
84b277
        src/core/dbus-execute.c
84b277
        src/core/execute.c
84b277
        src/core/execute.h
84b277
        src/shared/exit-status.c
84b277
        src/shared/exit-status.h
84b277
84b277
(cherry picked from commit 7b52a628f8b43ba521c302a7f32bccf9d0dc8bfd)
84b277
84b277
Related: #1113790
84b277
---
84b277
 man/systemd.exec.xml                  | 11 +++++++++++
84b277
 src/core/dbus-execute.c               |  1 +
84b277
 src/core/execute.c                    | 27 +++++++++++++++++++++++++++
84b277
 src/core/execute.h                    |  2 ++
84b277
 src/core/load-fragment-gperf.gperf.m4 |  3 ++-
84b277
 src/shared/exit-status.c              |  3 +++
84b277
 src/shared/exit-status.h              |  1 +
84b277
 7 files changed, 47 insertions(+), 1 deletion(-)
84b277
84b277
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
84b277
index 612b4d2..a68cfa7 100644
84b277
--- a/man/systemd.exec.xml
84b277
+++ b/man/systemd.exec.xml
84b277
@@ -919,6 +919,17 @@
84b277
                         </varlistentry>
84b277
 
84b277
                         <varlistentry>
84b277
+                                <term><varname>SELinuxContext=</varname></term>
84b277
+
84b277
+                                <listitem><para>Set the SELinux context of the
84b277
+                                executed process. If set, this will override the
84b277
+                                automated domain transition. However, the policy
84b277
+                                still need to autorize the transition. See
84b277
+                                <citerefentry><refentrytitle>setexeccon</refentrytitle><manvolnum>3</manvolnum></citerefentry>
84b277
+                                for details.</para></listitem>
84b277
+                        </varlistentry>
84b277
+
84b277
+                        <varlistentry>
84b277
                                 <term><varname>IgnoreSIGPIPE=</varname></term>
84b277
 
84b277
                                 <listitem><para>Takes a boolean
84b277
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
84b277
index 2402e8c..97d75fa 100644
84b277
--- a/src/core/dbus-execute.c
84b277
+++ b/src/core/dbus-execute.c
84b277
@@ -429,6 +429,7 @@ const BusProperty bus_exec_context_properties[] = {
84b277
         { "PrivateNetwork",           bus_property_append_bool,              "b", offsetof(ExecContext, private_network)              },
84b277
         { "SameProcessGroup",         bus_property_append_bool,              "b", offsetof(ExecContext, same_pgrp)                    },
84b277
         { "UtmpIdentifier",           bus_property_append_string,            "s", offsetof(ExecContext, utmp_id),                true },
84b277
+        { "SELinuxContext",           bus_property_append_string,            "s", offsetof(ExecContext, selinux_context),        true },
84b277
         { "IgnoreSIGPIPE",            bus_property_append_bool,              "b", offsetof(ExecContext, ignore_sigpipe)               },
84b277
         { "NoNewPrivileges",          bus_property_append_bool,              "b", offsetof(ExecContext, no_new_privileges)            },
84b277
         { "SystemCallFilter",         bus_execute_append_syscall_filter,    "au", 0                                                   },
84b277
diff --git a/src/core/execute.c b/src/core/execute.c
84b277
index 981b9e4..cf9d24e 100644
84b277
--- a/src/core/execute.c
84b277
+++ b/src/core/execute.c
84b277
@@ -46,6 +46,10 @@
84b277
 #include <security/pam_appl.h>
84b277
 #endif
84b277
 
84b277
+#ifdef HAVE_SELINUX
84b277
+#include <selinux/selinux.h>
84b277
+#endif
84b277
+
84b277
 #include "execute.h"
84b277
 #include "strv.h"
84b277
 #include "macro.h"
84b277
@@ -1467,6 +1471,20 @@ int exec_spawn(ExecCommand *command,
84b277
                                         goto fail_child;
84b277
                                 }
84b277
                         }
84b277
+#ifdef HAVE_SELINUX
84b277
+                        if (context->selinux_context) {
84b277
+                                err = security_check_context(context->selinux_context);
84b277
+                                if (err < 0) {
84b277
+                                        r = EXIT_SELINUX_CONTEXT;
84b277
+                                        goto fail_child;
84b277
+                                }
84b277
+                                err = setexeccon(context->selinux_context);
84b277
+                                if (err < 0) {
84b277
+                                        r = EXIT_SELINUX_CONTEXT;
84b277
+                                        goto fail_child;
84b277
+                                }
84b277
+                        }
84b277
+#endif
84b277
                 }
84b277
 
84b277
                 our_env = new0(char*, 7);
84b277
@@ -1696,6 +1714,9 @@ void exec_context_done(ExecContext *c, bool reloading_or_reexecuting) {
84b277
         free(c->utmp_id);
84b277
         c->utmp_id = NULL;
84b277
 
84b277
+        free(c->selinux_context);
84b277
+        c->selinux_context = NULL;
84b277
+
84b277
         free(c->syscall_filter);
84b277
         c->syscall_filter = NULL;
84b277
 
84b277
@@ -2067,6 +2088,12 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
84b277
                 fprintf(f,
84b277
                         "%sUtmpIdentifier: %s\n",
84b277
                         prefix, c->utmp_id);
84b277
+
84b277
+        if (c->selinux_context)
84b277
+                fprintf(f,
84b277
+                        "%sSELinuxContext: %s\n",
84b277
+                        prefix, c->selinux_context);
84b277
+
84b277
 }
84b277
 
84b277
 void exec_status_start(ExecStatus *s, pid_t pid) {
84b277
diff --git a/src/core/execute.h b/src/core/execute.h
84b277
index c1e9717..92ac8dd 100644
84b277
--- a/src/core/execute.h
84b277
+++ b/src/core/execute.h
84b277
@@ -124,6 +124,8 @@ struct ExecContext {
84b277
 
84b277
         char *utmp_id;
84b277
 
84b277
+        char *selinux_context;
84b277
+
84b277
         char **read_write_dirs, **read_only_dirs, **inaccessible_dirs;
84b277
         unsigned long mount_flags;
84b277
 
84b277
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
84b277
index 0991cb9..935f04e 100644
84b277
--- a/src/core/load-fragment-gperf.gperf.m4
84b277
+++ b/src/core/load-fragment-gperf.gperf.m4
84b277
@@ -75,7 +75,8 @@ $1.MountFlags,                   config_parse_exec_mount_flags,      0,
84b277
 $1.TCPWrapName,                  config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.tcpwrap_name)
84b277
 $1.PAMName,                      config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.pam_name)
84b277
 $1.IgnoreSIGPIPE,                config_parse_bool,                  0,                             offsetof($1, exec_context.ignore_sigpipe)
84b277
-$1.UtmpIdentifier,               config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.utmp_id)'
84b277
+$1.UtmpIdentifier,               config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.utmp_id)
84b277
+$1.SELinuxContext,               config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.selinux_context)'
84b277
 )m4_dnl
84b277
 m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
84b277
 `$1.SendSIGKILL,                 config_parse_bool,                  0,                             offsetof($1, kill_context.send_sigkill)
84b277
diff --git a/src/shared/exit-status.c b/src/shared/exit-status.c
84b277
index f15fdba..676291b 100644
84b277
--- a/src/shared/exit-status.c
84b277
+++ b/src/shared/exit-status.c
84b277
@@ -131,6 +131,9 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
84b277
                 case EXIT_SECCOMP:
84b277
                         return "SECCOMP";
84b277
 
84b277
+                case EXIT_SELINUX_CONTEXT:
84b277
+                        return "SELINUX_CONTEXT";
84b277
+
84b277
                 case EXIT_CHOWN:
84b277
                         return "CHOWN";
84b277
 
84b277
diff --git a/src/shared/exit-status.h b/src/shared/exit-status.h
84b277
index 52dd3d0..798f1e1 100644
84b277
--- a/src/shared/exit-status.h
84b277
+++ b/src/shared/exit-status.h
84b277
@@ -68,6 +68,7 @@ typedef enum ExitStatus {
84b277
         EXIT_NAMESPACE,
84b277
         EXIT_NO_NEW_PRIVILEGES,
84b277
         EXIT_SECCOMP,
84b277
+        EXIT_SELINUX_CONTEXT,
84b277
         EXIT_CHOWN
84b277
 } ExitStatus;
84b277