Commit 60359741 authored by Ian Kent's avatar Ian Kent Committed by Al Viro

autofs: use path_has_submounts() to fix unreliable have_submount() checks

If an automount mount is clone(2)ed into a file system that is propagation
private, when it later expires in the originating namespace, subsequent
calls to autofs ->d_automount() for that dentry in the original namespace
will return ELOOP until the mount is umounted in the cloned namespace.

Now that a struct path is available where needed use path_has_submounts()
instead of have_submounts() so we don't get false positives when checking
if a dentry is a mount point or contains mounts in the current namespace.

Link: http://lkml.kernel.org/r/20161011053423.27645.91233.stgit@pluto.themaw.netSigned-off-by: default avatarIan Kent <raven@themaw.net>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Omar Sandoval <osandov@osandov.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent cfaf86ab
...@@ -575,7 +575,7 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp, ...@@ -575,7 +575,7 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp,
devid = new_encode_dev(dev); devid = new_encode_dev(dev);
err = have_submounts(path.dentry); err = path_has_submounts(&path);
if (follow_down_one(&path)) if (follow_down_one(&path))
magic = path.dentry->d_sb->s_magic; magic = path.dentry->d_sb->s_magic;
......
...@@ -384,16 +384,16 @@ static struct vfsmount *autofs4_d_automount(struct path *path) ...@@ -384,16 +384,16 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
/* /*
* It's possible that user space hasn't removed directories * It's possible that user space hasn't removed directories
* after umounting a rootless multi-mount, although it * after umounting a rootless multi-mount, although it
* should. For v5 have_submounts() is sufficient to handle * should. For v5 path_has_submounts() is sufficient to
* this because the leaves of the directory tree under the * handle this because the leaves of the directory tree under
* mount never trigger mounts themselves (they have an autofs * the mount never trigger mounts themselves (they have an
* trigger mount mounted on them). But v4 pseudo direct mounts * autofs trigger mount mounted on them). But v4 pseudo direct
* do need the leaves to trigger mounts. In this case we * mounts do need the leaves to trigger mounts. In this case
* have no choice but to use the list_empty() check and * we have no choice but to use the list_empty() check and
* require user space behave. * require user space behave.
*/ */
if (sbi->version > 4) { if (sbi->version > 4) {
if (have_submounts(dentry)) { if (path_has_submounts(path)) {
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
goto done; goto done;
} }
......
...@@ -250,8 +250,9 @@ autofs4_find_wait(struct autofs_sb_info *sbi, const struct qstr *qstr) ...@@ -250,8 +250,9 @@ autofs4_find_wait(struct autofs_sb_info *sbi, const struct qstr *qstr)
static int validate_request(struct autofs_wait_queue **wait, static int validate_request(struct autofs_wait_queue **wait,
struct autofs_sb_info *sbi, struct autofs_sb_info *sbi,
const struct qstr *qstr, const struct qstr *qstr,
struct dentry *dentry, enum autofs_notify notify) const struct path *path, enum autofs_notify notify)
{ {
struct dentry *dentry = path->dentry;
struct autofs_wait_queue *wq; struct autofs_wait_queue *wq;
struct autofs_info *ino; struct autofs_info *ino;
...@@ -314,6 +315,7 @@ static int validate_request(struct autofs_wait_queue **wait, ...@@ -314,6 +315,7 @@ static int validate_request(struct autofs_wait_queue **wait,
*/ */
if (notify == NFY_MOUNT) { if (notify == NFY_MOUNT) {
struct dentry *new = NULL; struct dentry *new = NULL;
struct path this;
int valid = 1; int valid = 1;
/* /*
...@@ -333,7 +335,9 @@ static int validate_request(struct autofs_wait_queue **wait, ...@@ -333,7 +335,9 @@ static int validate_request(struct autofs_wait_queue **wait,
dentry = new; dentry = new;
} }
} }
if (have_submounts(dentry)) this.mnt = path->mnt;
this.dentry = dentry;
if (path_has_submounts(&this))
valid = 0; valid = 0;
if (new) if (new)
...@@ -406,7 +410,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, ...@@ -406,7 +410,7 @@ int autofs4_wait(struct autofs_sb_info *sbi,
return -EINTR; return -EINTR;
} }
ret = validate_request(&wq, sbi, &qstr, dentry, notify); ret = validate_request(&wq, sbi, &qstr, path, notify);
if (ret <= 0) { if (ret <= 0) {
if (ret != -EINTR) if (ret != -EINTR)
mutex_unlock(&sbi->wq_mutex); mutex_unlock(&sbi->wq_mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment