Commit 771b1371686e0a63e938ada28de020b9a0040f55

Authored by Eric W. Biederman
1 parent 8823c079ba

vfs: Add a user namespace reference from struct mnt_namespace

This will allow for support for unprivileged mounts in a new user namespace.

Acked-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Showing 4 changed files with 20 additions and 10 deletions Side-by-side Diff

... ... @@ -6,6 +6,7 @@
6 6 atomic_t count;
7 7 struct mount * root;
8 8 struct list_head list;
  9 + struct user_namespace *user_ns;
9 10 u64 seq; /* Sequence number to prevent loops */
10 11 wait_queue_head_t poll;
11 12 int event;
... ... @@ -12,6 +12,7 @@
12 12 #include <linux/export.h>
13 13 #include <linux/capability.h>
14 14 #include <linux/mnt_namespace.h>
  15 +#include <linux/user_namespace.h>
15 16 #include <linux/namei.h>
16 17 #include <linux/security.h>
17 18 #include <linux/idr.h>
... ... @@ -2286,6 +2287,12 @@
2286 2287 return retval;
2287 2288 }
2288 2289  
  2290 +static void free_mnt_ns(struct mnt_namespace *ns)
  2291 +{
  2292 + put_user_ns(ns->user_ns);
  2293 + kfree(ns);
  2294 +}
  2295 +
2289 2296 /*
2290 2297 * Assign a sequence number so we can detect when we attempt to bind
2291 2298 * mount a reference to an older mount namespace into the current
... ... @@ -2295,7 +2302,7 @@
2295 2302 */
2296 2303 static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
2297 2304  
2298   -static struct mnt_namespace *alloc_mnt_ns(void)
  2305 +static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
2299 2306 {
2300 2307 struct mnt_namespace *new_ns;
2301 2308  
... ... @@ -2308,6 +2315,7 @@
2308 2315 INIT_LIST_HEAD(&new_ns->list);
2309 2316 init_waitqueue_head(&new_ns->poll);
2310 2317 new_ns->event = 0;
  2318 + new_ns->user_ns = get_user_ns(user_ns);
2311 2319 return new_ns;
2312 2320 }
2313 2321  
... ... @@ -2316,7 +2324,7 @@
2316 2324 * copied from the namespace of the passed in task structure.
2317 2325 */
2318 2326 static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
2319   - struct fs_struct *fs)
  2327 + struct user_namespace *user_ns, struct fs_struct *fs)
2320 2328 {
2321 2329 struct mnt_namespace *new_ns;
2322 2330 struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
... ... @@ -2324,7 +2332,7 @@
2324 2332 struct mount *old = mnt_ns->root;
2325 2333 struct mount *new;
2326 2334  
2327   - new_ns = alloc_mnt_ns();
  2335 + new_ns = alloc_mnt_ns(user_ns);
2328 2336 if (IS_ERR(new_ns))
2329 2337 return new_ns;
2330 2338  
... ... @@ -2333,7 +2341,7 @@
2333 2341 new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE);
2334 2342 if (IS_ERR(new)) {
2335 2343 up_write(&namespace_sem);
2336   - kfree(new_ns);
  2344 + free_mnt_ns(new_ns);
2337 2345 return ERR_CAST(new);
2338 2346 }
2339 2347 new_ns->root = new;
... ... @@ -2374,7 +2382,7 @@
2374 2382 }
2375 2383  
2376 2384 struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
2377   - struct fs_struct *new_fs)
  2385 + struct user_namespace *user_ns, struct fs_struct *new_fs)
2378 2386 {
2379 2387 struct mnt_namespace *new_ns;
2380 2388  
... ... @@ -2384,7 +2392,7 @@
2384 2392 if (!(flags & CLONE_NEWNS))
2385 2393 return ns;
2386 2394  
2387   - new_ns = dup_mnt_ns(ns, new_fs);
  2395 + new_ns = dup_mnt_ns(ns, user_ns, new_fs);
2388 2396  
2389 2397 put_mnt_ns(ns);
2390 2398 return new_ns;
... ... @@ -2396,7 +2404,7 @@
2396 2404 */
2397 2405 static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
2398 2406 {
2399   - struct mnt_namespace *new_ns = alloc_mnt_ns();
  2407 + struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
2400 2408 if (!IS_ERR(new_ns)) {
2401 2409 struct mount *mnt = real_mount(m);
2402 2410 mnt->mnt_ns = new_ns;
... ... @@ -2682,7 +2690,7 @@
2682 2690 br_write_unlock(&vfsmount_lock);
2683 2691 up_write(&namespace_sem);
2684 2692 release_mounts(&umount_list);
2685   - kfree(ns);
  2693 + free_mnt_ns(ns);
2686 2694 }
2687 2695  
2688 2696 struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
include/linux/mnt_namespace.h
... ... @@ -4,9 +4,10 @@
4 4  
5 5 struct mnt_namespace;
6 6 struct fs_struct;
  7 +struct user_namespace;
7 8  
8 9 extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
9   - struct fs_struct *);
  10 + struct user_namespace *, struct fs_struct *);
10 11 extern void put_mnt_ns(struct mnt_namespace *ns);
11 12  
12 13 extern const struct file_operations proc_mounts_operations;
... ... @@ -66,7 +66,7 @@
66 66 if (!new_nsp)
67 67 return ERR_PTR(-ENOMEM);
68 68  
69   - new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
  69 + new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, task_cred_xxx(tsk, user_ns), new_fs);
70 70 if (IS_ERR(new_nsp->mnt_ns)) {
71 71 err = PTR_ERR(new_nsp->mnt_ns);
72 72 goto out_ns;