summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Scherer <misc@zarb.org>2014-02-06 10:05:16 +0100
committerLennart Poettering <lennart@poettering.net>2014-02-10 13:18:16 +0100
commit7b52a628f8b43ba521c302a7f32bccf9d0dc8bfd (patch)
treed23ed2ee1153ffa4e45c1752a077ae2df6901a36
parent36e0e6311bb4df37385db19b5eca03973b26b5ff (diff)
exec: Add SELinuxContext configuration item
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.
-rw-r--r--man/systemd.exec.xml11
-rw-r--r--src/core/dbus-execute.c1
-rw-r--r--src/core/execute.c27
-rw-r--r--src/core/execute.h2
-rw-r--r--src/core/load-fragment-gperf.gperf.m43
-rw-r--r--src/shared/exit-status.c3
-rw-r--r--src/shared/exit-status.h3
7 files changed, 48 insertions, 2 deletions
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index 7eaf52bc5..4281c03cf 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -951,6 +951,17 @@
</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
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 4236b9808..db1699023 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -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),
diff --git a/src/core/execute.c b/src/core/execute.c
index 91e4352f9..c02c768c6 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -47,6 +47,10 @@
#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) {
diff --git a/src/core/execute.h b/src/core/execute.h
index 485115274..be811a97c 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -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;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 59b2a645d..7d405788d 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -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)
diff --git a/src/shared/exit-status.c b/src/shared/exit-status.c
index ef2d63f57..70789f513 100644
--- a/src/shared/exit-status.c
+++ b/src/shared/exit-status.c
@@ -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";
}
}
diff --git a/src/shared/exit-status.h b/src/shared/exit-status.h
index 1ecf9d578..e84bfe370 100644
--- a/src/shared/exit-status.h
+++ b/src/shared/exit-status.h
@@ -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 {