libseccomp: turn into dlopen() dependency

This commit is contained in:
Lennart Poettering
2025-09-08 17:17:05 +02:00
committed by Yu Watanabe
parent 04e434cedb
commit aaca6bd5d9
19 changed files with 334 additions and 160 deletions

View File

@@ -1147,6 +1147,7 @@ libseccomp = dependency('libseccomp',
version : '>= 2.3.1',
required : get_option('seccomp'))
conf.set10('HAVE_SECCOMP', libseccomp.found())
libseccomp_cflags = libseccomp.partial_dependency(includes: true, compile_args: true)
libselinux = dependency('libselinux',
version : '>= 2.1.9',

View File

@@ -568,7 +568,7 @@ static bool syscall_names_in_filter(Set *s, bool allow_list, const SyscallFilter
}
/* Let's see if the system call actually exists on this platform, before complaining */
if (seccomp_syscall_resolve_name(syscall) < 0)
if (sym_seccomp_syscall_resolve_name(syscall) < 0)
continue;
if (set_contains(s, syscall) == allow_list) {
@@ -602,6 +602,13 @@ static int assess_system_call_filter(
uint64_t b;
int r;
r = dlopen_libseccomp();
if (r < 0) {
*ret_badness = UINT64_MAX;
*ret_description = NULL;
return r;
}
if (!info->system_call_filter_allow_list && set_isempty(info->system_call_filter)) {
r = strdup_to(&d, "Service does not filter system calls");
b = 10;
@@ -2439,6 +2446,8 @@ static int analyze_security_one(sd_bus *bus,
/* Refactoring SecurityInfo so that it can make use of existing struct variables instead of reading from dbus */
static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, SecurityInfo **ret_info) {
int r;
assert(ret_info);
_cleanup_(security_info_freep) SecurityInfo *info = security_info_new();
@@ -2568,32 +2577,35 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
info->_umask = c->umask;
#if HAVE_SECCOMP
SET_FOREACH(key, c->syscall_archs) {
const char *name;
r = dlopen_libseccomp();
if (r >= 0) {
SET_FOREACH(key, c->syscall_archs) {
const char *name;
name = seccomp_arch_to_string(PTR_TO_UINT32(key) - 1);
if (!name)
continue;
name = seccomp_arch_to_string(PTR_TO_UINT32(key) - 1);
if (!name)
continue;
if (set_put_strdup(&info->system_call_architectures, name) < 0)
return log_oom();
}
if (set_put_strdup(&info->system_call_architectures, name) < 0)
return log_oom();
}
info->system_call_filter_allow_list = c->syscall_allow_list;
info->system_call_filter_allow_list = c->syscall_allow_list;
void *id, *num;
HASHMAP_FOREACH_KEY(num, id, c->syscall_filter) {
_cleanup_free_ char *name = NULL;
void *id, *num;
HASHMAP_FOREACH_KEY(num, id, c->syscall_filter) {
_cleanup_free_ char *name = NULL;
if (info->system_call_filter_allow_list && PTR_TO_INT(num) >= 0)
continue;
if (info->system_call_filter_allow_list && PTR_TO_INT(num) >= 0)
continue;
name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
if (!name)
continue;
name = sym_seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
if (!name)
continue;
if (set_ensure_consume(&info->system_call_filter, &string_hash_ops_free, TAKE_PTR(name)) < 0)
return log_oom();
if (set_ensure_consume(&info->system_call_filter, &string_hash_ops_free, TAKE_PTR(name)) < 0)
return log_oom();
}
}
#endif
}

View File

@@ -53,7 +53,7 @@ executables += [
libcore,
libshared,
],
'dependencies' : libseccomp,
'dependencies' : libseccomp_cflags,
'install' : conf.get('ENABLE_ANALYZE') == 1,
},
core_test_template + {

View File

@@ -1577,6 +1577,10 @@ static bool seccomp_allows_drop_privileges(const ExecContext *c) {
assert(c);
/* No libseccomp, all is fine */
if (dlopen_libseccomp() < 0)
return true;
/* No syscall filter, we are allowed to drop privileges */
if (hashmap_isempty(c->syscall_filter))
return true;
@@ -1584,7 +1588,7 @@ static bool seccomp_allows_drop_privileges(const ExecContext *c) {
HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) {
_cleanup_free_ char *name = NULL;
name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
name = sym_seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
if (streq(name, "capget"))
have_capget = true;

View File

@@ -1489,27 +1489,29 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
fputc('~', f);
#if HAVE_SECCOMP
void *id, *val;
bool first = true;
HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) {
_cleanup_free_ char *name = NULL;
const char *errno_name = NULL;
int num = PTR_TO_INT(val);
if (dlopen_libseccomp() >= 0) {
void *id, *val;
bool first = true;
HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) {
_cleanup_free_ char *name = NULL;
const char *errno_name = NULL;
int num = PTR_TO_INT(val);
if (first)
first = false;
else
fputc(' ', f);
name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
fputs(strna(name), f);
if (num >= 0) {
errno_name = seccomp_errno_or_action_to_string(num);
if (errno_name)
fprintf(f, ":%s", errno_name);
if (first)
first = false;
else
fprintf(f, ":%d", num);
fputc(' ', f);
name = sym_seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
fputs(strna(name), f);
if (num >= 0) {
errno_name = seccomp_errno_or_action_to_string(num);
if (errno_name)
fprintf(f, ":%s", errno_name);
else
fprintf(f, ":%d", num);
}
}
}
#endif
@@ -1897,6 +1899,9 @@ char** exec_context_get_syscall_filter(const ExecContext *c) {
assert(c);
#if HAVE_SECCOMP
if (dlopen_libseccomp() < 0)
return strv_new(NULL);
void *id, *val;
HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) {
_cleanup_free_ char *name = NULL;
@@ -1908,7 +1913,7 @@ char** exec_context_get_syscall_filter(const ExecContext *c) {
/* syscall with num >= 0 in allow-list is denied. */
continue;
name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
name = sym_seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
if (!name)
continue;
@@ -1965,11 +1970,14 @@ char** exec_context_get_syscall_log(const ExecContext *c) {
assert(c);
#if HAVE_SECCOMP
if (dlopen_libseccomp() < 0)
return strv_new(NULL);
void *id, *val;
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);
name = sym_seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
if (!name)
continue;

View File

@@ -136,7 +136,7 @@ libcore_static = static_library(
libm,
libmount,
librt,
libseccomp,
libseccomp_cflags,
libselinux,
threads,
userspace],
@@ -199,7 +199,7 @@ executables += [
'dependencies' : [
libapparmor_cflags,
libkmod_cflags,
libseccomp,
libseccomp_cflags,
libselinux,
],
},
@@ -212,7 +212,7 @@ executables += [
'dependencies' : [
libapparmor_cflags,
libpam_cflags,
libseccomp,
libseccomp_cflags,
libselinux,
],
},

View File

@@ -229,7 +229,7 @@ libsystemd_tests += [
},
{
'sources' : files('sd-bus/test-bus-cleanup.c'),
'dependencies' : [threads, libseccomp],
'dependencies' : [threads, libseccomp_cflags],
},
{
'sources' : files('sd-bus/test-bus-marshal.c'),
@@ -264,7 +264,7 @@ libsystemd_tests += [
},
{
'sources' : files('sd-bus/test-bus-track.c'),
'dependencies' : libseccomp,
'dependencies' : libseccomp_cflags,
},
{
'sources' : files('sd-bus/test-bus-watch-bind.c'),

View File

@@ -30,7 +30,7 @@ generated_sources += nspawn_gperf_c
nspawn_extract_sources += nspawn_gperf_c
nspawn_common_template = {
'dependencies' : libseccomp,
'dependencies' : libseccomp_cflags,
'objects' : ['systemd-nspawn'],
}
nspawn_test_template = test_template + nspawn_common_template
@@ -47,7 +47,7 @@ executables += [
],
'extract' : nspawn_extract_sources,
'dependencies' : [
libseccomp,
libseccomp_cflags,
libselinux,
],
},

View File

@@ -1691,7 +1691,7 @@ static int oci_seccomp_archs(const char *name, sd_json_variant *v, sd_json_dispa
if (r < 0)
return json_log(e, flags, r, "Unknown architecture: %s", sd_json_variant_string(e));
r = seccomp_arch_add(sc, a);
r = sym_seccomp_arch_add(sc, a);
if (r == -EEXIST)
continue;
if (r < 0)
@@ -1810,13 +1810,13 @@ static int oci_seccomp_syscalls(const char *name, sd_json_variant *v, sd_json_di
STRV_FOREACH(i, rule.names) {
int nr;
nr = seccomp_syscall_resolve_name(*i);
nr = sym_seccomp_syscall_resolve_name(*i);
if (nr == __NR_SCMP_ERROR) {
log_debug("Unknown syscall %s, skipping.", *i);
continue;
}
r = seccomp_rule_add_array(sc, rule.action, nr, rule.n_arguments, rule.arguments);
r = sym_seccomp_rule_add_array(sc, rule.action, nr, rule.n_arguments, rule.arguments);
if (r < 0)
return r;
}
@@ -1853,7 +1853,11 @@ static int oci_seccomp(const char *name, sd_json_variant *v, sd_json_dispatch_fl
if (r < 0)
return json_log(def, flags, r, "Unknown default action: %s", sd_json_variant_string(def));
sc = seccomp_init(d);
r = dlopen_libseccomp();
if (r < 0)
return json_log(def, flags, r, "No support for libseccomp: %m");
sc = sym_seccomp_init(d);
if (!sc)
return json_log(v, flags, SYNTHETIC_ERRNO(ENOMEM), "Couldn't allocate seccomp object.");
@@ -1861,7 +1865,7 @@ static int oci_seccomp(const char *name, sd_json_variant *v, sd_json_dispatch_fl
if (r < 0)
return r;
seccomp_release(s->seccomp);
sym_seccomp_release(s->seccomp);
s->seccomp = TAKE_PTR(sc);
return 0;
#else

View File

@@ -163,7 +163,7 @@ static int add_syscall_filters(
#if (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 5) || SCMP_VER_MAJOR > 2
/* We have a large filter here, so let's turn on the binary tree mode if possible. */
r = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_OPTIMIZE, 2);
r = sym_seccomp_attr_set(ctx, SCMP_FLTATR_CTL_OPTIMIZE, 2);
if (r < 0)
log_warning_errno(r, "Failed to set SCMP_FLTATR_CTL_OPTIMIZE, ignoring: %m");
#endif
@@ -195,7 +195,7 @@ int setup_seccomp(uint64_t cap_list_retain, char **syscall_allow_list, char **sy
if (r < 0)
return r;
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return log_error_errno(r, "Failed to install seccomp filter: %m");
if (r < 0)
@@ -220,7 +220,7 @@ int setup_seccomp(uint64_t cap_list_retain, char **syscall_allow_list, char **sy
as indication that audit is disabled in the kernel.
*/
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EAFNOSUPPORT),
SCMP_SYS(socket),
@@ -232,7 +232,7 @@ int setup_seccomp(uint64_t cap_list_retain, char **syscall_allow_list, char **sy
continue;
}
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return log_error_errno(r, "Failed to install seccomp audit filter: %m");
if (r < 0)

View File

@@ -167,7 +167,8 @@ Settings* settings_free(Settings *s) {
strv_free(s->sysctl);
#if HAVE_SECCOMP
seccomp_release(s->seccomp);
if (s->seccomp)
sym_seccomp_release(s->seccomp);
#endif
return mfree(s);

View File

@@ -3507,7 +3507,7 @@ static int inner_child(
if (arg_seccomp) {
if (is_seccomp_available()) {
r = seccomp_load(arg_seccomp);
r = sym_seccomp_load(arg_seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return log_error_errno(r, "Failed to install seccomp filter: %m");
if (r < 0)
@@ -4835,7 +4835,7 @@ static int merge_settings(Settings *settings, const char *path) {
if (!arg_settings_trusted)
log_warning("Ignoring SECCOMP filter, file %s is not trusted.", path);
else {
seccomp_release(arg_seccomp);
sym_seccomp_release(arg_seccomp);
arg_seccomp = TAKE_PTR(settings->seccomp);
}
}

View File

@@ -327,7 +327,7 @@ libshared_deps = [threads,
libp11kit_cflags,
libpam_cflags,
librt,
libseccomp,
libseccomp_cflags,
libselinux,
libxenctrl_cflags,
libxz_cflags,

View File

@@ -32,6 +32,46 @@
#include "strv.h"
#if HAVE_SECCOMP
static void *libseccomp_dl = NULL;
DLSYM_PROTOTYPE(seccomp_api_get) = NULL;
DLSYM_PROTOTYPE(seccomp_arch_add) = NULL;
DLSYM_PROTOTYPE(seccomp_arch_exist) = NULL;
DLSYM_PROTOTYPE(seccomp_arch_native) = NULL;
DLSYM_PROTOTYPE(seccomp_arch_remove) = NULL;
DLSYM_PROTOTYPE(seccomp_attr_set) = NULL;
DLSYM_PROTOTYPE(seccomp_init) = NULL;
DLSYM_PROTOTYPE(seccomp_load) = NULL;
DLSYM_PROTOTYPE(seccomp_release) = NULL;
DLSYM_PROTOTYPE(seccomp_rule_add_array) = NULL;
DLSYM_PROTOTYPE(seccomp_rule_add_exact) = NULL;
DLSYM_PROTOTYPE(seccomp_syscall_resolve_name) = NULL;
DLSYM_PROTOTYPE(seccomp_syscall_resolve_num_arch) = NULL;
int dlopen_libseccomp(void) {
ELF_NOTE_DLOPEN("seccomp",
"Support for Seccomp Sandboxes",
ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
"libseccomp.so.2");
return dlopen_many_sym_or_warn(
&libseccomp_dl,
"libseccomp.so.2",
LOG_DEBUG,
DLSYM_ARG(seccomp_api_get),
DLSYM_ARG(seccomp_arch_add),
DLSYM_ARG(seccomp_arch_exist),
DLSYM_ARG(seccomp_arch_native),
DLSYM_ARG(seccomp_arch_remove),
DLSYM_ARG(seccomp_attr_set),
DLSYM_ARG(seccomp_init),
DLSYM_ARG(seccomp_load),
DLSYM_ARG(seccomp_release),
DLSYM_ARG(seccomp_rule_add_array),
DLSYM_ARG(seccomp_rule_add_exact),
DLSYM_ARG(seccomp_syscall_resolve_name),
DLSYM_ARG(seccomp_syscall_resolve_num_arch));
}
/* This array will be modified at runtime as seccomp_restrict_archs is called. */
uint32_t seccomp_local_archs[] = {
@@ -246,40 +286,44 @@ int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_
/* Much like seccomp_init(), but initializes the filter for one specific architecture only, without affecting
* any others. Also, turns off the NNP fiddling. */
seccomp = seccomp_init(default_action);
r = dlopen_libseccomp();
if (r < 0)
return r;
seccomp = sym_seccomp_init(default_action);
if (!seccomp)
return -ENOMEM;
if (arch != SCMP_ARCH_NATIVE &&
arch != seccomp_arch_native()) {
arch != sym_seccomp_arch_native()) {
r = seccomp_arch_remove(seccomp, seccomp_arch_native());
r = sym_seccomp_arch_remove(seccomp, sym_seccomp_arch_native());
if (r < 0)
return r;
r = seccomp_arch_add(seccomp, arch);
r = sym_seccomp_arch_add(seccomp, arch);
if (r < 0)
return r;
assert(seccomp_arch_exist(seccomp, arch) >= 0);
assert(seccomp_arch_exist(seccomp, SCMP_ARCH_NATIVE) == -EEXIST);
assert(seccomp_arch_exist(seccomp, seccomp_arch_native()) == -EEXIST);
assert(sym_seccomp_arch_exist(seccomp, arch) >= 0);
assert(sym_seccomp_arch_exist(seccomp, SCMP_ARCH_NATIVE) == -EEXIST);
assert(sym_seccomp_arch_exist(seccomp, sym_seccomp_arch_native()) == -EEXIST);
} else {
assert(seccomp_arch_exist(seccomp, SCMP_ARCH_NATIVE) >= 0);
assert(seccomp_arch_exist(seccomp, seccomp_arch_native()) >= 0);
assert(sym_seccomp_arch_exist(seccomp, SCMP_ARCH_NATIVE) >= 0);
assert(sym_seccomp_arch_exist(seccomp, sym_seccomp_arch_native()) >= 0);
}
r = seccomp_attr_set(seccomp, SCMP_FLTATR_ACT_BADARCH, SCMP_ACT_ALLOW);
r = sym_seccomp_attr_set(seccomp, SCMP_FLTATR_ACT_BADARCH, SCMP_ACT_ALLOW);
if (r < 0)
return r;
r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
r = sym_seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
if (r < 0)
return r;
#if SCMP_VER_MAJOR >= 3 || (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 4)
if (getenv_bool("SYSTEMD_LOG_SECCOMP") > 0) {
r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_LOG, 1);
r = sym_seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_LOG, 1);
if (r < 0)
log_debug_errno(r, "Failed to enable seccomp event logging: %m");
}
@@ -302,9 +346,10 @@ bool is_seccomp_available(void) {
static int cached_enabled = -1;
if (cached_enabled < 0) {
int b;
if (dlopen_libseccomp() < 0)
return (cached_enabled = false);
b = secure_getenv_bool("SYSTEMD_SECCOMP");
int b = secure_getenv_bool("SYSTEMD_SECCOMP");
if (b != 0) {
if (b < 0 && b != -ENXIO) /* ENXIO: env var unset */
log_debug_errno(b, "Failed to parse $SYSTEMD_SECCOMP value, ignoring.");
@@ -1049,14 +1094,18 @@ int seccomp_add_syscall_filter_item(
} else {
int id, r;
id = seccomp_syscall_resolve_name(name);
r = dlopen_libseccomp();
if (r < 0)
return r;
id = sym_seccomp_syscall_resolve_name(name);
if (id == __NR_SCMP_ERROR) {
if (log_missing)
log_debug("System call %s is not known, ignoring.", name);
return 0;
}
r = seccomp_rule_add_exact(seccomp, action, id, 0);
r = sym_seccomp_rule_add_exact(seccomp, action, id, 0);
if (r < 0) {
/* If the system call is not known on this architecture, then that's fine, let's ignore it */
bool ignore = r == -EDOM;
@@ -1127,6 +1176,10 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter
/* The one-stop solution: allocate a seccomp object, add the specified filter to it, and apply it. Once for
* each local arch. */
r = dlopen_libseccomp();
if (r < 0)
return r;
default_action_override = override_default_action(default_action);
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
@@ -1147,7 +1200,7 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter
NULSTR_FOREACH(name, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value) {
int id;
id = seccomp_syscall_resolve_name(name);
id = sym_seccomp_syscall_resolve_name(name);
if (id < 0)
continue;
@@ -1155,7 +1208,7 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter
if (strv_contains(added, name))
continue;
r = seccomp_rule_add_exact(seccomp, default_action, id, 0);
r = sym_seccomp_rule_add_exact(seccomp, default_action, id, 0);
if (r < 0 && r != -EDOM) /* EDOM means that the syscall is not available for arch */
return log_debug_errno(r, "Failed to add rule for system call %s() / %d: %m",
name, id);
@@ -1163,12 +1216,12 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter
#if (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 5) || SCMP_VER_MAJOR > 2
/* We have a large filter here, so let's turn on the binary tree mode if possible. */
r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_OPTIMIZE, 2);
r = sym_seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_OPTIMIZE, 2);
if (r < 0)
log_warning_errno(r, "Failed to set SCMP_FLTATR_CTL_OPTIMIZE, ignoring: %m");
#endif
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -1189,6 +1242,10 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter
if (hashmap_isempty(filter) && default_action == SCMP_ACT_ALLOW)
return 0;
r = dlopen_libseccomp();
if (r < 0)
return r;
default_action_override = override_default_action(default_action);
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
@@ -1215,14 +1272,14 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter
else if (error >= 0)
a = SCMP_ACT_ERRNO(error);
r = seccomp_rule_add_exact(seccomp, a, id, 0);
r = sym_seccomp_rule_add_exact(seccomp, a, id, 0);
if (r < 0) {
/* If the system call is not known on this architecture, then that's
* fine, let's ignore it */
_cleanup_free_ char *n = NULL;
bool ignore;
n = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, id);
n = sym_seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, id);
ignore = r == -EDOM;
if (!ignore || log_missing)
log_debug_errno(r, "Failed to add rule for system call %s() / %d%s: %m",
@@ -1236,7 +1293,7 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter
NULSTR_FOREACH(name, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value) {
int id;
id = seccomp_syscall_resolve_name(name);
id = sym_seccomp_syscall_resolve_name(name);
if (id < 0)
continue;
@@ -1244,7 +1301,7 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter
if (hashmap_contains(filter, INT_TO_PTR(id + 1)))
continue;
r = seccomp_rule_add_exact(seccomp, default_action, id, 0);
r = sym_seccomp_rule_add_exact(seccomp, default_action, id, 0);
if (r < 0 && r != -EDOM) /* EDOM means that the syscall is not available for arch */
return log_debug_errno(r, "Failed to add rule for system call %s() / %d: %m",
name, id);
@@ -1252,12 +1309,12 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter
#if (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 5) || SCMP_VER_MAJOR > 2
/* We have a large filter here, so let's turn on the binary tree mode if possible. */
r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_OPTIMIZE, 2);
r = sym_seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_OPTIMIZE, 2);
if (r < 0)
log_warning_errno(r, "Failed to set SCMP_FLTATR_CTL_OPTIMIZE, ignoring: %m");
#endif
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -1310,7 +1367,17 @@ int seccomp_parse_syscall_filter(
} else {
int id;
id = seccomp_syscall_resolve_name(name);
r = dlopen_libseccomp();
if (r < 0) {
if (!FLAGS_SET(flags, SECCOMP_PARSE_PERMISSIVE))
return r;
log_syntax(unit, FLAGS_SET(flags, SECCOMP_PARSE_LOG) ? LOG_WARNING : LOG_DEBUG, filename, line, r,
"System call %s cannot be resolved as libseccomp is not available, ignoring: %m", name);
return 0;
}
id = sym_seccomp_syscall_resolve_name(name);
if (id == __NR_SCMP_ERROR) {
if (!FLAGS_SET(flags, SECCOMP_PARSE_PERMISSIVE))
return -EINVAL;
@@ -1358,6 +1425,10 @@ int seccomp_restrict_namespaces(unsigned long retain) {
if (FLAGS_SET(retain, NAMESPACE_FLAGS_ALL))
return 0;
r = dlopen_libseccomp();
if (r < 0)
return r;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
@@ -1374,7 +1445,7 @@ int seccomp_restrict_namespaces(unsigned long retain) {
* C.f. https://github.com/flatpak/flatpak/commit/a10f52a7565c549612c92b8e736a6698a53db330,
* https://github.com/moby/moby/issues/42680. */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(ENOSYS),
SCMP_SYS(clone3),
@@ -1386,7 +1457,7 @@ int seccomp_restrict_namespaces(unsigned long retain) {
if ((retain & NAMESPACE_FLAGS_ALL) == 0)
/* If every single kind of namespace shall be prohibited, then let's block the whole
* setns() syscall altogether. */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(setns),
@@ -1394,7 +1465,7 @@ int seccomp_restrict_namespaces(unsigned long retain) {
else
/* Otherwise, block only the invocations with the appropriate flags in the loop
* below, but also the special invocation with a zero flags argument, right here. */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(setns),
@@ -1417,7 +1488,7 @@ int seccomp_restrict_namespaces(unsigned long retain) {
log_trace("Blocking %s.", namespace_info[i].proc_name);
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(unshare),
@@ -1431,14 +1502,14 @@ int seccomp_restrict_namespaces(unsigned long retain) {
/* On s390/s390x the first two parameters to clone are switched */
if (!IN_SET(arch, SCMP_ARCH_S390, SCMP_ARCH_S390X))
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(clone),
1,
SCMP_A0(SCMP_CMP_MASKED_EQ, f, f));
else
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(clone),
@@ -1451,7 +1522,7 @@ int seccomp_restrict_namespaces(unsigned long retain) {
}
if ((retain & NAMESPACE_FLAGS_ALL) != 0) {
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(setns),
@@ -1467,7 +1538,7 @@ int seccomp_restrict_namespaces(unsigned long retain) {
if (r < 0)
continue;
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -1482,6 +1553,10 @@ int seccomp_protect_sysctl(void) {
uint32_t arch;
int r;
r = dlopen_libseccomp();
if (r < 0)
return r;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
@@ -1504,7 +1579,7 @@ int seccomp_protect_sysctl(void) {
if (r < 0)
return r;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(_sysctl),
@@ -1515,7 +1590,7 @@ int seccomp_protect_sysctl(void) {
continue;
}
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -1530,6 +1605,10 @@ int seccomp_protect_syslog(void) {
uint32_t arch;
int r;
r = dlopen_libseccomp();
if (r < 0)
return r;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
@@ -1537,7 +1616,7 @@ int seccomp_protect_syslog(void) {
if (r < 0)
return r;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(syslog),
@@ -1548,7 +1627,7 @@ int seccomp_protect_syslog(void) {
continue;
}
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -1563,6 +1642,10 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) {
uint32_t arch;
int r;
r = dlopen_libseccomp();
if (r < 0)
return r;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
bool supported;
@@ -1642,7 +1725,7 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) {
if (first == 0) {
/* No entries in the valid range, block everything */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EAFNOSUPPORT),
SCMP_SYS(socket),
@@ -1656,7 +1739,7 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) {
} else {
/* Block everything below the first entry */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EAFNOSUPPORT),
SCMP_SYS(socket),
@@ -1669,7 +1752,7 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) {
}
/* Block everything above the last entry */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EAFNOSUPPORT),
SCMP_SYS(socket),
@@ -1687,7 +1770,7 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) {
if (set_contains(address_families, INT_TO_PTR(af)))
continue;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EAFNOSUPPORT),
SCMP_SYS(socket),
@@ -1710,7 +1793,7 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) {
* then combined in OR checks. */
SET_FOREACH(af, address_families) {
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EAFNOSUPPORT),
SCMP_SYS(socket),
@@ -1726,7 +1809,7 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) {
}
}
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -1749,6 +1832,10 @@ int seccomp_restrict_realtime_full(int error_code) {
assert(error_code > 0);
r = dlopen_libseccomp();
if (r < 0)
return r;
/* Determine the highest policy constant we want to allow */
FOREACH_ELEMENT(policy, permitted_policies)
if (*policy > max_policy)
@@ -1780,7 +1867,7 @@ int seccomp_restrict_realtime_full(int error_code) {
continue;
/* Deny this policy */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(error_code),
SCMP_SYS(sched_setscheduler),
@@ -1795,7 +1882,7 @@ int seccomp_restrict_realtime_full(int error_code) {
/* Deny-list all other policies, i.e. the ones with higher values. Note that all comparisons
* are unsigned here, hence no need no check for < 0 values. */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(error_code),
SCMP_SYS(sched_setscheduler),
@@ -1807,7 +1894,7 @@ int seccomp_restrict_realtime_full(int error_code) {
continue;
}
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -1825,11 +1912,11 @@ static int add_seccomp_syscall_filter(scmp_filter_ctx seccomp,
const struct scmp_arg_cmp arg) {
int r;
r = seccomp_rule_add_exact(seccomp, SCMP_ACT_ERRNO(EPERM), nr, arg_cnt, arg);
r = sym_seccomp_rule_add_exact(seccomp, SCMP_ACT_ERRNO(EPERM), nr, arg_cnt, arg);
if (r < 0) {
_cleanup_free_ char *n = NULL;
n = seccomp_syscall_resolve_num_arch(arch, nr);
n = sym_seccomp_syscall_resolve_num_arch(arch, nr);
log_debug_errno(r, "Failed to add %s() rule for architecture %s, skipping: %m",
strna(n),
seccomp_arch_to_string(arch));
@@ -1848,10 +1935,15 @@ assert_cc(SCMP_SYS(shmdt) > 0);
int seccomp_memory_deny_write_execute(void) {
uint32_t arch;
unsigned loaded = 0;
int r;
r = dlopen_libseccomp();
if (r < 0)
return r;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
int filter_syscall = 0, block_syscall = 0, shmat_syscall = 0, r;
int filter_syscall = 0, block_syscall = 0, shmat_syscall = 0;
log_trace("Operating on architecture: %s", seccomp_arch_to_string(arch));
@@ -1945,7 +2037,7 @@ int seccomp_memory_deny_write_execute(void) {
continue;
}
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -1965,6 +2057,10 @@ int seccomp_restrict_archs(Set *archs) {
int r;
bool blocked_new = false;
r = dlopen_libseccomp();
if (r < 0)
return r;
/* This installs a filter with no rules, but that restricts the system call architectures to the specified
* list.
*
@@ -1975,7 +2071,7 @@ int seccomp_restrict_archs(Set *archs) {
/* Note libseccomp includes our "native" (current) architecture in the filter by default.
* We do not remove it. For example, our callers expect to be able to call execve() afterwards
* to run a program with the restrictions applied. */
seccomp = seccomp_init(SCMP_ACT_ALLOW);
seccomp = sym_seccomp_init(SCMP_ACT_ALLOW);
if (!seccomp)
return -ENOMEM;
@@ -1983,7 +2079,7 @@ int seccomp_restrict_archs(Set *archs) {
uint32_t arch = seccomp_local_archs[i];
/* See above comment, our "native" architecture is never blocked. */
if (arch == seccomp_arch_native())
if (arch == sym_seccomp_arch_native())
continue;
/* That architecture might have already been blocked by a previous call to seccomp_restrict_archs. */
@@ -1996,14 +2092,14 @@ int seccomp_restrict_archs(Set *archs) {
* x32 syscalls should basically match x86-64 for everything except the pointer type.
* The important thing is that you can block the old 32-bit x86 syscalls.
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=850047 */
if (block && arch == SCMP_ARCH_X86_64 && seccomp_arch_native() == SCMP_ARCH_X32)
if (block && arch == SCMP_ARCH_X86_64 && sym_seccomp_arch_native() == SCMP_ARCH_X32)
block = !set_contains(archs, UINT32_TO_PTR(SCMP_ARCH_X32 + 1));
if (block) {
seccomp_local_archs[i] = SECCOMP_LOCAL_ARCH_BLOCKED;
blocked_new = true;
} else {
r = seccomp_arch_add(seccomp, arch);
r = sym_seccomp_arch_add(seccomp, arch);
if (r < 0 && r != -EEXIST)
return r;
}
@@ -2014,11 +2110,11 @@ int seccomp_restrict_archs(Set *archs) {
if (!blocked_new)
return 0;
r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
r = sym_seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
if (r < 0)
return r;
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -2049,9 +2145,15 @@ int parse_syscall_archs(char **l, Set **archs) {
}
int seccomp_filter_set_add_by_name(Hashmap *filter, bool add, const char *name) {
int r;
assert(filter);
assert(name);
r = dlopen_libseccomp();
if (r < 0)
return r;
if (name[0] == '@') {
const SyscallFilterSet *more;
@@ -2062,7 +2164,7 @@ int seccomp_filter_set_add_by_name(Hashmap *filter, bool add, const char *name)
return seccomp_filter_set_add(filter, add, more);
}
int id = seccomp_syscall_resolve_name(name);
int id = sym_seccomp_syscall_resolve_name(name);
if (id == __NR_SCMP_ERROR) {
log_debug("System call %s is not known, ignoring.", name);
return 0;
@@ -2097,6 +2199,10 @@ int seccomp_lock_personality(unsigned long personality) {
if (personality >= PERSONALITY_INVALID)
return -EINVAL;
r = dlopen_libseccomp();
if (r < 0)
return r;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
@@ -2104,7 +2210,7 @@ int seccomp_lock_personality(unsigned long personality) {
if (r < 0)
return r;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(personality),
@@ -2116,7 +2222,7 @@ int seccomp_lock_personality(unsigned long personality) {
continue;
}
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -2131,6 +2237,10 @@ int seccomp_protect_hostname(void) {
uint32_t arch;
int r;
r = dlopen_libseccomp();
if (r < 0)
return r;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
@@ -2138,7 +2248,7 @@ int seccomp_protect_hostname(void) {
if (r < 0)
return r;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(sethostname),
@@ -2149,7 +2259,7 @@ int seccomp_protect_hostname(void) {
continue;
}
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(setdomainname),
@@ -2160,7 +2270,7 @@ int seccomp_protect_hostname(void) {
continue;
}
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -2184,7 +2294,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
int r;
bool any = false;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(chmod),
@@ -2195,7 +2305,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
else
any = true;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(fchmod),
@@ -2206,7 +2316,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
else
any = true;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(fchmodat),
@@ -2218,7 +2328,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
any = true;
#if defined(__SNR_fchmodat2)
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(fchmodat2),
@@ -2228,7 +2338,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
/* It looks like this libseccomp does not know about fchmodat2().
* Pretend the fchmodat2() system call is not supported at all,
* regardless of the kernel version. */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(ENOSYS),
__NR_fchmodat2,
@@ -2239,7 +2349,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
else
any = true;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(mkdir),
@@ -2250,7 +2360,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
else
any = true;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(mkdirat),
@@ -2261,7 +2371,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
else
any = true;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(mknod),
@@ -2272,7 +2382,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
else
any = true;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(mknodat),
@@ -2283,7 +2393,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
else
any = true;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(open),
@@ -2295,7 +2405,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
else
any = true;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(openat),
@@ -2314,7 +2424,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
* compatible with kernels that are not absolutely recent. We would normally return EPERM for a
* policy check, but this isn't strictly a policy check. Instead, we return ENOSYS to force programs
* to call open() or openat() instead. We can properly enforce policy for those functions. */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(ENOSYS),
SCMP_SYS(openat2),
@@ -2325,7 +2435,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
any = true;
#endif
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(creat),
@@ -2343,6 +2453,10 @@ int seccomp_restrict_suid_sgid(void) {
uint32_t arch;
int r, k;
r = dlopen_libseccomp();
if (r < 0)
return r;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
@@ -2363,7 +2477,7 @@ int seccomp_restrict_suid_sgid(void) {
if (r < 0 && k < 0)
continue;
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
@@ -2382,7 +2496,7 @@ uint32_t scmp_act_kill_process(void) {
* for single-threaded apps does the right thing. */
#ifdef SCMP_ACT_KILL_PROCESS
if (seccomp_api_get() >= 3)
if (dlopen_libseccomp() >= 0 && sym_seccomp_api_get() >= 3)
return SCMP_ACT_KILL_PROCESS;
#endif
@@ -2434,7 +2548,7 @@ static int block_open_flag(scmp_filter_ctx seccomp, int flag) {
/* Blocks open() with the specified flag, where flag is O_SYNC or so. This makes these calls return
* EINVAL, in the hope the client code will retry without O_SYNC then. */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EINVAL),
SCMP_SYS(open),
@@ -2445,7 +2559,7 @@ static int block_open_flag(scmp_filter_ctx seccomp, int flag) {
else
any = true;
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EINVAL),
SCMP_SYS(openat),
@@ -2458,7 +2572,7 @@ static int block_open_flag(scmp_filter_ctx seccomp, int flag) {
#if defined(__SNR_openat2)
/* The new openat2() system call can't be filtered sensibly, see above. */
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(ENOSYS),
SCMP_SYS(openat2),
@@ -2481,6 +2595,10 @@ int seccomp_suppress_sync(void) {
*
* Additionally, O_SYNC/O_DSYNC are masked. */
r = dlopen_libseccomp();
if (r < 0)
return r;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
@@ -2491,14 +2609,14 @@ int seccomp_suppress_sync(void) {
NULSTR_FOREACH(c, syscall_filter_sets[SYSCALL_FILTER_SET_SYNC].value) {
int id;
id = seccomp_syscall_resolve_name(c);
id = sym_seccomp_syscall_resolve_name(c);
if (id == __NR_SCMP_ERROR) {
log_debug("System call %s is not known, ignoring.", c);
continue;
}
if (STR_IN_SET(c, "fdatasync", "fsync", "sync_file_range", "sync_file_range2", "syncfs"))
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(0), /* success → we want this to be a NOP after all */
id,
@@ -2507,7 +2625,7 @@ int seccomp_suppress_sync(void) {
* means non-negative fd matches the rule, and the negative
* fd passed to the syscall (then it fails with EBADF). */
else
r = seccomp_rule_add_exact(
r = sym_seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(0), /* success → we want this to be a NOP after all */
id,
@@ -2521,7 +2639,7 @@ int seccomp_suppress_sync(void) {
(void) block_open_flag(seccomp, O_DSYNC);
#endif
r = seccomp_load(seccomp);
r = sym_seccomp_load(seccomp);
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)

View File

@@ -1,14 +1,29 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#if HAVE_SECCOMP
#include <seccomp.h> /* IWYU pragma: export */
#endif
#include "errno-util.h"
#include "forward.h"
#if HAVE_SECCOMP
#include <seccomp.h> /* IWYU pragma: export */
#include "dlfcn-util.h"
extern DLSYM_PROTOTYPE(seccomp_api_get);
extern DLSYM_PROTOTYPE(seccomp_arch_add);
extern DLSYM_PROTOTYPE(seccomp_arch_exist);
extern DLSYM_PROTOTYPE(seccomp_arch_native);
extern DLSYM_PROTOTYPE(seccomp_arch_remove);
extern DLSYM_PROTOTYPE(seccomp_attr_set);
extern DLSYM_PROTOTYPE(seccomp_init);
extern DLSYM_PROTOTYPE(seccomp_load);
extern DLSYM_PROTOTYPE(seccomp_release);
extern DLSYM_PROTOTYPE(seccomp_rule_add_array);
extern DLSYM_PROTOTYPE(seccomp_rule_add_exact);
extern DLSYM_PROTOTYPE(seccomp_syscall_resolve_name);
extern DLSYM_PROTOTYPE(seccomp_syscall_resolve_num_arch);
int dlopen_libseccomp(void);
const char* seccomp_arch_to_string(uint32_t c);
int seccomp_arch_from_string(const char *n, uint32_t *ret);
@@ -135,7 +150,7 @@ static inline bool ERRNO_IS_NEG_SECCOMP_FATAL(intmax_t r) {
}
_DEFINE_ABS_WRAPPER(SECCOMP_FATAL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(scmp_filter_ctx, seccomp_release, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(scmp_filter_ctx, sym_seccomp_release, seccomp_releasep, NULL);
int parse_syscall_archs(char **l, Set **ret_archs);
@@ -151,6 +166,10 @@ static inline bool is_seccomp_available(void) {
return false;
}
static inline int dlopen_libseccomp(void) {
return -EOPNOTSUPP;
}
#endif
/* This is a special value to be used where syscall filters otherwise expect errno numbers, will be

View File

@@ -217,7 +217,7 @@ simple_tests += files(
common_test_dependencies = [
libmount,
librt,
libseccomp,
libseccomp_cflags,
libselinux,
threads,
]
@@ -290,6 +290,7 @@ executables += [
libblkid_cflags,
libkmod_cflags,
libp11kit_cflags,
libseccomp_cflags,
],
},
test_template + {
@@ -310,7 +311,7 @@ executables += [
},
test_template + {
'sources' : files('test-fd-util.c'),
'dependencies' : libseccomp,
'dependencies' : libseccomp_cflags,
},
test_template + {
'sources' : files(
@@ -378,7 +379,7 @@ executables += [
'extract' : files('nss-test-util.c'),
'dependencies' : [
libdl,
libseccomp,
libseccomp_cflags,
],
'conditions' : ['ENABLE_NSS'],
'timeout' : 120,
@@ -425,7 +426,7 @@ executables += [
},
test_template + {
'sources' : files('test-seccomp.c'),
'dependencies' : libseccomp,
'dependencies' : libseccomp_cflags,
'conditions' : ['HAVE_SECCOMP'],
},
test_template + {

View File

@@ -20,6 +20,7 @@
#include "pcre2-util.h"
#include "pkcs11-util.h"
#include "qrcode-util.h"
#include "seccomp-util.h"
#include "tests.h"
#include "tpm2-util.h"
@@ -56,6 +57,7 @@ static int run(int argc, char **argv) {
ASSERT_DLOPEN(dlopen_libpam, HAVE_PAM);
ASSERT_DLOPEN(dlopen_libacl, HAVE_ACL);
ASSERT_DLOPEN(dlopen_libblkid, HAVE_BLKID);
ASSERT_DLOPEN(dlopen_libseccomp, HAVE_SECCOMP);
return 0;
}

View File

@@ -1569,7 +1569,7 @@ TEST(run_tests_without_unshare) {
if (prepare_ns("(test-execute-without-unshare)") == 0) {
_cleanup_hashmap_free_ Hashmap *s = NULL;
r = seccomp_syscall_resolve_name("unshare");
r = sym_seccomp_syscall_resolve_name("unshare");
ASSERT_NE(r, __NR_SCMP_ERROR);
ASSERT_OK(hashmap_ensure_put(&s, NULL, UINT32_TO_PTR(r + 1), INT_TO_PTR(-1)));
ASSERT_OK(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EOPNOTSUPP), true));

View File

@@ -54,6 +54,8 @@ TEST(parse_syscall_and_errno) {
_cleanup_free_ char *n = NULL;
int e;
CHECK_SECCOMP(/* refuse_container= */ false);
assert_se(parse_syscall_and_errno("uname:EILSEQ", &n, &e) >= 0);
ASSERT_STREQ(n, "uname");
assert_se(e == errno_from_name("EILSEQ") && e >= 0);
@@ -112,7 +114,9 @@ TEST(seccomp_arch_to_string) {
uint32_t a, b;
const char *name;
a = seccomp_arch_native();
CHECK_SECCOMP(/* refuse_container= */ false);
a = sym_seccomp_arch_native();
assert_se(a > 0);
name = seccomp_arch_to_string(a);
assert_se(name);