From mboxrd@z Thu Jan 1 00:00:00 1970 From: ebiederm@xmission.com (Eric W. Biederman) Subject: [PATCH review 3/4] vfs: Handle mounts whose parents are unreachable from their mountpoint Date: Wed, 08 Apr 2015 18:33:34 -0500 Message-ID: <87mw2i8ab5.fsf_-_@x220.int.ebiederm.org> References: <871tncuaf6.fsf@x220.int.ebiederm.org> <87mw5xq7lt.fsf@x220.int.ebiederm.org> <87a8yqou41.fsf_-_@x220.int.ebiederm.org> <874moq9oyb.fsf_-_@x220.int.ebiederm.org> Mime-Version: 1.0 Content-Type: text/plain Cc: , Al Viro , Andy Lutomirski , "Serge E. Hallyn" , Richard Weinberger , Andrey Vagin , Jann Horn , Willy Tarreau , Omar Sandoval To: Linux Containers Return-path: Received: from out03.mta.xmission.com ([166.70.13.233]:60330 "EHLO out03.mta.xmission.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754893AbbDHXhj (ORCPT ); Wed, 8 Apr 2015 19:37:39 -0400 In-Reply-To: <874moq9oyb.fsf_-_@x220.int.ebiederm.org> (Eric W. Biederman's message of "Wed, 08 Apr 2015 18:31:56 -0500") Sender: linux-fsdevel-owner@vger.kernel.org List-ID: - 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" --- 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