From 5469d511b3e444ed48a1bc20e27808348b1331e1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 1 Oct 2024 16:44:18 +0200 Subject: [PATCH] tree-wide: always do dlopen() with RTLD_NOW + RTLD_NODELETE Let's systematically use RTL_NOW|RLTD_NODELETE as flags passed to dlopen(), across our codebase. Various distros build with "-z now" anyway, hence it's weird to specify RTLD_LAZY trying to override that (which it doesn't). Hence, let's follow suit, and just do what everybody else does. Also set RTLD_NODELETE, which is apparently what distros will probably end up implying sooner or later anyway. Given that for pretty much all our dlopen() calls we never call dlclose() anyway, let's just set this everywhere too, to make things systematic. This way, the flags we use by default match what distros such as fedora do, there are no surprises, and read-only relocations can be a thing. Fixes: #34537 (cherry picked from commit bd4beaa2ebfbbec0a1263a7091a91e528ce8cf13) (cherry picked from commit e012eedd727a38bd18c9a540b92b95aa880d2b42) (cherry picked from commit 82019cc6913a0901baef4fed6442cee1afb61e6f) (cherry picked from commit 4d4e8b37a64e6d122bb2d0b0a48659ca122da03a) --- src/shared/bpf-dlopen.c | 4 ++-- src/shared/dlfcn-util.c | 2 +- src/shared/idn-util.c | 5 ++--- src/shared/tpm2-util.c | 2 +- src/shared/userdb.c | 2 +- src/test/test-dlopen.c | 2 +- src/test/test-nss-hosts.c | 2 +- src/test/test-nss-users.c | 2 +- 8 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/shared/bpf-dlopen.c b/src/shared/bpf-dlopen.c index f00dbeabae..dfdf995052 100644 --- a/src/shared/bpf-dlopen.c +++ b/src/shared/bpf-dlopen.c @@ -63,13 +63,13 @@ int dlopen_bpf(void) { DISABLE_WARNING_DEPRECATED_DECLARATIONS; - dl = dlopen("libbpf.so.1", RTLD_LAZY); + dl = dlopen("libbpf.so.1", RTLD_NOW|RTLD_NODELETE); if (!dl) { /* libbpf < 1.0.0 (we rely on 0.1.0+) provide most symbols we care about, but * unfortunately not all until 0.7.0. See bpf-compat.h for more details. * Once we consider we can assume 0.7+ is present we can just use the same symbol * list for both files, and when we assume 1.0+ is present we can remove this dlopen */ - dl = dlopen("libbpf.so.0", RTLD_LAZY); + dl = dlopen("libbpf.so.0", RTLD_NOW|RTLD_NODELETE); if (!dl) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "neither libbpf.so.1 nor libbpf.so.0 are installed: %s", dlerror()); diff --git a/src/shared/dlfcn-util.c b/src/shared/dlfcn-util.c index 8022f55294..2ebb1463c2 100644 --- a/src/shared/dlfcn-util.c +++ b/src/shared/dlfcn-util.c @@ -44,7 +44,7 @@ int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_l if (*dlp) return 0; /* Already loaded */ - dl = dlopen(filename, RTLD_LAZY); + dl = dlopen(filename, RTLD_NOW|RTLD_NODELETE); if (!dl) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "%s is not installed: %s", filename, dlerror()); diff --git a/src/shared/idn-util.c b/src/shared/idn-util.c index 26a9d608ec..28d2dc1309 100644 --- a/src/shared/idn-util.c +++ b/src/shared/idn-util.c @@ -42,11 +42,11 @@ int dlopen_idn(void) { if (idn_dl) return 0; /* Already loaded */ - dl = dlopen("libidn.so.12", RTLD_LAZY); + dl = dlopen("libidn.so.12", RTLD_NOW|RTLD_NODELETE); if (!dl) { /* libidn broke ABI in 1.34, but not in a way we care about (a new field got added to an * open-coded struct we do not use), hence support both versions. */ - dl = dlopen("libidn.so.11", RTLD_LAZY); + dl = dlopen("libidn.so.11", RTLD_NOW|RTLD_NODELETE); if (!dl) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "libidn support is not installed: %s", dlerror()); @@ -54,7 +54,6 @@ int dlopen_idn(void) { } else log_debug("Loaded 'libidn.so.12' via dlopen()"); - r = dlsym_many_or_warn( dl, LOG_DEBUG, diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 3aa09190ab..272f3dd59f 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -179,7 +179,7 @@ int tpm2_context_new(const char *device, Tpm2Context **ret_context) { if (!filename_is_valid(fn)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver); - context->tcti_dl = dlopen(fn, RTLD_NOW); + context->tcti_dl = dlopen(fn, RTLD_NOW|RTLD_NODELETE); if (!context->tcti_dl) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror()); diff --git a/src/shared/userdb.c b/src/shared/userdb.c index a77eff4407..049484fe7a 100644 --- a/src/shared/userdb.c +++ b/src/shared/userdb.c @@ -1454,7 +1454,7 @@ int userdb_block_nss_systemd(int b) { /* Note that we might be called from libnss_systemd.so.2 itself, but that should be fine, really. */ - dl = dlopen(ROOTLIBDIR "/libnss_systemd.so.2", RTLD_LAZY|RTLD_NODELETE); + dl = dlopen(ROOTLIBDIR "/libnss_systemd.so.2", RTLD_NOW|RTLD_NODELETE); if (!dl) { /* If the file isn't installed, don't complain loudly */ log_debug("Failed to dlopen(libnss_systemd.so.2), ignoring: %s", dlerror()); diff --git a/src/test/test-dlopen.c b/src/test/test-dlopen.c index 9c315373b4..6704e936e7 100644 --- a/src/test/test-dlopen.c +++ b/src/test/test-dlopen.c @@ -10,7 +10,7 @@ int main(int argc, char **argv) { int i; for (i = 0; i < argc - 1; i++) - assert_se(handles[i] = dlopen(argv[i + 1], RTLD_NOW)); + assert_se(handles[i] = dlopen(argv[i + 1], RTLD_NOW|RTLD_NODELETE)); for (i--; i >= 0; i--) assert_se(dlclose(handles[i]) == 0); diff --git a/src/test/test-nss-hosts.c b/src/test/test-nss-hosts.c index 72a9c6454c..611e135766 100644 --- a/src/test/test-nss-hosts.c +++ b/src/test/test-nss-hosts.c @@ -380,7 +380,7 @@ static int test_one_module(const char *dir, log_info("======== %s ========", module); - _cleanup_(dlclosep) void *handle = nss_open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE); + _cleanup_(dlclosep) void *handle = nss_open_handle(dir, module, RTLD_NOW|RTLD_NODELETE); if (!handle) return -EINVAL; diff --git a/src/test/test-nss-users.c b/src/test/test-nss-users.c index 5178779d54..cba0f823b9 100644 --- a/src/test/test-nss-users.c +++ b/src/test/test-nss-users.c @@ -166,7 +166,7 @@ static int test_one_module(const char *dir, log_info("======== %s ========", module); - _cleanup_(dlclosep) void *handle = nss_open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE); + _cleanup_(dlclosep) void *handle = nss_open_handle(dir, module, RTLD_NOW|RTLD_NODELETE); if (!handle) return -EINVAL;