From 93f6cee97e28868b5c4a5411e411d97b51026096 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 25 Jan 2025 09:33:58 +0900 Subject: [PATCH] libmount-util: introduce two helper functions This introduces libmount_parse_mountinfo() and libmount_parse_with_utab(). The former one parses only mountinfo, but the latter one also parse utab. Hopefully this avoids pitfalls like issue #35949. --- src/core/mount.c | 2 +- src/mount/mount-tool.c | 2 +- src/shared/libmount-util.c | 2 +- src/shared/libmount-util.h | 17 ++++++++++++++++- src/shared/mount-util.c | 15 +++++++++------ src/shutdown/test-umount.c | 8 +++++--- src/shutdown/umount.c | 10 +++++----- src/shutdown/umount.h | 3 ++- src/test/test-libmount.c | 2 +- src/test/test-mount-util.c | 2 +- 10 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/core/mount.c b/src/core/mount.c index 073e9c71933..6fff94d19b2 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1927,7 +1927,7 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { assert(m); - r = libmount_parse(NULL, NULL, &table, &iter); + r = libmount_parse_with_utab(&table, &iter); if (r < 0) return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index 5f9cf44b5df..d1b4773ce8c 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -805,7 +805,7 @@ static int find_mount_points(const char *what, char ***list) { /* Returns all mount points obtained from /proc/self/mountinfo in *list, * and the number of mount points as return value. */ - r = libmount_parse(NULL, NULL, &table, &iter); + r = libmount_parse_mountinfo(/* source = */ NULL, &table, &iter); if (r < 0) return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); diff --git a/src/shared/libmount-util.c b/src/shared/libmount-util.c index 38189047332..1a6b68f9202 100644 --- a/src/shared/libmount-util.c +++ b/src/shared/libmount-util.c @@ -4,7 +4,7 @@ #include "libmount-util.h" -int libmount_parse( +int libmount_parse_full( const char *path, FILE *source, struct libmnt_table **ret_table, diff --git a/src/shared/libmount-util.h b/src/shared/libmount-util.h index 2f789e7426f..a363f7e9b74 100644 --- a/src/shared/libmount-util.h +++ b/src/shared/libmount-util.h @@ -9,12 +9,27 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct libmnt_table*, mnt_free_table, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct libmnt_iter*, mnt_free_iter, NULL); -int libmount_parse( +int libmount_parse_full( const char *path, FILE *source, struct libmnt_table **ret_table, struct libmnt_iter **ret_iter); +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, 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, ret_table, ret_iter); +} + int libmount_is_leaf( struct libmnt_table *table, struct libmnt_fs *fs); diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c index 720965c46e8..75a18051bc1 100644 --- a/src/shared/mount-util.c +++ b/src/shared/mount-util.c @@ -60,7 +60,7 @@ int umount_recursive_full(const char *prefix, int flags, char **keep) { _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; bool again = false; - r = libmount_parse("/proc/self/mountinfo", f, &table, &iter); + r = libmount_parse_mountinfo(f, &table, &iter); if (r < 0) return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m"); @@ -217,7 +217,7 @@ int bind_remount_recursive_with_mountinfo( rewind(proc_self_mountinfo); - r = libmount_parse("/proc/self/mountinfo", proc_self_mountinfo, &table, &iter); + r = libmount_parse_mountinfo(proc_self_mountinfo, &table, &iter); if (r < 0) return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m"); @@ -1571,7 +1571,7 @@ int get_sub_mounts(const char *prefix, SubMount **ret_mounts, size_t *ret_n_moun assert(ret_mounts); assert(ret_n_mounts); - r = libmount_parse("/proc/self/mountinfo", NULL, &table, &iter); + r = libmount_parse_mountinfo(/* source = */ NULL, &table, &iter); if (r < 0) return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m"); @@ -1894,9 +1894,12 @@ static int path_get_mount_info_at( if (r < 0) return log_debug_errno(r, "Failed to get mount ID: %m"); - /* When getting options is requested, do not pass filename, otherwise utab will not read, and - * userspace options like "_netdev" will be lost. */ - r = libmount_parse(ret_options ? NULL : "/proc/self/mountinfo", /* source = */ NULL, &table, &iter); + /* When getting options is requested, we also need to parse utab, otherwise userspace options like + * "_netdev" will be lost. */ + if (ret_options) + r = libmount_parse_with_utab(&table, &iter); + else + r = libmount_parse_mountinfo(/* source = */ NULL, &table, &iter); if (r < 0) return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m"); diff --git a/src/shutdown/test-umount.c b/src/shutdown/test-umount.c index 93da2e0fc34..fe30d9a2fe8 100644 --- a/src/shutdown/test-umount.c +++ b/src/shutdown/test-umount.c @@ -3,6 +3,7 @@ #include "alloc-util.h" #include "detach-swap.h" #include "errno-util.h" +#include "fd-util.h" #include "log.h" #include "path-util.h" #include "string-util.h" @@ -11,17 +12,18 @@ static void test_mount_points_list_one(const char *fname) { _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head); - _cleanup_free_ char *testdata_fname = NULL; + _cleanup_fclose_ FILE *f = NULL; log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/self/mountinfo"); if (fname) { + _cleanup_free_ char *testdata_fname = NULL; assert_se(get_testdata_dir(fname, &testdata_fname) >= 0); - fname = testdata_fname; + ASSERT_NOT_NULL(f = fopen(testdata_fname, "re")); } LIST_HEAD_INIT(mp_list_head); - assert_se(mount_points_list_get(fname, &mp_list_head) >= 0); + assert_se(mount_points_list_get(f, &mp_list_head) >= 0); LIST_FOREACH(mount_point, m, mp_list_head) log_debug("path=%s o=%s f=0x%lx try-ro=%s", diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index 4bc01c75e08..a788f8cf838 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -47,16 +47,16 @@ void mount_points_list_free(MountPoint **head) { mount_point_free(head, *head); } -int mount_points_list_get(const char *mountinfo, MountPoint **head) { +int mount_points_list_get(FILE *f, MountPoint **head) { _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; int r; assert(head); - r = libmount_parse(mountinfo, NULL, &table, &iter); + r = libmount_parse_mountinfo(f, &table, &iter); if (r < 0) - return log_error_errno(r, "Failed to parse %s: %m", mountinfo ?: "/proc/self/mountinfo"); + return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); for (;;) { _cleanup_free_ char *options = NULL, *remount_options = NULL; @@ -70,7 +70,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) { if (r == 1) /* EOF */ break; if (r < 0) - return log_error_errno(r, "Failed to get next entry from %s: %m", mountinfo ?: "/proc/self/mountinfo"); + return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m"); path = mnt_fs_get_target(fs); if (!path) @@ -141,7 +141,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) { r = libmount_is_leaf(table, fs); if (r < 0) - return log_error_errno(r, "Failed to get children mounts for %s from %s: %m", path, mountinfo ?: "/proc/self/mountinfo"); + return log_error_errno(r, "Failed to get children mounts for %s from /proc/self/mountinfo: %m", path); bool leaf = r; *m = (MountPoint) { diff --git a/src/shutdown/umount.h b/src/shutdown/umount.h index f8f9ae80380..22498e1e776 100644 --- a/src/shutdown/umount.h +++ b/src/shutdown/umount.h @@ -6,6 +6,7 @@ ***/ #include +#include #include "list.h" @@ -22,5 +23,5 @@ typedef struct MountPoint { LIST_FIELDS(struct MountPoint, mount_point); } MountPoint; -int mount_points_list_get(const char *mountinfo, MountPoint **head); +int mount_points_list_get(FILE *f, MountPoint **head); void mount_points_list_free(MountPoint **head); diff --git a/src/test/test-libmount.c b/src/test/test-libmount.c index 9ba428e5bef..d514bb94d3b 100644 --- a/src/test/test-libmount.c +++ b/src/test/test-libmount.c @@ -24,7 +24,7 @@ static void test_libmount_unescaping_one( f = fmemopen((char*) string, strlen(string), "r"); assert_se(f); - assert_se(libmount_parse(title, f, &table, &iter) >= 0); + assert_se(libmount_parse_mountinfo(f, &table, &iter) >= 0); struct libmnt_fs *fs; const char *source, *target; diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c index 352c5a1af68..5fb4d23f3e8 100644 --- a/src/test/test-mount-util.c +++ b/src/test/test-mount-util.c @@ -393,7 +393,7 @@ TEST(umount_recursive) { assert_se(umount_recursive_full(t->prefix, MNT_DETACH, (char**) t->keep) >= 0); - r = libmount_parse("/proc/self/mountinfo", f, &table, &iter); + r = libmount_parse_mountinfo(f, &table, &iter); if (r < 0) { log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); _exit(EXIT_FAILURE); -- 2.47.3