From a08f2ea02dc4fcbd7f2f73a5a24e0af32b34fe55 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Nov 2025 14:43:22 +0100 Subject: [PATCH] process-util: also disable dlopen() in safe_fork() --- src/basic/process-util.c | 10 ++++++++++ src/libsystemd/meson.build | 5 ++++- src/libsystemd/sd-device/test-sd-device.c | 9 ++++++++- src/test/test-execute.c | 7 +++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 5759de38f4c..592e4c329c3 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -22,6 +22,7 @@ #include "argv-util.h" #include "cgroup-util.h" #include "dirent-util.h" +#include "dlfcn-util.h" #include "env-file.h" #include "errno-util.h" #include "escape.h" @@ -1695,6 +1696,15 @@ int pidref_safe_fork_full( r, "Failed to rename process, ignoring: %m"); } + /* let's disable dlopen() in the child, as a paranoia safety precaution: children should not live for + * long and only do minimal work before exiting or exec()ing. Doing dlopen() is not either. If people + * want dlopen() they should do it before forking. This is a safety precuation in particular for + * cases where the child does namespace shenanigans: we should never end up loading a module from a + * foreign environment. Note that this has no effect on NSS! (i.e. it only has effect on uses of our + * dlopen_safe(), which we use comprehensively in our codebase, but glibc NSS doesn't bother, of + * course.) */ + block_dlopen(); + if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL)) if (prctl(PR_SET_PDEATHSIG, fork_flags_to_signal(flags)) < 0) { log_full_errno(prio, errno, "Failed to set death signal: %m"); diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build index ec1ac471d9b..976f0e99876 100644 --- a/src/libsystemd/meson.build +++ b/src/libsystemd/meson.build @@ -203,7 +203,6 @@ simple_tests += files( 'sd-bus/test-bus-vtable.c', 'sd-device/test-device-util.c', 'sd-device/test-sd-device-monitor.c', - 'sd-device/test-sd-device.c', 'sd-journal/test-journal-flush.c', 'sd-journal/test-journal-interleaving.c', 'sd-journal/test-journal-stream.c', @@ -214,6 +213,10 @@ simple_tests += files( ) libsystemd_tests += [ + { + 'sources' : files('sd-device/test-sd-device.c'), + 'dependencies' : [ threads, libmount_cflags ], + }, { 'sources' : files('sd-bus/test-bus-address.c'), 'dependencies' : threads diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c index dc4a32e8a18..02525c83ec5 100644 --- a/src/libsystemd/sd-device/test-sd-device.c +++ b/src/libsystemd/sd-device/test-sd-device.c @@ -13,6 +13,7 @@ #include "fd-util.h" #include "fs-util.h" #include "hashmap.h" +#include "libmount-util.h" #include "mkdir.h" #include "mount-util.h" #include "mountpoint-util.h" @@ -833,8 +834,14 @@ TEST(devname_from_devnum) { } static int intro(void) { + int r; + if (path_is_mount_point("/sys") <= 0) - return log_tests_skipped("/sys is not mounted"); + return log_tests_skipped("/sys/ is not mounted"); + + r = dlopen_libmount(); + if (r < 0) + return log_tests_skipped("libmount not available."); return EXIT_SUCCESS; } diff --git a/src/test/test-execute.c b/src/test/test-execute.c index d0435210349..bccc6dc7fba 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -20,6 +20,7 @@ #include "fd-util.h" #include "fileio.h" #include "fs-util.h" +#include "libmount-util.h" #include "manager.h" #include "mkdir.h" #include "mount-util.h" @@ -1604,6 +1605,8 @@ TEST(run_tests_unprivileged) { } static int intro(void) { + int r; + #if HAS_FEATURE_ADDRESS_SANITIZER if (strstr_ptr(ci_environment(), "travis") || strstr_ptr(ci_environment(), "github-actions")) return log_tests_skipped("Running on Travis CI/GH Actions under ASan, see https://github.com/systemd/systemd/issues/10696"); @@ -1621,6 +1624,10 @@ static int intro(void) { if (path_is_read_only_fs("/sys") > 0) return log_tests_skipped("/sys is mounted read-only"); + r = dlopen_libmount(); + if (r < 0) + return log_tests_skipped("libmount not available."); + /* Create dummy network interface for testing PrivateNetwork=yes */ have_net_dummy = system("ip link add dummy-test-exec type dummy") == 0; -- 2.47.3