diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-11-07 19:56:46 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2024-11-08 13:25:17 +0100 |
commit | 5261c521e3a98932241f36e91cf6f7823c578aca (patch) | |
tree | 8ae2fd5cc093fe60cd1fd08de9fb5d7be24b3855 /src/shared | |
parent | test: install integration-test-setup.sh in testdata/ (diff) | |
download | systemd-5261c521e3a98932241f36e91cf6f7823c578aca.tar.xz systemd-5261c521e3a98932241f36e91cf6f7823c578aca.zip |
mount-util: make path_get_mount_info() work arbitrary inode
Follow-up for d49d95df0a260aaca9a3fdd1e6ce535592a53bca.
Replaces 9a032ec55a9820a0424309670fe551c99203e5f1.
Fixes #35075.
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/mount-util.c | 92 | ||||
-rw-r--r-- | src/shared/mount-util.h | 5 |
2 files changed, 59 insertions, 38 deletions
diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c index f04235001d..576f7e83aa 100644 --- a/src/shared/mount-util.c +++ b/src/shared/mount-util.c @@ -1808,63 +1808,81 @@ char* umount_and_unlink_and_free(char *p) { return mfree(p); } -static int path_get_mount_info( +static int path_get_mount_info_at( + int dir_fd, const char *path, char **ret_fstype, char **ret_options) { _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; - _cleanup_free_ char *fstype = NULL, *options = NULL; - struct libmnt_fs *fs; - int r; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; + int r, mnt_id; - assert(path); + assert(dir_fd >= 0 || dir_fd == AT_FDCWD); - table = mnt_new_table(); - if (!table) - return -ENOMEM; + r = path_get_mnt_id_at(dir_fd, path, &mnt_id); + if (r < 0) + return log_debug_errno(r, "Failed to get mount ID: %m"); - r = mnt_table_parse_mtab(table, /* filename = */ NULL); + r = libmount_parse("/proc/self/mountinfo", NULL, &table, &iter); if (r < 0) - return r; + return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m"); - fs = mnt_table_find_mountpoint(table, path, MNT_ITER_FORWARD); - if (!fs) - return -EINVAL; + for (;;) { + struct libmnt_fs *fs; - if (ret_fstype) { - fstype = strdup(strempty(mnt_fs_get_fstype(fs))); - if (!fstype) - return -ENOMEM; - } + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) + break; /* EOF */ + if (r < 0) + return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m"); - if (ret_options) { - options = strdup(strempty(mnt_fs_get_options(fs))); - if (!options) - return -ENOMEM; - } + if (mnt_fs_get_id(fs) != mnt_id) + continue; - if (ret_fstype) - *ret_fstype = TAKE_PTR(fstype); - if (ret_options) - *ret_options = TAKE_PTR(options); + _cleanup_free_ char *fstype = NULL, *options = NULL; - return 0; + if (ret_fstype) { + fstype = strdup(strempty(mnt_fs_get_fstype(fs))); + if (!fstype) + return log_oom_debug(); + } + + if (ret_options) { + options = strdup(strempty(mnt_fs_get_options(fs))); + if (!options) + return log_oom_debug(); + } + + if (ret_fstype) + *ret_fstype = TAKE_PTR(fstype); + if (ret_options) + *ret_options = TAKE_PTR(options); + + return 0; + } + + return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "Cannot find mount ID %i from /proc/self/mountinfo.", mnt_id); } -int path_is_network_fs_harder(const char *path) { - _cleanup_free_ char *fstype = NULL, *options = NULL; - int r, ret; +int path_is_network_fs_harder_at(int dir_fd, const char *path) { + _cleanup_close_ int fd = -EBADF; + int r; - assert(path); + assert(dir_fd >= 0 || dir_fd == AT_FDCWD); - ret = path_is_network_fs(path); - if (ret > 0) - return true; + fd = xopenat(dir_fd, path, O_PATH | O_CLOEXEC | O_NOFOLLOW); + if (fd < 0) + return fd; + + r = fd_is_network_fs(fd); + if (r != 0) + return r; - r = path_get_mount_info(path, &fstype, &options); + _cleanup_free_ char *fstype = NULL, *options = NULL; + r = path_get_mount_info_at(fd, /* path = */ NULL, &fstype, &options); if (r < 0) - return RET_GATHER(ret, r); + return r; if (fstype_is_network(fstype)) return true; diff --git a/src/shared/mount-util.h b/src/shared/mount-util.h index 067ed0e4d9..496a95ab05 100644 --- a/src/shared/mount-util.h +++ b/src/shared/mount-util.h @@ -181,4 +181,7 @@ int mount_credentials_fs(const char *path, size_t size, bool ro); int make_fsmount(int error_log_level, const char *what, const char *type, unsigned long flags, const char *options, int userns_fd); -int path_is_network_fs_harder(const char *path); +int path_is_network_fs_harder_at(int dir_fd, const char *path); +static inline int path_is_network_fs_harder(const char *path) { + return path_is_network_fs_harder_at(AT_FDCWD, path); +} |