|
@@ -12,6 +12,7 @@
|
|
|
#include <linux/export.h>
|
|
|
#include <linux/capability.h>
|
|
|
#include <linux/mnt_namespace.h>
|
|
|
+#include <linux/user_namespace.h>
|
|
|
#include <linux/namei.h>
|
|
|
#include <linux/security.h>
|
|
|
#include <linux/idr.h>
|
|
@@ -2286,6 +2287,12 @@ dput_out:
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
+static void free_mnt_ns(struct mnt_namespace *ns)
|
|
|
+{
|
|
|
+ put_user_ns(ns->user_ns);
|
|
|
+ kfree(ns);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Assign a sequence number so we can detect when we attempt to bind
|
|
|
* mount a reference to an older mount namespace into the current
|
|
@@ -2295,7 +2302,7 @@ dput_out:
|
|
|
*/
|
|
|
static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
|
|
|
|
|
|
-static struct mnt_namespace *alloc_mnt_ns(void)
|
|
|
+static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
|
|
|
{
|
|
|
struct mnt_namespace *new_ns;
|
|
|
|
|
@@ -2308,6 +2315,7 @@ static struct mnt_namespace *alloc_mnt_ns(void)
|
|
|
INIT_LIST_HEAD(&new_ns->list);
|
|
|
init_waitqueue_head(&new_ns->poll);
|
|
|
new_ns->event = 0;
|
|
|
+ new_ns->user_ns = get_user_ns(user_ns);
|
|
|
return new_ns;
|
|
|
}
|
|
|
|
|
@@ -2316,7 +2324,7 @@ static struct mnt_namespace *alloc_mnt_ns(void)
|
|
|
* copied from the namespace of the passed in task structure.
|
|
|
*/
|
|
|
static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
|
|
|
- struct fs_struct *fs)
|
|
|
+ struct user_namespace *user_ns, struct fs_struct *fs)
|
|
|
{
|
|
|
struct mnt_namespace *new_ns;
|
|
|
struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
|
|
@@ -2324,7 +2332,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
|
|
|
struct mount *old = mnt_ns->root;
|
|
|
struct mount *new;
|
|
|
|
|
|
- new_ns = alloc_mnt_ns();
|
|
|
+ new_ns = alloc_mnt_ns(user_ns);
|
|
|
if (IS_ERR(new_ns))
|
|
|
return new_ns;
|
|
|
|
|
@@ -2333,7 +2341,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
|
|
|
new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE);
|
|
|
if (IS_ERR(new)) {
|
|
|
up_write(&namespace_sem);
|
|
|
- kfree(new_ns);
|
|
|
+ free_mnt_ns(new_ns);
|
|
|
return ERR_CAST(new);
|
|
|
}
|
|
|
new_ns->root = new;
|
|
@@ -2374,7 +2382,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
|
|
|
}
|
|
|
|
|
|
struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
|
|
|
- struct fs_struct *new_fs)
|
|
|
+ struct user_namespace *user_ns, struct fs_struct *new_fs)
|
|
|
{
|
|
|
struct mnt_namespace *new_ns;
|
|
|
|
|
@@ -2384,7 +2392,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
|
|
|
if (!(flags & CLONE_NEWNS))
|
|
|
return ns;
|
|
|
|
|
|
- new_ns = dup_mnt_ns(ns, new_fs);
|
|
|
+ new_ns = dup_mnt_ns(ns, user_ns, new_fs);
|
|
|
|
|
|
put_mnt_ns(ns);
|
|
|
return new_ns;
|
|
@@ -2396,7 +2404,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
|
|
|
*/
|
|
|
static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
|
|
|
{
|
|
|
- struct mnt_namespace *new_ns = alloc_mnt_ns();
|
|
|
+ struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
|
|
|
if (!IS_ERR(new_ns)) {
|
|
|
struct mount *mnt = real_mount(m);
|
|
|
mnt->mnt_ns = new_ns;
|
|
@@ -2682,7 +2690,7 @@ void put_mnt_ns(struct mnt_namespace *ns)
|
|
|
br_write_unlock(&vfsmount_lock);
|
|
|
up_write(&namespace_sem);
|
|
|
release_mounts(&umount_list);
|
|
|
- kfree(ns);
|
|
|
+ free_mnt_ns(ns);
|
|
|
}
|
|
|
|
|
|
struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
|