diff options
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/internal.h | 11 | ||||
-rw-r--r-- | security/keys/key.c | 47 | ||||
-rw-r--r-- | security/keys/keyctl.c | 65 | ||||
-rw-r--r-- | security/keys/keyring.c | 273 | ||||
-rw-r--r-- | security/keys/permission.c | 2 | ||||
-rw-r--r-- | security/keys/proc.c | 2 | ||||
-rw-r--r-- | security/keys/process_keys.c | 6 | ||||
-rw-r--r-- | security/keys/request_key.c | 55 |
8 files changed, 279 insertions, 182 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h index 24ba0307b7ad..5d4402a1161a 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -87,7 +87,16 @@ extern wait_queue_head_t request_key_conswq; | |||
87 | extern struct key_type *key_type_lookup(const char *type); | 87 | extern struct key_type *key_type_lookup(const char *type); |
88 | extern void key_type_put(struct key_type *ktype); | 88 | extern void key_type_put(struct key_type *ktype); |
89 | 89 | ||
90 | extern int __key_link(struct key *keyring, struct key *key); | 90 | extern int __key_link_begin(struct key *keyring, |
91 | const struct key_type *type, | ||
92 | const char *description, | ||
93 | struct keyring_list **_prealloc); | ||
94 | extern int __key_link_check_live_key(struct key *keyring, struct key *key); | ||
95 | extern void __key_link(struct key *keyring, struct key *key, | ||
96 | struct keyring_list **_prealloc); | ||
97 | extern void __key_link_end(struct key *keyring, | ||
98 | struct key_type *type, | ||
99 | struct keyring_list *prealloc); | ||
91 | 100 | ||
92 | extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, | 101 | extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, |
93 | const struct key_type *type, | 102 | const struct key_type *type, |
diff --git a/security/keys/key.c b/security/keys/key.c index e50d264c9ad1..c1eac8084ade 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -355,7 +355,7 @@ EXPORT_SYMBOL(key_alloc); | |||
355 | */ | 355 | */ |
356 | int key_payload_reserve(struct key *key, size_t datalen) | 356 | int key_payload_reserve(struct key *key, size_t datalen) |
357 | { | 357 | { |
358 | int delta = (int) datalen - key->datalen; | 358 | int delta = (int)datalen - key->datalen; |
359 | int ret = 0; | 359 | int ret = 0; |
360 | 360 | ||
361 | key_check(key); | 361 | key_check(key); |
@@ -398,7 +398,8 @@ static int __key_instantiate_and_link(struct key *key, | |||
398 | const void *data, | 398 | const void *data, |
399 | size_t datalen, | 399 | size_t datalen, |
400 | struct key *keyring, | 400 | struct key *keyring, |
401 | struct key *authkey) | 401 | struct key *authkey, |
402 | struct keyring_list **_prealloc) | ||
402 | { | 403 | { |
403 | int ret, awaken; | 404 | int ret, awaken; |
404 | 405 | ||
@@ -425,7 +426,7 @@ static int __key_instantiate_and_link(struct key *key, | |||
425 | 426 | ||
426 | /* and link it into the destination keyring */ | 427 | /* and link it into the destination keyring */ |
427 | if (keyring) | 428 | if (keyring) |
428 | ret = __key_link(keyring, key); | 429 | __key_link(keyring, key, _prealloc); |
429 | 430 | ||
430 | /* disable the authorisation key */ | 431 | /* disable the authorisation key */ |
431 | if (authkey) | 432 | if (authkey) |
@@ -453,15 +454,21 @@ int key_instantiate_and_link(struct key *key, | |||
453 | struct key *keyring, | 454 | struct key *keyring, |
454 | struct key *authkey) | 455 | struct key *authkey) |
455 | { | 456 | { |
457 | struct keyring_list *prealloc; | ||
456 | int ret; | 458 | int ret; |
457 | 459 | ||
458 | if (keyring) | 460 | if (keyring) { |
459 | down_write(&keyring->sem); | 461 | ret = __key_link_begin(keyring, key->type, key->description, |
462 | &prealloc); | ||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | } | ||
460 | 466 | ||
461 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey); | 467 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, |
468 | &prealloc); | ||
462 | 469 | ||
463 | if (keyring) | 470 | if (keyring) |
464 | up_write(&keyring->sem); | 471 | __key_link_end(keyring, key->type, prealloc); |
465 | 472 | ||
466 | return ret; | 473 | return ret; |
467 | 474 | ||
@@ -478,8 +485,9 @@ int key_negate_and_link(struct key *key, | |||
478 | struct key *keyring, | 485 | struct key *keyring, |
479 | struct key *authkey) | 486 | struct key *authkey) |
480 | { | 487 | { |
488 | struct keyring_list *prealloc; | ||
481 | struct timespec now; | 489 | struct timespec now; |
482 | int ret, awaken; | 490 | int ret, awaken, link_ret = 0; |
483 | 491 | ||
484 | key_check(key); | 492 | key_check(key); |
485 | key_check(keyring); | 493 | key_check(keyring); |
@@ -488,7 +496,8 @@ int key_negate_and_link(struct key *key, | |||
488 | ret = -EBUSY; | 496 | ret = -EBUSY; |
489 | 497 | ||
490 | if (keyring) | 498 | if (keyring) |
491 | down_write(&keyring->sem); | 499 | link_ret = __key_link_begin(keyring, key->type, |
500 | key->description, &prealloc); | ||
492 | 501 | ||
493 | mutex_lock(&key_construction_mutex); | 502 | mutex_lock(&key_construction_mutex); |
494 | 503 | ||
@@ -508,8 +517,8 @@ int key_negate_and_link(struct key *key, | |||
508 | ret = 0; | 517 | ret = 0; |
509 | 518 | ||
510 | /* and link it into the destination keyring */ | 519 | /* and link it into the destination keyring */ |
511 | if (keyring) | 520 | if (keyring && link_ret == 0) |
512 | ret = __key_link(keyring, key); | 521 | __key_link(keyring, key, &prealloc); |
513 | 522 | ||
514 | /* disable the authorisation key */ | 523 | /* disable the authorisation key */ |
515 | if (authkey) | 524 | if (authkey) |
@@ -519,13 +528,13 @@ int key_negate_and_link(struct key *key, | |||
519 | mutex_unlock(&key_construction_mutex); | 528 | mutex_unlock(&key_construction_mutex); |
520 | 529 | ||
521 | if (keyring) | 530 | if (keyring) |
522 | up_write(&keyring->sem); | 531 | __key_link_end(keyring, key->type, prealloc); |
523 | 532 | ||
524 | /* wake up anyone waiting for a key to be constructed */ | 533 | /* wake up anyone waiting for a key to be constructed */ |
525 | if (awaken) | 534 | if (awaken) |
526 | wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); | 535 | wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); |
527 | 536 | ||
528 | return ret; | 537 | return ret == 0 ? link_ret : ret; |
529 | 538 | ||
530 | } /* end key_negate_and_link() */ | 539 | } /* end key_negate_and_link() */ |
531 | 540 | ||
@@ -749,6 +758,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
749 | key_perm_t perm, | 758 | key_perm_t perm, |
750 | unsigned long flags) | 759 | unsigned long flags) |
751 | { | 760 | { |
761 | struct keyring_list *prealloc; | ||
752 | const struct cred *cred = current_cred(); | 762 | const struct cred *cred = current_cred(); |
753 | struct key_type *ktype; | 763 | struct key_type *ktype; |
754 | struct key *keyring, *key = NULL; | 764 | struct key *keyring, *key = NULL; |
@@ -775,7 +785,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
775 | if (keyring->type != &key_type_keyring) | 785 | if (keyring->type != &key_type_keyring) |
776 | goto error_2; | 786 | goto error_2; |
777 | 787 | ||
778 | down_write(&keyring->sem); | 788 | ret = __key_link_begin(keyring, ktype, description, &prealloc); |
789 | if (ret < 0) | ||
790 | goto error_2; | ||
779 | 791 | ||
780 | /* if we're going to allocate a new key, we're going to have | 792 | /* if we're going to allocate a new key, we're going to have |
781 | * to modify the keyring */ | 793 | * to modify the keyring */ |
@@ -817,7 +829,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
817 | } | 829 | } |
818 | 830 | ||
819 | /* instantiate it and link it into the target keyring */ | 831 | /* instantiate it and link it into the target keyring */ |
820 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL); | 832 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, |
833 | &prealloc); | ||
821 | if (ret < 0) { | 834 | if (ret < 0) { |
822 | key_put(key); | 835 | key_put(key); |
823 | key_ref = ERR_PTR(ret); | 836 | key_ref = ERR_PTR(ret); |
@@ -827,7 +840,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
827 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); | 840 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); |
828 | 841 | ||
829 | error_3: | 842 | error_3: |
830 | up_write(&keyring->sem); | 843 | __key_link_end(keyring, ktype, prealloc); |
831 | error_2: | 844 | error_2: |
832 | key_type_put(ktype); | 845 | key_type_put(ktype); |
833 | error: | 846 | error: |
@@ -837,7 +850,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
837 | /* we found a matching key, so we're going to try to update it | 850 | /* we found a matching key, so we're going to try to update it |
838 | * - we can drop the locks first as we have the key pinned | 851 | * - we can drop the locks first as we have the key pinned |
839 | */ | 852 | */ |
840 | up_write(&keyring->sem); | 853 | __key_link_end(keyring, ktype, prealloc); |
841 | key_type_put(ktype); | 854 | key_type_put(ktype); |
842 | 855 | ||
843 | key_ref = __key_update(key_ref, payload, plen); | 856 | key_ref = __key_update(key_ref, payload, plen); |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index e9c2e7c584d9..8f4dce1987c4 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -212,15 +212,15 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type, | |||
212 | ret = key->serial; | 212 | ret = key->serial; |
213 | 213 | ||
214 | key_put(key); | 214 | key_put(key); |
215 | error5: | 215 | error5: |
216 | key_type_put(ktype); | 216 | key_type_put(ktype); |
217 | error4: | 217 | error4: |
218 | key_ref_put(dest_ref); | 218 | key_ref_put(dest_ref); |
219 | error3: | 219 | error3: |
220 | kfree(callout_info); | 220 | kfree(callout_info); |
221 | error2: | 221 | error2: |
222 | kfree(description); | 222 | kfree(description); |
223 | error: | 223 | error: |
224 | return ret; | 224 | return ret; |
225 | 225 | ||
226 | } /* end sys_request_key() */ | 226 | } /* end sys_request_key() */ |
@@ -246,7 +246,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create) | |||
246 | 246 | ||
247 | ret = key_ref_to_ptr(key_ref)->serial; | 247 | ret = key_ref_to_ptr(key_ref)->serial; |
248 | key_ref_put(key_ref); | 248 | key_ref_put(key_ref); |
249 | error: | 249 | error: |
250 | return ret; | 250 | return ret; |
251 | 251 | ||
252 | } /* end keyctl_get_keyring_ID() */ | 252 | } /* end keyctl_get_keyring_ID() */ |
@@ -275,7 +275,7 @@ long keyctl_join_session_keyring(const char __user *_name) | |||
275 | ret = join_session_keyring(name); | 275 | ret = join_session_keyring(name); |
276 | kfree(name); | 276 | kfree(name); |
277 | 277 | ||
278 | error: | 278 | error: |
279 | return ret; | 279 | return ret; |
280 | 280 | ||
281 | } /* end keyctl_join_session_keyring() */ | 281 | } /* end keyctl_join_session_keyring() */ |
@@ -322,9 +322,9 @@ long keyctl_update_key(key_serial_t id, | |||
322 | ret = key_update(key_ref, payload, plen); | 322 | ret = key_update(key_ref, payload, plen); |
323 | 323 | ||
324 | key_ref_put(key_ref); | 324 | key_ref_put(key_ref); |
325 | error2: | 325 | error2: |
326 | kfree(payload); | 326 | kfree(payload); |
327 | error: | 327 | error: |
328 | return ret; | 328 | return ret; |
329 | 329 | ||
330 | } /* end keyctl_update_key() */ | 330 | } /* end keyctl_update_key() */ |
@@ -356,7 +356,7 @@ long keyctl_revoke_key(key_serial_t id) | |||
356 | ret = 0; | 356 | ret = 0; |
357 | 357 | ||
358 | key_ref_put(key_ref); | 358 | key_ref_put(key_ref); |
359 | error: | 359 | error: |
360 | return ret; | 360 | return ret; |
361 | 361 | ||
362 | } /* end keyctl_revoke_key() */ | 362 | } /* end keyctl_revoke_key() */ |
@@ -381,7 +381,7 @@ long keyctl_keyring_clear(key_serial_t ringid) | |||
381 | ret = keyring_clear(key_ref_to_ptr(keyring_ref)); | 381 | ret = keyring_clear(key_ref_to_ptr(keyring_ref)); |
382 | 382 | ||
383 | key_ref_put(keyring_ref); | 383 | key_ref_put(keyring_ref); |
384 | error: | 384 | error: |
385 | return ret; | 385 | return ret; |
386 | 386 | ||
387 | } /* end keyctl_keyring_clear() */ | 387 | } /* end keyctl_keyring_clear() */ |
@@ -413,9 +413,9 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid) | |||
413 | ret = key_link(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); | 413 | ret = key_link(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); |
414 | 414 | ||
415 | key_ref_put(key_ref); | 415 | key_ref_put(key_ref); |
416 | error2: | 416 | error2: |
417 | key_ref_put(keyring_ref); | 417 | key_ref_put(keyring_ref); |
418 | error: | 418 | error: |
419 | return ret; | 419 | return ret; |
420 | 420 | ||
421 | } /* end keyctl_keyring_link() */ | 421 | } /* end keyctl_keyring_link() */ |
@@ -447,9 +447,9 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) | |||
447 | ret = key_unlink(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); | 447 | ret = key_unlink(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); |
448 | 448 | ||
449 | key_ref_put(key_ref); | 449 | key_ref_put(key_ref); |
450 | error2: | 450 | error2: |
451 | key_ref_put(keyring_ref); | 451 | key_ref_put(keyring_ref); |
452 | error: | 452 | error: |
453 | return ret; | 453 | return ret; |
454 | 454 | ||
455 | } /* end keyctl_keyring_unlink() */ | 455 | } /* end keyctl_keyring_unlink() */ |
@@ -529,9 +529,9 @@ okay: | |||
529 | } | 529 | } |
530 | 530 | ||
531 | kfree(tmpbuf); | 531 | kfree(tmpbuf); |
532 | error2: | 532 | error2: |
533 | key_ref_put(key_ref); | 533 | key_ref_put(key_ref); |
534 | error: | 534 | error: |
535 | return ret; | 535 | return ret; |
536 | 536 | ||
537 | } /* end keyctl_describe_key() */ | 537 | } /* end keyctl_describe_key() */ |
@@ -616,17 +616,17 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
616 | 616 | ||
617 | ret = key_ref_to_ptr(key_ref)->serial; | 617 | ret = key_ref_to_ptr(key_ref)->serial; |
618 | 618 | ||
619 | error6: | 619 | error6: |
620 | key_ref_put(key_ref); | 620 | key_ref_put(key_ref); |
621 | error5: | 621 | error5: |
622 | key_type_put(ktype); | 622 | key_type_put(ktype); |
623 | error4: | 623 | error4: |
624 | key_ref_put(dest_ref); | 624 | key_ref_put(dest_ref); |
625 | error3: | 625 | error3: |
626 | key_ref_put(keyring_ref); | 626 | key_ref_put(keyring_ref); |
627 | error2: | 627 | error2: |
628 | kfree(description); | 628 | kfree(description); |
629 | error: | 629 | error: |
630 | return ret; | 630 | return ret; |
631 | 631 | ||
632 | } /* end keyctl_keyring_search() */ | 632 | } /* end keyctl_keyring_search() */ |
@@ -673,7 +673,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
673 | } | 673 | } |
674 | 674 | ||
675 | /* the key is probably readable - now try to read it */ | 675 | /* the key is probably readable - now try to read it */ |
676 | can_read_key: | 676 | can_read_key: |
677 | ret = key_validate(key); | 677 | ret = key_validate(key); |
678 | if (ret == 0) { | 678 | if (ret == 0) { |
679 | ret = -EOPNOTSUPP; | 679 | ret = -EOPNOTSUPP; |
@@ -686,9 +686,9 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
686 | } | 686 | } |
687 | } | 687 | } |
688 | 688 | ||
689 | error2: | 689 | error2: |
690 | key_put(key); | 690 | key_put(key); |
691 | error: | 691 | error: |
692 | return ret; | 692 | return ret; |
693 | 693 | ||
694 | } /* end keyctl_read_key() */ | 694 | } /* end keyctl_read_key() */ |
@@ -1282,26 +1282,19 @@ long keyctl_session_to_parent(void) | |||
1282 | 1282 | ||
1283 | /* the parent must have the same effective ownership and mustn't be | 1283 | /* the parent must have the same effective ownership and mustn't be |
1284 | * SUID/SGID */ | 1284 | * SUID/SGID */ |
1285 | if (pcred-> uid != mycred->euid || | 1285 | if (pcred->uid != mycred->euid || |
1286 | pcred->euid != mycred->euid || | 1286 | pcred->euid != mycred->euid || |
1287 | pcred->suid != mycred->euid || | 1287 | pcred->suid != mycred->euid || |
1288 | pcred-> gid != mycred->egid || | 1288 | pcred->gid != mycred->egid || |
1289 | pcred->egid != mycred->egid || | 1289 | pcred->egid != mycred->egid || |
1290 | pcred->sgid != mycred->egid) | 1290 | pcred->sgid != mycred->egid) |
1291 | goto not_permitted; | 1291 | goto not_permitted; |
1292 | 1292 | ||
1293 | /* the keyrings must have the same UID */ | 1293 | /* the keyrings must have the same UID */ |
1294 | if (pcred ->tgcred->session_keyring->uid != mycred->euid || | 1294 | if (pcred->tgcred->session_keyring->uid != mycred->euid || |
1295 | mycred->tgcred->session_keyring->uid != mycred->euid) | 1295 | mycred->tgcred->session_keyring->uid != mycred->euid) |
1296 | goto not_permitted; | 1296 | goto not_permitted; |
1297 | 1297 | ||
1298 | /* the LSM must permit the replacement of the parent's keyring with the | ||
1299 | * keyring from this process */ | ||
1300 | ret = security_key_session_to_parent(mycred, pcred, | ||
1301 | key_ref_to_ptr(keyring_r)); | ||
1302 | if (ret < 0) | ||
1303 | goto not_permitted; | ||
1304 | |||
1305 | /* if there's an already pending keyring replacement, then we replace | 1298 | /* if there's an already pending keyring replacement, then we replace |
1306 | * that */ | 1299 | * that */ |
1307 | oldcred = parent->replacement_session_keyring; | 1300 | oldcred = parent->replacement_session_keyring; |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 1e4b0037935c..ef03a82a0135 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <keys/keyring-type.h> | 19 | #include <keys/keyring-type.h> |
20 | #include <asm/uaccess.h> | 20 | #include <linux/uaccess.h> |
21 | #include "internal.h" | 21 | #include "internal.h" |
22 | 22 | ||
23 | #define rcu_dereference_locked_keyring(keyring) \ | 23 | #define rcu_dereference_locked_keyring(keyring) \ |
@@ -44,7 +44,7 @@ static inline unsigned keyring_hash(const char *desc) | |||
44 | unsigned bucket = 0; | 44 | unsigned bucket = 0; |
45 | 45 | ||
46 | for (; *desc; desc++) | 46 | for (; *desc; desc++) |
47 | bucket += (unsigned char) *desc; | 47 | bucket += (unsigned char)*desc; |
48 | 48 | ||
49 | return bucket & (KEYRING_NAME_HASH_SIZE - 1); | 49 | return bucket & (KEYRING_NAME_HASH_SIZE - 1); |
50 | } | 50 | } |
@@ -175,12 +175,10 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) | |||
175 | { | 175 | { |
176 | struct keyring_list *klist; | 176 | struct keyring_list *klist; |
177 | 177 | ||
178 | if (keyring->description) { | 178 | if (keyring->description) |
179 | seq_puts(m, keyring->description); | 179 | seq_puts(m, keyring->description); |
180 | } | 180 | else |
181 | else { | ||
182 | seq_puts(m, "[anon]"); | 181 | seq_puts(m, "[anon]"); |
183 | } | ||
184 | 182 | ||
185 | rcu_read_lock(); | 183 | rcu_read_lock(); |
186 | klist = rcu_dereference(keyring->payload.subscriptions); | 184 | klist = rcu_dereference(keyring->payload.subscriptions); |
@@ -241,7 +239,7 @@ static long keyring_read(const struct key *keyring, | |||
241 | ret = qty; | 239 | ret = qty; |
242 | } | 240 | } |
243 | 241 | ||
244 | error: | 242 | error: |
245 | return ret; | 243 | return ret; |
246 | 244 | ||
247 | } /* end keyring_read() */ | 245 | } /* end keyring_read() */ |
@@ -310,7 +308,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
310 | key_check(keyring); | 308 | key_check(keyring); |
311 | 309 | ||
312 | /* top keyring must have search permission to begin the search */ | 310 | /* top keyring must have search permission to begin the search */ |
313 | err = key_task_permission(keyring_ref, cred, KEY_SEARCH); | 311 | err = key_task_permission(keyring_ref, cred, KEY_SEARCH); |
314 | if (err < 0) { | 312 | if (err < 0) { |
315 | key_ref = ERR_PTR(err); | 313 | key_ref = ERR_PTR(err); |
316 | goto error; | 314 | goto error; |
@@ -512,7 +510,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, | |||
512 | rcu_read_unlock(); | 510 | rcu_read_unlock(); |
513 | return ERR_PTR(-ENOKEY); | 511 | return ERR_PTR(-ENOKEY); |
514 | 512 | ||
515 | found: | 513 | found: |
516 | atomic_inc(&key->usage); | 514 | atomic_inc(&key->usage); |
517 | rcu_read_unlock(); | 515 | rcu_read_unlock(); |
518 | return make_key_ref(key, possessed); | 516 | return make_key_ref(key, possessed); |
@@ -602,7 +600,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
602 | sp = 0; | 600 | sp = 0; |
603 | 601 | ||
604 | /* start processing a new keyring */ | 602 | /* start processing a new keyring */ |
605 | descend: | 603 | descend: |
606 | if (test_bit(KEY_FLAG_REVOKED, &subtree->flags)) | 604 | if (test_bit(KEY_FLAG_REVOKED, &subtree->flags)) |
607 | goto not_this_keyring; | 605 | goto not_this_keyring; |
608 | 606 | ||
@@ -611,7 +609,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
611 | goto not_this_keyring; | 609 | goto not_this_keyring; |
612 | kix = 0; | 610 | kix = 0; |
613 | 611 | ||
614 | ascend: | 612 | ascend: |
615 | /* iterate through the remaining keys in this keyring */ | 613 | /* iterate through the remaining keys in this keyring */ |
616 | for (; kix < keylist->nkeys; kix++) { | 614 | for (; kix < keylist->nkeys; kix++) { |
617 | key = keylist->keys[kix]; | 615 | key = keylist->keys[kix]; |
@@ -637,7 +635,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
637 | 635 | ||
638 | /* the keyring we're looking at was disqualified or didn't contain a | 636 | /* the keyring we're looking at was disqualified or didn't contain a |
639 | * matching key */ | 637 | * matching key */ |
640 | not_this_keyring: | 638 | not_this_keyring: |
641 | if (sp > 0) { | 639 | if (sp > 0) { |
642 | /* resume the checking of a keyring higher up in the tree */ | 640 | /* resume the checking of a keyring higher up in the tree */ |
643 | sp--; | 641 | sp--; |
@@ -648,34 +646,20 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
648 | 646 | ||
649 | ret = 0; /* no cycles detected */ | 647 | ret = 0; /* no cycles detected */ |
650 | 648 | ||
651 | error: | 649 | error: |
652 | rcu_read_unlock(); | 650 | rcu_read_unlock(); |
653 | return ret; | 651 | return ret; |
654 | 652 | ||
655 | too_deep: | 653 | too_deep: |
656 | ret = -ELOOP; | 654 | ret = -ELOOP; |
657 | goto error; | 655 | goto error; |
658 | 656 | ||
659 | cycle_detected: | 657 | cycle_detected: |
660 | ret = -EDEADLK; | 658 | ret = -EDEADLK; |
661 | goto error; | 659 | goto error; |
662 | 660 | ||
663 | } /* end keyring_detect_cycle() */ | 661 | } /* end keyring_detect_cycle() */ |
664 | 662 | ||
665 | /*****************************************************************************/ | ||
666 | /* | ||
667 | * dispose of a keyring list after the RCU grace period | ||
668 | */ | ||
669 | static void keyring_link_rcu_disposal(struct rcu_head *rcu) | ||
670 | { | ||
671 | struct keyring_list *klist = | ||
672 | container_of(rcu, struct keyring_list, rcu); | ||
673 | |||
674 | kfree(klist); | ||
675 | |||
676 | } /* end keyring_link_rcu_disposal() */ | ||
677 | |||
678 | /*****************************************************************************/ | ||
679 | /* | 663 | /* |
680 | * dispose of a keyring list after the RCU grace period, freeing the unlinked | 664 | * dispose of a keyring list after the RCU grace period, freeing the unlinked |
681 | * key | 665 | * key |
@@ -685,55 +669,51 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) | |||
685 | struct keyring_list *klist = | 669 | struct keyring_list *klist = |
686 | container_of(rcu, struct keyring_list, rcu); | 670 | container_of(rcu, struct keyring_list, rcu); |
687 | 671 | ||
688 | key_put(klist->keys[klist->delkey]); | 672 | if (klist->delkey != USHORT_MAX) |
673 | key_put(klist->keys[klist->delkey]); | ||
689 | kfree(klist); | 674 | kfree(klist); |
675 | } | ||
690 | 676 | ||
691 | } /* end keyring_unlink_rcu_disposal() */ | ||
692 | |||
693 | /*****************************************************************************/ | ||
694 | /* | 677 | /* |
695 | * link a key into to a keyring | 678 | * preallocate memory so that a key can be linked into to a keyring |
696 | * - must be called with the keyring's semaphore write-locked | ||
697 | * - discard already extant link to matching key if there is one | ||
698 | */ | 679 | */ |
699 | int __key_link(struct key *keyring, struct key *key) | 680 | int __key_link_begin(struct key *keyring, const struct key_type *type, |
681 | const char *description, | ||
682 | struct keyring_list **_prealloc) | ||
683 | __acquires(&keyring->sem) | ||
700 | { | 684 | { |
701 | struct keyring_list *klist, *nklist; | 685 | struct keyring_list *klist, *nklist; |
702 | unsigned max; | 686 | unsigned max; |
703 | size_t size; | 687 | size_t size; |
704 | int loop, ret; | 688 | int loop, ret; |
705 | 689 | ||
706 | ret = -EKEYREVOKED; | 690 | kenter("%d,%s,%s,", key_serial(keyring), type->name, description); |
707 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | ||
708 | goto error; | ||
709 | 691 | ||
710 | ret = -ENOTDIR; | ||
711 | if (keyring->type != &key_type_keyring) | 692 | if (keyring->type != &key_type_keyring) |
712 | goto error; | 693 | return -ENOTDIR; |
713 | 694 | ||
714 | /* serialise link/link calls to prevent parallel calls causing a | 695 | down_write(&keyring->sem); |
715 | * cycle when applied to two keyring in opposite orders */ | ||
716 | down_write(&keyring_serialise_link_sem); | ||
717 | 696 | ||
718 | /* check that we aren't going to create a cycle adding one keyring to | 697 | ret = -EKEYREVOKED; |
719 | * another */ | 698 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
720 | if (key->type == &key_type_keyring) { | 699 | goto error_krsem; |
721 | ret = keyring_detect_cycle(keyring, key); | 700 | |
722 | if (ret < 0) | 701 | /* serialise link/link calls to prevent parallel calls causing a cycle |
723 | goto error2; | 702 | * when linking two keyring in opposite orders */ |
724 | } | 703 | if (type == &key_type_keyring) |
704 | down_write(&keyring_serialise_link_sem); | ||
725 | 705 | ||
726 | /* see if there's a matching key we can displace */ | ||
727 | klist = rcu_dereference_locked_keyring(keyring); | 706 | klist = rcu_dereference_locked_keyring(keyring); |
728 | if (klist && klist->nkeys > 0) { | ||
729 | struct key_type *type = key->type; | ||
730 | 707 | ||
708 | /* see if there's a matching key we can displace */ | ||
709 | if (klist && klist->nkeys > 0) { | ||
731 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { | 710 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { |
732 | if (klist->keys[loop]->type == type && | 711 | if (klist->keys[loop]->type == type && |
733 | strcmp(klist->keys[loop]->description, | 712 | strcmp(klist->keys[loop]->description, |
734 | key->description) == 0 | 713 | description) == 0 |
735 | ) { | 714 | ) { |
736 | /* found a match - replace with new key */ | 715 | /* found a match - we'll replace this one with |
716 | * the new key */ | ||
737 | size = sizeof(struct key *) * klist->maxkeys; | 717 | size = sizeof(struct key *) * klist->maxkeys; |
738 | size += sizeof(*klist); | 718 | size += sizeof(*klist); |
739 | BUG_ON(size > PAGE_SIZE); | 719 | BUG_ON(size > PAGE_SIZE); |
@@ -741,22 +721,10 @@ int __key_link(struct key *keyring, struct key *key) | |||
741 | ret = -ENOMEM; | 721 | ret = -ENOMEM; |
742 | nklist = kmemdup(klist, size, GFP_KERNEL); | 722 | nklist = kmemdup(klist, size, GFP_KERNEL); |
743 | if (!nklist) | 723 | if (!nklist) |
744 | goto error2; | 724 | goto error_sem; |
745 | |||
746 | /* replace matched key */ | ||
747 | atomic_inc(&key->usage); | ||
748 | nklist->keys[loop] = key; | ||
749 | |||
750 | rcu_assign_pointer( | ||
751 | keyring->payload.subscriptions, | ||
752 | nklist); | ||
753 | |||
754 | /* dispose of the old keyring list and the | ||
755 | * displaced key */ | ||
756 | klist->delkey = loop; | ||
757 | call_rcu(&klist->rcu, | ||
758 | keyring_unlink_rcu_disposal); | ||
759 | 725 | ||
726 | /* note replacement slot */ | ||
727 | klist->delkey = nklist->delkey = loop; | ||
760 | goto done; | 728 | goto done; |
761 | } | 729 | } |
762 | } | 730 | } |
@@ -766,88 +734,167 @@ int __key_link(struct key *keyring, struct key *key) | |||
766 | ret = key_payload_reserve(keyring, | 734 | ret = key_payload_reserve(keyring, |
767 | keyring->datalen + KEYQUOTA_LINK_BYTES); | 735 | keyring->datalen + KEYQUOTA_LINK_BYTES); |
768 | if (ret < 0) | 736 | if (ret < 0) |
769 | goto error2; | 737 | goto error_sem; |
770 | 738 | ||
771 | if (klist && klist->nkeys < klist->maxkeys) { | 739 | if (klist && klist->nkeys < klist->maxkeys) { |
772 | /* there's sufficient slack space to add directly */ | 740 | /* there's sufficient slack space to append directly */ |
773 | atomic_inc(&key->usage); | 741 | nklist = NULL; |
774 | 742 | } else { | |
775 | klist->keys[klist->nkeys] = key; | ||
776 | smp_wmb(); | ||
777 | klist->nkeys++; | ||
778 | smp_wmb(); | ||
779 | } | ||
780 | else { | ||
781 | /* grow the key list */ | 743 | /* grow the key list */ |
782 | max = 4; | 744 | max = 4; |
783 | if (klist) | 745 | if (klist) |
784 | max += klist->maxkeys; | 746 | max += klist->maxkeys; |
785 | 747 | ||
786 | ret = -ENFILE; | 748 | ret = -ENFILE; |
787 | if (max > 65535) | 749 | if (max > USHORT_MAX - 1) |
788 | goto error3; | 750 | goto error_quota; |
789 | size = sizeof(*klist) + sizeof(struct key *) * max; | 751 | size = sizeof(*klist) + sizeof(struct key *) * max; |
790 | if (size > PAGE_SIZE) | 752 | if (size > PAGE_SIZE) |
791 | goto error3; | 753 | goto error_quota; |
792 | 754 | ||
793 | ret = -ENOMEM; | 755 | ret = -ENOMEM; |
794 | nklist = kmalloc(size, GFP_KERNEL); | 756 | nklist = kmalloc(size, GFP_KERNEL); |
795 | if (!nklist) | 757 | if (!nklist) |
796 | goto error3; | 758 | goto error_quota; |
797 | nklist->maxkeys = max; | ||
798 | nklist->nkeys = 0; | ||
799 | 759 | ||
760 | nklist->maxkeys = max; | ||
800 | if (klist) { | 761 | if (klist) { |
801 | nklist->nkeys = klist->nkeys; | 762 | memcpy(nklist->keys, klist->keys, |
802 | memcpy(nklist->keys, | ||
803 | klist->keys, | ||
804 | sizeof(struct key *) * klist->nkeys); | 763 | sizeof(struct key *) * klist->nkeys); |
764 | nklist->delkey = klist->nkeys; | ||
765 | nklist->nkeys = klist->nkeys + 1; | ||
766 | klist->delkey = USHORT_MAX; | ||
767 | } else { | ||
768 | nklist->nkeys = 1; | ||
769 | nklist->delkey = 0; | ||
805 | } | 770 | } |
806 | 771 | ||
807 | /* add the key into the new space */ | 772 | /* add the key into the new space */ |
808 | atomic_inc(&key->usage); | 773 | nklist->keys[nklist->delkey] = NULL; |
809 | nklist->keys[nklist->nkeys++] = key; | ||
810 | |||
811 | rcu_assign_pointer(keyring->payload.subscriptions, nklist); | ||
812 | |||
813 | /* dispose of the old keyring list */ | ||
814 | if (klist) | ||
815 | call_rcu(&klist->rcu, keyring_link_rcu_disposal); | ||
816 | } | 774 | } |
817 | 775 | ||
818 | done: | 776 | done: |
819 | ret = 0; | 777 | *_prealloc = nklist; |
820 | error2: | 778 | kleave(" = 0"); |
821 | up_write(&keyring_serialise_link_sem); | 779 | return 0; |
822 | error: | ||
823 | return ret; | ||
824 | 780 | ||
825 | error3: | 781 | error_quota: |
826 | /* undo the quota changes */ | 782 | /* undo the quota changes */ |
827 | key_payload_reserve(keyring, | 783 | key_payload_reserve(keyring, |
828 | keyring->datalen - KEYQUOTA_LINK_BYTES); | 784 | keyring->datalen - KEYQUOTA_LINK_BYTES); |
829 | goto error2; | 785 | error_sem: |
786 | if (type == &key_type_keyring) | ||
787 | up_write(&keyring_serialise_link_sem); | ||
788 | error_krsem: | ||
789 | up_write(&keyring->sem); | ||
790 | kleave(" = %d", ret); | ||
791 | return ret; | ||
792 | } | ||
830 | 793 | ||
831 | } /* end __key_link() */ | 794 | /* |
795 | * check already instantiated keys aren't going to be a problem | ||
796 | * - the caller must have called __key_link_begin() | ||
797 | * - don't need to call this for keys that were created since __key_link_begin() | ||
798 | * was called | ||
799 | */ | ||
800 | int __key_link_check_live_key(struct key *keyring, struct key *key) | ||
801 | { | ||
802 | if (key->type == &key_type_keyring) | ||
803 | /* check that we aren't going to create a cycle by linking one | ||
804 | * keyring to another */ | ||
805 | return keyring_detect_cycle(keyring, key); | ||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | /* | ||
810 | * link a key into to a keyring | ||
811 | * - must be called with __key_link_begin() having being called | ||
812 | * - discard already extant link to matching key if there is one | ||
813 | */ | ||
814 | void __key_link(struct key *keyring, struct key *key, | ||
815 | struct keyring_list **_prealloc) | ||
816 | { | ||
817 | struct keyring_list *klist, *nklist; | ||
818 | |||
819 | nklist = *_prealloc; | ||
820 | *_prealloc = NULL; | ||
821 | |||
822 | kenter("%d,%d,%p", keyring->serial, key->serial, nklist); | ||
823 | |||
824 | klist = rcu_dereference_protected(keyring->payload.subscriptions, | ||
825 | rwsem_is_locked(&keyring->sem)); | ||
826 | |||
827 | atomic_inc(&key->usage); | ||
828 | |||
829 | /* there's a matching key we can displace or an empty slot in a newly | ||
830 | * allocated list we can fill */ | ||
831 | if (nklist) { | ||
832 | kdebug("replace %hu/%hu/%hu", | ||
833 | nklist->delkey, nklist->nkeys, nklist->maxkeys); | ||
834 | |||
835 | nklist->keys[nklist->delkey] = key; | ||
836 | |||
837 | rcu_assign_pointer(keyring->payload.subscriptions, nklist); | ||
838 | |||
839 | /* dispose of the old keyring list and, if there was one, the | ||
840 | * displaced key */ | ||
841 | if (klist) { | ||
842 | kdebug("dispose %hu/%hu/%hu", | ||
843 | klist->delkey, klist->nkeys, klist->maxkeys); | ||
844 | call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); | ||
845 | } | ||
846 | } else { | ||
847 | /* there's sufficient slack space to append directly */ | ||
848 | klist->keys[klist->nkeys] = key; | ||
849 | smp_wmb(); | ||
850 | klist->nkeys++; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | /* | ||
855 | * finish linking a key into to a keyring | ||
856 | * - must be called with __key_link_begin() having being called | ||
857 | */ | ||
858 | void __key_link_end(struct key *keyring, struct key_type *type, | ||
859 | struct keyring_list *prealloc) | ||
860 | __releases(&keyring->sem) | ||
861 | { | ||
862 | BUG_ON(type == NULL); | ||
863 | BUG_ON(type->name == NULL); | ||
864 | kenter("%d,%s,%p", keyring->serial, type->name, prealloc); | ||
865 | |||
866 | if (type == &key_type_keyring) | ||
867 | up_write(&keyring_serialise_link_sem); | ||
868 | |||
869 | if (prealloc) { | ||
870 | kfree(prealloc); | ||
871 | key_payload_reserve(keyring, | ||
872 | keyring->datalen - KEYQUOTA_LINK_BYTES); | ||
873 | } | ||
874 | up_write(&keyring->sem); | ||
875 | } | ||
832 | 876 | ||
833 | /*****************************************************************************/ | ||
834 | /* | 877 | /* |
835 | * link a key to a keyring | 878 | * link a key to a keyring |
836 | */ | 879 | */ |
837 | int key_link(struct key *keyring, struct key *key) | 880 | int key_link(struct key *keyring, struct key *key) |
838 | { | 881 | { |
882 | struct keyring_list *prealloc; | ||
839 | int ret; | 883 | int ret; |
840 | 884 | ||
841 | key_check(keyring); | 885 | key_check(keyring); |
842 | key_check(key); | 886 | key_check(key); |
843 | 887 | ||
844 | down_write(&keyring->sem); | 888 | ret = __key_link_begin(keyring, key->type, key->description, &prealloc); |
845 | ret = __key_link(keyring, key); | 889 | if (ret == 0) { |
846 | up_write(&keyring->sem); | 890 | ret = __key_link_check_live_key(keyring, key); |
891 | if (ret == 0) | ||
892 | __key_link(keyring, key, &prealloc); | ||
893 | __key_link_end(keyring, key->type, prealloc); | ||
894 | } | ||
847 | 895 | ||
848 | return ret; | 896 | return ret; |
849 | 897 | } | |
850 | } /* end key_link() */ | ||
851 | 898 | ||
852 | EXPORT_SYMBOL(key_link); | 899 | EXPORT_SYMBOL(key_link); |
853 | 900 | ||
diff --git a/security/keys/permission.c b/security/keys/permission.c index 0ed802c9e698..28645502cd0d 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c | |||
@@ -109,7 +109,7 @@ int key_validate(struct key *key) | |||
109 | } | 109 | } |
110 | } | 110 | } |
111 | 111 | ||
112 | error: | 112 | error: |
113 | return ret; | 113 | return ret; |
114 | 114 | ||
115 | } /* end key_validate() */ | 115 | } /* end key_validate() */ |
diff --git a/security/keys/proc.c b/security/keys/proc.c index 706d63f4f185..068b66ea2f1b 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -306,7 +306,7 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) | |||
306 | static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) | 306 | static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) |
307 | { | 307 | { |
308 | (*_pos)++; | 308 | (*_pos)++; |
309 | return key_user_next((struct rb_node *) v); | 309 | return key_user_next((struct rb_node *)v); |
310 | } | 310 | } |
311 | 311 | ||
312 | static void proc_key_users_stop(struct seq_file *p, void *v) | 312 | static void proc_key_users_stop(struct seq_file *p, void *v) |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 06c2ccf26ed3..20a38fed61b1 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -508,7 +508,7 @@ try_again: | |||
508 | 508 | ||
509 | ret = install_thread_keyring(); | 509 | ret = install_thread_keyring(); |
510 | if (ret < 0) { | 510 | if (ret < 0) { |
511 | key = ERR_PTR(ret); | 511 | key_ref = ERR_PTR(ret); |
512 | goto error; | 512 | goto error; |
513 | } | 513 | } |
514 | goto reget_creds; | 514 | goto reget_creds; |
@@ -526,7 +526,7 @@ try_again: | |||
526 | 526 | ||
527 | ret = install_process_keyring(); | 527 | ret = install_process_keyring(); |
528 | if (ret < 0) { | 528 | if (ret < 0) { |
529 | key = ERR_PTR(ret); | 529 | key_ref = ERR_PTR(ret); |
530 | goto error; | 530 | goto error; |
531 | } | 531 | } |
532 | goto reget_creds; | 532 | goto reget_creds; |
@@ -585,7 +585,7 @@ try_again: | |||
585 | 585 | ||
586 | case KEY_SPEC_GROUP_KEYRING: | 586 | case KEY_SPEC_GROUP_KEYRING: |
587 | /* group keyrings are not yet supported */ | 587 | /* group keyrings are not yet supported */ |
588 | key = ERR_PTR(-EINVAL); | 588 | key_ref = ERR_PTR(-EINVAL); |
589 | goto error; | 589 | goto error; |
590 | 590 | ||
591 | case KEY_SPEC_REQKEY_AUTH_KEY: | 591 | case KEY_SPEC_REQKEY_AUTH_KEY: |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index d8c1a6a0fb08..f656e9c069e3 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -299,12 +299,15 @@ 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 | int ret; | ||
305 | 307 | ||
306 | kenter("%s,%s,,,", type->name, description); | 308 | kenter("%s,%s,,,", type->name, description); |
307 | 309 | ||
310 | *_key = NULL; | ||
308 | mutex_lock(&user->cons_lock); | 311 | mutex_lock(&user->cons_lock); |
309 | 312 | ||
310 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, | 313 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, |
@@ -314,8 +317,12 @@ static int construct_alloc_key(struct key_type *type, | |||
314 | 317 | ||
315 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); | 318 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); |
316 | 319 | ||
317 | if (dest_keyring) | 320 | if (dest_keyring) { |
318 | 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 | } | ||
319 | 326 | ||
320 | /* 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 |
321 | * 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 |
@@ -327,31 +334,49 @@ static int construct_alloc_key(struct key_type *type, | |||
327 | goto key_already_present; | 334 | goto key_already_present; |
328 | 335 | ||
329 | if (dest_keyring) | 336 | if (dest_keyring) |
330 | __key_link(dest_keyring, key); | 337 | __key_link(dest_keyring, key, &prealloc); |
331 | 338 | ||
332 | mutex_unlock(&key_construction_mutex); | 339 | mutex_unlock(&key_construction_mutex); |
333 | if (dest_keyring) | 340 | if (dest_keyring) |
334 | up_write(&dest_keyring->sem); | 341 | __key_link_end(dest_keyring, type, prealloc); |
335 | mutex_unlock(&user->cons_lock); | 342 | mutex_unlock(&user->cons_lock); |
336 | *_key = key; | 343 | *_key = key; |
337 | kleave(" = 0 [%d]", key_serial(key)); | 344 | kleave(" = 0 [%d]", key_serial(key)); |
338 | return 0; | 345 | return 0; |
339 | 346 | ||
347 | /* the key is now present - we tell the caller that we found it by | ||
348 | * returning -EINPROGRESS */ | ||
340 | key_already_present: | 349 | key_already_present: |
350 | key_put(key); | ||
341 | mutex_unlock(&key_construction_mutex); | 351 | mutex_unlock(&key_construction_mutex); |
352 | key = key_ref_to_ptr(key_ref); | ||
342 | if (dest_keyring) { | 353 | if (dest_keyring) { |
343 | __key_link(dest_keyring, key_ref_to_ptr(key_ref)); | 354 | ret = __key_link_check_live_key(dest_keyring, key); |
344 | 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; | ||
345 | } | 360 | } |
346 | mutex_unlock(&user->cons_lock); | 361 | mutex_unlock(&user->cons_lock); |
347 | key_put(key); | 362 | *_key = key; |
348 | *_key = key = key_ref_to_ptr(key_ref); | ||
349 | kleave(" = -EINPROGRESS [%d]", key_serial(key)); | 363 | kleave(" = -EINPROGRESS [%d]", key_serial(key)); |
350 | return -EINPROGRESS; | 364 | return -EINPROGRESS; |
351 | 365 | ||
366 | link_check_failed: | ||
367 | mutex_unlock(&user->cons_lock); | ||
368 | key_put(key); | ||
369 | kleave(" = %d [linkcheck]", ret); | ||
370 | return ret; | ||
371 | |||
372 | link_prealloc_failed: | ||
373 | up_write(&dest_keyring->sem); | ||
374 | mutex_unlock(&user->cons_lock); | ||
375 | kleave(" = %d [prelink]", ret); | ||
376 | return ret; | ||
377 | |||
352 | alloc_failed: | 378 | alloc_failed: |
353 | mutex_unlock(&user->cons_lock); | 379 | mutex_unlock(&user->cons_lock); |
354 | *_key = NULL; | ||
355 | kleave(" = %ld", PTR_ERR(key)); | 380 | kleave(" = %ld", PTR_ERR(key)); |
356 | return PTR_ERR(key); | 381 | return PTR_ERR(key); |
357 | } | 382 | } |
@@ -390,6 +415,10 @@ static struct key *construct_key_and_link(struct key_type *type, | |||
390 | kdebug("cons failed"); | 415 | kdebug("cons failed"); |
391 | goto construction_failed; | 416 | goto construction_failed; |
392 | } | 417 | } |
418 | } else if (ret == -EINPROGRESS) { | ||
419 | ret = 0; | ||
420 | } else { | ||
421 | key = ERR_PTR(ret); | ||
393 | } | 422 | } |
394 | 423 | ||
395 | key_put(dest_keyring); | 424 | key_put(dest_keyring); |
@@ -422,6 +451,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
422 | const struct cred *cred = current_cred(); | 451 | const struct cred *cred = current_cred(); |
423 | struct key *key; | 452 | struct key *key; |
424 | key_ref_t key_ref; | 453 | key_ref_t key_ref; |
454 | int ret; | ||
425 | 455 | ||
426 | kenter("%s,%s,%p,%zu,%p,%p,%lx", | 456 | kenter("%s,%s,%p,%zu,%p,%p,%lx", |
427 | type->name, description, callout_info, callout_len, aux, | 457 | type->name, description, callout_info, callout_len, aux, |
@@ -435,8 +465,13 @@ struct key *request_key_and_link(struct key_type *type, | |||
435 | key = key_ref_to_ptr(key_ref); | 465 | key = key_ref_to_ptr(key_ref); |
436 | if (dest_keyring) { | 466 | if (dest_keyring) { |
437 | construct_get_dest_keyring(&dest_keyring); | 467 | construct_get_dest_keyring(&dest_keyring); |
438 | key_link(dest_keyring, key); | 468 | ret = key_link(dest_keyring, key); |
439 | key_put(dest_keyring); | 469 | key_put(dest_keyring); |
470 | if (ret < 0) { | ||
471 | key_put(key); | ||
472 | key = ERR_PTR(ret); | ||
473 | goto error; | ||
474 | } | ||
440 | } | 475 | } |
441 | } else if (PTR_ERR(key_ref) != -EAGAIN) { | 476 | } else if (PTR_ERR(key_ref) != -EAGAIN) { |
442 | key = ERR_CAST(key_ref); | 477 | key = ERR_CAST(key_ref); |