aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/request_key.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/request_key.c')
-rw-r--r--security/keys/request_key.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index ac49c8aacbf..f656e9c069e 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -299,6 +299,7 @@ static int construct_alloc_key(struct key_type *type,
299 struct key_user *user, 299 struct key_user *user,
300 struct key **_key) 300 struct key **_key)
301{ 301{
302 struct keyring_list *prealloc;
302 const struct cred *cred = current_cred(); 303 const struct cred *cred = current_cred();
303 struct key *key; 304 struct key *key;
304 key_ref_t key_ref; 305 key_ref_t key_ref;
@@ -306,6 +307,7 @@ static int construct_alloc_key(struct key_type *type,
306 307
307 kenter("%s,%s,,,", type->name, description); 308 kenter("%s,%s,,,", type->name, description);
308 309
310 *_key = NULL;
309 mutex_lock(&user->cons_lock); 311 mutex_lock(&user->cons_lock);
310 312
311 key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, 313 key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred,
@@ -315,8 +317,12 @@ static int construct_alloc_key(struct key_type *type,
315 317
316 set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); 318 set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
317 319
318 if (dest_keyring) 320 if (dest_keyring) {
319 down_write(&dest_keyring->sem); 321 ret = __key_link_begin(dest_keyring, type, description,
322 &prealloc);
323 if (ret < 0)
324 goto link_prealloc_failed;
325 }
320 326
321 /* attach the key to the destination keyring under lock, but we do need 327 /* attach the key to the destination keyring under lock, but we do need
322 * to do another check just in case someone beat us to it whilst we 328 * to do another check just in case someone beat us to it whilst we
@@ -328,11 +334,11 @@ static int construct_alloc_key(struct key_type *type,
328 goto key_already_present; 334 goto key_already_present;
329 335
330 if (dest_keyring) 336 if (dest_keyring)
331 __key_link(dest_keyring, key); 337 __key_link(dest_keyring, key, &prealloc);
332 338
333 mutex_unlock(&key_construction_mutex); 339 mutex_unlock(&key_construction_mutex);
334 if (dest_keyring) 340 if (dest_keyring)
335 up_write(&dest_keyring->sem); 341 __key_link_end(dest_keyring, type, prealloc);
336 mutex_unlock(&user->cons_lock); 342 mutex_unlock(&user->cons_lock);
337 *_key = key; 343 *_key = key;
338 kleave(" = 0 [%d]", key_serial(key)); 344 kleave(" = 0 [%d]", key_serial(key));
@@ -341,27 +347,36 @@ static int construct_alloc_key(struct key_type *type,
341 /* the key is now present - we tell the caller that we found it by 347 /* the key is now present - we tell the caller that we found it by
342 * returning -EINPROGRESS */ 348 * returning -EINPROGRESS */
343key_already_present: 349key_already_present:
350 key_put(key);
344 mutex_unlock(&key_construction_mutex); 351 mutex_unlock(&key_construction_mutex);
345 ret = 0; 352 key = key_ref_to_ptr(key_ref);
346 if (dest_keyring) { 353 if (dest_keyring) {
347 ret = __key_link(dest_keyring, key_ref_to_ptr(key_ref)); 354 ret = __key_link_check_live_key(dest_keyring, key);
348 up_write(&dest_keyring->sem); 355 if (ret == 0)
356 __key_link(dest_keyring, key, &prealloc);
357 __key_link_end(dest_keyring, type, prealloc);
358 if (ret < 0)
359 goto link_check_failed;
349 } 360 }
350 mutex_unlock(&user->cons_lock); 361 mutex_unlock(&user->cons_lock);
351 key_put(key); 362 *_key = key;
352 if (ret < 0) {
353 key_ref_put(key_ref);
354 *_key = NULL;
355 kleave(" = %d [link]", ret);
356 return ret;
357 }
358 *_key = key = key_ref_to_ptr(key_ref);
359 kleave(" = -EINPROGRESS [%d]", key_serial(key)); 363 kleave(" = -EINPROGRESS [%d]", key_serial(key));
360 return -EINPROGRESS; 364 return -EINPROGRESS;
361 365
366link_check_failed:
367 mutex_unlock(&user->cons_lock);
368 key_put(key);
369 kleave(" = %d [linkcheck]", ret);
370 return ret;
371
372link_prealloc_failed:
373 up_write(&dest_keyring->sem);
374 mutex_unlock(&user->cons_lock);
375 kleave(" = %d [prelink]", ret);
376 return ret;
377
362alloc_failed: 378alloc_failed:
363 mutex_unlock(&user->cons_lock); 379 mutex_unlock(&user->cons_lock);
364 *_key = NULL;
365 kleave(" = %ld", PTR_ERR(key)); 380 kleave(" = %ld", PTR_ERR(key));
366 return PTR_ERR(key); 381 return PTR_ERR(key);
367} 382}