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:
+1
-1
@@ -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");
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user