diff options
Diffstat (limited to 'kernel/user_namespace.c')
-rw-r--r-- | kernel/user_namespace.c | 99 |
1 files changed, 85 insertions, 14 deletions
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 68f594212759..86b7854fec8e 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
@@ -29,6 +29,17 @@ static DEFINE_MUTEX(userns_state_mutex); | |||
29 | static bool new_idmap_permitted(const struct file *file, | 29 | static bool new_idmap_permitted(const struct file *file, |
30 | struct user_namespace *ns, int cap_setid, | 30 | struct user_namespace *ns, int cap_setid, |
31 | struct uid_gid_map *map); | 31 | struct uid_gid_map *map); |
32 | static void free_user_ns(struct work_struct *work); | ||
33 | |||
34 | static struct ucounts *inc_user_namespaces(struct user_namespace *ns, kuid_t uid) | ||
35 | { | ||
36 | return inc_ucount(ns, uid, UCOUNT_USER_NAMESPACES); | ||
37 | } | ||
38 | |||
39 | static void dec_user_namespaces(struct ucounts *ucounts) | ||
40 | { | ||
41 | return dec_ucount(ucounts, UCOUNT_USER_NAMESPACES); | ||
42 | } | ||
32 | 43 | ||
33 | static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) | 44 | static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) |
34 | { | 45 | { |
@@ -62,10 +73,16 @@ int create_user_ns(struct cred *new) | |||
62 | struct user_namespace *ns, *parent_ns = new->user_ns; | 73 | struct user_namespace *ns, *parent_ns = new->user_ns; |
63 | kuid_t owner = new->euid; | 74 | kuid_t owner = new->euid; |
64 | kgid_t group = new->egid; | 75 | kgid_t group = new->egid; |
65 | int ret; | 76 | struct ucounts *ucounts; |
77 | int ret, i; | ||
66 | 78 | ||
79 | ret = -ENOSPC; | ||
67 | if (parent_ns->level > 32) | 80 | if (parent_ns->level > 32) |
68 | return -EUSERS; | 81 | goto fail; |
82 | |||
83 | ucounts = inc_user_namespaces(parent_ns, owner); | ||
84 | if (!ucounts) | ||
85 | goto fail; | ||
69 | 86 | ||
70 | /* | 87 | /* |
71 | * Verify that we can not violate the policy of which files | 88 | * Verify that we can not violate the policy of which files |
@@ -73,26 +90,27 @@ int create_user_ns(struct cred *new) | |||
73 | * by verifing that the root directory is at the root of the | 90 | * by verifing that the root directory is at the root of the |
74 | * mount namespace which allows all files to be accessed. | 91 | * mount namespace which allows all files to be accessed. |
75 | */ | 92 | */ |
93 | ret = -EPERM; | ||
76 | if (current_chrooted()) | 94 | if (current_chrooted()) |
77 | return -EPERM; | 95 | goto fail_dec; |
78 | 96 | ||
79 | /* The creator needs a mapping in the parent user namespace | 97 | /* The creator needs a mapping in the parent user namespace |
80 | * or else we won't be able to reasonably tell userspace who | 98 | * or else we won't be able to reasonably tell userspace who |
81 | * created a user_namespace. | 99 | * created a user_namespace. |
82 | */ | 100 | */ |
101 | ret = -EPERM; | ||
83 | if (!kuid_has_mapping(parent_ns, owner) || | 102 | if (!kuid_has_mapping(parent_ns, owner) || |
84 | !kgid_has_mapping(parent_ns, group)) | 103 | !kgid_has_mapping(parent_ns, group)) |
85 | return -EPERM; | 104 | goto fail_dec; |
86 | 105 | ||
106 | ret = -ENOMEM; | ||
87 | ns = kmem_cache_zalloc(user_ns_cachep, GFP_KERNEL); | 107 | ns = kmem_cache_zalloc(user_ns_cachep, GFP_KERNEL); |
88 | if (!ns) | 108 | if (!ns) |
89 | return -ENOMEM; | 109 | goto fail_dec; |
90 | 110 | ||
91 | ret = ns_alloc_inum(&ns->ns); | 111 | ret = ns_alloc_inum(&ns->ns); |
92 | if (ret) { | 112 | if (ret) |
93 | kmem_cache_free(user_ns_cachep, ns); | 113 | goto fail_free; |
94 | return ret; | ||
95 | } | ||
96 | ns->ns.ops = &userns_operations; | 114 | ns->ns.ops = &userns_operations; |
97 | 115 | ||
98 | atomic_set(&ns->count, 1); | 116 | atomic_set(&ns->count, 1); |
@@ -101,18 +119,37 @@ int create_user_ns(struct cred *new) | |||
101 | ns->level = parent_ns->level + 1; | 119 | ns->level = parent_ns->level + 1; |
102 | ns->owner = owner; | 120 | ns->owner = owner; |
103 | ns->group = group; | 121 | ns->group = group; |
122 | INIT_WORK(&ns->work, free_user_ns); | ||
123 | for (i = 0; i < UCOUNT_COUNTS; i++) { | ||
124 | ns->ucount_max[i] = INT_MAX; | ||
125 | } | ||
126 | ns->ucounts = ucounts; | ||
104 | 127 | ||
105 | /* Inherit USERNS_SETGROUPS_ALLOWED from our parent */ | 128 | /* Inherit USERNS_SETGROUPS_ALLOWED from our parent */ |
106 | mutex_lock(&userns_state_mutex); | 129 | mutex_lock(&userns_state_mutex); |
107 | ns->flags = parent_ns->flags; | 130 | ns->flags = parent_ns->flags; |
108 | mutex_unlock(&userns_state_mutex); | 131 | mutex_unlock(&userns_state_mutex); |
109 | 132 | ||
110 | set_cred_user_ns(new, ns); | ||
111 | |||
112 | #ifdef CONFIG_PERSISTENT_KEYRINGS | 133 | #ifdef CONFIG_PERSISTENT_KEYRINGS |
113 | init_rwsem(&ns->persistent_keyring_register_sem); | 134 | init_rwsem(&ns->persistent_keyring_register_sem); |
114 | #endif | 135 | #endif |
136 | ret = -ENOMEM; | ||
137 | if (!setup_userns_sysctls(ns)) | ||
138 | goto fail_keyring; | ||
139 | |||
140 | set_cred_user_ns(new, ns); | ||
115 | return 0; | 141 | return 0; |
142 | fail_keyring: | ||
143 | #ifdef CONFIG_PERSISTENT_KEYRINGS | ||
144 | key_put(ns->persistent_keyring_register); | ||
145 | #endif | ||
146 | ns_free_inum(&ns->ns); | ||
147 | fail_free: | ||
148 | kmem_cache_free(user_ns_cachep, ns); | ||
149 | fail_dec: | ||
150 | dec_user_namespaces(ucounts); | ||
151 | fail: | ||
152 | return ret; | ||
116 | } | 153 | } |
117 | 154 | ||
118 | int unshare_userns(unsigned long unshare_flags, struct cred **new_cred) | 155 | int unshare_userns(unsigned long unshare_flags, struct cred **new_cred) |
@@ -135,21 +172,30 @@ int unshare_userns(unsigned long unshare_flags, struct cred **new_cred) | |||
135 | return err; | 172 | return err; |
136 | } | 173 | } |
137 | 174 | ||
138 | void free_user_ns(struct user_namespace *ns) | 175 | static void free_user_ns(struct work_struct *work) |
139 | { | 176 | { |
140 | struct user_namespace *parent; | 177 | struct user_namespace *parent, *ns = |
178 | container_of(work, struct user_namespace, work); | ||
141 | 179 | ||
142 | do { | 180 | do { |
181 | struct ucounts *ucounts = ns->ucounts; | ||
143 | parent = ns->parent; | 182 | parent = ns->parent; |
183 | retire_userns_sysctls(ns); | ||
144 | #ifdef CONFIG_PERSISTENT_KEYRINGS | 184 | #ifdef CONFIG_PERSISTENT_KEYRINGS |
145 | key_put(ns->persistent_keyring_register); | 185 | key_put(ns->persistent_keyring_register); |
146 | #endif | 186 | #endif |
147 | ns_free_inum(&ns->ns); | 187 | ns_free_inum(&ns->ns); |
148 | kmem_cache_free(user_ns_cachep, ns); | 188 | kmem_cache_free(user_ns_cachep, ns); |
189 | dec_user_namespaces(ucounts); | ||
149 | ns = parent; | 190 | ns = parent; |
150 | } while (atomic_dec_and_test(&parent->count)); | 191 | } while (atomic_dec_and_test(&parent->count)); |
151 | } | 192 | } |
152 | EXPORT_SYMBOL(free_user_ns); | 193 | |
194 | void __put_user_ns(struct user_namespace *ns) | ||
195 | { | ||
196 | schedule_work(&ns->work); | ||
197 | } | ||
198 | EXPORT_SYMBOL(__put_user_ns); | ||
153 | 199 | ||
154 | static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count) | 200 | static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count) |
155 | { | 201 | { |
@@ -1004,12 +1050,37 @@ static int userns_install(struct nsproxy *nsproxy, struct ns_common *ns) | |||
1004 | return commit_creds(cred); | 1050 | return commit_creds(cred); |
1005 | } | 1051 | } |
1006 | 1052 | ||
1053 | struct ns_common *ns_get_owner(struct ns_common *ns) | ||
1054 | { | ||
1055 | struct user_namespace *my_user_ns = current_user_ns(); | ||
1056 | struct user_namespace *owner, *p; | ||
1057 | |||
1058 | /* See if the owner is in the current user namespace */ | ||
1059 | owner = p = ns->ops->owner(ns); | ||
1060 | for (;;) { | ||
1061 | if (!p) | ||
1062 | return ERR_PTR(-EPERM); | ||
1063 | if (p == my_user_ns) | ||
1064 | break; | ||
1065 | p = p->parent; | ||
1066 | } | ||
1067 | |||
1068 | return &get_user_ns(owner)->ns; | ||
1069 | } | ||
1070 | |||
1071 | static struct user_namespace *userns_owner(struct ns_common *ns) | ||
1072 | { | ||
1073 | return to_user_ns(ns)->parent; | ||
1074 | } | ||
1075 | |||
1007 | const struct proc_ns_operations userns_operations = { | 1076 | const struct proc_ns_operations userns_operations = { |
1008 | .name = "user", | 1077 | .name = "user", |
1009 | .type = CLONE_NEWUSER, | 1078 | .type = CLONE_NEWUSER, |
1010 | .get = userns_get, | 1079 | .get = userns_get, |
1011 | .put = userns_put, | 1080 | .put = userns_put, |
1012 | .install = userns_install, | 1081 | .install = userns_install, |
1082 | .owner = userns_owner, | ||
1083 | .get_parent = ns_get_owner, | ||
1013 | }; | 1084 | }; |
1014 | 1085 | ||
1015 | static __init int user_namespaces_init(void) | 1086 | static __init int user_namespaces_init(void) |