Messages in this thread Patch in this message |  | | | Date | Fri, 25 Mar 2011 16:44:25 -0700 | | From | Greg KH <> | | Subject | [49/63] fix deadlock in pivot_root() |
| |
2.6.38-stable review patch. If anyone has any objections, please let us know.
------------------ From: Al Viro <viro@zeniv.linux.org.uk>
commit 27cb1572e3e6bb1f8cf6bb3d74c914a87b131792 upstream.
Don't hold vfsmount_lock over the loop traversing ->mnt_parent; do check_mnt(new.mnt) under namespace_sem instead; combined with namespace_sem held over all that code it'll guarantee the stability of ->mnt_parent chain all the way to the root.
Doing check_mnt() outside of namespace_sem in case of pivot_root() is wrong anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
--- fs/namespace.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2469,9 +2469,6 @@ SYSCALL_DEFINE2(pivot_root, const char _ error = user_path_dir(new_root, &new); if (error) goto out0; - error = -EINVAL; - if (!check_mnt(new.mnt)) - goto out1; error = user_path_dir(put_old, &old); if (error) @@ -2491,7 +2488,7 @@ SYSCALL_DEFINE2(pivot_root, const char _ IS_MNT_SHARED(new.mnt->mnt_parent) || IS_MNT_SHARED(root.mnt->mnt_parent)) goto out2; - if (!check_mnt(root.mnt)) + if (!check_mnt(root.mnt) || !check_mnt(new.mnt)) goto out2; error = -ENOENT; if (cant_mount(old.dentry)) @@ -2515,19 +2512,19 @@ SYSCALL_DEFINE2(pivot_root, const char _ goto out2; /* not attached */ /* make sure we can reach put_old from new_root */ tmp = old.mnt; - br_write_lock(vfsmount_lock); if (tmp != new.mnt) { for (;;) { if (tmp->mnt_parent == tmp) - goto out3; /* already mounted on put_old */ + goto out2; /* already mounted on put_old */ if (tmp->mnt_parent == new.mnt) break; tmp = tmp->mnt_parent; } if (!is_subdir(tmp->mnt_mountpoint, new.dentry)) - goto out3; + goto out2; } else if (!is_subdir(old.dentry, new.dentry)) - goto out3; + goto out2; + br_write_lock(vfsmount_lock); detach_mnt(new.mnt, &parent_path); detach_mnt(root.mnt, &root_parent); /* mount old root on put_old */ @@ -2550,9 +2547,6 @@ out1: path_put(&new); out0: return error; -out3: - br_write_unlock(vfsmount_lock); - goto out2; } static void __init init_mount_tree(void)
|  |