diff options
author | Ian Kent <raven@themaw.net> | 2012-12-13 21:23:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 22:13:25 -0500 |
commit | 0259cb02c4004d3088b0999799f8f5c8801f6b97 (patch) | |
tree | b93489768a12a36fbb2ec33d1e04742f84238d9e /fs/autofs4/root.c | |
parent | f55fb0c24386cee8b78f60d60186716bd0909493 (diff) |
autofs4 - use simple_empty() for empty directory check
For direct (and offset) mounts, if an automounted mount is manually
umounted the trigger mount dentry can appear non-empty causing it to
not trigger mounts. This can also happen if there is a file handle
leak in a user space automounting application.
This happens because, when a ioctl control file handle is opened
on the mount, a cursor dentry is created which causes list_empty()
to see the dentry as non-empty. Since there is a case where listing
the directory of these dentrys is needed, the use of dcache_dir_*()
functions for .open() and .release() is needed.
Consequently simple_empty() must be used instead of list_empty()
when checking for an empty directory.
Signed-off-by: Ian Kent <raven@themaw.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/autofs4/root.c')
-rw-r--r-- | fs/autofs4/root.c | 22 |
1 files changed, 5 insertions, 17 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 30a6ab66e99a..c93447604da8 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -124,13 +124,10 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
124 | * it. | 124 | * it. |
125 | */ | 125 | */ |
126 | spin_lock(&sbi->lookup_lock); | 126 | spin_lock(&sbi->lookup_lock); |
127 | spin_lock(&dentry->d_lock); | 127 | if (!d_mountpoint(dentry) && simple_empty(dentry)) { |
128 | if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { | ||
129 | spin_unlock(&dentry->d_lock); | ||
130 | spin_unlock(&sbi->lookup_lock); | 128 | spin_unlock(&sbi->lookup_lock); |
131 | return -ENOENT; | 129 | return -ENOENT; |
132 | } | 130 | } |
133 | spin_unlock(&dentry->d_lock); | ||
134 | spin_unlock(&sbi->lookup_lock); | 131 | spin_unlock(&sbi->lookup_lock); |
135 | 132 | ||
136 | out: | 133 | out: |
@@ -386,12 +383,8 @@ static struct vfsmount *autofs4_d_automount(struct path *path) | |||
386 | goto done; | 383 | goto done; |
387 | } | 384 | } |
388 | } else { | 385 | } else { |
389 | spin_lock(&dentry->d_lock); | 386 | if (!simple_empty(dentry)) |
390 | if (!list_empty(&dentry->d_subdirs)) { | ||
391 | spin_unlock(&dentry->d_lock); | ||
392 | goto done; | 387 | goto done; |
393 | } | ||
394 | spin_unlock(&dentry->d_lock); | ||
395 | } | 388 | } |
396 | ino->flags |= AUTOFS_INF_PENDING; | 389 | ino->flags |= AUTOFS_INF_PENDING; |
397 | spin_unlock(&sbi->fs_lock); | 390 | spin_unlock(&sbi->fs_lock); |
@@ -610,9 +603,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) | |||
610 | 603 | ||
611 | spin_lock(&sbi->lookup_lock); | 604 | spin_lock(&sbi->lookup_lock); |
612 | __autofs4_add_expiring(dentry); | 605 | __autofs4_add_expiring(dentry); |
613 | spin_lock(&dentry->d_lock); | 606 | d_drop(dentry); |
614 | __d_drop(dentry); | ||
615 | spin_unlock(&dentry->d_lock); | ||
616 | spin_unlock(&sbi->lookup_lock); | 607 | spin_unlock(&sbi->lookup_lock); |
617 | 608 | ||
618 | return 0; | 609 | return 0; |
@@ -683,15 +674,12 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) | |||
683 | return -EACCES; | 674 | return -EACCES; |
684 | 675 | ||
685 | spin_lock(&sbi->lookup_lock); | 676 | spin_lock(&sbi->lookup_lock); |
686 | spin_lock(&dentry->d_lock); | 677 | if (!simple_empty(dentry)) { |
687 | if (!list_empty(&dentry->d_subdirs)) { | ||
688 | spin_unlock(&dentry->d_lock); | ||
689 | spin_unlock(&sbi->lookup_lock); | 678 | spin_unlock(&sbi->lookup_lock); |
690 | return -ENOTEMPTY; | 679 | return -ENOTEMPTY; |
691 | } | 680 | } |
692 | __autofs4_add_expiring(dentry); | 681 | __autofs4_add_expiring(dentry); |
693 | __d_drop(dentry); | 682 | d_drop(dentry); |
694 | spin_unlock(&dentry->d_lock); | ||
695 | spin_unlock(&sbi->lookup_lock); | 683 | spin_unlock(&sbi->lookup_lock); |
696 | 684 | ||
697 | if (sbi->version < 5) | 685 | if (sbi->version < 5) |