summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/dbus-execute.c79
-rw-r--r--src/core/execute.c41
-rw-r--r--src/core/execute.h1
-rw-r--r--src/core/load-fragment-gperf.gperf.m42
-rw-r--r--src/core/load-fragment.c55
-rw-r--r--src/core/load-fragment.h1
6 files changed, 161 insertions, 18 deletions
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 435c3d505f..a62f517dc6 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -21,6 +21,10 @@
#include <sys/prctl.h>
+#ifdef HAVE_SECCOMP
+#include <seccomp.h>
+#endif
+
#include "bus-util.h"
#include "missing.h"
#include "ioprio.h"
@@ -31,6 +35,10 @@
#include "capability.h"
#include "env-util.h"
+#ifdef HAVE_SECCOMP
+#include "seccomp-util.h"
+#endif
+
BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
@@ -349,17 +357,25 @@ static int property_get_syscall_filter(
ExecContext *c = userdata;
_cleanup_strv_free_ char **l = NULL;
- _cleanup_free_ char *t = NULL;
+ int r;
+
#ifdef HAVE_SECCOMP
Iterator i;
void *id;
- int r;
#endif
assert(bus);
assert(reply);
assert(c);
+ r = sd_bus_message_open_container(reply, 'r', "bas");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
+ if (r < 0)
+ return r;
+
#ifdef HAVE_SECCOMP
SET_FOREACH(id, c->syscall_filter, i) {
char *name;
@@ -378,22 +394,56 @@ static int property_get_syscall_filter(
strv_sort(l);
- t = strv_join(l, " ");
- if (!t)
- return -ENOMEM;
+ r = sd_bus_message_append_strv(reply, l);
+ if (r < 0)
+ return r;
- if (!c->syscall_whitelist) {
- char *d;
+ return sd_bus_message_close_container(reply);
+}
- d = strappend("~", t);
- if (!d)
- return -ENOMEM;
+static int property_get_syscall_archs(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
- free(t);
- t = d;
+ ExecContext *c = userdata;
+ _cleanup_strv_free_ char **l = NULL;
+ int r;
+
+#ifdef HAVE_SECCOMP
+ Iterator i;
+ void *id;
+#endif
+
+ assert(bus);
+ assert(reply);
+ assert(c);
+
+#ifdef HAVE_SECCOMP
+ SET_FOREACH(id, c->syscall_archs, i) {
+ const char *name;
+
+ name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
+ if (!name)
+ continue;
+
+ r = strv_extend(&l, name);
+ if (r < 0)
+ return -ENOMEM;
}
+#endif
- return sd_bus_message_append(reply, "s", t);
+ strv_sort(l);
+
+ r = sd_bus_message_append_strv(reply, l);
+ if (r < 0)
+ return r;
+
+ return 0;
}
static int property_get_syscall_errno(
@@ -476,7 +526,8 @@ const sd_bus_vtable bus_exec_vtable[] = {
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", "s", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_VTABLE_END
};
diff --git a/src/core/execute.c b/src/core/execute.c
index 4033470e5b..06ddd5c91c 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -77,6 +77,10 @@
#include "selinux-util.h"
#include "errno-list.h"
+#ifdef HAVE_SECCOMP
+#include "seccomp-util.h"
+#endif
+
#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
#define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
@@ -953,8 +957,17 @@ static int apply_seccomp(ExecContext *c) {
if (!seccomp)
return -ENOMEM;
- action = c->syscall_whitelist ? SCMP_ACT_ALLOW : negative_action;
+ SET_FOREACH(id, c->syscall_archs, i) {
+ r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1);
+ if (r == -EEXIST)
+ continue;
+ if (r < 0) {
+ seccomp_release(seccomp);
+ return r;
+ }
+ }
+ action = c->syscall_whitelist ? SCMP_ACT_ALLOW : negative_action;
SET_FOREACH(id, c->syscall_filter, i) {
r = seccomp_rule_add(seccomp, action, PTR_TO_INT(id) - 1, 0);
if (r < 0) {
@@ -1548,7 +1561,7 @@ int exec_spawn(ExecCommand *command,
}
#ifdef HAVE_SECCOMP
- if (context->syscall_filter) {
+ if (context->syscall_filter || context->syscall_archs) {
err = apply_seccomp(context);
if (err < 0) {
r = EXIT_SECCOMP;
@@ -1740,6 +1753,9 @@ void exec_context_done(ExecContext *c) {
#ifdef HAVE_SECCOMP
set_free(c->syscall_filter);
c->syscall_filter = NULL;
+
+ set_free(c->syscall_archs);
+ c->syscall_archs = NULL;
#endif
}
@@ -2122,7 +2138,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
#endif
fprintf(f,
- "%sSystemCallFilter: \n",
+ "%sSystemCallFilter: ",
prefix);
if (!c->syscall_whitelist)
@@ -2137,7 +2153,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
else
fputc(' ', f);
- name = seccomp_syscall_resolve_num_arch(PTR_TO_INT(id)-1, SCMP_ARCH_NATIVE);
+ name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
fputs(strna(name), f);
}
#endif
@@ -2145,6 +2161,23 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
fputc('\n', f);
}
+ if (c->syscall_archs) {
+#ifdef HAVE_SECCOMP
+ Iterator j;
+ void *id;
+#endif
+
+ fprintf(f,
+ "%sSystemCallArchitectures:",
+ prefix);
+
+#ifdef HAVE_SECCOMP
+ SET_FOREACH(id, c->syscall_archs, j)
+ fprintf(f, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id) - 1)));
+#endif
+ fputc('\n', f);
+ }
+
if (c->syscall_errno != 0)
fprintf(f,
"%sSystemCallErrorNumber: %s\n",
diff --git a/src/core/execute.h b/src/core/execute.h
index baf430a047..06b6b3fb2d 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -168,6 +168,7 @@ struct ExecContext {
bool same_pgrp;
Set *syscall_filter;
+ Set *syscall_archs;
int syscall_errno;
bool syscall_whitelist:1;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 16c9e25785..fa559e58f9 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -51,8 +51,10 @@ $1.TimerSlackNSec, config_parse_nsec, 0,
$1.NoNewPrivileges, config_parse_bool, 0, offsetof($1, exec_context.no_new_privileges)
m4_ifdef(`HAVE_SECCOMP',
`$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context)
+$1.SystemCallArchitectures, config_parse_syscall_archs, 0, offsetof($1, exec_context)
$1.SystemCallErrorNumber, config_parse_syscall_errno, 0, offsetof($1, exec_context)',
`$1.SystemCallFilter, config_parse_warn_compat, 0, 0
+$1.SystemCallArchitectures, config_parse_warn_compat, 0, 0
$1.SystemCallErrorNumber, config_parse_warn_compat, 0, 0')
$1.LimitCPU, config_parse_limit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
$1.LimitFSIZE, config_parse_limit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 1b5856e273..ec04ad28ba 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -57,6 +57,10 @@
#include "bus-error.h"
#include "errno-list.h"
+#ifdef HAVE_SECCOMP
+#include "seccomp-util.h"
+#endif
+
#if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP)
int config_parse_warn_compat(
const char *unit,
@@ -2029,6 +2033,57 @@ int config_parse_syscall_filter(
return 0;
}
+int config_parse_syscall_archs(
+ 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;
+ char *w, *state;
+ size_t l;
+ int r;
+
+ if (isempty(rvalue)) {
+ set_free(c->syscall_archs);
+ c->syscall_archs = NULL;
+ return 0;
+ }
+
+ r = set_ensure_allocated(&c->syscall_archs, trivial_hash_func, trivial_compare_func);
+ if (r < 0)
+ return log_oom();
+
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+ _cleanup_free_ char *t = NULL;
+ uint32_t a;
+
+ t = strndup(w, l);
+ if (!t)
+ return log_oom();
+
+ r = seccomp_arch_from_string(t, &a);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call architecture, ignoring: %s", t);
+ continue;
+ }
+
+ r = set_put(c->syscall_archs, UINT32_TO_PTR(a + 1));
+ if (r == -EEXIST)
+ continue;
+ if (r < 0)
+ return log_oom();
+ }
+
+ return 0;
+}
+
int config_parse_syscall_errno(
const char *unit,
const char *filename,
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 4cefa76157..23e9d1131b 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -74,6 +74,7 @@ int config_parse_notify_access(const char *unit, const char *filename, unsigned
int config_parse_start_limit_action(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_unit_requires_mounts_for(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_syscall_filter(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_syscall_archs(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_syscall_errno(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_environ(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_unit_slice(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);