From b8c78d33311ca4ead62f4d1af6c50017b49406f8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 15 Aug 2025 16:11:35 +0900 Subject: [PATCH 1/7] seccomp-util: use consistent argument names --- src/shared/seccomp-util.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index bde97acbec..54d4aa4d35 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -65,8 +65,8 @@ extern const SyscallFilterSet syscall_filter_sets[]; const SyscallFilterSet *syscall_filter_set_find(const char *name); -int seccomp_filter_set_add_by_name(Hashmap *s, bool b, const char *name); -int seccomp_filter_set_add(Hashmap *s, bool b, const SyscallFilterSet *set); +int seccomp_filter_set_add_by_name(Hashmap *filter, bool add, const char *name); +int seccomp_filter_set_add(Hashmap *filter, bool add, const SyscallFilterSet *set); int seccomp_add_syscall_filter_item( scmp_filter_ctx *ctx, @@ -77,7 +77,7 @@ int seccomp_add_syscall_filter_item( char ***added); int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action, bool log_missing); -int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action, bool log_missing); +int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap *filter, uint32_t action, bool log_missing); typedef enum SeccompParseFlags { SECCOMP_PARSE_INVERT = 1 << 0, From 45079ae1e6773530c990954a65499c7b73a943d6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 15 Aug 2025 13:21:59 +0900 Subject: [PATCH 2/7] hostname-setup: do not trigger assertion when uname() is prohibited by seccomp gethostname_full() is used in nss-myhostname, and hence random application may indirectly call it. When an application with a too strict seccomp filter loads the nss module, the application may trigger the assertion. Partially fixes #38582. --- src/shared/hostname-setup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shared/hostname-setup.c b/src/shared/hostname-setup.c index 0d21e0482d..ac13d06fb2 100644 --- a/src/shared/hostname-setup.c +++ b/src/shared/hostname-setup.c @@ -316,7 +316,8 @@ int gethostname_full(GetHostnameFlags flags, char **ret) { assert(ret); - assert_se(uname(&u) >= 0); + if (uname(&u) < 0) + return -errno; s = u.nodename; if (isempty(s) || streq(s, "(none)") || From 9bfcc81c322ae2371c2cc1591a4ef3406fd54737 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 15 Aug 2025 13:51:25 +0900 Subject: [PATCH 3/7] assert-util: drop message argument of assert_log() As it is always equals to #expr. --- src/basic/assert-util.h | 11 ++++++----- src/fundamental/assert-fundamental.h | 2 +- src/libsystemd/sd-bus/bus-internal.h | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/basic/assert-util.h b/src/basic/assert-util.h index f6bb7702ea..beb52ba884 100644 --- a/src/basic/assert-util.h +++ b/src/basic/assert-util.h @@ -10,19 +10,20 @@ bool log_get_assert_return_is_critical(void) _pure_; void log_assert_failed_return(const char *text, const char *file, int line, const char *func); -#define assert_log(expr, message) ((_likely_(expr)) \ - ? (true) \ - : (log_assert_failed_return(message, PROJECT_FILE, __LINE__, __func__), false)) +#define assert_log(expr) \ + (_likely_(expr) ? \ + true : \ + (log_assert_failed_return(#expr, PROJECT_FILE, __LINE__, __func__), false)) #define assert_return(expr, r) \ do { \ - if (!assert_log(expr, #expr)) \ + if (!assert_log(expr)) \ return (r); \ } while (false) #define assert_return_errno(expr, r, err) \ do { \ - if (!assert_log(expr, #expr)) { \ + if (!assert_log(expr)) { \ errno = err; \ return (r); \ } \ diff --git a/src/fundamental/assert-fundamental.h b/src/fundamental/assert-fundamental.h index 0b5c7f21de..3168e5699a 100644 --- a/src/fundamental/assert-fundamental.h +++ b/src/fundamental/assert-fundamental.h @@ -50,7 +50,7 @@ static inline int __coverity_check_and_return__(int condition) { #define assert_message_se(expr, message) __coverity_check__(!!(expr)) -#define assert_log(expr, message) __coverity_check_and_return__(!!(expr)) +#define assert_log(expr) __coverity_check_and_return__(!!(expr)) #else /* ! __COVERITY__ */ diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 0a0dd4143b..e8145622de 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -399,7 +399,7 @@ int bus_maybe_reply_error(sd_bus_message *m, int r, const sd_bus_error *e); #define bus_assert_return(expr, r, error) \ do { \ - if (!assert_log(expr, #expr)) \ + if (!assert_log(expr)) \ return sd_bus_error_set_errno(error, r); \ } while (false) From ed9c82095adb25af91d2f00d923bf00a25b35567 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 15 Aug 2025 15:24:07 +0900 Subject: [PATCH 4/7] assert-util: introduce log_set_assert_return_is_critical_from_env() It will be used for testing nss modules. --- docs/ENVIRONMENT.md | 3 +++ src/basic/assert-util.c | 17 +++++++++++++++++ src/basic/assert-util.h | 1 + 3 files changed, 21 insertions(+) diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index d423d9cd9c..d95ac4c430 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -454,6 +454,9 @@ systemd tests: causes all non-matching test functions to be skipped. Only applies to tests using our regular test boilerplate. +* `$SYSTEMD_ASSERT_RETURN_IS_CRITICAL` — Takes a boolean to control if + `assert_return()` and friends call `abort()`. + fuzzers: * `$SYSTEMD_FUZZ_OUTPUT` — A boolean that specifies whether to write output to diff --git a/src/basic/assert-util.c b/src/basic/assert-util.c index a1aa5c82e2..87b760e8fe 100644 --- a/src/basic/assert-util.c +++ b/src/basic/assert-util.c @@ -4,6 +4,7 @@ #include #include "assert-util.h" +#include "env-util.h" #include "errno-util.h" #include "log.h" @@ -17,6 +18,22 @@ void log_set_assert_return_is_critical(bool b) { assert_return_is_critical = b; } +void log_set_assert_return_is_critical_from_env(void) { + static int cached = INT_MIN; + int r; + + if (cached == INT_MIN) { + r = secure_getenv_bool("SYSTEMD_ASSERT_RETURN_IS_CRITICAL"); + if (r < 0 && r != -ENXIO) + log_debug_errno(r, "Failed to parse $SYSTEMD_ASSERT_RETURN_IS_CRITICAL, ignoring: %m"); + + cached = r; + } + + if (cached >= 0) + log_set_assert_return_is_critical(cached); +} + bool log_get_assert_return_is_critical(void) { return assert_return_is_critical; } diff --git a/src/basic/assert-util.h b/src/basic/assert-util.h index beb52ba884..fa3e13b220 100644 --- a/src/basic/assert-util.h +++ b/src/basic/assert-util.h @@ -6,6 +6,7 @@ /* Logging for various assertions */ void log_set_assert_return_is_critical(bool b); +void log_set_assert_return_is_critical_from_env(void); bool log_get_assert_return_is_critical(void) _pure_; void log_assert_failed_return(const char *text, const char *file, int line, const char *func); From ea70753479fbfe19b4ae5de9db846ab9edd290a8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 15 Aug 2025 15:06:53 +0900 Subject: [PATCH 5/7] nss: move definition of NSS_ENTRYPOINT_BEGIN to nss-util.h Then, also make nss modules parse $SYSTEMD_ASSERT_RETURN_IS_CRITICAL environment variable. This also moves nss-util.c and nss-util.h from src/basic/ to src/shared/, as they are not used by libsystemd. --- src/nss-myhostname/nss-myhostname.c | 6 ++--- src/nss-mymachines/nss-mymachines.c | 9 -------- src/nss-resolve/nss-resolve.c | 36 ++++++++--------------------- src/nss-systemd/nss-systemd.c | 9 -------- src/shared/meson.build | 1 + src/shared/nss-util.c | 23 ++++++++++++++++++ src/{basic => shared}/nss-util.h | 22 +++++++++++++++++- 7 files changed, 57 insertions(+), 49 deletions(-) create mode 100644 src/shared/nss-util.c rename src/{basic => shared}/nss-util.h (95%) diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c index b1a4cfebb8..333e1b3ba7 100644 --- a/src/nss-myhostname/nss-myhostname.c +++ b/src/nss-myhostname/nss-myhostname.c @@ -43,7 +43,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r( char *r_name; PROTECT_ERRNO; - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + NSS_ENTRYPOINT_BEGIN; assert(name); assert(pat); @@ -326,7 +326,7 @@ enum nss_status _nss_myhostname_gethostbyname3_r( int n_addresses = 0; PROTECT_ERRNO; - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + NSS_ENTRYPOINT_BEGIN; assert(name); assert(host); @@ -425,7 +425,7 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r( unsigned n; PROTECT_ERRNO; - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + NSS_ENTRYPOINT_BEGIN; assert(addr); assert(host); diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c index 2878ddc6b6..232e9cb91e 100644 --- a/src/nss-mymachines/nss-mymachines.c +++ b/src/nss-mymachines/nss-mymachines.c @@ -17,15 +17,6 @@ #include "signal-util.h" #include "string-util.h" -static void setup_logging_once(void) { - static pthread_once_t once = PTHREAD_ONCE_INIT; - assert_se(pthread_once(&once, log_parse_environment_variables) == 0); -} - -#define NSS_ENTRYPOINT_BEGIN \ - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); \ - setup_logging_once() - NSS_GETHOSTBYNAME_PROTOTYPES(mymachines); NSS_GETPW_PROTOTYPES(mymachines); NSS_GETGR_PROTOTYPES(mymachines); diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c index 3a660ca8b2..4edd6b5fda 100644 --- a/src/nss-resolve/nss-resolve.c +++ b/src/nss-resolve/nss-resolve.c @@ -19,24 +19,6 @@ #include "strv.h" #include "time-util.h" -static sd_json_dispatch_flags_t json_dispatch_flags = SD_JSON_ALLOW_EXTENSIONS; - -static void setup_logging(void) { - log_parse_environment_variables(); - - if (DEBUG_LOGGING) - json_dispatch_flags = SD_JSON_LOG; -} - -static void setup_logging_once(void) { - static pthread_once_t once = PTHREAD_ONCE_INIT; - assert_se(pthread_once(&once, setup_logging) == 0); -} - -#define NSS_ENTRYPOINT_BEGIN \ - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); \ - setup_logging_once() - NSS_GETHOSTBYNAME_PROTOTYPES(resolve); NSS_GETHOSTBYADDR_PROTOTYPES(resolve); @@ -258,7 +240,7 @@ enum nss_status _nss_resolve_gethostbyname4_r( goto not_found; } - r = sd_json_dispatch(rparams, resolve_hostname_reply_dispatch_table, json_dispatch_flags, &p); + r = sd_json_dispatch(rparams, resolve_hostname_reply_dispatch_table, nss_json_dispatch_flags, &p); if (r < 0) goto fail; if (sd_json_variant_is_blank_object(p.addresses)) @@ -268,7 +250,7 @@ enum nss_status _nss_resolve_gethostbyname4_r( JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) { AddressParameters q = {}; - r = sd_json_dispatch(entry, address_parameters_dispatch_table, json_dispatch_flags, &q); + r = sd_json_dispatch(entry, address_parameters_dispatch_table, nss_json_dispatch_flags, &q); if (r < 0) goto fail; @@ -306,7 +288,7 @@ enum nss_status _nss_resolve_gethostbyname4_r( JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) { AddressParameters q = {}; - r = sd_json_dispatch(entry, address_parameters_dispatch_table, json_dispatch_flags, &q); + r = sd_json_dispatch(entry, address_parameters_dispatch_table, nss_json_dispatch_flags, &q); if (r < 0) goto fail; @@ -422,7 +404,7 @@ enum nss_status _nss_resolve_gethostbyname3_r( goto not_found; } - r = sd_json_dispatch(rparams, resolve_hostname_reply_dispatch_table, json_dispatch_flags, &p); + r = sd_json_dispatch(rparams, resolve_hostname_reply_dispatch_table, nss_json_dispatch_flags, &p); if (r < 0) goto fail; if (sd_json_variant_is_blank_object(p.addresses)) @@ -432,7 +414,7 @@ enum nss_status _nss_resolve_gethostbyname3_r( JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) { AddressParameters q = {}; - r = sd_json_dispatch(entry, address_parameters_dispatch_table, json_dispatch_flags, &q); + r = sd_json_dispatch(entry, address_parameters_dispatch_table, nss_json_dispatch_flags, &q); if (r < 0) goto fail; @@ -478,7 +460,7 @@ enum nss_status _nss_resolve_gethostbyname3_r( JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) { AddressParameters q = {}; - r = sd_json_dispatch(entry, address_parameters_dispatch_table, json_dispatch_flags, &q); + r = sd_json_dispatch(entry, address_parameters_dispatch_table, nss_json_dispatch_flags, &q); if (r < 0) goto fail; @@ -640,7 +622,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( goto not_found; } - r = sd_json_dispatch(rparams, resolve_address_reply_dispatch_table, json_dispatch_flags, &p); + r = sd_json_dispatch(rparams, resolve_address_reply_dispatch_table, nss_json_dispatch_flags, &p); if (r < 0) goto fail; if (sd_json_variant_is_blank_object(p.names)) @@ -651,7 +633,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( JSON_VARIANT_ARRAY_FOREACH(entry, p.names) { _cleanup_(name_parameters_destroy) NameParameters q = {}; - r = sd_json_dispatch(entry, name_parameters_dispatch_table, json_dispatch_flags, &q); + r = sd_json_dispatch(entry, name_parameters_dispatch_table, nss_json_dispatch_flags, &q); if (r < 0) goto fail; @@ -692,7 +674,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( JSON_VARIANT_ARRAY_FOREACH(entry, p.names) { _cleanup_(name_parameters_destroy) NameParameters q = {}; - r = sd_json_dispatch(entry, name_parameters_dispatch_table, json_dispatch_flags, &q); + r = sd_json_dispatch(entry, name_parameters_dispatch_table, nss_json_dispatch_flags, &q); if (r < 0) goto fail; diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index 3c92cc2d00..f9a7d6caea 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -122,15 +122,6 @@ static GetentData getsgent_data = { }; REENABLE_WARNING; -static void setup_logging_once(void) { - static pthread_once_t once = PTHREAD_ONCE_INIT; - assert_se(pthread_once(&once, log_parse_environment_variables) == 0); -} - -#define NSS_ENTRYPOINT_BEGIN \ - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); \ - setup_logging_once() - NSS_GETPW_PROTOTYPES(systemd); NSS_GETSP_PROTOTYPES(systemd); NSS_GETGR_PROTOTYPES(systemd); diff --git a/src/shared/meson.build b/src/shared/meson.build index d433087459..ea5aa21b0c 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -137,6 +137,7 @@ shared_sources = files( 'notify-recv.c', 'nsflags.c', 'nsresource.c', + 'nss-util.c', 'numa-util.c', 'open-file.c', 'openssl-util.c', diff --git a/src/shared/nss-util.c b/src/shared/nss-util.c new file mode 100644 index 0000000000..32a36cd57e --- /dev/null +++ b/src/shared/nss-util.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +#include "sd-json.h" + +#include "assert-util.h" +#include "log.h" +#include "nss-util.h" + +sd_json_dispatch_flags_t nss_json_dispatch_flags = SD_JSON_ALLOW_EXTENSIONS; + +static void log_setup_nss_internal(void) { + log_set_assert_return_is_critical_from_env(); + log_parse_environment_variables(); + if (DEBUG_LOGGING) + nss_json_dispatch_flags = SD_JSON_LOG; +} + +void log_setup_nss(void) { + static pthread_once_t once = PTHREAD_ONCE_INIT; + assert_se(pthread_once(&once, log_setup_nss_internal) == 0); +} diff --git a/src/basic/nss-util.h b/src/shared/nss-util.h similarity index 95% rename from src/basic/nss-util.h rename to src/shared/nss-util.h index 2f55b7bc74..a4a4b5d920 100644 --- a/src/basic/nss-util.h +++ b/src/shared/nss-util.h @@ -7,7 +7,27 @@ #include #include -#define NSS_SIGNALS_BLOCK SIGALRM,SIGVTALRM,SIGPIPE,SIGCHLD,SIGTSTP,SIGIO,SIGHUP,SIGUSR1,SIGUSR2,SIGPROF,SIGURG,SIGWINCH +#include "forward.h" +#include "signal-util.h" + +extern sd_json_dispatch_flags_t nss_json_dispatch_flags; + +void log_setup_nss(void); + +#define NSS_ENTRYPOINT_BEGIN \ + log_setup_nss(); \ + BLOCK_SIGNALS(SIGALRM, \ + SIGVTALRM, \ + SIGPIPE, \ + SIGCHLD, \ + SIGTSTP, \ + SIGIO, \ + SIGHUP, \ + SIGUSR1, \ + SIGUSR2, \ + SIGPROF, \ + SIGURG, \ + SIGWINCH) #ifndef DEPRECATED_RES_USE_INET6 # define DEPRECATED_RES_USE_INET6 0x00002000 From 4ca46971a08f9009c01c2d3e5c0c7366df242ca1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 15 Aug 2025 13:57:51 +0900 Subject: [PATCH 6/7] signal-util: do not abort when sigprocmask() failed BLOCK_SIGNALS() is also used in nss modules. If an application is running with a too strict seccomp loads our nss modules, then the assertion may be triggered. Fixes #38582. --- src/basic/signal-util.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h index 7d8a284c50..04f3e73c78 100644 --- a/src/basic/signal-util.h +++ b/src/basic/signal-util.h @@ -36,16 +36,21 @@ int signal_from_string(const char *s) _pure_; void nop_signal_handler(int sig); -static inline void block_signals_reset(sigset_t *ss) { - assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0); +static inline void block_signals_reset(sigset_t **ss) { + assert(ss); + + if (!*ss) + return; + + assert_log(sigprocmask(SIG_SETMASK, *ss, NULL) >= 0); } -#define BLOCK_SIGNALS(...) \ - _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({ \ - sigset_t _t; \ - assert_se(sigprocmask_many(SIG_BLOCK, &_t, __VA_ARGS__) >= 0); \ - _t; \ - }) +#define BLOCK_SIGNALS(...) \ + sigset_t _saved_sigset; \ + _cleanup_(block_signals_reset) _unused_ sigset_t *_saved_sigsetp = \ + assert_log(sigprocmask_many(SIG_BLOCK, &_saved_sigset, __VA_ARGS__) >= 0) ? \ + &_saved_sigset : NULL; + #define SIGNO_INVALID (-EINVAL) static inline bool SIGNAL_VALID(int signo) { From 788b3e030e717404cbb65b4261bff2ef7ddb1b90 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 15 Aug 2025 14:44:13 +0900 Subject: [PATCH 7/7] test-nss-hosts: add test case for issue #38582 --- src/test/meson.build | 5 ++++- src/test/test-nss-hosts.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/test/meson.build b/src/test/meson.build index c65e73f487..da04b82d47 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -376,7 +376,10 @@ executables += [ 'nss-test-util.c', ), 'extract' : files('nss-test-util.c'), - 'dependencies' : libdl, + 'dependencies' : [ + libdl, + libseccomp, + ], 'conditions' : ['ENABLE_NSS'], 'timeout' : 120, }, diff --git a/src/test/test-nss-hosts.c b/src/test/test-nss-hosts.c index 8756fcd394..93de6d7add 100644 --- a/src/test/test-nss-hosts.c +++ b/src/test/test-nss-hosts.c @@ -8,6 +8,7 @@ #include "env-util.h" #include "errno-list.h" #include "format-ifname.h" +#include "hashmap.h" #include "hexdecoct.h" #include "hostname-setup.h" #include "in-addr-util.h" @@ -18,6 +19,8 @@ #include "nss-util.h" #include "parse-util.h" #include "path-util.h" +#include "process-util.h" +#include "seccomp-util.h" #include "socket-util.h" #include "string-util.h" #include "strv.h" @@ -472,7 +475,7 @@ static int run(int argc, char **argv) { int n_addresses = 0; int r; - test_setup_logging(LOG_INFO); + test_setup_logging(LOG_DEBUG); r = parse_argv(argc, argv, &modules, &names, &addresses, &n_addresses); if (r < 0) @@ -480,6 +483,32 @@ static int run(int argc, char **argv) { assert_se(path_extract_directory(argv[0], &dir) >= 0); + if (geteuid() != 0 || !is_seccomp_available()) + log_tests_skipped("Not privileged or seccomp is not available"); + else { + /* Testing with several syscalls filtered, and check if the nss modules gracefully handle failures in + * masked syscalls. See issue #38582. */ + + ASSERT_OK(r = safe_fork("(with-seccomp)", FORK_LOG | FORK_WAIT, /* ret_pid = */ NULL)); + if (r == 0) { + _cleanup_hashmap_free_ Hashmap *filter = NULL; + ASSERT_NOT_NULL(filter = hashmap_new(NULL)); + FOREACH_STRING(s, "uname", "olduname", "oldolduname", "sigprocmask", "rt_sigprocmask", "osf_sigprocmask") + ASSERT_OK(seccomp_filter_set_add_by_name(filter, /* add = */ true, s)); + ASSERT_OK(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, filter, SCMP_ACT_ERRNO(ENOSYS), /* log_missing = */ true)); + + /* To make assert_return() and friends not call abort(), even built as developer mode. */ + ASSERT_OK_ERRNO(setenv("SYSTEMD_ASSERT_RETURN_IS_CRITICAL", "0", /* overwrite = */ true)); + /* Let's also make nss modules output debugging logs. */ + ASSERT_OK_ERRNO(setenv("SYSTEMD_LOG_LEVEL", "debug", /* overwrite = */ true)); + + STRV_FOREACH(module, modules) + ASSERT_OK(test_one_module(dir, *module, names, addresses, n_addresses)); + + _exit(EXIT_SUCCESS); + } + } + STRV_FOREACH(module, modules) { r = test_one_module(dir, *module, names, addresses, n_addresses); if (r < 0)