aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/keyring.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r--security/keys/keyring.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 29de5ee3457b..3f425a65906f 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -20,6 +20,11 @@
20#include <linux/uaccess.h> 20#include <linux/uaccess.h>
21#include "internal.h" 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 * when plumbing the depths of the key tree, this sets a hard limit set on how 29 * when plumbing the depths of the key tree, this sets a hard limit set on how
25 * deep we're willing to go 30 * deep we're willing to go
@@ -199,8 +204,7 @@ static long keyring_read(const struct key *keyring,
199 int loop, ret; 204 int loop, ret;
200 205
201 ret = 0; 206 ret = 0;
202 klist = keyring->payload.subscriptions; 207 klist = rcu_dereference_locked_keyring(keyring);
203
204 if (klist) { 208 if (klist) {
205 /* calculate how much data we could return */ 209 /* calculate how much data we could return */
206 qty = klist->nkeys * sizeof(key_serial_t); 210 qty = klist->nkeys * sizeof(key_serial_t);
@@ -524,9 +528,8 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
524 struct key *keyring; 528 struct key *keyring;
525 int bucket; 529 int bucket;
526 530
527 keyring = ERR_PTR(-EINVAL);
528 if (!name) 531 if (!name)
529 goto error; 532 return ERR_PTR(-EINVAL);
530 533
531 bucket = keyring_hash(name); 534 bucket = keyring_hash(name);
532 535
@@ -553,17 +556,18 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
553 KEY_SEARCH) < 0) 556 KEY_SEARCH) < 0)
554 continue; 557 continue;
555 558
556 /* we've got a match */ 559 /* we've got a match but we might end up racing with
557 atomic_inc(&keyring->usage); 560 * key_cleanup() if the keyring is currently 'dead'
558 read_unlock(&keyring_name_lock); 561 * (ie. it has a zero usage count) */
559 goto error; 562 if (!atomic_inc_not_zero(&keyring->usage))
563 continue;
564 goto out;
560 } 565 }
561 } 566 }
562 567
563 read_unlock(&keyring_name_lock);
564 keyring = ERR_PTR(-ENOKEY); 568 keyring = ERR_PTR(-ENOKEY);
565 569out:
566error: 570 read_unlock(&keyring_name_lock);
567 return keyring; 571 return keyring;
568 572
569} /* end find_keyring_by_name() */ 573} /* end find_keyring_by_name() */
@@ -719,8 +723,7 @@ int __key_link(struct key *keyring, struct key *key)
719 } 723 }
720 724
721 /* see if there's a matching key we can displace */ 725 /* see if there's a matching key we can displace */
722 klist = keyring->payload.subscriptions; 726 klist = rcu_dereference_locked_keyring(keyring);
723
724 if (klist && klist->nkeys > 0) { 727 if (klist && klist->nkeys > 0) {
725 struct key_type *type = key->type; 728 struct key_type *type = key->type;
726 729
@@ -764,8 +767,6 @@ int __key_link(struct key *keyring, struct key *key)
764 if (ret < 0) 767 if (ret < 0)
765 goto error2; 768 goto error2;
766 769
767 klist = keyring->payload.subscriptions;
768
769 if (klist && klist->nkeys < klist->maxkeys) { 770 if (klist && klist->nkeys < klist->maxkeys) {
770 /* there's sufficient slack space to add directly */ 771 /* there's sufficient slack space to add directly */
771 atomic_inc(&key->usage); 772 atomic_inc(&key->usage);
@@ -867,7 +868,7 @@ int key_unlink(struct key *keyring, struct key *key)
867 868
868 down_write(&keyring->sem); 869 down_write(&keyring->sem);
869 870
870 klist = keyring->payload.subscriptions; 871 klist = rcu_dereference_locked_keyring(keyring);
871 if (klist) { 872 if (klist) {
872 /* search the keyring for the key */ 873 /* search the keyring for the key */
873 for (loop = 0; loop < klist->nkeys; loop++) 874 for (loop = 0; loop < klist->nkeys; loop++)
@@ -958,7 +959,7 @@ int keyring_clear(struct key *keyring)
958 /* detach the pointer block with the locks held */ 959 /* detach the pointer block with the locks held */
959 down_write(&keyring->sem); 960 down_write(&keyring->sem);
960 961
961 klist = keyring->payload.subscriptions; 962 klist = rcu_dereference_locked_keyring(keyring);
962 if (klist) { 963 if (klist) {
963 /* adjust the quota */ 964 /* adjust the quota */
964 key_payload_reserve(keyring, 965 key_payload_reserve(keyring,
@@ -990,7 +991,9 @@ EXPORT_SYMBOL(keyring_clear);
990 */ 991 */
991static void keyring_revoke(struct key *keyring) 992static void keyring_revoke(struct key *keyring)
992{ 993{
993 struct keyring_list *klist = keyring->payload.subscriptions; 994 struct keyring_list *klist;
995
996 klist = rcu_dereference_locked_keyring(keyring);
994 997
995 /* adjust the quota */ 998 /* adjust the quota */
996 key_payload_reserve(keyring, 0); 999 key_payload_reserve(keyring, 0);
@@ -1024,7 +1027,7 @@ void keyring_gc(struct key *keyring, time_t limit)
1024 1027
1025 down_write(&keyring->sem); 1028 down_write(&keyring->sem);
1026 1029
1027 klist = keyring->payload.subscriptions; 1030 klist = rcu_dereference_locked_keyring(keyring);
1028 if (!klist) 1031 if (!klist)
1029 goto no_klist; 1032 goto no_klist;
1030 1033