summaryrefslogtreecommitdiff
path: root/src/core/load-fragment.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-07-17 04:17:53 +0200
committerLennart Poettering <lennart@poettering.net>2012-07-17 04:17:53 +0200
commit8351ceaea9480d9c2979aa2ff0f4982cfdfef58d (patch)
treefc1f94e5a17679960774da386a54d145255e4ef1 /src/core/load-fragment.c
parentcd96b3b86abb4a88cac2722bdfb6e5d4413f6831 (diff)
execute: support syscall filtering using seccomp filters
Diffstat (limited to 'src/core/load-fragment.c')
-rw-r--r--src/core/load-fragment.c85
1 files changed, 84 insertions, 1 deletions
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 748ab55d54..7fcd63a17a 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -45,6 +45,7 @@
#include "bus-errors.h"
#include "utf8.h"
#include "path-util.h"
+#include "syscall-list.h"
#ifndef HAVE_SYSV_COMPAT
int config_parse_warn_compat(
@@ -879,7 +880,7 @@ int config_parse_bounding_set(
if (r < 0) {
log_error("[%s:%u] Failed to parse capability bounding set, ignoring: %s", filename, line, rvalue);
- return 0;
+ continue;
}
sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
@@ -2001,6 +2002,88 @@ int config_parse_documentation(
return r;
}
+static void syscall_set(uint32_t *p, int nr) {
+ p[nr >> 4] |= 1 << (nr & 31);
+}
+
+static void syscall_unset(uint32_t *p, int nr) {
+ p[nr >> 4] &= ~(1 << (nr & 31));
+}
+
+int config_parse_syscall_filter(
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ ExecContext *c = data;
+ Unit *u = userdata;
+ bool invert;
+ char *w;
+ size_t l;
+ char *state;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(u);
+
+ if (rvalue[0] == '~') {
+ invert = true;
+ rvalue++;
+ }
+
+ if (!c->syscall_filter) {
+ size_t n;
+
+ n = (syscall_max() + 31) >> 4;
+ c->syscall_filter = new(uint32_t, n);
+ if (!c->syscall_filter)
+ return -ENOMEM;
+
+ memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
+
+ /* Add these by default */
+ syscall_set(c->syscall_filter, __NR_execve);
+ syscall_set(c->syscall_filter, __NR_rt_sigreturn);
+#ifdef __NR_sigreturn
+ syscall_set(c->syscall_filter, __NR_sigreturn);
+#endif
+ syscall_set(c->syscall_filter, __NR_exit_group);
+ syscall_set(c->syscall_filter, __NR_exit);
+ }
+
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+ int id;
+ char *t;
+
+ t = strndup(w, l);
+ if (!t)
+ return -ENOMEM;
+
+ id = syscall_from_name(t);
+ free(t);
+
+ if (id < 0) {
+ log_error("[%s:%u] Failed to parse syscall, ignoring: %s", filename, line, rvalue);
+ continue;
+ }
+
+ if (invert)
+ syscall_unset(c->syscall_filter, id);
+ else
+ syscall_set(c->syscall_filter, id);
+ }
+
+ c->no_new_privileges = true;
+
+ return 0;
+}
+
#define FOLLOW_MAX 8
static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {