summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-04-17 23:37:12 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2023-04-19 03:38:47 +0900
commit8d3c49b1680a20ae5d157baa4adaa59c1ea33519 (patch)
tree8d9ae68b9427fa964bcf5211c348a84a4e2c87d8 /src/basic
parent4b1e461c49ea935df0c740b31aecfd161b12d2e7 (diff)
downloadsystemd-8d3c49b1680a20ae5d157baa4adaa59c1ea33519.tar.gz
fd-util: skip to check mount ID if kernel is too old and /proc is not mounted
Now, dir_fd_is_root() is heavily used in chaseat(), which is used at various places. If the kernel is too old and /proc is not mounted, then there is no way to get the mount ID of a directory. In that case, let's silently skip the mount ID check. Fixes https://github.com/systemd/systemd/pull/27299#issuecomment-1511403680.
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/fd-util.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index 7125e28e1b..974a7aac65 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -911,10 +911,23 @@ int dir_fd_is_root(int dir_fd) {
if (!statx_inode_same(&st.sx, &pst.sx))
return false;
+ /* Even if the parent directory has the same inode, the fd may not point to the root directory "/",
+ * and we also need to check that the mount ids are the same. Otherwise, a construct like the
+ * following could be used to trick us:
+ *
+ * $ mkdir /tmp/x /tmp/x/y
+ * $ mount --bind /tmp/x /tmp/x/y
+ *
+ * Note, statx() does not provide the mount ID and path_get_mnt_id_at() does not work when an old
+ * kernel is used without /proc mounted. In that case, let's assume that we do not have such spurious
+ * mount points in an early boot stage, and silently skip the following check. */
+
if (!FLAGS_SET(st.nsx.stx_mask, STATX_MNT_ID)) {
int mntid;
r = path_get_mnt_id_at(dir_fd, "", &mntid);
+ if (r == -ENOSYS)
+ return true; /* skip the mount ID check */
if (r < 0)
return r;
assert(mntid >= 0);
@@ -927,6 +940,8 @@ int dir_fd_is_root(int dir_fd) {
int mntid;
r = path_get_mnt_id_at(dir_fd, "..", &mntid);
+ if (r == -ENOSYS)
+ return true; /* skip the mount ID check */
if (r < 0)
return r;
assert(mntid >= 0);
@@ -935,13 +950,6 @@ int dir_fd_is_root(int dir_fd) {
pst.nsx.stx_mask |= STATX_MNT_ID;
}
- /* Even if the parent directory has the same inode, the fd may not point to the root directory "/",
- * and we also need to check that the mount ids are the same. Otherwise, a construct like the
- * following could be used to trick us:
- *
- * $ mkdir /tmp/x /tmp/x/y
- * $ mount --bind /tmp/x /tmp/x/y
- */
return statx_mount_same(&st.nsx, &pst.nsx);
}