summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2024-11-07 19:56:46 +0100
committerLennart Poettering <lennart@poettering.net>2024-11-08 13:25:17 +0100
commit5261c521e3a98932241f36e91cf6f7823c578aca (patch)
tree8ae2fd5cc093fe60cd1fd08de9fb5d7be24b3855 /src/shared
parenttest: install integration-test-setup.sh in testdata/ (diff)
downloadsystemd-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.c92
-rw-r--r--src/shared/mount-util.h5
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);
+}