exec: SystemCallLog= directive

With new directive SystemCallLog= it's possible to list system calls to be
logged. This can be used for auditing or temporarily when constructing system
call filters.

---
v5: drop intermediary, update HASHMAP_FOREACH_KEY() use
v4: skip useless debug messages, actually parse directive
v3: don't declare unused variables with old libseccomp
v2: fix build without seccomp or old libseccomp
This commit is contained in:
Topi Miettinen
2020-09-15 12:54:17 +03:00
parent 005bfaf118
commit 9df2cdd8ec
11 changed files with 280 additions and 2 deletions
+47
View File
@@ -1407,6 +1407,13 @@ static bool context_has_syscall_filters(const ExecContext *c) {
!hashmap_isempty(c->syscall_filter);
}
static bool context_has_syscall_logs(const ExecContext *c) {
assert(c);
return c->syscall_log_allow_list ||
!hashmap_isempty(c->syscall_log);
}
static bool context_has_no_new_privileges(const ExecContext *c) {
assert(c);
@@ -1428,6 +1435,7 @@ static bool context_has_no_new_privileges(const ExecContext *c) {
c->protect_kernel_logs ||
c->private_devices ||
context_has_syscall_filters(c) ||
context_has_syscall_logs(c) ||
!set_isempty(c->syscall_archs) ||
c->lock_personality ||
c->protect_hostname;
@@ -1484,6 +1492,39 @@ static int apply_syscall_filter(const Unit* u, const ExecContext *c, bool needs_
return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action, false);
}
static int apply_syscall_log(const Unit* u, const ExecContext *c) {
#ifdef SCMP_ACT_LOG
uint32_t default_action, action;
#endif
assert(u);
assert(c);
if (!context_has_syscall_logs(c))
return 0;
#ifdef SCMP_ACT_LOG
if (skip_seccomp_unavailable(u, "SystemCallLog="))
return 0;
if (c->syscall_log_allow_list) {
/* Log nothing but the ones listed */
default_action = SCMP_ACT_ALLOW;
action = SCMP_ACT_LOG;
} else {
/* Log everything but the ones listed */
default_action = SCMP_ACT_LOG;
action = SCMP_ACT_ALLOW;
}
return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_log, action, false);
#else
/* old libseccomp */
log_unit_debug(u, "SECCOMP feature SCMP_ACT_LOG not available, skipping SystemCallLog=");
return 0;
#endif
}
static int apply_syscall_archs(const Unit *u, const ExecContext *c) {
assert(u);
assert(c);
@@ -4438,6 +4479,12 @@ static int exec_child(
return log_unit_error_errno(unit, r, "Failed to lock personalities: %m");
}
r = apply_syscall_log(unit, context);
if (r < 0) {
*exit_status = EXIT_SECCOMP;
return log_unit_error_errno(unit, r, "Failed to apply system call log filters: %m");
}
/* This really should remain the last step before the execve(), to make sure our own code is unaffected
* by the filter as little as possible. */
r = apply_syscall_filter(unit, context, needs_ambient_hack);