Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6:
KEYS: call_sbin_request_key() must write lock keyrings before modifying them
KEYS: Use RCU dereference wrappers in keyring key type code
KEYS: find_keyring_by_name() can gain access to a freed keyring

+23 -20
+22 -19
security/keys/keyring.c
··· 20 20 #include <asm/uaccess.h> 21 21 #include "internal.h" 22 22 23 + #define rcu_dereference_locked_keyring(keyring) \ 24 + (rcu_dereference_protected( \ 25 + (keyring)->payload.subscriptions, \ 26 + rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem))) 27 + 23 28 /* 24 29 * when plumbing the depths of the key tree, this sets a hard limit set on how 25 30 * deep we're willing to go ··· 206 201 int loop, ret; 207 202 208 203 ret = 0; 209 - klist = keyring->payload.subscriptions; 210 - 204 + klist = rcu_dereference_locked_keyring(keyring); 211 205 if (klist) { 212 206 /* calculate how much data we could return */ 213 207 qty = klist->nkeys * sizeof(key_serial_t); ··· 530 526 struct key *keyring; 531 527 int bucket; 532 528 533 - keyring = ERR_PTR(-EINVAL); 534 529 if (!name) 535 - goto error; 530 + return ERR_PTR(-EINVAL); 536 531 537 532 bucket = keyring_hash(name); 538 533 ··· 558 555 KEY_SEARCH) < 0) 559 556 continue; 560 557 561 - /* we've got a match */ 562 - atomic_inc(&keyring->usage); 563 - read_unlock(&keyring_name_lock); 564 - goto error; 558 + /* we've got a match but we might end up racing with 559 + * key_cleanup() if the keyring is currently 'dead' 560 + * (ie. it has a zero usage count) */ 561 + if (!atomic_inc_not_zero(&keyring->usage)) 562 + continue; 563 + goto out; 565 564 } 566 565 } 567 566 568 - read_unlock(&keyring_name_lock); 569 567 keyring = ERR_PTR(-ENOKEY); 570 - 571 - error: 568 + out: 569 + read_unlock(&keyring_name_lock); 572 570 return keyring; 573 571 574 572 } /* end find_keyring_by_name() */ ··· 724 720 } 725 721 726 722 /* see if there's a matching key we can displace */ 727 - klist = keyring->payload.subscriptions; 728 - 723 + klist = rcu_dereference_locked_keyring(keyring); 729 724 if (klist && klist->nkeys > 0) { 730 725 struct key_type *type = key->type; 731 726 ··· 767 764 keyring->datalen + KEYQUOTA_LINK_BYTES); 768 765 if (ret < 0) 769 766 goto error2; 770 - 771 - klist = keyring->payload.subscriptions; 772 767 773 768 if (klist && klist->nkeys < klist->maxkeys) { 774 769 /* there's sufficient slack space to add directly */ ··· 869 868 870 869 down_write(&keyring->sem); 871 870 872 - klist = keyring->payload.subscriptions; 871 + klist = rcu_dereference_locked_keyring(keyring); 873 872 if (klist) { 874 873 /* search the keyring for the key */ 875 874 for (loop = 0; loop < klist->nkeys; loop++) ··· 960 959 /* detach the pointer block with the locks held */ 961 960 down_write(&keyring->sem); 962 961 963 - klist = keyring->payload.subscriptions; 962 + klist = rcu_dereference_locked_keyring(keyring); 964 963 if (klist) { 965 964 /* adjust the quota */ 966 965 key_payload_reserve(keyring, ··· 992 991 */ 993 992 static void keyring_revoke(struct key *keyring) 994 993 { 995 - struct keyring_list *klist = keyring->payload.subscriptions; 994 + struct keyring_list *klist; 995 + 996 + klist = rcu_dereference_locked_keyring(keyring); 996 997 997 998 /* adjust the quota */ 998 999 key_payload_reserve(keyring, 0); ··· 1028 1025 1029 1026 down_write(&keyring->sem); 1030 1027 1031 - klist = keyring->payload.subscriptions; 1028 + klist = rcu_dereference_locked_keyring(keyring); 1032 1029 if (!klist) 1033 1030 goto no_klist; 1034 1031
+1 -1
security/keys/request_key.c
··· 94 94 } 95 95 96 96 /* attach the auth key to the session keyring */ 97 - ret = __key_link(keyring, authkey); 97 + ret = key_link(keyring, authkey); 98 98 if (ret < 0) 99 99 goto error_link; 100 100