Merge pull request #16675 from topimiettinen/exec-syscall-error-action

SystemCallFilter, SystemCallErrorAction error actions kill and log
This commit is contained in:
Lennart Poettering 2020-09-16 17:01:44 +02:00 committed by GitHub
commit c796b91d2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 375 additions and 19 deletions

View File

@ -156,6 +156,7 @@ All execution-related settings are available for transient units.
✓ SystemCallFilter=
✓ SystemCallArchitectures=
✓ SystemCallErrorNumber=
✓ SystemCallLog=
✓ MemoryDenyWriteExecute=
✓ RestrictNamespaces=
✓ RestrictRealtime=

View File

@ -1888,7 +1888,8 @@ RestrictNamespaces=~cgroup net</programlisting>
<constant>EACCES</constant> or <constant>EUCLEAN</constant> (see <citerefentry
project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry> for a
full list). This value will be returned when a deny-listed system call is triggered, instead of
terminating the processes immediately. This value takes precedence over the one given in
terminating the processes immediately. Special setting <literal>kill</literal> can be used to
explicitly specify killing. This value takes precedence over the one given in
<varname>SystemCallErrorNumber=</varname>, see below. If running in user mode, or in system mode,
but without the <constant>CAP_SYS_ADMIN</constant> capability (e.g. setting
<varname>User=nobody</varname>), <varname>NoNewPrivileges=yes</varname> is implied. This feature
@ -2098,8 +2099,9 @@ SystemCallErrorNumber=EPERM</programlisting>
return when the system call filter configured with <varname>SystemCallFilter=</varname> is triggered,
instead of terminating the process immediately. See <citerefentry
project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry> for a
full list of error codes. When this setting is not used, or when the empty string is assigned, the
process will be terminated immediately when the filter is triggered.</para></listitem>
full list of error codes. When this setting is not used, or when the empty string or the special
setting <literal>kill</literal> is assigned, the process will be terminated immediately when the
filter is triggered.</para></listitem>
</varlistentry>
<varlistentry>
@ -2134,6 +2136,21 @@ SystemCallErrorNumber=EPERM</programlisting>
details.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SystemCallLog=</varname></term>
<listitem><para>Takes a space-separated list of system call names. If this setting is used, all
system calls executed by the unit processes for the listed ones will be logged. If the first
character of the list is <literal>~</literal>, the effect is inverted: all system calls except the
listed system calls will be logged. If running in user mode, or in system mode, but without the
<constant>CAP_SYS_ADMIN</constant> capability (e.g. setting <varname>User=nobody</varname>),
<varname>NoNewPrivileges=yes</varname> is implied. This feature makes use of the Secure Computing
Mode 2 interfaces of the kernel ('seccomp filtering') and is useful for auditing or setting up a
minimal sandboxing environment. This option may be specified more than once, in which case the filter
masks are merged. If the empty string is assigned, the filter is reset, all prior assignments will
have no effect. This does not affect commands prefixed with <literal>+</literal>.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -16,6 +16,9 @@
#include "missing_network.h"
#include "parse-util.h"
#include "process-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
@ -314,6 +317,7 @@ int parse_errno(const char *t) {
return e;
}
#if HAVE_SECCOMP
int parse_syscall_and_errno(const char *in, char **name, int *error) {
_cleanup_free_ char *n = NULL;
char *p;
@ -332,7 +336,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) {
p = strchr(in, ':');
if (p) {
e = parse_errno(p + 1);
e = seccomp_parse_errno_or_action(p + 1);
if (e < 0)
return e;
@ -351,6 +355,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) {
return 0;
}
#endif
static const char *mangle_base(const char *s, unsigned *base) {
const char *k;

View File

@ -19,7 +19,9 @@ int parse_mtu(int family, const char *s, uint32_t *ret);
int parse_size(const char *t, uint64_t base, uint64_t *size);
int parse_range(const char *t, unsigned *lower, unsigned *upper);
int parse_errno(const char *t);
#if HAVE_SECCOMP
int parse_syscall_and_errno(const char *in, char **name, int *error);
#endif
#define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30)
#define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29)

View File

@ -387,7 +387,7 @@ static int property_get_syscall_filter(
continue;
if (num >= 0) {
e = errno_to_name(num);
e = seccomp_errno_or_action_to_string(num);
if (e) {
s = strjoin(name, ":", e);
if (!s)
@ -415,6 +415,58 @@ static int property_get_syscall_filter(
return sd_bus_message_close_container(reply);
}
static int property_get_syscall_log(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
ExecContext *c = userdata;
_cleanup_strv_free_ char **l = NULL;
int r;
#if HAVE_SECCOMP
void *id, *val;
#endif
assert(bus);
assert(reply);
assert(c);
r = sd_bus_message_open_container(reply, 'r', "bas");
if (r < 0)
return r;
r = sd_bus_message_append(reply, "b", c->syscall_log_allow_list);
if (r < 0)
return r;
#if HAVE_SECCOMP
HASHMAP_FOREACH_KEY(val, id, c->syscall_log) {
char *name = NULL;
name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
if (!name)
continue;
r = strv_consume(&l, name);
if (r < 0)
return r;
}
#endif
strv_sort(l);
r = sd_bus_message_append_strv(reply, l);
if (r < 0)
return r;
return sd_bus_message_close_container(reply);
}
static int property_get_syscall_archs(
sd_bus *bus,
const char *path,
@ -1068,6 +1120,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int, offsetof(ExecContext, syscall_errno), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallLog", "(bas)", property_get_syscall_log, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@ -1424,7 +1477,7 @@ static const char* mount_propagation_flags_to_string_with_check(unsigned long n)
static BUS_DEFINE_SET_TRANSIENT(nsec, "t", uint64_t, nsec_t, NSEC_FMT);
static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level, "i", int32_t, int, "%" PRIi32, log_level_is_valid);
#if HAVE_SECCOMP
static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, errno_is_valid);
static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, seccomp_errno_or_action_is_valid);
#endif
static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string);
@ -2230,6 +2283,76 @@ int bus_exec_context_set_transient_property(
return 1;
} else if (streq(name, "SystemCallLog")) {
int allow_list;
_cleanup_strv_free_ char **l = NULL;
r = sd_bus_message_enter_container(message, 'r', "bas");
if (r < 0)
return r;
r = sd_bus_message_read(message, "b", &allow_list);
if (r < 0)
return r;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
r = sd_bus_message_exit_container(message);
if (r < 0)
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *joined = NULL;
SeccompParseFlags invert_flag = allow_list ? 0 : SECCOMP_PARSE_INVERT;
char **s;
if (strv_isempty(l)) {
c->syscall_log_allow_list = false;
c->syscall_log = hashmap_free(c->syscall_log);
unit_write_settingf(u, flags, name, "SystemCallLog=");
return 1;
}
if (!c->syscall_log) {
c->syscall_log = hashmap_new(NULL);
if (!c->syscall_log)
return log_oom();
c->syscall_log_allow_list = allow_list;
}
STRV_FOREACH(s, l) {
_cleanup_free_ char *n = NULL;
int e;
r = parse_syscall_and_errno(*s, &n, &e);
if (r < 0)
return r;
r = seccomp_parse_syscall_filter(n,
0, /* errno not used */
c->syscall_log,
SECCOMP_PARSE_LOG | SECCOMP_PARSE_PERMISSIVE |
invert_flag |
(c->syscall_log_allow_list ? SECCOMP_PARSE_ALLOW_LIST : 0),
u->id,
NULL, 0);
if (r < 0)
return r;
}
joined = strv_join(l, " ");
if (!joined)
return -ENOMEM;
unit_write_settingf(u, flags, name, "SystemCallLog=%s%s", allow_list ? "" : "~", joined);
}
return 1;
} else if (streq(name, "SystemCallArchitectures")) {
_cleanup_strv_free_ char **l = NULL;

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;
@ -1465,7 +1473,7 @@ static int apply_syscall_filter(const Unit* u, const ExecContext *c, bool needs_
if (skip_seccomp_unavailable(u, "SystemCallFilter="))
return 0;
negative_action = c->syscall_errno == 0 ? scmp_act_kill_process() : SCMP_ACT_ERRNO(c->syscall_errno);
negative_action = c->syscall_errno == SECCOMP_ERROR_NUMBER_KILL ? scmp_act_kill_process() : SCMP_ACT_ERRNO(c->syscall_errno);
if (c->syscall_allow_list) {
default_action = negative_action;
@ -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);
@ -4675,6 +4722,9 @@ void exec_context_init(ExecContext *c) {
assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL);
c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL;
c->log_level_max = -1;
#if HAVE_SECCOMP
c->syscall_errno = SECCOMP_ERROR_NUMBER_KILL;
#endif
numa_policy_reset(&c->numa_policy);
}
@ -5474,7 +5524,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
fputs(strna(name), f);
if (num >= 0) {
errno_name = errno_to_name(num);
errno_name = seccomp_errno_or_action_to_string(num);
if (errno_name)
fprintf(f, ":%s", errno_name);
else
@ -5517,15 +5567,20 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
prefix, c->network_namespace_path);
if (c->syscall_errno > 0) {
#if HAVE_SECCOMP
const char *errno_name;
#endif
fprintf(f, "%sSystemCallErrorNumber: ", prefix);
errno_name = errno_to_name(c->syscall_errno);
#if HAVE_SECCOMP
errno_name = seccomp_errno_or_action_to_string(c->syscall_errno);
if (errno_name)
fprintf(f, "%s\n", errno_name);
fputs(errno_name, f);
else
fprintf(f, "%d\n", c->syscall_errno);
fprintf(f, "%d", c->syscall_errno);
#endif
fputc('\n', f);
}
for (size_t i = 0; i < c->n_mount_images; i++) {

View File

@ -302,6 +302,9 @@ struct ExecContext {
int syscall_errno;
bool syscall_allow_list:1;
Hashmap *syscall_log;
bool syscall_log_allow_list:1; /* Log listed system calls */
bool address_families_allow_list:1;
Set *address_families;

View File

@ -79,6 +79,7 @@ m4_ifdef(`HAVE_SECCOMP',
`$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context)
$1.SystemCallArchitectures, config_parse_syscall_archs, 0, offsetof($1, exec_context.syscall_archs)
$1.SystemCallErrorNumber, config_parse_syscall_errno, 0, offsetof($1, exec_context)
$1.SystemCallLog, config_parse_syscall_log, 0, offsetof($1, exec_context)
$1.MemoryDenyWriteExecute, config_parse_bool, 0, offsetof($1, exec_context.memory_deny_write_execute)
$1.RestrictNamespaces, config_parse_restrict_namespaces, 0, offsetof($1, exec_context)
$1.RestrictRealtime, config_parse_bool, 0, offsetof($1, exec_context.restrict_realtime)
@ -88,6 +89,7 @@ $1.LockPersonality, config_parse_bool, 0,
`$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.SystemCallArchitectures, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.SystemCallLog, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0

View File

@ -3197,6 +3197,86 @@ int config_parse_syscall_filter(
}
}
int config_parse_syscall_log(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
_unused_ const Unit *u = userdata;
bool invert = false;
const char *p;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(u);
if (isempty(rvalue)) {
/* Empty assignment resets the list */
c->syscall_log = hashmap_free(c->syscall_log);
c->syscall_log_allow_list = false;
return 0;
}
if (rvalue[0] == '~') {
invert = true;
rvalue++;
}
if (!c->syscall_log) {
c->syscall_log = hashmap_new(NULL);
if (!c->syscall_log)
return log_oom();
if (invert)
/* Log everything but the ones listed */
c->syscall_log_allow_list = false;
else
/* Log nothing but the ones listed */
c->syscall_log_allow_list = true;
}
p = rvalue;
for (;;) {
_cleanup_free_ char *word = NULL, *name = NULL;
int num;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
r = parse_syscall_and_errno(word, &name, &num);
if (r < 0 || num >= 0) { /* errno code not allowed */
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse syscall, ignoring: %s", word);
continue;
}
r = seccomp_parse_syscall_filter(
name, 0, c->syscall_log,
SECCOMP_PARSE_LOG|SECCOMP_PARSE_PERMISSIVE|
(invert ? SECCOMP_PARSE_INVERT : 0)|
(c->syscall_log_allow_list ? SECCOMP_PARSE_ALLOW_LIST : 0),
unit, filename, line);
if (r < 0)
return r;
}
}
int config_parse_syscall_archs(
const char *unit,
const char *filename,
@ -3264,9 +3344,9 @@ int config_parse_syscall_errno(
assert(lvalue);
assert(rvalue);
if (isempty(rvalue)) {
if (isempty(rvalue) || streq(rvalue, "kill")) {
/* Empty assignment resets to KILL */
c->syscall_errno = 0;
c->syscall_errno = SECCOMP_ERROR_NUMBER_KILL;
return 0;
}
@ -5444,6 +5524,7 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_syscall_filter, "SYSCALLS" },
{ config_parse_syscall_archs, "ARCHS" },
{ config_parse_syscall_errno, "ERRNO" },
{ config_parse_syscall_log, "SYSCALLS" },
{ config_parse_address_families, "FAMILIES" },
{ config_parse_restrict_namespaces, "NAMESPACES" },
#endif

View File

@ -65,6 +65,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_unit_requires_mounts_for);
CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter);
CONFIG_PARSER_PROTOTYPE(config_parse_syscall_archs);
CONFIG_PARSER_PROTOTYPE(config_parse_syscall_errno);
CONFIG_PARSER_PROTOTYPE(config_parse_syscall_log);
CONFIG_PARSER_PROTOTYPE(config_parse_environ);
CONFIG_PARSER_PROTOTYPE(config_parse_pass_environ);
CONFIG_PARSER_PROTOTYPE(config_parse_unset_environ);

View File

@ -30,6 +30,9 @@
#include "path-util.h"
#include "process-util.h"
#include "rlimit-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
#include "securebits-util.h"
#include "signal-util.h"
#include "socket-util.h"
@ -107,7 +110,10 @@ DEFINE_BUS_APPEND_PARSE("i", ioprio_class_from_string);
DEFINE_BUS_APPEND_PARSE("i", ip_tos_from_string);
DEFINE_BUS_APPEND_PARSE("i", log_facility_unshifted_from_string);
DEFINE_BUS_APPEND_PARSE("i", log_level_from_string);
DEFINE_BUS_APPEND_PARSE("i", parse_errno);
#if !HAVE_SECCOMP
static inline int seccomp_parse_errno_or_action(const char *eq) { return -EINVAL; }
#endif
DEFINE_BUS_APPEND_PARSE("i", seccomp_parse_errno_or_action);
DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string);
DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string);
DEFINE_BUS_APPEND_PARSE("i", signal_from_string);
@ -927,7 +933,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
return bus_append_parse_nice(m, field, eq);
if (streq(field, "SystemCallErrorNumber"))
return bus_append_parse_errno(m, field, eq);
return bus_append_seccomp_parse_errno_or_action(m, field, eq);
if (streq(field, "IOSchedulingClass"))
return bus_append_ioprio_class_from_string(m, field, eq);
@ -1293,7 +1299,8 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
}
if (STR_IN_SET(field, "RestrictAddressFamilies",
"SystemCallFilter")) {
"SystemCallFilter",
"SystemCallLog")) {
int allow_list = 1;
const char *p = eq;

View File

@ -1071,7 +1071,13 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, u
int id = PTR_TO_INT(syscall_id) - 1;
int error = PTR_TO_INT(val);
if (action != SCMP_ACT_ALLOW && error >= 0)
if (error == SECCOMP_ERROR_NUMBER_KILL)
a = scmp_act_kill_process();
#ifdef SCMP_ACT_LOG
else if (action == SCMP_ACT_LOG)
a = SCMP_ACT_LOG;
#endif
else if (action != SCMP_ACT_ALLOW && error >= 0)
a = SCMP_ACT_ERRNO(error);
r = seccomp_rule_add_exact(seccomp, a, id, 0);

View File

@ -5,7 +5,10 @@
#include <stdbool.h>
#include <stdint.h>
#include "errno-list.h"
#include "parse-util.h"
#include "set.h"
#include "string-util.h"
const char* seccomp_arch_to_string(uint32_t c);
int seccomp_arch_from_string(const char *n, uint32_t *ret);
@ -115,3 +118,25 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(scmp_filter_ctx, seccomp_release);
int parse_syscall_archs(char **l, Set **ret_archs);
uint32_t scmp_act_kill_process(void);
/* This is a special value to be used where syscall filters otherwise expect errno numbers, will be
replaced with real seccomp action. */
enum {
SECCOMP_ERROR_NUMBER_KILL = INT_MAX - 1,
};
static inline bool seccomp_errno_or_action_is_valid(int n) {
return n == SECCOMP_ERROR_NUMBER_KILL || errno_is_valid(n);
}
static inline int seccomp_parse_errno_or_action(const char *p) {
if (streq_ptr(p, "kill"))
return SECCOMP_ERROR_NUMBER_KILL;
return parse_errno(p);
}
static inline const char *seccomp_errno_or_action_to_string(int num) {
if (num == SECCOMP_ERROR_NUMBER_KILL)
return "kill";
return errno_to_name(num);
}

View File

@ -4822,7 +4822,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
return 1;
} else if (STR_IN_SET(name, "SystemCallFilter", "RestrictAddressFamilies")) {
} else if (STR_IN_SET(name, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies")) {
_cleanup_strv_free_ char **l = NULL;
int allow_list;

View File

@ -434,6 +434,8 @@ static void test_exec_systemcallfilter(Manager *m) {
test(__func__, m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-with-errno-multi.service", errno_from_name("EILSEQ"), CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-override-error-action.service", SIGSYS, CLD_KILLED);
test(__func__, m, "exec-systemcallfilter-override-error-action2.service", errno_from_name("EILSEQ"), CLD_EXITED);
#endif
}

View File

@ -10,6 +10,9 @@
#include "log.h"
#include "parse-util.h"
#include "string-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
static void test_parse_boolean(void) {
assert_se(parse_boolean("1") == 1);
@ -852,6 +855,7 @@ static void test_parse_errno(void) {
}
static void test_parse_syscall_and_errno(void) {
#if HAVE_SECCOMP
_cleanup_free_ char *n = NULL;
int e;
@ -882,11 +886,16 @@ static void test_parse_syscall_and_errno(void) {
assert_se(e == 255);
n = mfree(n);
assert_se(parse_syscall_and_errno("hoge:kill", &n, &e) >= 0);
assert_se(streq(n, "hoge"));
assert_se(e == SECCOMP_ERROR_NUMBER_KILL);
n = mfree(n);
/* The function checks the syscall name is empty or not. */
assert_se(parse_syscall_and_errno("", &n, &e) == -EINVAL);
assert_se(parse_syscall_and_errno(":255", &n, &e) == -EINVAL);
/* errno must be a valid errno name or number between 0 and ERRNO_MAX == 4095 */
/* errno must be a valid errno name or number between 0 and ERRNO_MAX == 4095, or "kill" */
assert_se(parse_syscall_and_errno("hoge:4096", &n, &e) == -ERANGE);
assert_se(parse_syscall_and_errno("hoge:-3", &n, &e) == -ERANGE);
assert_se(parse_syscall_and_errno("hoge:12.3", &n, &e) == -EINVAL);
@ -896,6 +905,7 @@ static void test_parse_syscall_and_errno(void) {
assert_se(parse_syscall_and_errno("hoge:-EINVAL", &n, &e) == -EINVAL);
assert_se(parse_syscall_and_errno("hoge:EINVALaaa", &n, &e) == -EINVAL);
assert_se(parse_syscall_and_errno("hoge:", &n, &e) == -EINVAL);
#endif
}
static void test_parse_mtu(void) {

View File

@ -0,0 +1,8 @@
[Unit]
Description=Test for SystemCallFilter with specific kill action overriding default errno action
[Service]
ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
Type=oneshot
SystemCallFilter=~uname:kill
SystemCallErrorNumber=EILSEQ

View File

@ -0,0 +1,8 @@
[Unit]
Description=Test for SystemCallFilter with specific errno action overriding default kill action
[Service]
ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
Type=oneshot
SystemCallFilter=~uname:EILSEQ
SystemCallErrorNumber=kill