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.net Signed-off-by: Ian 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
cfaf86ab6c
commit
6035974147
|
@ -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)
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
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,
|
||||||
*/
|
*/
|
||||||
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,
|
||||||
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,
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue