diff options
author | David Howells <dhowells@redhat.com> | 2010-04-30 09:32:18 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-05-05 09:50:12 -0400 |
commit | f0641cba7729e5e14f82d2eedc398103f5fa31b1 (patch) | |
tree | 578cc4ea4686528eb587f3df7fbd908e1819fe66 /security/keys | |
parent | cea7daa3589d6b550546a8c8963599f7c1a3ae5c (diff) |
KEYS: Use RCU dereference wrappers in keyring key type code
The keyring key type code should use RCU dereference wrappers, even when it
holds the keyring's key semaphore.
Reported-by: Vegard Nossum <vegard.nossum@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/keyring.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 0b27271c670c..1e4b0037935c 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -20,6 +20,11 @@ | |||
20 | #include <asm/uaccess.h> | 20 | #include <asm/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 |
@@ -201,8 +206,7 @@ static long keyring_read(const struct key *keyring, | |||
201 | int loop, ret; | 206 | int loop, ret; |
202 | 207 | ||
203 | ret = 0; | 208 | ret = 0; |
204 | klist = keyring->payload.subscriptions; | 209 | klist = rcu_dereference_locked_keyring(keyring); |
205 | |||
206 | if (klist) { | 210 | if (klist) { |
207 | /* calculate how much data we could return */ | 211 | /* calculate how much data we could return */ |
208 | qty = klist->nkeys * sizeof(key_serial_t); | 212 | qty = klist->nkeys * sizeof(key_serial_t); |
@@ -720,8 +724,7 @@ int __key_link(struct key *keyring, struct key *key) | |||
720 | } | 724 | } |
721 | 725 | ||
722 | /* see if there's a matching key we can displace */ | 726 | /* see if there's a matching key we can displace */ |
723 | klist = keyring->payload.subscriptions; | 727 | klist = rcu_dereference_locked_keyring(keyring); |
724 | |||
725 | if (klist && klist->nkeys > 0) { | 728 | if (klist && klist->nkeys > 0) { |
726 | struct key_type *type = key->type; | 729 | struct key_type *type = key->type; |
727 | 730 | ||
@@ -765,8 +768,6 @@ int __key_link(struct key *keyring, struct key *key) | |||
765 | if (ret < 0) | 768 | if (ret < 0) |
766 | goto error2; | 769 | goto error2; |
767 | 770 | ||
768 | klist = keyring->payload.subscriptions; | ||
769 | |||
770 | if (klist && klist->nkeys < klist->maxkeys) { | 771 | if (klist && klist->nkeys < klist->maxkeys) { |
771 | /* there's sufficient slack space to add directly */ | 772 | /* there's sufficient slack space to add directly */ |
772 | atomic_inc(&key->usage); | 773 | atomic_inc(&key->usage); |
@@ -868,7 +869,7 @@ int key_unlink(struct key *keyring, struct key *key) | |||
868 | 869 | ||
869 | down_write(&keyring->sem); | 870 | down_write(&keyring->sem); |
870 | 871 | ||
871 | klist = keyring->payload.subscriptions; | 872 | klist = rcu_dereference_locked_keyring(keyring); |
872 | if (klist) { | 873 | if (klist) { |
873 | /* search the keyring for the key */ | 874 | /* search the keyring for the key */ |
874 | for (loop = 0; loop < klist->nkeys; loop++) | 875 | for (loop = 0; loop < klist->nkeys; loop++) |
@@ -959,7 +960,7 @@ int keyring_clear(struct key *keyring) | |||
959 | /* detach the pointer block with the locks held */ | 960 | /* detach the pointer block with the locks held */ |
960 | down_write(&keyring->sem); | 961 | down_write(&keyring->sem); |
961 | 962 | ||
962 | klist = keyring->payload.subscriptions; | 963 | klist = rcu_dereference_locked_keyring(keyring); |
963 | if (klist) { | 964 | if (klist) { |
964 | /* adjust the quota */ | 965 | /* adjust the quota */ |
965 | key_payload_reserve(keyring, | 966 | key_payload_reserve(keyring, |
@@ -991,7 +992,9 @@ EXPORT_SYMBOL(keyring_clear); | |||
991 | */ | 992 | */ |
992 | static void keyring_revoke(struct key *keyring) | 993 | static void keyring_revoke(struct key *keyring) |
993 | { | 994 | { |
994 | struct keyring_list *klist = keyring->payload.subscriptions; | 995 | struct keyring_list *klist; |
996 | |||
997 | klist = rcu_dereference_locked_keyring(keyring); | ||
995 | 998 | ||
996 | /* adjust the quota */ | 999 | /* adjust the quota */ |
997 | key_payload_reserve(keyring, 0); | 1000 | key_payload_reserve(keyring, 0); |
@@ -1025,7 +1028,7 @@ void keyring_gc(struct key *keyring, time_t limit) | |||
1025 | 1028 | ||
1026 | down_write(&keyring->sem); | 1029 | down_write(&keyring->sem); |
1027 | 1030 | ||
1028 | klist = keyring->payload.subscriptions; | 1031 | klist = rcu_dereference_locked_keyring(keyring); |
1029 | if (!klist) | 1032 | if (!klist) |
1030 | goto no_klist; | 1033 | goto no_klist; |
1031 | 1034 | ||