#include <sys/poll.h>
#include <glob.h>
#include <libgen.h>
-#ifdef HAVE_SECCOMP
-#include <seccomp.h>
-
-#include "set.h"
-#endif
#undef basename
#ifdef HAVE_PAM
#include <selinux/selinux.h>
#endif
+#ifdef HAVE_SECCOMP
+#include <seccomp.h>
+#endif
+
#include "execute.h"
#include "strv.h"
#include "macro.h"
#include "unit.h"
#include "async.h"
#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)
}
#ifdef HAVE_SECCOMP
+
static int apply_seccomp(ExecContext *c) {
- uint32_t action = SCMP_ACT_ALLOW;
+ uint32_t negative_action, action;
+ scmp_filter_ctx *seccomp;
Iterator i;
void *id;
+ int r;
assert(c);
- c->syscall_filter = seccomp_init(c->syscall_filter_default_action);
- if (!c->syscall_filter)
- return -1;
+ negative_action = c->syscall_errno == 0 ? SCMP_ACT_KILL : SCMP_ACT_ERRNO(c->syscall_errno);
+
+ seccomp = seccomp_init(c->syscall_whitelist ? negative_action : SCMP_ACT_ALLOW);
+ if (!seccomp)
+ return -ENOMEM;
- if (c->syscall_filter_default_action == SCMP_ACT_ALLOW)
- action = SCMP_ACT_KILL;
+ if (c->syscall_archs) {
- SET_FOREACH(id, c->filtered_syscalls, i) {
- int r = seccomp_rule_add(c->syscall_filter, action, PTR_TO_INT(id) - 1, 0);
+ 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;
+ }
+ }
+ } else {
+
+ r = seccomp_add_secondary_archs(seccomp);
if (r < 0) {
- log_error("Failed to add syscall filter");
+ seccomp_release(seccomp);
return r;
}
}
- return seccomp_load(c->syscall_filter);
+ 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) {
+ seccomp_release(seccomp);
+ return r;
+ }
+ }
+
+ r = seccomp_load(seccomp);
+ seccomp_release(seccomp);
+
+ return r;
}
#endif
}
#ifdef HAVE_SECCOMP
- if (context->filtered_syscalls) {
+ if (context->syscall_filter || context->syscall_archs) {
err = apply_seccomp(context);
if (err < 0) {
r = EXIT_SECCOMP;
}
}
#endif
+
#ifdef HAVE_SELINUX
if (context->selinux_context && use_selinux()) {
- bool ignore;
- char* c;
-
- c = context->selinux_context;
- if (c[0] == '-') {
- c++;
- ignore = true;
- } else
- ignore = false;
-
- err = setexeccon(c);
- if (err < 0 && !ignore) {
+ err = setexeccon(context->selinux_context);
+ if (err < 0 && !context->selinux_context_ignore) {
r = EXIT_SELINUX_CONTEXT;
goto fail_child;
}
free(c->selinux_context);
c->selinux_context = NULL;
- free(c->syscall_filter);
+#ifdef HAVE_SECCOMP
+ set_free(c->syscall_filter);
c->syscall_filter = NULL;
- free(c->syscall_filter_string);
- c->syscall_filter_string = NULL;
-
-#ifdef HAVE_SECCOMP
- if (c->syscall_filter) {
- seccomp_release(c->syscall_filter);
- c->syscall_filter = NULL;
- }
- set_free(c->filtered_syscalls);
- c->filtered_syscalls = NULL;
+ set_free(c->syscall_archs);
+ c->syscall_archs = NULL;
#endif
}
if (c->selinux_context)
fprintf(f,
- "%sSELinuxContext: %s\n",
- prefix, c->selinux_context);
+ "%sSELinuxContext: %s%s\n",
+ prefix, c->selinux_context_ignore ? "-" : "", c->selinux_context);
+
+ if (c->syscall_filter) {
+#ifdef HAVE_SECCOMP
+ Iterator j;
+ void *id;
+ bool first = true;
+#endif
+
+ fprintf(f,
+ "%sSystemCallFilter: ",
+ prefix);
+
+ if (!c->syscall_whitelist)
+ fputc('~', f);
+
+#ifdef HAVE_SECCOMP
+ SET_FOREACH(id, c->syscall_filter, j) {
+ _cleanup_free_ char *name = NULL;
+
+ if (first)
+ first = false;
+ else
+ fputc(' ', f);
+
+ name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
+ fputs(strna(name), f);
+ }
+#endif
+
+ 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",
+ prefix, strna(errno_to_name(c->syscall_errno)));
}
void exec_status_start(ExecStatus *s, pid_t pid) {