mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-15 19:01:45 -04:00
Merge patch series "vfs: if RESOLVE_NO_XDEV passed to openat2, don't *trigger* automounts"
Askar Safin <safinaskar@zohomail.com> says: openat2 had a bug: if we pass RESOLVE_NO_XDEV, then openat2 doesn't traverse through automounts, but may still trigger them. See this link for full bug report with reproducer: https://lore.kernel.org/linux-fsdevel/20250817075252.4137628-1-safinaskar@zohomail.com/ This patchset fixes the bug. RESOLVE_NO_XDEV logic hopefully becomes more clear: now we immediately fail when we cross mountpoints. * patches from https://lore.kernel.org/20250825181233.2464822-1-safinaskar@zohomail.com: openat2: don't trigger automounts with RESOLVE_NO_XDEV namei: move cross-device check to __traverse_mounts namei: remove LOOKUP_NO_XDEV check from handle_mounts namei: move cross-device check to traverse_mounts Link: https://lore.kernel.org/20250825181233.2464822-1-safinaskar@zohomail.com Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
20
fs/namei.c
20
fs/namei.c
@@ -1449,6 +1449,10 @@ static int follow_automount(struct path *path, int *count, unsigned lookup_flags
|
||||
dentry->d_inode)
|
||||
return -EISDIR;
|
||||
|
||||
/* No need to trigger automounts if mountpoint crossing is disabled. */
|
||||
if (lookup_flags & LOOKUP_NO_XDEV)
|
||||
return -EXDEV;
|
||||
|
||||
if (count && (*count)++ >= MAXSYMLINKS)
|
||||
return -ELOOP;
|
||||
|
||||
@@ -1472,6 +1476,10 @@ static int __traverse_mounts(struct path *path, unsigned flags, bool *jumped,
|
||||
/* Allow the filesystem to manage the transit without i_rwsem
|
||||
* being held. */
|
||||
if (flags & DCACHE_MANAGE_TRANSIT) {
|
||||
if (lookup_flags & LOOKUP_NO_XDEV) {
|
||||
ret = -EXDEV;
|
||||
break;
|
||||
}
|
||||
ret = path->dentry->d_op->d_manage(path, false);
|
||||
flags = smp_load_acquire(&path->dentry->d_flags);
|
||||
if (ret < 0)
|
||||
@@ -1489,6 +1497,10 @@ static int __traverse_mounts(struct path *path, unsigned flags, bool *jumped,
|
||||
// here we know it's positive
|
||||
flags = path->dentry->d_flags;
|
||||
need_mntput = true;
|
||||
if (unlikely(lookup_flags & LOOKUP_NO_XDEV)) {
|
||||
ret = -EXDEV;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1630,12 +1642,8 @@ static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
|
||||
return -ECHILD;
|
||||
}
|
||||
ret = traverse_mounts(path, &jumped, &nd->total_link_count, nd->flags);
|
||||
if (jumped) {
|
||||
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
||||
ret = -EXDEV;
|
||||
else
|
||||
nd->state |= ND_JUMPED;
|
||||
}
|
||||
if (jumped)
|
||||
nd->state |= ND_JUMPED;
|
||||
if (unlikely(ret)) {
|
||||
dput(path->dentry);
|
||||
if (path->mnt != nd->path.mnt)
|
||||
|
||||
Reference in New Issue
Block a user