aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-07-31 16:13:04 -0400
committerEric W. Biederman <ebiederm@xmission.com>2012-11-19 08:59:20 -0500
commit7a472ef4be8387bc05a42e16309b02c8ca943a40 (patch)
treed08fef7f89da670c24116805dbe1bcf60e094497 /fs/namespace.c
parent771b1371686e0a63e938ada28de020b9a0040f55 (diff)
vfs: Only support slave subtrees across different user namespaces
Sharing mount subtress with mount namespaces created by unprivileged users allows unprivileged mounts created by unprivileged users to propagate to mount namespaces controlled by privileged users. Prevent nasty consequences by changing shared subtrees to slave subtress when an unprivileged users creates a new mount namespace. Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 207c7ba84ad3..4dfcaf05d17c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -786,7 +786,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
786 if (!mnt) 786 if (!mnt)
787 return ERR_PTR(-ENOMEM); 787 return ERR_PTR(-ENOMEM);
788 788
789 if (flag & (CL_SLAVE | CL_PRIVATE)) 789 if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
790 mnt->mnt_group_id = 0; /* not a peer of original */ 790 mnt->mnt_group_id = 0; /* not a peer of original */
791 else 791 else
792 mnt->mnt_group_id = old->mnt_group_id; 792 mnt->mnt_group_id = old->mnt_group_id;
@@ -807,7 +807,8 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
807 list_add_tail(&mnt->mnt_instance, &sb->s_mounts); 807 list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
808 br_write_unlock(&vfsmount_lock); 808 br_write_unlock(&vfsmount_lock);
809 809
810 if (flag & CL_SLAVE) { 810 if ((flag & CL_SLAVE) ||
811 ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
811 list_add(&mnt->mnt_slave, &old->mnt_slave_list); 812 list_add(&mnt->mnt_slave, &old->mnt_slave_list);
812 mnt->mnt_master = old; 813 mnt->mnt_master = old;
813 CLEAR_MNT_SHARED(mnt); 814 CLEAR_MNT_SHARED(mnt);
@@ -2331,6 +2332,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
2331 struct mount *p, *q; 2332 struct mount *p, *q;
2332 struct mount *old = mnt_ns->root; 2333 struct mount *old = mnt_ns->root;
2333 struct mount *new; 2334 struct mount *new;
2335 int copy_flags;
2334 2336
2335 new_ns = alloc_mnt_ns(user_ns); 2337 new_ns = alloc_mnt_ns(user_ns);
2336 if (IS_ERR(new_ns)) 2338 if (IS_ERR(new_ns))
@@ -2338,7 +2340,10 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
2338 2340
2339 down_write(&namespace_sem); 2341 down_write(&namespace_sem);
2340 /* First pass: copy the tree topology */ 2342 /* First pass: copy the tree topology */
2341 new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE); 2343 copy_flags = CL_COPY_ALL | CL_EXPIRE;
2344 if (user_ns != mnt_ns->user_ns)
2345 copy_flags |= CL_SHARED_TO_SLAVE;
2346 new = copy_tree(old, old->mnt.mnt_root, copy_flags);
2342 if (IS_ERR(new)) { 2347 if (IS_ERR(new)) {
2343 up_write(&namespace_sem); 2348 up_write(&namespace_sem);
2344 free_mnt_ns(new_ns); 2349 free_mnt_ns(new_ns);