mount-util: make path_get_mount_info_at() also read utab (#36154)

As "_netdev" is only stored in utab.

Fixes a bug introduced by 5261c521e3.
Fixes #35949.
This commit is contained in:
Yu Watanabe
2025-01-27 08:45:13 +09:00
committed by GitHub
10 changed files with 42 additions and 19 deletions
+1 -1
View File
@@ -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");
+1 -1
View File
@@ -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");
+1 -1
View File
@@ -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,
+16 -1
View File
@@ -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);
+9 -4
View File
@@ -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,7 +1894,12 @@ static int path_get_mount_info_at(
if (r < 0)
return log_debug_errno(r, "Failed to get mount ID: %m");
r = libmount_parse("/proc/self/mountinfo", 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");
+5 -3
View File
@@ -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",
+5 -5
View File
@@ -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) {
+2 -1
View File
@@ -6,6 +6,7 @@
***/
#include <stdbool.h>
#include <stdio.h>
#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);
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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);