- In follup_up and follow_up_rcu don't follow up if the current mount's mountpoint can not reach the parent mount's root. - In prepend_path and it's callers in the d_path family don't follow to the parent mount if the current mount's mountpoint can not reach the parent mount's root. Signed-off-by: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> --- fs/dcache.c | 14 ++++++++++---- fs/namei.c | 27 +++++++++++++++++---------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index e07eb03f6de6..6e68312494ed 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2894,10 +2894,16 @@ restart: struct mount *parent = ACCESS_ONCE(mnt->mnt_parent); /* Global root? */ if (mnt != parent) { - dentry = ACCESS_ONCE(mnt->mnt_mountpoint); - mnt = parent; - vfsmnt = &mnt->mnt; - continue; + struct path new = { + .dentry = ACCESS_ONCE(mnt->mnt_mountpoint), + .mnt = &parent->mnt, + }; + if (path_connected(&new)) { + mnt = parent; + dentry = new.dentry; + vfsmnt = new.mnt; + continue; + } } /* * Filesystems needing to implement special "root names" diff --git a/fs/namei.c b/fs/namei.c index 83cdcdf36eed..40e56d76df34 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -935,14 +935,16 @@ static int follow_up_rcu(struct path *path) { struct mount *mnt = real_mount(path->mnt); struct mount *parent; - struct dentry *mountpoint; + struct path new; parent = mnt->mnt_parent; - if (&parent->mnt == path->mnt) + if (parent == mnt) return 0; - mountpoint = mnt->mnt_mountpoint; - path->dentry = mountpoint; - path->mnt = &parent->mnt; + new.dentry = mnt->mnt_mountpoint; + new.mnt = &parent->mnt; + if (!path_connected(&new)) + return 0; + *path = new; return 1; } @@ -960,7 +962,7 @@ int follow_up(struct path *path) { struct mount *mnt = real_mount(path->mnt); struct mount *parent; - struct dentry *mountpoint; + struct path new; read_seqlock_excl(&mount_lock); parent = mnt->mnt_parent; @@ -968,13 +970,18 @@ int follow_up(struct path *path) read_sequnlock_excl(&mount_lock); return 0; } - mntget(&parent->mnt); - mountpoint = dget(mnt->mnt_mountpoint); + new.dentry = mnt->mnt_mountpoint; + new.mnt = &parent->mnt; + if (!path_connected(&new)) { + read_sequnlock_excl(&mount_lock); + return 0; + } + mntget(new.mnt); + dget(new.dentry); read_sequnlock_excl(&mount_lock); dput(path->dentry); - path->dentry = mountpoint; mntput(path->mnt); - path->mnt = &parent->mnt; + *path = new; return 1; } EXPORT_SYMBOL(follow_up); -- 2.2.1 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html