mirror of
https://github.com/systemd/systemd.git
synced 2024-10-31 16:21:26 +03:00
core,seccomp: fix logic to parse syscall filter in dbus-execute.c
If multiple SystemCallFilter= settings, some of them are whitelist and the others are blacklist, are sent to bus, then the parse result was corrupted. This fixes the parse logic, now it is the same as one used in load-fragment.c
This commit is contained in:
parent
e7bcff4ec4
commit
898748d8b9
@ -1361,59 +1361,42 @@ int bus_exec_context_set_transient_property(
|
||||
|
||||
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;
|
||||
|
||||
unit_write_settingf(u, flags, name, "SystemCallFilter=");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!c->syscall_filter) {
|
||||
c->syscall_filter = hashmap_new(NULL);
|
||||
if (!c->syscall_filter)
|
||||
return log_oom();
|
||||
|
||||
c->syscall_whitelist = whitelist;
|
||||
|
||||
r = hashmap_ensure_allocated(&c->syscall_filter, NULL);
|
||||
if (c->syscall_whitelist) {
|
||||
r = seccomp_parse_syscall_filter(invert, "@default", -1, c->syscall_filter, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
STRV_FOREACH(s, l) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
int e;
|
||||
|
||||
r = parse_syscall_and_errno(*s, &n, &e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(s, l) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
int e;
|
||||
|
||||
r = parse_syscall_and_errno(*s, &n, &e);
|
||||
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;
|
||||
|
||||
id = seccomp_syscall_resolve_name(n);
|
||||
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;
|
||||
}
|
||||
}
|
||||
r = seccomp_parse_syscall_filter(invert, n, e, c->syscall_filter, c->syscall_whitelist);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
joined = strv_join(l, " ");
|
||||
|
@ -2891,60 +2891,6 @@ int config_parse_documentation(const char *unit,
|
||||
}
|
||||
|
||||
#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,
|
||||
@ -2993,7 +2939,7 @@ int config_parse_syscall_filter(
|
||||
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;
|
||||
}
|
||||
@ -3020,7 +2966,7 @@ int config_parse_syscall_filter(
|
||||
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;
|
||||
}
|
||||
|
@ -950,6 +950,65 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, u
|
||||
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;
|
||||
|
@ -81,6 +81,24 @@ int seccomp_add_syscall_filter_item(scmp_filter_ctx *ctx, const char *name, uint
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user