diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-09-28 13:02:53 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-09-28 13:02:53 -0400 |
| commit | 7596824e6626c62557b9eb6411ee74fec68b8ff9 (patch) | |
| tree | 4a906422538887be858b9cbdf848d68f8db6c116 | |
| parent | 97956605d8f2a0d17706cbd338a6cfe8de1920e9 (diff) | |
| parent | c5aa1e554a20fb3542c62688ae46049c9225a965 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro:
"A couple of fixes; one for automount/lazy umount race, another a
classic "we don't protect the refcount transition to zero with the
lock that protects looking for object in hash" kind of crap in lockd."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
close the race in nlmsvc_free_block()
do_add_mount()/umount -l races
| -rw-r--r-- | fs/lockd/svclock.c | 3 | ||||
| -rw-r--r-- | fs/namespace.c | 10 |
2 files changed, 9 insertions, 4 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index fb1a2bedbe97..8d80c990dffd 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
| @@ -289,7 +289,6 @@ static void nlmsvc_free_block(struct kref *kref) | |||
| 289 | dprintk("lockd: freeing block %p...\n", block); | 289 | dprintk("lockd: freeing block %p...\n", block); |
| 290 | 290 | ||
| 291 | /* Remove block from file's list of blocks */ | 291 | /* Remove block from file's list of blocks */ |
| 292 | mutex_lock(&file->f_mutex); | ||
| 293 | list_del_init(&block->b_flist); | 292 | list_del_init(&block->b_flist); |
| 294 | mutex_unlock(&file->f_mutex); | 293 | mutex_unlock(&file->f_mutex); |
| 295 | 294 | ||
| @@ -303,7 +302,7 @@ static void nlmsvc_free_block(struct kref *kref) | |||
| 303 | static void nlmsvc_release_block(struct nlm_block *block) | 302 | static void nlmsvc_release_block(struct nlm_block *block) |
| 304 | { | 303 | { |
| 305 | if (block != NULL) | 304 | if (block != NULL) |
| 306 | kref_put(&block->b_count, nlmsvc_free_block); | 305 | kref_put_mutex(&block->b_count, nlmsvc_free_block, &block->b_file->f_mutex); |
| 307 | } | 306 | } |
| 308 | 307 | ||
| 309 | /* | 308 | /* |
diff --git a/fs/namespace.c b/fs/namespace.c index 4d31f73e2561..7bdf7907413f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -1886,8 +1886,14 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags) | |||
| 1886 | return err; | 1886 | return err; |
| 1887 | 1887 | ||
| 1888 | err = -EINVAL; | 1888 | err = -EINVAL; |
| 1889 | if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(real_mount(path->mnt))) | 1889 | if (unlikely(!check_mnt(real_mount(path->mnt)))) { |
| 1890 | goto unlock; | 1890 | /* that's acceptable only for automounts done in private ns */ |
| 1891 | if (!(mnt_flags & MNT_SHRINKABLE)) | ||
| 1892 | goto unlock; | ||
| 1893 | /* ... and for those we'd better have mountpoint still alive */ | ||
| 1894 | if (!real_mount(path->mnt)->mnt_ns) | ||
| 1895 | goto unlock; | ||
| 1896 | } | ||
| 1891 | 1897 | ||
| 1892 | /* Refuse the same filesystem on the same mount point */ | 1898 | /* Refuse the same filesystem on the same mount point */ |
| 1893 | err = -EBUSY; | 1899 | err = -EBUSY; |
