aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/namespace.c11
-rw-r--r--fs/pnode.h1
2 files changed, 9 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);
diff --git a/fs/pnode.h b/fs/pnode.h
index 65c60979d541..19b853a3445c 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -22,6 +22,7 @@
22#define CL_COPY_ALL 0x04 22#define CL_COPY_ALL 0x04
23#define CL_MAKE_SHARED 0x08 23#define CL_MAKE_SHARED 0x08
24#define CL_PRIVATE 0x10 24#define CL_PRIVATE 0x10
25#define CL_SHARED_TO_SLAVE 0x20
25 26
26static inline void set_mnt_shared(struct mount *mnt) 27static inline void set_mnt_shared(struct mount *mnt)
27{ 28{