if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *joined = NULL;
+ bool invert = !whitelist;
+ char **s;
if (strv_isempty(l)) {
c->syscall_whitelist = false;
c->syscall_filter = hashmap_free(c->syscall_filter);
- } else {
- char **s;
- c->syscall_whitelist = whitelist;
+ unit_write_settingf(u, flags, name, "SystemCallFilter=");
+ return 1;
+ }
- r = hashmap_ensure_allocated(&c->syscall_filter, NULL);
- if (r < 0)
- return r;
+ if (!c->syscall_filter) {
+ c->syscall_filter = hashmap_new(NULL);
+ if (!c->syscall_filter)
+ return log_oom();
- STRV_FOREACH(s, l) {
- _cleanup_free_ char *n = NULL;
- int e;
+ c->syscall_whitelist = whitelist;
- r = parse_syscall_and_errno(*s, &n, &e);
+ if (c->syscall_whitelist) {
+ r = seccomp_parse_syscall_filter(invert, "@default", -1, c->syscall_filter, true);
if (r < 0)
return r;
+ }
+ }
- if (*n == '@') {
- const SyscallFilterSet *set;
- const char *i;
-
- set = syscall_filter_set_find(n);
- if (!set)
- return -EINVAL;
-
- NULSTR_FOREACH(i, set->value) {
- int id;
-
- id = seccomp_syscall_resolve_name(i);
- if (id == __NR_SCMP_ERROR)
- return -EINVAL;
-
- r = hashmap_put(c->syscall_filter, INT_TO_PTR(id + 1), INT_TO_PTR(e));
- if (r < 0)
- return r;
- }
-
- } else {
- int id;
+ STRV_FOREACH(s, l) {
+ _cleanup_free_ char *n = NULL;
+ int e;
- id = seccomp_syscall_resolve_name(n);
- if (id == __NR_SCMP_ERROR)
- return -EINVAL;
+ r = parse_syscall_and_errno(*s, &n, &e);
+ if (r < 0)
+ return r;
- r = hashmap_put(c->syscall_filter, INT_TO_PTR(id + 1), INT_TO_PTR(e));
- if (r < 0)
- return r;
- }
- }
+ r = seccomp_parse_syscall_filter(invert, n, e, c->syscall_filter, c->syscall_whitelist);
+ if (r < 0)
+ return r;
}
joined = strv_join(l, " ");
}
#if HAVE_SECCOMP
-
-static int syscall_filter_parse_one(
- const char *unit,
- const char *filename,
- unsigned line,
- ExecContext *c,
- bool invert,
- const char *t,
- bool warn,
- int errno_num) {
- int r;
-
- if (t[0] == '@') {
- const SyscallFilterSet *set;
- const char *i;
-
- set = syscall_filter_set_find(t);
- if (!set) {
- if (warn)
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown system call group, ignoring: %s", t);
- return 0;
- }
-
- NULSTR_FOREACH(i, set->value) {
- r = syscall_filter_parse_one(unit, filename, line, c, invert, i, false, errno_num);
- if (r < 0)
- return r;
- }
- } else {
- int id;
-
- id = seccomp_syscall_resolve_name(t);
- if (id == __NR_SCMP_ERROR) {
- if (warn)
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse system call, ignoring: %s", t);
- return 0;
- }
-
- /* If we previously wanted to forbid a syscall and now
- * we want to allow it, then remove it from the list.
- */
- if (!invert == c->syscall_whitelist) {
- r = hashmap_put(c->syscall_filter, INT_TO_PTR(id + 1), INT_TO_PTR(errno_num));
- if (r == 0)
- return 0;
- if (r < 0)
- return log_oom();
- } else
- (void) hashmap_remove(c->syscall_filter, INT_TO_PTR(id + 1));
- }
-
- return 0;
-}
-
int config_parse_syscall_filter(
const char *unit,
const char *filename,
c->syscall_whitelist = true;
/* Accept default syscalls if we are on a whitelist */
- r = syscall_filter_parse_one(unit, filename, line, c, false, "@default", false, -1);
+ r = seccomp_parse_syscall_filter(false, "@default", -1, c->syscall_filter, true);
if (r < 0)
return r;
}
continue;
}
- r = syscall_filter_parse_one(unit, filename, line, c, invert, name, true, num);
+ r = seccomp_parse_syscall_filter_and_warn(invert, name, num, c->syscall_filter, c->syscall_whitelist, unit, filename, line);
if (r < 0)
return r;
}
return 0;
}
+int seccomp_parse_syscall_filter_internal(
+ bool invert,
+ const char *name,
+ int errno_num,
+ Hashmap *filter,
+ bool whitelist,
+ bool warn,
+ const char *unit,
+ const char *filename,
+ unsigned line) {
+
+ int r;
+
+ assert(name);
+ assert(filter);
+
+ if (name[0] == '@') {
+ const SyscallFilterSet *set;
+ const char *i;
+
+ set = syscall_filter_set_find(name);
+ if (!set) {
+ if (warn) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown system call group, ignoring: %s", name);
+ return 0;
+ } else
+ return -EINVAL;
+ }
+
+ NULSTR_FOREACH(i, set->value) {
+ r = seccomp_parse_syscall_filter_internal(invert, i, errno_num, filter, whitelist, warn, unit, filename, line);
+ if (r < 0)
+ return r;
+ }
+ } else {
+ int id;
+
+ id = seccomp_syscall_resolve_name(name);
+ if (id == __NR_SCMP_ERROR) {
+ if (warn) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse system call, ignoring: %s", name);
+ return 0;
+ } else
+ return -EINVAL;
+ }
+
+ /* If we previously wanted to forbid a syscall and now
+ * we want to allow it, then remove it from the list. */
+ if (!invert == whitelist) {
+ r = hashmap_put(filter, INT_TO_PTR(id + 1), INT_TO_PTR(errno_num));
+ if (r < 0)
+ return warn ? log_oom() : -ENOMEM;
+ } else
+ (void) hashmap_remove(filter, INT_TO_PTR(id + 1));
+ }
+
+ return 0;
+}
+
int seccomp_restrict_namespaces(unsigned long retain) {
uint32_t arch;
int r;
int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action);
int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action);
+int seccomp_parse_syscall_filter_internal(
+ bool invert, const char *name, int errno_num, Hashmap *filter, bool whitelist,
+ bool warn, const char *unit, const char *filename, unsigned line);
+
+static inline int seccomp_parse_syscall_filter_and_warn(
+ bool invert, const char *name, int errno_num, Hashmap *filter, bool whitelist,
+ const char *unit, const char *filename, unsigned line) {
+ assert(unit);
+ assert(filename);
+
+ return seccomp_parse_syscall_filter_internal(invert, name, errno_num, filter, whitelist, true, unit, filename, line);
+}
+
+static inline int seccomp_parse_syscall_filter(
+ bool invert, const char *name, int errno_num, Hashmap *filter, bool whitelist) {
+ return seccomp_parse_syscall_filter_internal(invert, name, errno_num, filter, whitelist, false, NULL, NULL, 0);
+}
+
int seccomp_restrict_archs(Set *archs);
int seccomp_restrict_namespaces(unsigned long retain);
int seccomp_protect_sysctl(void);