block dlopen() once we transition into some foreign namespace (#39824)
Let's make sure we never accidentally end up loading code from a foreign namespace.
This commit is contained in:
+58
-6
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "dlfcn-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "log.h"
|
||||
|
||||
void* safe_dlclose(void *dl) {
|
||||
@@ -47,18 +48,20 @@ int dlsym_many_or_warn_sentinel(void *dl, int log_level, ...) {
|
||||
}
|
||||
|
||||
int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_level, ...) {
|
||||
_cleanup_(dlclosep) void *dl = NULL;
|
||||
int r;
|
||||
|
||||
if (*dlp)
|
||||
return 0; /* Already loaded */
|
||||
|
||||
dl = dlopen(filename, RTLD_NOW|RTLD_NODELETE);
|
||||
if (!dl)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"%s is not installed: %s", filename, dlerror());
|
||||
_cleanup_(dlclosep) void *dl = NULL;
|
||||
const char *dle = NULL;
|
||||
r = dlopen_safe(filename, &dl, &dle);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Shared library '%s' is not available: %s", filename, dle ?: STRERROR(r));
|
||||
return -EOPNOTSUPP; /* Turn into recognizable error */
|
||||
}
|
||||
|
||||
log_debug("Loaded '%s' via dlopen()", filename);
|
||||
log_debug("Loaded shared library '%s' via dlopen().", filename);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, log_level);
|
||||
@@ -73,3 +76,52 @@ int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_l
|
||||
*dlp = TAKE_PTR(dl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool dlopen_blocked = false;
|
||||
|
||||
void block_dlopen(void) {
|
||||
dlopen_blocked = true;
|
||||
}
|
||||
|
||||
int dlopen_safe(const char *filename, void **ret, const char **reterr_dlerror) {
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
|
||||
/* A wrapper around dlopen(), that takes dlopen_blocked into account, and tries to normalize the
|
||||
* error reporting a bit. */
|
||||
|
||||
int flags = RTLD_NOW|RTLD_NODELETE; /* Always set RTLD_NOW + RTLD_NODELETE, for security reasons */
|
||||
|
||||
/* If dlopen() is blocked we'll still try it, but set RTLD_NOLOAD, so that it will still work if
|
||||
* already loaded (for example because the binary linked to things regularly), but fail if not. */
|
||||
if (dlopen_blocked)
|
||||
flags |= RTLD_NOLOAD;
|
||||
|
||||
errno = 0;
|
||||
void *p = dlopen(filename, flags);
|
||||
if (!p) {
|
||||
if (dlopen_blocked) {
|
||||
(void) dlerror(); /* consume error, so that no later call will return it */
|
||||
|
||||
if (reterr_dlerror)
|
||||
*reterr_dlerror = NULL;
|
||||
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EPERM), "Refusing loading of '%s', as loading further dlopen() modules has been blocked.", filename);
|
||||
}
|
||||
|
||||
r = errno_or_else(ENOPKG);
|
||||
|
||||
if (reterr_dlerror)
|
||||
*reterr_dlerror = dlerror();
|
||||
else
|
||||
(void) dlerror(); /* consume error, so that no later call will return it */
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
*ret = TAKE_PTR(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -72,3 +72,11 @@ int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_l
|
||||
* _SONAME_ARRAY<X+1> will need to be added). */
|
||||
#define ELF_NOTE_DLOPEN(feature, description, priority, ...) \
|
||||
_ELF_NOTE_DLOPEN("[{\"feature\":\"" feature "\",\"description\":\"" description "\",\"priority\":\"" priority "\",\"soname\":" _SONAME_ARRAY(__VA_ARGS__) "}]", UNIQ_T(s, UNIQ))
|
||||
|
||||
/* If called dlopen_many_sym_or_warn() will fail with EPERM. This can be used to block lazy loading of shared
|
||||
* libs, if we transfer a process into a different namespace. Note that this does not work for all calls of
|
||||
* dlopen(), just those through our dlopen_safe() wrapper (which we use comprehensively in our
|
||||
* codebase). This hence has *no* effect on NSS. (Would be great if we could change that...) */
|
||||
void block_dlopen(void);
|
||||
|
||||
int dlopen_safe(const char *filename, void **ret, const char **reterr_dlerror);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "constants.h"
|
||||
#include "crash-handler.h"
|
||||
#include "dlfcn-util.h"
|
||||
#include "exit-status.h"
|
||||
#include "format-util.h"
|
||||
#include "log.h"
|
||||
@@ -70,6 +71,9 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) {
|
||||
* memory allocation is not async-signal-safe anyway — see signal-safety(7) for details —, and thus
|
||||
* is not permissible in signal handlers.) */
|
||||
|
||||
block_dlopen(); /* paranoia: never end up doing dlopen() as side-effect from some call anymore from
|
||||
* here */
|
||||
|
||||
if (getpid_cached() != 1)
|
||||
/* Pass this on immediately, if this is not PID 1 */
|
||||
propagate_signal(sig, siginfo);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "constants.h"
|
||||
#include "copy.h"
|
||||
#include "coredump-util.h"
|
||||
#include "cryptsetup-util.h"
|
||||
#include "dissect-image.h"
|
||||
#include "dynamic-user.h"
|
||||
#include "env-util.h"
|
||||
@@ -48,6 +49,7 @@
|
||||
#include "io-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "journal-send.h"
|
||||
#include "libmount-util.h"
|
||||
#include "manager.h"
|
||||
#include "memfd-util.h"
|
||||
#include "mkdir-label.h"
|
||||
@@ -5818,6 +5820,16 @@ int exec_invoke(
|
||||
}
|
||||
}
|
||||
|
||||
/* Load a bunch of libraries we'll possibly need later, before we turn off dlopen() */
|
||||
(void) dlopen_bpf();
|
||||
(void) dlopen_cryptsetup();
|
||||
(void) dlopen_libmount();
|
||||
(void) dlopen_libseccomp();
|
||||
|
||||
/* Let's now disable further dlopen()ing of libraries, since we are about to do namespace
|
||||
* shenanigans, and do not want to mix resources from host and namespace */
|
||||
block_dlopen();
|
||||
|
||||
if (needs_sandboxing && !have_cap_sys_admin && exec_needs_cap_sys_admin(context, params)) {
|
||||
/* If we're unprivileged, set up the user namespace first to enable use of the other namespaces.
|
||||
* Users with CAP_SYS_ADMIN can set up user namespaces last because they will be able to
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "killall.h"
|
||||
#include "kmod-setup.h"
|
||||
#include "label-util.h"
|
||||
#include "libmount-util.h"
|
||||
#include "limits-util.h"
|
||||
#include "load-fragment.h"
|
||||
#include "log.h"
|
||||
@@ -3310,6 +3311,12 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = dlopen_libmount();
|
||||
if (r < 0) {
|
||||
error_message = "Failed to load libmount.so";
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = initialize_runtime(skip_setup,
|
||||
first_boot,
|
||||
&saved_rlimit_nofile,
|
||||
|
||||
@@ -158,6 +158,8 @@ libcore_static = static_library(
|
||||
implicit_include_directories : false,
|
||||
c_args : ['-fvisibility=default'],
|
||||
dependencies : [libaudit_cflags,
|
||||
libbpf_cflags,
|
||||
libcryptsetup_cflags,
|
||||
libdl,
|
||||
libm,
|
||||
libmount_cflags,
|
||||
@@ -223,6 +225,7 @@ executables += [
|
||||
'dependencies' : [
|
||||
libapparmor_cflags,
|
||||
libkmod_cflags,
|
||||
libmount_cflags,
|
||||
libseccomp_cflags,
|
||||
libselinux_cflags,
|
||||
],
|
||||
@@ -235,6 +238,9 @@ executables += [
|
||||
'link_with' : executor_libs,
|
||||
'dependencies' : [
|
||||
libapparmor_cflags,
|
||||
libbpf_cflags,
|
||||
libcryptsetup_cflags,
|
||||
libmount_cflags,
|
||||
libpam_cflags,
|
||||
libseccomp_cflags,
|
||||
libselinux_cflags,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "bus-error.h"
|
||||
#include "bus-util.h"
|
||||
#include "chase.h"
|
||||
#include "cryptsetup-util.h"
|
||||
#include "dbus-service.h"
|
||||
#include "dbus-unit.h"
|
||||
#include "devnum-util.h"
|
||||
@@ -5552,6 +5553,8 @@ static int service_live_mount(
|
||||
u->id);
|
||||
}
|
||||
|
||||
(void) dlopen_cryptsetup();
|
||||
|
||||
service_unwatch_control_pid(s);
|
||||
s->live_mount_result = SERVICE_SUCCESS;
|
||||
s->control_command = NULL;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ executables += [
|
||||
include_directories('.')
|
||||
],
|
||||
'dependencies' : [
|
||||
libmount_cflags,
|
||||
libseccomp_cflags,
|
||||
libselinux_cflags,
|
||||
],
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "image-policy.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "io-util.h"
|
||||
#include "libmount-util.h"
|
||||
#include "log.h"
|
||||
#include "loop-util.h"
|
||||
#include "loopback-setup.h"
|
||||
@@ -4372,6 +4373,9 @@ static int outer_child(
|
||||
if (pid == 0) {
|
||||
fd_outer_socket = safe_close(fd_outer_socket);
|
||||
|
||||
/* In the child refuse dlopen(), so that we never mix shared libraries from payload and parent */
|
||||
block_dlopen();
|
||||
|
||||
/* The inner child has all namespaces that are requested, so that we all are owned by the
|
||||
* user if user namespaces are turned on. */
|
||||
|
||||
@@ -5962,6 +5966,10 @@ static int run(int argc, char *argv[]) {
|
||||
if (arg_cleanup)
|
||||
return do_cleanup();
|
||||
|
||||
(void) dlopen_libmount();
|
||||
(void) dlopen_libseccomp();
|
||||
(void) dlopen_libselinux();
|
||||
|
||||
r = cg_has_legacy();
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@@ -29,6 +29,8 @@ executables += [
|
||||
'sources' : systemd_portabled_sources,
|
||||
'link_with' : portabled_link_with,
|
||||
'dependencies' : [
|
||||
libcryptsetup_cflags,
|
||||
libmount_cflags,
|
||||
libselinux_cflags,
|
||||
threads,
|
||||
],
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "chase.h"
|
||||
#include "conf-files.h"
|
||||
#include "copy.h"
|
||||
#include "cryptsetup-util.h"
|
||||
#include "data-fd-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "discover-image.h"
|
||||
@@ -28,6 +29,7 @@
|
||||
#include "glyph-util.h"
|
||||
#include "install.h"
|
||||
#include "iovec-util.h"
|
||||
#include "libmount-util.h"
|
||||
#include "log-context.h"
|
||||
#include "log.h"
|
||||
#include "loop-util.h"
|
||||
@@ -420,6 +422,10 @@ static int portable_extract_by_path(
|
||||
|
||||
BLOCK_SIGNALS(SIGCHLD);
|
||||
|
||||
/* Load some libraries before we fork workers off that want to use them */
|
||||
(void) dlopen_cryptsetup();
|
||||
(void) dlopen_libmount();
|
||||
|
||||
r = mkdtemp_malloc("/tmp/inspect-XXXXXX", &tmpdir);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create temporary directory: %m");
|
||||
|
||||
@@ -16,6 +16,7 @@ executables += [
|
||||
'dependencies' : [
|
||||
libblkid_cflags,
|
||||
libfdisk,
|
||||
libmount_cflags,
|
||||
libopenssl,
|
||||
threads,
|
||||
],
|
||||
@@ -35,6 +36,7 @@ executables += [
|
||||
'dependencies' : [
|
||||
libblkid_cflags,
|
||||
libfdisk,
|
||||
libmount_cflags,
|
||||
libopenssl,
|
||||
threads,
|
||||
],
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "initrd-util.h"
|
||||
#include "io-util.h"
|
||||
#include "json-util.h"
|
||||
#include "libmount-util.h"
|
||||
#include "list.h"
|
||||
#include "loop-util.h"
|
||||
#include "main-func.h"
|
||||
@@ -6616,6 +6617,8 @@ static int partition_populate_filesystem(Context *context, Partition *p, const c
|
||||
* appear in the host namespace. Hence we fork a child that has its own file system namespace and
|
||||
* detached mount propagation. */
|
||||
|
||||
(void) dlopen_libmount();
|
||||
|
||||
r = safe_fork("(sd-copy)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
+11
-8
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "bpf-dlopen.h"
|
||||
#include "dlfcn-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "initrd-util.h"
|
||||
#include "log.h"
|
||||
|
||||
@@ -73,7 +74,6 @@ static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_lis
|
||||
}
|
||||
|
||||
int dlopen_bpf_full(int log_level) {
|
||||
_cleanup_(dlclosep) void *dl = NULL;
|
||||
static int cached = 0;
|
||||
int r;
|
||||
|
||||
@@ -87,17 +87,20 @@ int dlopen_bpf_full(int log_level) {
|
||||
|
||||
DISABLE_WARNING_DEPRECATED_DECLARATIONS;
|
||||
|
||||
dl = dlopen("libbpf.so.1", RTLD_NOW|RTLD_NODELETE);
|
||||
if (!dl) {
|
||||
_cleanup_(dlclosep) void *dl = NULL;
|
||||
r = dlopen_safe("libbpf.so.1", &dl, /* reterr_dlerror= */ NULL);
|
||||
if (r < 0) {
|
||||
/* 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_NOW|RTLD_NODELETE);
|
||||
if (!dl)
|
||||
return cached = log_full_errno(in_initrd() ? LOG_DEBUG : log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"Neither libbpf.so.1 nor libbpf.so.0 are installed, cgroup BPF features disabled: %s",
|
||||
dlerror());
|
||||
const char *dle = NULL;
|
||||
r = dlopen_safe("libbpf.so.0", &dl, &dle);
|
||||
if (r < 0) {
|
||||
log_full_errno(in_initrd() ? LOG_DEBUG : log_level, r,
|
||||
"Neither libbpf.so.1 nor libbpf.so.0 are installed, cgroup BPF features disabled: %s", dle ?: STRERROR(r));
|
||||
return (cached = -EOPNOTSUPP); /* turn into recognizable error */
|
||||
}
|
||||
|
||||
log_debug("Loaded 'libbpf.so.0' via dlopen()");
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "io-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "json-util.h"
|
||||
#include "libmount-util.h"
|
||||
#include "loop-util.h"
|
||||
#include "mkdir-label.h"
|
||||
#include "mount-util.h"
|
||||
@@ -3907,6 +3908,10 @@ int dissected_image_acquire_metadata(
|
||||
|
||||
assert(m);
|
||||
|
||||
r = dlopen_libmount();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (; n_meta_initialized < _META_MAX; n_meta_initialized++) {
|
||||
assert(paths[n_meta_initialized]);
|
||||
|
||||
|
||||
+13
-7
@@ -41,7 +41,6 @@ DLSYM_PROTOTYPE(stringprep_ucs4_to_utf8) = NULL;
|
||||
DLSYM_PROTOTYPE(stringprep_utf8_to_ucs4) = NULL;
|
||||
|
||||
int dlopen_idn(void) {
|
||||
_cleanup_(dlclosep) void *dl = NULL;
|
||||
int r;
|
||||
|
||||
ELF_NOTE_DLOPEN("idn",
|
||||
@@ -52,14 +51,21 @@ int dlopen_idn(void) {
|
||||
if (idn_dl)
|
||||
return 0; /* Already loaded */
|
||||
|
||||
dl = dlopen("libidn.so.12", RTLD_NOW|RTLD_NODELETE);
|
||||
if (!dl) {
|
||||
r = check_dlopen_blocked("libidn.so.12");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(dlclosep) void *dl = NULL;
|
||||
r = dlopen_safe("libidn.so.12", &dl, /* reterr_dlerror= */ NULL);
|
||||
if (r < 0) {
|
||||
/* 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_NOW|RTLD_NODELETE);
|
||||
if (!dl)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"libidn support is not installed: %s", dlerror());
|
||||
const char *dle = NULL;
|
||||
r = dlopen_safe("libidn.so.11", &dl, &dle);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "libidn support is not available: %s", dle ?: STRERROR(r));
|
||||
return -EOPNOTSUPP; /* turn into recognizable error */
|
||||
}
|
||||
log_debug("Loaded 'libidn.so.11' via dlopen()");
|
||||
} else
|
||||
log_debug("Loaded 'libidn.so.12' via dlopen()");
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "dirent-util.h"
|
||||
#include "dlfcn-util.h"
|
||||
#include "efi-api.h"
|
||||
#include "errno-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@@ -742,9 +743,12 @@ int tpm2_context_new(const char *device, Tpm2Context **ret_context) {
|
||||
if (!filename_is_valid(fn))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver);
|
||||
|
||||
context->tcti_dl = dlopen(fn, RTLD_NOW|RTLD_NODELETE);
|
||||
if (!context->tcti_dl)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOPKG), "Failed to load %s: %s", fn, dlerror());
|
||||
const char *dle = NULL;
|
||||
r = dlopen_safe(fn, &context->tcti_dl, &dle);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to load %s: %s", fn, dle ?: STRERROR(r));
|
||||
return -ENOPKG; /* Turn into recognizable error */
|
||||
}
|
||||
|
||||
log_debug("Loaded '%s' via dlopen()", fn);
|
||||
|
||||
|
||||
+7
-6
@@ -1977,21 +1977,22 @@ int membershipdb_by_group_strv(const char *name, UserDBFlags flags, char ***ret)
|
||||
}
|
||||
|
||||
int userdb_block_nss_systemd(int b) {
|
||||
_cleanup_(dlclosep) void *dl = NULL;
|
||||
int (*call)(bool b);
|
||||
int r;
|
||||
|
||||
/* Note that we might be called from libnss_systemd.so.2 itself, but that should be fine, really. */
|
||||
|
||||
dl = dlopen(LIBDIR "/libnss_systemd.so.2", RTLD_NOW|RTLD_NODELETE);
|
||||
if (!dl) {
|
||||
_cleanup_(dlclosep) void *dl = NULL;
|
||||
const char *dle;
|
||||
r = dlopen_safe(LIBDIR "/libnss_systemd.so.2", &dl, &dle);
|
||||
if (r < 0) {
|
||||
/* If the file isn't installed, don't complain loudly */
|
||||
log_debug("Failed to dlopen(libnss_systemd.so.2), ignoring: %s", dlerror());
|
||||
log_debug_errno(r, "Failed to dlopen(libnss_systemd.so.2), ignoring: %s", dle ?: STRERROR(r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("Loaded '%s' via dlopen()", LIBDIR "/libnss_systemd.so.2");
|
||||
|
||||
call = dlsym(dl, "_nss_systemd_block");
|
||||
int (*call)(bool b) = dlsym(dl, "_nss_systemd_block");
|
||||
if (!call)
|
||||
/* If the file is installed but lacks the symbol we expect, things are weird, let's complain */
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ELIBBAD),
|
||||
|
||||
@@ -6,6 +6,11 @@ executables += [
|
||||
'public' : true,
|
||||
'conditions' : ['ENABLE_SYSEXT'],
|
||||
'sources' : files('sysext.c'),
|
||||
'dependencies' : [
|
||||
libblkid_cflags,
|
||||
libcryptsetup_cflags,
|
||||
libmount_cflags,
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "sd-varlink.h"
|
||||
|
||||
#include "argv-util.h"
|
||||
#include "blkid-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "build.h"
|
||||
#include "bus-unit-util.h"
|
||||
@@ -18,6 +19,7 @@
|
||||
#include "capability-util.h"
|
||||
#include "chase.h"
|
||||
#include "conf-parser.h"
|
||||
#include "cryptsetup-util.h"
|
||||
#include "devnum-util.h"
|
||||
#include "discover-image.h"
|
||||
#include "dissect-image.h"
|
||||
@@ -33,6 +35,7 @@
|
||||
#include "image-policy.h"
|
||||
#include "initrd-util.h"
|
||||
#include "label-util.h" /* IWYU pragma: keep */
|
||||
#include "libmount-util.h"
|
||||
#include "log.h"
|
||||
#include "loop-util.h"
|
||||
#include "main-func.h"
|
||||
@@ -523,6 +526,8 @@ static int unmerge(
|
||||
bool need_to_reload;
|
||||
int r;
|
||||
|
||||
(void) dlopen_libmount();
|
||||
|
||||
r = need_reload(image_class, hierarchies, no_reload);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -2100,6 +2105,10 @@ static int merge(ImageClass image_class,
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
(void) dlopen_cryptsetup();
|
||||
(void) dlopen_libblkid();
|
||||
(void) dlopen_libmount();
|
||||
|
||||
r = safe_fork("(sd-merge)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS, &pid);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to fork off child: %m");
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dlfcn-util.h"
|
||||
#include "shared-forward.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
@@ -10,7 +11,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|RTLD_NODELETE));
|
||||
assert_se(dlopen_safe(argv[i + 1], handles + i, /* reterr_dlerror= */ NULL) >= 0);
|
||||
|
||||
for (i--; i >= 0; i--)
|
||||
assert_se(dlclose(handles[i]) == 0);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -116,7 +116,8 @@ endif
|
||||
udev_dependencies = [
|
||||
libacl_cflags,
|
||||
libblkid_cflags,
|
||||
libkmod,
|
||||
libkmod_cflags,
|
||||
libmount_cflags,
|
||||
threads,
|
||||
]
|
||||
|
||||
|
||||
@@ -8,10 +8,14 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "acl-util.h"
|
||||
#include "blkid-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "label-util.h"
|
||||
#include "libmount-util.h"
|
||||
#include "log.h"
|
||||
#include "module-util.h"
|
||||
#include "process-util.h"
|
||||
#include "rlimit-util.h"
|
||||
#include "terminal-util.h"
|
||||
@@ -52,6 +56,12 @@ int run_udevd(int argc, char *argv[]) {
|
||||
if (r < 0 && r != -EEXIST)
|
||||
return log_error_errno(r, "Failed to create /run/udev: %m");
|
||||
|
||||
/* Load some shared libraries before we fork any workers */
|
||||
(void) dlopen_libacl();
|
||||
(void) dlopen_libblkid();
|
||||
(void) dlopen_libkmod();
|
||||
(void) dlopen_libmount();
|
||||
|
||||
if (arg_daemonize) {
|
||||
pid_t pid;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user