aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-07-31 13:13:04 -0700
committerZiyan <jaraidaniel@gmail.com>2016-04-03 14:55:54 +0200
commitdc5c351d1b7429e8f2188cc980ef0137f90838e2 (patch)
tree2091d6a4c10134f027a89adffe09df19871c1dda /fs
parentcd3e667d8bc6ec17361f9ae7cb274c0805803822 (diff)
downloadkernel_samsung_tuna-dc5c351d1b7429e8f2188cc980ef0137f90838e2.zip
kernel_samsung_tuna-dc5c351d1b7429e8f2188cc980ef0137f90838e2.tar.gz
kernel_samsung_tuna-dc5c351d1b7429e8f2188cc980ef0137f90838e2.tar.bz2
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> (cherry picked from commit 7a472ef4be8387bc05a42e16309b02c8ca943a40)
Diffstat (limited to 'fs')
-rw-r--r--fs/namespace.c12
-rw-r--r--fs/pnode.h1
2 files changed, 9 insertions, 4 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 3f5e356..3c0dc94 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -714,7 +714,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
if (!mnt)
return ERR_PTR(-ENOMEM);
- if (flag & (CL_SLAVE | CL_PRIVATE))
+ if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
mnt->mnt_group_id = 0; /* not a peer of original */
else
mnt->mnt_group_id = old->mnt_group_id;
@@ -732,7 +732,8 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
mnt->mnt_mountpoint = mnt->mnt_root;
mnt->mnt_parent = mnt;
- if (flag & CL_SLAVE) {
+ if ((flag & CL_SLAVE) ||
+ ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
list_add(&mnt->mnt_slave, &old->mnt_slave_list);
mnt->mnt_master = old;
CLEAR_MNT_SHARED(mnt);
@@ -2438,6 +2439,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
struct mnt_namespace *new_ns;
struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
struct vfsmount *p, *q;
+ int copy_flags;
new_ns = alloc_mnt_ns(user_ns);
if (IS_ERR(new_ns))
@@ -2445,8 +2447,10 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
down_write(&namespace_sem);
/* First pass: copy the tree topology */
- new_ns->root = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root,
- CL_COPY_ALL | CL_EXPIRE);
+ copy_flags = CL_COPY_ALL | CL_EXPIRE;
+ if (user_ns != mnt_ns->user_ns)
+ copy_flags |= CL_SHARED_TO_SLAVE;
+ new_ns->root = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, copy_flags);
if (IS_ERR(new_ns->root)) {
up_write(&namespace_sem);
free_mnt_ns(new_ns);
diff --git a/fs/pnode.h b/fs/pnode.h
index 1ea4ae1..3b6eae3 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -22,6 +22,7 @@
#define CL_COPY_ALL 0x04
#define CL_MAKE_SHARED 0x08
#define CL_PRIVATE 0x10
+#define CL_SHARED_TO_SLAVE 0x20
static inline void set_mnt_shared(struct vfsmount *mnt)
{