diff options
Diffstat (limited to 'security/keys/request_key.c')
-rw-r--r-- | security/keys/request_key.c | 75 |
1 files changed, 51 insertions, 24 deletions
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 91953c814497..8e9d93b4a402 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -76,6 +76,10 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
76 | 76 | ||
77 | kenter("{%d},{%d},%s", key->serial, authkey->serial, op); | 77 | kenter("{%d},{%d},%s", key->serial, authkey->serial, op); |
78 | 78 | ||
79 | ret = install_user_keyrings(); | ||
80 | if (ret < 0) | ||
81 | goto error_alloc; | ||
82 | |||
79 | /* allocate a new session keyring */ | 83 | /* allocate a new session keyring */ |
80 | sprintf(desc, "_req.%u", key->serial); | 84 | sprintf(desc, "_req.%u", key->serial); |
81 | 85 | ||
@@ -165,7 +169,8 @@ error_alloc: | |||
165 | * - we ignore program failure and go on key status instead | 169 | * - we ignore program failure and go on key status instead |
166 | */ | 170 | */ |
167 | static int construct_key(struct key *key, const void *callout_info, | 171 | static int construct_key(struct key *key, const void *callout_info, |
168 | size_t callout_len, void *aux) | 172 | size_t callout_len, void *aux, |
173 | struct key *dest_keyring) | ||
169 | { | 174 | { |
170 | struct key_construction *cons; | 175 | struct key_construction *cons; |
171 | request_key_actor_t actor; | 176 | request_key_actor_t actor; |
@@ -179,7 +184,8 @@ static int construct_key(struct key *key, const void *callout_info, | |||
179 | return -ENOMEM; | 184 | return -ENOMEM; |
180 | 185 | ||
181 | /* allocate an authorisation key */ | 186 | /* allocate an authorisation key */ |
182 | authkey = request_key_auth_new(key, callout_info, callout_len); | 187 | authkey = request_key_auth_new(key, callout_info, callout_len, |
188 | dest_keyring); | ||
183 | if (IS_ERR(authkey)) { | 189 | if (IS_ERR(authkey)) { |
184 | kfree(cons); | 190 | kfree(cons); |
185 | ret = PTR_ERR(authkey); | 191 | ret = PTR_ERR(authkey); |
@@ -207,27 +213,48 @@ static int construct_key(struct key *key, const void *callout_info, | |||
207 | } | 213 | } |
208 | 214 | ||
209 | /* | 215 | /* |
210 | * link a key to the appropriate destination keyring | 216 | * get the appropriate destination keyring for the request |
211 | * - the caller must hold a write lock on the destination keyring | 217 | * - we return whatever keyring we select with an extra reference upon it which |
218 | * the caller must release | ||
212 | */ | 219 | */ |
213 | static void construct_key_make_link(struct key *key, struct key *dest_keyring) | 220 | static void construct_get_dest_keyring(struct key **_dest_keyring) |
214 | { | 221 | { |
222 | struct request_key_auth *rka; | ||
215 | struct task_struct *tsk = current; | 223 | struct task_struct *tsk = current; |
216 | struct key *drop = NULL; | 224 | struct key *dest_keyring = *_dest_keyring, *authkey; |
217 | 225 | ||
218 | kenter("{%d},%p", key->serial, dest_keyring); | 226 | kenter("%p", dest_keyring); |
219 | 227 | ||
220 | /* find the appropriate keyring */ | 228 | /* find the appropriate keyring */ |
221 | if (!dest_keyring) { | 229 | if (dest_keyring) { |
230 | /* the caller supplied one */ | ||
231 | key_get(dest_keyring); | ||
232 | } else { | ||
233 | /* use a default keyring; falling through the cases until we | ||
234 | * find one that we actually have */ | ||
222 | switch (tsk->jit_keyring) { | 235 | switch (tsk->jit_keyring) { |
223 | case KEY_REQKEY_DEFL_DEFAULT: | 236 | case KEY_REQKEY_DEFL_DEFAULT: |
237 | case KEY_REQKEY_DEFL_REQUESTOR_KEYRING: | ||
238 | if (tsk->request_key_auth) { | ||
239 | authkey = tsk->request_key_auth; | ||
240 | down_read(&authkey->sem); | ||
241 | rka = authkey->payload.data; | ||
242 | if (!test_bit(KEY_FLAG_REVOKED, | ||
243 | &authkey->flags)) | ||
244 | dest_keyring = | ||
245 | key_get(rka->dest_keyring); | ||
246 | up_read(&authkey->sem); | ||
247 | if (dest_keyring) | ||
248 | break; | ||
249 | } | ||
250 | |||
224 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | 251 | case KEY_REQKEY_DEFL_THREAD_KEYRING: |
225 | dest_keyring = tsk->thread_keyring; | 252 | dest_keyring = key_get(tsk->thread_keyring); |
226 | if (dest_keyring) | 253 | if (dest_keyring) |
227 | break; | 254 | break; |
228 | 255 | ||
229 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | 256 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: |
230 | dest_keyring = tsk->signal->process_keyring; | 257 | dest_keyring = key_get(tsk->signal->process_keyring); |
231 | if (dest_keyring) | 258 | if (dest_keyring) |
232 | break; | 259 | break; |
233 | 260 | ||
@@ -236,17 +263,16 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring) | |||
236 | dest_keyring = key_get( | 263 | dest_keyring = key_get( |
237 | rcu_dereference(tsk->signal->session_keyring)); | 264 | rcu_dereference(tsk->signal->session_keyring)); |
238 | rcu_read_unlock(); | 265 | rcu_read_unlock(); |
239 | drop = dest_keyring; | ||
240 | 266 | ||
241 | if (dest_keyring) | 267 | if (dest_keyring) |
242 | break; | 268 | break; |
243 | 269 | ||
244 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: | 270 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: |
245 | dest_keyring = tsk->user->session_keyring; | 271 | dest_keyring = key_get(tsk->user->session_keyring); |
246 | break; | 272 | break; |
247 | 273 | ||
248 | case KEY_REQKEY_DEFL_USER_KEYRING: | 274 | case KEY_REQKEY_DEFL_USER_KEYRING: |
249 | dest_keyring = tsk->user->uid_keyring; | 275 | dest_keyring = key_get(tsk->user->uid_keyring); |
250 | break; | 276 | break; |
251 | 277 | ||
252 | case KEY_REQKEY_DEFL_GROUP_KEYRING: | 278 | case KEY_REQKEY_DEFL_GROUP_KEYRING: |
@@ -255,10 +281,9 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring) | |||
255 | } | 281 | } |
256 | } | 282 | } |
257 | 283 | ||
258 | /* and attach the key to it */ | 284 | *_dest_keyring = dest_keyring; |
259 | __key_link(dest_keyring, key); | 285 | kleave(" [dk %d]", key_serial(dest_keyring)); |
260 | key_put(drop); | 286 | return; |
261 | kleave(""); | ||
262 | } | 287 | } |
263 | 288 | ||
264 | /* | 289 | /* |
@@ -288,8 +313,7 @@ static int construct_alloc_key(struct key_type *type, | |||
288 | 313 | ||
289 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); | 314 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); |
290 | 315 | ||
291 | if (dest_keyring) | 316 | down_write(&dest_keyring->sem); |
292 | down_write(&dest_keyring->sem); | ||
293 | 317 | ||
294 | /* attach the key to the destination keyring under lock, but we do need | 318 | /* attach the key to the destination keyring under lock, but we do need |
295 | * to do another check just in case someone beat us to it whilst we | 319 | * to do another check just in case someone beat us to it whilst we |
@@ -301,12 +325,10 @@ static int construct_alloc_key(struct key_type *type, | |||
301 | if (!IS_ERR(key_ref)) | 325 | if (!IS_ERR(key_ref)) |
302 | goto key_already_present; | 326 | goto key_already_present; |
303 | 327 | ||
304 | if (dest_keyring) | 328 | __key_link(dest_keyring, key); |
305 | construct_key_make_link(key, dest_keyring); | ||
306 | 329 | ||
307 | mutex_unlock(&key_construction_mutex); | 330 | mutex_unlock(&key_construction_mutex); |
308 | if (dest_keyring) | 331 | up_write(&dest_keyring->sem); |
309 | up_write(&dest_keyring->sem); | ||
310 | mutex_unlock(&user->cons_lock); | 332 | mutex_unlock(&user->cons_lock); |
311 | *_key = key; | 333 | *_key = key; |
312 | kleave(" = 0 [%d]", key_serial(key)); | 334 | kleave(" = 0 [%d]", key_serial(key)); |
@@ -348,21 +370,26 @@ static struct key *construct_key_and_link(struct key_type *type, | |||
348 | if (!user) | 370 | if (!user) |
349 | return ERR_PTR(-ENOMEM); | 371 | return ERR_PTR(-ENOMEM); |
350 | 372 | ||
373 | construct_get_dest_keyring(&dest_keyring); | ||
374 | |||
351 | ret = construct_alloc_key(type, description, dest_keyring, flags, user, | 375 | ret = construct_alloc_key(type, description, dest_keyring, flags, user, |
352 | &key); | 376 | &key); |
353 | key_user_put(user); | 377 | key_user_put(user); |
354 | 378 | ||
355 | if (ret == 0) { | 379 | if (ret == 0) { |
356 | ret = construct_key(key, callout_info, callout_len, aux); | 380 | ret = construct_key(key, callout_info, callout_len, aux, |
381 | dest_keyring); | ||
357 | if (ret < 0) | 382 | if (ret < 0) |
358 | goto construction_failed; | 383 | goto construction_failed; |
359 | } | 384 | } |
360 | 385 | ||
386 | key_put(dest_keyring); | ||
361 | return key; | 387 | return key; |
362 | 388 | ||
363 | construction_failed: | 389 | construction_failed: |
364 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); | 390 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); |
365 | key_put(key); | 391 | key_put(key); |
392 | key_put(dest_keyring); | ||
366 | return ERR_PTR(ret); | 393 | return ERR_PTR(ret); |
367 | } | 394 | } |
368 | 395 | ||