userns: Simplify the user_namespace by making userns->creator a kuid.
[firefly-linux-kernel-4.4.55.git] / kernel / user_namespace.c
1 /*
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
5  *  License.
6  */
7
8 #include <linux/export.h>
9 #include <linux/nsproxy.h>
10 #include <linux/slab.h>
11 #include <linux/user_namespace.h>
12 #include <linux/highuid.h>
13 #include <linux/cred.h>
14 #include <linux/securebits.h>
15
16 static struct kmem_cache *user_ns_cachep __read_mostly;
17
18 /*
19  * Create a new user namespace, deriving the creator from the user in the
20  * passed credentials, and replacing that user with the new root user for the
21  * new namespace.
22  *
23  * This is called by copy_creds(), which will finish setting the target task's
24  * credentials.
25  */
26 int create_user_ns(struct cred *new)
27 {
28         struct user_namespace *ns, *parent_ns = new->user_ns;
29         struct user_struct *root_user;
30         kuid_t owner = make_kuid(new->user_ns, new->euid);
31         kgid_t group = make_kgid(new->user_ns, new->egid);
32
33         /* The creator needs a mapping in the parent user namespace
34          * or else we won't be able to reasonably tell userspace who
35          * created a user_namespace.
36          */
37         if (!kuid_has_mapping(parent_ns, owner) ||
38             !kgid_has_mapping(parent_ns, group))
39                 return -EPERM;
40
41         ns = kmem_cache_alloc(user_ns_cachep, GFP_KERNEL);
42         if (!ns)
43                 return -ENOMEM;
44
45         kref_init(&ns->kref);
46
47         /* Alloc new root user.  */
48         root_user = alloc_uid(make_kuid(ns, 0));
49         if (!root_user) {
50                 kmem_cache_free(user_ns_cachep, ns);
51                 return -ENOMEM;
52         }
53
54         /* set the new root user in the credentials under preparation */
55         ns->parent = parent_ns;
56         ns->owner = owner;
57         ns->group = group;
58         free_uid(new->user);
59         new->user = root_user;
60         new->uid = new->euid = new->suid = new->fsuid = 0;
61         new->gid = new->egid = new->sgid = new->fsgid = 0;
62         put_group_info(new->group_info);
63         new->group_info = get_group_info(&init_groups);
64         /* Start with the same capabilities as init but useless for doing
65          * anything as the capabilities are bound to the new user namespace.
66          */
67         new->securebits = SECUREBITS_DEFAULT;
68         new->cap_inheritable = CAP_EMPTY_SET;
69         new->cap_permitted = CAP_FULL_SET;
70         new->cap_effective = CAP_FULL_SET;
71         new->cap_bset = CAP_FULL_SET;
72 #ifdef CONFIG_KEYS
73         key_put(new->request_key_auth);
74         new->request_key_auth = NULL;
75 #endif
76         /* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */
77
78         /* Leave the new->user_ns reference with the new user namespace. */
79         /* Leave the reference to our user_ns with the new cred. */
80         new->user_ns = ns;
81
82         return 0;
83 }
84
85 void free_user_ns(struct kref *kref)
86 {
87         struct user_namespace *parent, *ns =
88                 container_of(kref, struct user_namespace, kref);
89
90         parent = ns->parent;
91         kmem_cache_free(user_ns_cachep, ns);
92         put_user_ns(parent);
93 }
94 EXPORT_SYMBOL(free_user_ns);
95
96 uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid)
97 {
98         struct user_namespace *tmp;
99
100         if (likely(to == cred->user_ns))
101                 return uid;
102
103         /* Is cred->user the creator of the target user_ns
104          * or the creator of one of it's parents?
105          */
106         for ( tmp = to; tmp != &init_user_ns; tmp = tmp->parent ) {
107                 if (uid_eq(cred->user->uid, tmp->owner)) {
108                         return (uid_t)0;
109                 }
110         }
111
112         /* No useful relationship so no mapping */
113         return overflowuid;
114 }
115
116 gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid)
117 {
118         struct user_namespace *tmp;
119
120         if (likely(to == cred->user_ns))
121                 return gid;
122
123         /* Is cred->user the creator of the target user_ns
124          * or the creator of one of it's parents?
125          */
126         for ( tmp = to; tmp != &init_user_ns; tmp = tmp->parent ) {
127                 if (uid_eq(cred->user->uid, tmp->owner)) {
128                         return (gid_t)0;
129                 }
130         }
131
132         /* No useful relationship so no mapping */
133         return overflowgid;
134 }
135
136 static __init int user_namespaces_init(void)
137 {
138         user_ns_cachep = KMEM_CACHE(user_namespace, SLAB_PANIC);
139         return 0;
140 }
141 module_init(user_namespaces_init);