From f76f91b7c99574b3e7120f0dd008b2ab703efc47 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Tue, 25 Nov 2025 03:52:57 +0100 Subject: [PATCH 1/4] dlfcn-util: fix potential dl handle leak Follow-up for 2c7bdaf9f144ad339c72628579183fc849f2b794 --- src/basic/dlfcn-util.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/basic/dlfcn-util.c b/src/basic/dlfcn-util.c index 26c5a44ffe..8574e99546 100644 --- a/src/basic/dlfcn-util.c +++ b/src/basic/dlfcn-util.c @@ -84,6 +84,7 @@ void block_dlopen(void) { } int dlopen_safe(const char *filename, void **ret, const char **reterr_dlerror) { + _cleanup_(dlclosep) void *dl = NULL; int r; assert(filename); @@ -99,8 +100,8 @@ int dlopen_safe(const char *filename, void **ret, const char **reterr_dlerror) { flags |= RTLD_NOLOAD; errno = 0; - void *p = dlopen(filename, flags); - if (!p) { + dl = dlopen(filename, flags); + if (!dl) { if (dlopen_blocked) { (void) dlerror(); /* consume error, so that no later call will return it */ @@ -121,7 +122,7 @@ int dlopen_safe(const char *filename, void **ret, const char **reterr_dlerror) { } if (ret) - *ret = TAKE_PTR(p); + *ret = TAKE_PTR(dl); return 0; } From 1bee93e6e291b689c307ccf1496a44a73021fc84 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Tue, 25 Nov 2025 02:34:08 +0100 Subject: [PATCH 2/4] core/mount: comprehensively disable mount unit support if no libmount Follow-up for b3243f4beead231e27a4f017f53288a303177cb2 and 5df44d0f6a1ba23b52b0c46a5e720f334f152ae5 Since we now consider this a supported senario, let's hook up libmount loading with the high-level unit_type_supported() machinery and gracefully skip the whole unit accordingly. --- src/core/automount.c | 3 ++ src/core/mount.c | 106 +++++++++++++++++++++---------------------- src/core/unit.c | 5 ++ 3 files changed, 61 insertions(+), 53 deletions(-) diff --git a/src/core/automount.c b/src/core/automount.c index b53d91dda1..ddb524d01a 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -1033,6 +1033,9 @@ static void automount_reset_failed(Unit *u) { static bool automount_supported(void) { static int supported = -1; + if (!unit_type_supported(UNIT_MOUNT)) + return false; + if (supported < 0) supported = access("/dev/autofs", F_OK) >= 0; diff --git a/src/core/mount.c b/src/core/mount.c index 3bd22bfb9c..c2bc210616 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -240,34 +240,6 @@ static void mount_done(Unit *u) { m->timer_event_source = sd_event_source_disable_unref(m->timer_event_source); } -static int update_parameters_proc_self_mountinfo( - Mount *m, - const char *what, - const char *options, - const char *fstype) { - - MountParameters *p; - int r, q, w; - - assert(m); - - p = &m->parameters_proc_self_mountinfo; - - r = free_and_strdup(&p->what, what); - if (r < 0) - return r; - - q = free_and_strdup(&p->options, options); - if (q < 0) - return q; - - w = free_and_strdup(&p->fstype, fstype); - if (w < 0) - return w; - - return r > 0 || q > 0 || w > 0; -} - static int mount_add_mount_dependencies(Mount *m) { MountParameters *pm; int r; @@ -1747,6 +1719,34 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user } #if HAVE_LIBMOUNT +static int update_parameters_proc_self_mountinfo( + Mount *m, + const char *what, + const char *options, + const char *fstype) { + + MountParameters *p; + int r, q, w; + + assert(m); + + p = &m->parameters_proc_self_mountinfo; + + r = free_and_strdup(&p->what, what); + if (r < 0) + return r; + + q = free_and_strdup(&p->options, options); + if (q < 0) + return q; + + w = free_and_strdup(&p->fstype, fstype); + if (w < 0) + return w; + + return r > 0 || q > 0 || w > 0; +} + static int mount_setup_new_unit( Manager *m, const char *name, @@ -1927,10 +1927,8 @@ static int mount_setup_unit( return 0; } -#endif static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { -#if HAVE_LIBMOUNT _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; _cleanup_set_free_ Set *devices = NULL; @@ -1970,10 +1968,8 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { } return 0; -#else - return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "libmount support not compiled in"); -#endif } +#endif static void mount_shutdown(Manager *m) { assert(m); @@ -2025,6 +2021,7 @@ static void mount_enumerate_perpetual(Manager *m) { int r; assert(m); + assert(unit_type_supported(UNIT_MOUNT)); /* Whatever happens, we know for sure that the root directory is around, and cannot go away. Let's * unconditionally synthesize it here and mark it as perpetual. */ @@ -2044,13 +2041,13 @@ static void mount_enumerate_perpetual(Manager *m) { unit_add_to_dbus_queue(u); } +#if HAVE_LIBMOUNT static bool mount_is_mounted(Mount *m) { assert(m); return UNIT(m)->perpetual || FLAGS_SET(m->proc_flags, MOUNT_PROC_IS_MOUNTED); } -#if HAVE_LIBMOUNT static int mount_on_ratelimit_expire(sd_event_source *s, void *userdata) { Manager *m = ASSERT_PTR(userdata); Job *j; @@ -2072,17 +2069,12 @@ static int mount_on_ratelimit_expire(sd_event_source *s, void *userdata) { #endif static void mount_enumerate(Manager *m) { + assert(m); + assert(unit_type_supported(UNIT_MOUNT)); + #if HAVE_LIBMOUNT int r; - assert(m); - - r = dlopen_libmount(); - if (r < 0) { - log_error_errno(r, "Cannot enumerate mounts, as libmount is not available: %m"); - goto fail; - } - sym_mnt_init_debug(0); if (!m->mount_monitor) { @@ -2164,23 +2156,20 @@ static void mount_enumerate(Manager *m) { return; fail: - mount_shutdown(m); -#else - log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Cannot enumerate mounts, as libmount support is not compiled in"); - mount_shutdown(m); #endif + mount_shutdown(m); } static int drain_libmount(Manager *m) { -#if HAVE_LIBMOUNT - bool rescan = false; - int r; - assert(m); if (!m->mount_monitor) return false; +#if HAVE_LIBMOUNT + bool rescan = false; + int r; + /* Drain all events and verify that the event is valid. * * Note that libmount also monitors /run/mount mkdir if the directory does not exist yet. The mkdir @@ -2196,14 +2185,13 @@ static int drain_libmount(Manager *m) { } while (r == 0); return rescan; + #else - return 0; + assert_not_reached(); #endif } static int mount_process_proc_self_mountinfo(Manager *m) { - _cleanup_set_free_ Set *around = NULL, *gone = NULL; - const char *what; int r; assert(m); @@ -2212,6 +2200,7 @@ static int mount_process_proc_self_mountinfo(Manager *m) { if (r <= 0) return r; +#if HAVE_LIBMOUNT r = mount_load_proc_self_mountinfo(m, true); if (r < 0) { /* Reset flags, just in case, for later calls */ @@ -2223,6 +2212,8 @@ static int mount_process_proc_self_mountinfo(Manager *m) { manager_dispatch_load_queue(m); + _cleanup_set_free_ Set *around = NULL, *gone = NULL; + LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) { Mount *mount = MOUNT(u); @@ -2302,6 +2293,7 @@ static int mount_process_proc_self_mountinfo(Manager *m) { mount->proc_flags = 0; } + const char *what; SET_FOREACH(what, gone) { if (set_contains(around, what)) continue; @@ -2311,6 +2303,9 @@ static int mount_process_proc_self_mountinfo(Manager *m) { } return 0; +#else + assert_not_reached(); +#endif } #if HAVE_LIBMOUNT @@ -2410,6 +2405,10 @@ static int mount_test_startable(Unit *u) { return true; } +static bool mount_supported(void) { + return dlopen_libmount() >= 0; +} + static int mount_subsystem_ratelimited(Manager *m) { assert(m); @@ -2554,6 +2553,7 @@ const UnitVTable mount_vtable = { .enumerate_perpetual = mount_enumerate_perpetual, .enumerate = mount_enumerate, .shutdown = mount_shutdown, + .supported = mount_supported, .subsystem_ratelimited = mount_subsystem_ratelimited, .status_message_formats = { diff --git a/src/core/unit.c b/src/core/unit.c index b840370e24..50c744f5c8 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -5023,6 +5023,11 @@ int unit_add_mounts_for(Unit *u, const char *path, UnitDependencyMask mask, Unit if (hashmap_contains(*unit_map, path)) /* Exit quickly if the path is already covered. */ return 0; + if (!unit_type_supported(UNIT_MOUNT)) { + log_once(LOG_NOTICE, "Mount unit not supported, skipping *MountsFor= dependencies."); + return 0; + } + /* Use the canonical form of the path as the stored key. We call path_is_normalized() * only after simplification, since path_is_normalized() rejects paths with '.'. * path_is_normalized() also verifies that the path fits in PATH_MAX. */ From 46b4b33c256b918652d5e0b1b5ec376b598111f6 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Tue, 25 Nov 2025 03:19:37 +0100 Subject: [PATCH 3/4] Revert "pid1: pull in libmount unconditionally" This reverts commit 6069de1ed34735482dc63ba7431f605b858ea719. --- src/core/main.c | 7 ------- src/core/meson.build | 1 - 2 files changed, 8 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index f4acdb02c6..d7651d0df9 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -59,7 +59,6 @@ #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" @@ -3311,12 +3310,6 @@ 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, diff --git a/src/core/meson.build b/src/core/meson.build index c7beb8742a..acf665fba4 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -202,7 +202,6 @@ executables += [ 'dependencies' : [ libapparmor_cflags, libkmod_cflags, - libmount_cflags, libseccomp_cflags, libselinux_cflags, ], From 38b59a83d2caee6cede2d6946c4cc11ee54efea8 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Tue, 25 Nov 2025 03:26:10 +0100 Subject: [PATCH 4/4] libmount-util: build .c only if libmount feature is enabled Follow-up for 7336f2c748fd37a60a3f5353ad198c1534d6cb5f This alignes with some other optional modules in shraed/, and it allows dlopen_libmount() to be optimized out entirely. Let's avoid emitting pointless symbols. --- src/shared/libmount-util.c | 11 +---------- src/shared/libmount-util.h | 13 ++++++++++--- src/shared/meson.build | 13 ++++++++----- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/shared/libmount-util.c b/src/shared/libmount-util.c index 8de8baeff8..c6c6074c25 100644 --- a/src/shared/libmount-util.c +++ b/src/shared/libmount-util.c @@ -1,11 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "libmount-util.h" - -#if HAVE_LIBMOUNT #include #include "fstab-util.h" +#include "libmount-util.h" #include "log.h" static void *libmount_dl = NULL; @@ -41,10 +39,8 @@ DLSYM_PROTOTYPE(mnt_table_parse_mtab) = NULL; DLSYM_PROTOTYPE(mnt_table_parse_stream) = NULL; DLSYM_PROTOTYPE(mnt_table_parse_swaps) = NULL; DLSYM_PROTOTYPE(mnt_unref_monitor) = NULL; -#endif int dlopen_libmount(void) { -#if HAVE_LIBMOUNT ELF_NOTE_DLOPEN("mount", "Support for mount enumeration", ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED, @@ -85,12 +81,8 @@ int dlopen_libmount(void) { DLSYM_ARG(mnt_table_parse_stream), DLSYM_ARG(mnt_table_parse_swaps), DLSYM_ARG(mnt_unref_monitor)); -#else - return -EOPNOTSUPP; -#endif } -#if HAVE_LIBMOUNT int libmount_parse_full( const char *path, FILE *source, @@ -159,4 +151,3 @@ int libmount_is_leaf( return r == 1; } -#endif diff --git a/src/shared/libmount-util.h b/src/shared/libmount-util.h index 2f74299625..bfbb00cd4a 100644 --- a/src/shared/libmount-util.h +++ b/src/shared/libmount-util.h @@ -42,6 +42,8 @@ extern DLSYM_PROTOTYPE(mnt_table_parse_stream); extern DLSYM_PROTOTYPE(mnt_table_parse_swaps); extern DLSYM_PROTOTYPE(mnt_unref_monitor); +int dlopen_libmount(void); + DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct libmnt_table*, sym_mnt_free_table, mnt_free_tablep, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct libmnt_iter*, sym_mnt_free_iter, mnt_free_iterp, NULL); @@ -56,12 +58,14 @@ static inline int libmount_parse_mountinfo( FILE *source, struct libmnt_table **ret_table, struct libmnt_iter **ret_iter) { + return libmount_parse_full("/proc/self/mountinfo", source, MNT_ITER_FORWARD, ret_table, ret_iter); } static inline int libmount_parse_with_utab( struct libmnt_table **ret_table, struct libmnt_iter **ret_iter) { + return libmount_parse_full(NULL, NULL, MNT_ITER_FORWARD, ret_table, ret_iter); } @@ -70,15 +74,18 @@ int libmount_parse_fstab(struct libmnt_table **ret_table, struct libmnt_iter **r int libmount_is_leaf( struct libmnt_table *table, struct libmnt_fs *fs); + #else struct libmnt_monitor; -static inline void *sym_mnt_unref_monitor(struct libmnt_monitor *p) { +static inline int dlopen_libmount(void) { + return -EOPNOTSUPP; +} + +static inline void* sym_mnt_unref_monitor(struct libmnt_monitor *p) { assert(p == NULL); return NULL; } #endif - -int dlopen_libmount(void); diff --git a/src/shared/meson.build b/src/shared/meson.build index f2d73118bb..671bcb2f4f 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -115,7 +115,6 @@ shared_sources = files( 'libaudit-util.c', 'libcrypt-util.c', 'libfido2-util.c', - 'libmount-util.c', 'local-addresses.c', 'locale-setup.c', 'log-assert-critical.c', @@ -239,10 +238,6 @@ shared_sources = files( 'xml.c', ) -if conf.get('ENABLE_NSS') == 1 - shared_sources += files('nss-util.c') -endif - if get_option('tests') != 'false' shared_sources += files('tests.c') endif @@ -257,6 +252,10 @@ syscall_list_inc = custom_target( generated_sources += syscall_list_inc shared_sources += syscall_list_inc +if conf.get('ENABLE_NSS') == 1 + shared_sources += files('nss-util.c') +endif + if conf.get('ENABLE_UTMP') == 1 shared_sources += files('utmp-wtmp.c') endif @@ -269,6 +268,10 @@ if conf.get('HAVE_PAM') == 1 shared_sources += files('pam-util.c') endif +if conf.get('HAVE_LIBMOUNT') == 1 + shared_sources += files('libmount-util.c') +endif + generate_ip_protocol_list = files('generate-ip-protocol-list.sh') ip_protocol_list_txt = custom_target( input : [generate_ip_protocol_list, ipproto_sources],