]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
process-util: also disable dlopen() in safe_fork()
authorLennart Poettering <lennart@poettering.net>
Thu, 20 Nov 2025 13:43:22 +0000 (14:43 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 24 Nov 2025 10:56:47 +0000 (11:56 +0100)
src/basic/process-util.c
src/libsystemd/meson.build
src/libsystemd/sd-device/test-sd-device.c
src/test/test-execute.c

index 5759de38f4c4f36165079aeced282d9e7a680894..592e4c329c30e0181770548b375a089af3b7448c 100644 (file)
@@ -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");
index ec1ac471d9b1e0066681ccd79ebfd7eac96dfbe3..976f0e998766c4e42c02531b6e9a8ed543bde552 100644 (file)
@@ -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
index dc4a32e8a188f0e3b72a744f8e70afe3937fac87..02525c83ec553b3501f50579dee6a37244b880b9 100644 (file)
@@ -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;
 }
index d043521034915c76b11087a071f576244bbb7a3c..bccc6dc7fba42e574bd4ec468a05463f12e1327e 100644 (file)
@@ -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;