summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.exec.xml29
-rw-r--r--src/core/dbus-execute.c19
-rw-r--r--src/core/execute.c11
-rw-r--r--src/core/execute.h3
-rw-r--r--src/core/load-fragment-gperf.gperf.m47
-rw-r--r--src/core/load-fragment.c50
-rw-r--r--src/core/load-fragment.h1
-rw-r--r--src/shared/exit-status.h1
-rw-r--r--src/shared/smack-util.c20
-rw-r--r--src/shared/smack-util.h1
10 files changed, 140 insertions, 2 deletions
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index e9af4abd6d..0747d0e1f9 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -1138,6 +1138,35 @@
</varlistentry>
<varlistentry>
+ <term><varname>SmackProcessLabel=</varname></term>
+
+ <listitem><para>Takes a
+ <option>SMACK64</option> security
+ label as argument. The process
+ executed by the unit will be started
+ under this label and SMACK will decide
+ whether the processes is allowed to
+ run or not based on it. The process
+ will continue to run under the label
+ specified here unless the executable
+ has its own
+ <option>SMACK64EXEC</option> label, in
+ which case the process will transition
+ to run under that label. When not
+ specified, the label that systemd is
+ running under is used. This directive
+ is ignored if SMACK is
+ disabled.</para>
+
+ <para>The value may be prefixed by
+ <literal>-</literal>, in which case
+ all errors will be ignored. An empty
+ value may be specified to unset
+ previous assignments.</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 9276da4cdc..bbcd6106ad 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -508,6 +508,24 @@ static int property_get_apparmor_profile(
return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
}
+static int property_get_smack_process_label(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ExecContext *c = userdata;
+
+ assert(bus);
+ assert(reply);
+ assert(c);
+
+ return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
+}
+
static int property_get_personality(
sd_bus *bus,
const char *path,
@@ -636,6 +654,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, 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", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
diff --git a/src/core/execute.c b/src/core/execute.c
index 5cfd4a1f97..e6c19993ae 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -83,6 +83,7 @@
#include "af-list.h"
#include "mkdir.h"
#include "apparmor-util.h"
+#include "smack-util.h"
#include "bus-kernel.h"
#include "label.h"
@@ -1618,6 +1619,16 @@ static int exec_child(ExecCommand *command,
}
}
+#ifdef HAVE_SMACK
+ if (context->smack_process_label) {
+ err = mac_smack_apply_pid(0, context->smack_process_label);
+ if (err < 0) {
+ *error = EXIT_SMACK_PROCESS_LABEL;
+ return err;
+ }
+ }
+#endif
+
if (context->user) {
err = enforce_user(context, uid);
if (err < 0) {
diff --git a/src/core/execute.h b/src/core/execute.h
index b16a24d0c6..5ed750534d 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -142,6 +142,9 @@ struct ExecContext {
bool apparmor_profile_ignore;
char *apparmor_profile;
+ bool smack_process_label_ignore;
+ char *smack_process_label;
+
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 1d2debe70f..a94b805b4b 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -95,8 +95,11 @@ m4_ifdef(`HAVE_SELINUX',
`$1.SELinuxContext, config_parse_exec_selinux_context, 0, offsetof($1, exec_context)',
`$1.SELinuxContext, config_parse_warn_compat, 0, 0')
m4_ifdef(`HAVE_APPARMOR',
-`$1.AppArmorProfile, config_parse_exec_apparmor_profile,0, offsetof($1, exec_context)',
-`$1.AppArmorProfile, config_parse_warn_compat, 0, 0')'
+`$1.AppArmorProfile, config_parse_exec_apparmor_profile, 0, offsetof($1, exec_context)',
+`$1.AppArmorProfile, config_parse_warn_compat, 0, 0')
+m4_ifdef(`HAVE_SMACK',
+`$1.SmackProcessLabel, config_parse_exec_smack_process_label, 0, offsetof($1, exec_context)',
+`$1.SmackProcessLabel, config_parse_warn_compat, 0, 0')'
)m4_dnl
m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
`$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, kill_context.send_sigkill)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 2ee16bdef9..4309121649 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -1313,6 +1313,56 @@ int config_parse_exec_apparmor_profile(
return 0;
}
+int config_parse_exec_smack_process_label(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ ExecContext *c = data;
+ Unit *u = userdata;
+ bool ignore;
+ char *k;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ free(c->smack_process_label);
+ c->smack_process_label = NULL;
+ c->smack_process_label_ignore = false;
+ return 0;
+ }
+
+ if (rvalue[0] == '-') {
+ ignore = true;
+ rvalue++;
+ } else
+ ignore = false;
+
+ r = unit_name_printf(u, rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve specifiers, ignoring: %s", strerror(-r));
+ return 0;
+ }
+
+ free(c->smack_process_label);
+ c->smack_process_label = k;
+ c->smack_process_label_ignore = ignore;
+
+ return 0;
+}
+
int config_parse_timer(const char *unit,
const char *filename,
unsigned line,
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 65100c9bd7..a799c9a690 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -94,6 +94,7 @@ int config_parse_job_mode_isolate(const char *unit, const char *filename, unsign
int config_parse_exec_selinux_context(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_personality(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_exec_apparmor_profile(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_exec_smack_process_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_address_families(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_runtime_directory(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_set_status(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/shared/exit-status.h b/src/shared/exit-status.h
index f719580426..1d774f25dc 100644
--- a/src/shared/exit-status.h
+++ b/src/shared/exit-status.h
@@ -78,6 +78,7 @@ typedef enum ExitStatus {
EXIT_MAKE_STARTER,
EXIT_CHOWN,
EXIT_BUS_ENDPOINT,
+ EXIT_SMACK_PROCESS_LABEL,
} ExitStatus;
typedef enum ExitStatusLevel {
diff --git a/src/shared/smack-util.c b/src/shared/smack-util.c
index a8dccd1554..b6c96435ce 100644
--- a/src/shared/smack-util.c
+++ b/src/shared/smack-util.c
@@ -25,6 +25,7 @@
#include "util.h"
#include "path-util.h"
+#include "fileio.h"
#include "smack-util.h"
#define SMACK_FLOOR_LABEL "_"
@@ -123,6 +124,25 @@ int mac_smack_apply_ip_in_fd(int fd, const char *label) {
return r;
}
+int mac_smack_apply_pid(pid_t pid, const char *label) {
+ int r = 0;
+ const char *p;
+
+ assert(label);
+
+#ifdef HAVE_SMACK
+ if (!mac_smack_use())
+ return 0;
+
+ p = procfs_file_alloca(pid, "attr/current");
+ r = write_string_file(p, label);
+ if (r < 0)
+ return r;
+#endif
+
+ return r;
+}
+
int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
int r = 0;
diff --git a/src/shared/smack-util.h b/src/shared/smack-util.h
index 68778da38b..50f55b1f4b 100644
--- a/src/shared/smack-util.h
+++ b/src/shared/smack-util.h
@@ -31,5 +31,6 @@ int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
int mac_smack_apply(const char *path, const char *label);
int mac_smack_apply_fd(int fd, const char *label);
+int mac_smack_apply_pid(pid_t pid, const char *label);
int mac_smack_apply_ip_in_fd(int fd, const char *label);
int mac_smack_apply_ip_out_fd(int fd, const char *label);