From 8d3c49b1680a20ae5d157baa4adaa59c1ea33519 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Apr 2023 23:37:12 +0900 Subject: 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. --- src/basic/fd-util.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'src/basic') 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); } -- cgit v1.2.1