2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation, version 2 of the
8 #include <linux/module.h>
9 #include <linux/nsproxy.h>
10 #include <linux/slab.h>
11 #include <linux/user_namespace.h>
12 #include <linux/cred.h>
15 * Create a new user namespace, deriving the creator from the user in the
16 * passed credentials, and replacing that user with the new root user for the
19 * This is called by copy_creds(), which will finish setting the target task's
22 int create_user_ns(struct cred
*new)
24 struct user_namespace
*ns
;
25 struct user_struct
*root_user
;
28 ns
= kmalloc(sizeof(struct user_namespace
), GFP_KERNEL
);
34 for (n
= 0; n
< UIDHASH_SZ
; ++n
)
35 INIT_HLIST_HEAD(ns
->uidhash_table
+ n
);
37 /* Alloc new root user. */
38 root_user
= alloc_uid(ns
, 0);
44 /* set the new root user in the credentials under preparation */
45 ns
->creator
= new->user
;
46 new->user
= root_user
;
47 new->uid
= new->euid
= new->suid
= new->fsuid
= 0;
48 new->gid
= new->egid
= new->sgid
= new->fsgid
= 0;
49 put_group_info(new->group_info
);
50 new->group_info
= get_group_info(&init_groups
);
52 key_put(new->request_key_auth
);
53 new->request_key_auth
= NULL
;
55 /* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */
57 /* alloc_uid() incremented the userns refcount. Just set it to 1 */
58 kref_set(&ns
->kref
, 1);
64 * Deferred destructor for a user namespace. This is required because
65 * free_user_ns() may be called with uidhash_lock held, but we need to call
66 * back to free_uid() which will want to take the lock again.
68 static void free_user_ns_work(struct work_struct
*work
)
70 struct user_namespace
*ns
=
71 container_of(work
, struct user_namespace
, destroyer
);
72 free_uid(ns
->creator
);
76 void free_user_ns(struct kref
*kref
)
78 struct user_namespace
*ns
=
79 container_of(kref
, struct user_namespace
, kref
);
81 INIT_WORK(&ns
->destroyer
, free_user_ns_work
);
82 schedule_work(&ns
->destroyer
);
84 EXPORT_SYMBOL(free_user_ns
);