From: Mike Yuan Date: Tue, 16 Dec 2025 00:54:40 +0000 (+0100) Subject: process-util: add a flag for retaining dlopen()-ability X-Git-Tag: v259~7^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=29a823b3b6058f86a6fcd4a8fa9fd37d46109a2b;p=thirdparty%2Fsystemd.git process-util: add a flag for retaining dlopen()-ability While blocking dlopen() in child generally makes sense, it does also lead to misery - in the very case of extension/cred refreshing it then enforces loading of libcryptsetup/libacl in pid1, which are otherwise never used. Let's add a flag to opt out hence, but still prohibit it in namespace_fork/enter(). --- diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index c8ee38b4f12..3a960e19cc5 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -8,6 +8,7 @@ #include #include +#include "dlfcn-util.h" #include "errno-util.h" #include "fd-util.h" #include "fileio.h" @@ -217,6 +218,9 @@ int namespace_open( int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) { int r; + /* Block dlopen() now, to avoid us inadvertently loading shared library from another namespace */ + block_dlopen(); + if (userns_fd >= 0) { /* Can't setns to your own userns, since then you could escalate from non-root to root in * your own namespace, so check if namespaces are equal before attempting to enter. */ diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 9cb3b131fb7..31dbdff87a2 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1703,7 +1703,8 @@ int pidref_safe_fork_full( * 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_SET(flags, FORK_ALLOW_DLOPEN)) + block_dlopen(); if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL)) if (prctl(PR_SET_PDEATHSIG, fork_flags_to_signal(flags)) < 0) { @@ -1906,6 +1907,7 @@ int namespace_fork( /* This is much like safe_fork(), but forks twice, and joins the specified namespaces in the middle * process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that * /proc/self/fd works correctly. */ + assert(!FLAGS_SET(flags, FORK_ALLOW_DLOPEN)); /* never allow loading shared library from another ns */ r = safe_fork_full(outer_name, NULL, diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 9217eebc8b5..0290978b998 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -187,8 +187,9 @@ typedef enum ForkFlags { FORK_NEW_NETNS = 1 << 20, /* Run child in its own network namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */ FORK_NEW_PIDNS = 1 << 21, /* Run child in its own PID namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */ FORK_FREEZE = 1 << 22, /* Don't return in child, just call freeze() instead */ + FORK_ALLOW_DLOPEN = 1 << 23, /* Do not block dlopen() in child */ - _FORK_PID_ONLY = 1 << 23, /* Don't open a pidfd referencing the child process */ + _FORK_PID_ONLY = 1 << 24, /* Don't open a pidfd referencing the child process */ } ForkFlags; int pidref_safe_fork_full(