diff options
| author | James Morris <jmorris@namei.org> | 2010-05-06 08:21:04 -0400 |
|---|---|---|
| committer | James Morris <jmorris@namei.org> | 2010-05-06 08:21:04 -0400 |
| commit | 043b4d40f53131c5f72eca2a46555fe35328a930 (patch) | |
| tree | 02a40eeb688f7ed9730e26a22f39ad7e04378de2 /security | |
| parent | 292823814261e085cdcef06b6b691e6c2563fbd4 (diff) | |
| parent | 722154e4cacf015161efe60009ae9be23d492296 (diff) | |
Merge branch 'master' into next
Conflicts:
security/keys/keyring.c
Resolved conflict with whitespace fix in find_keyring_by_name()
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
| -rw-r--r-- | security/keys/keyring.c | 41 | ||||
| -rw-r--r-- | security/keys/request_key.c | 2 |
2 files changed, 23 insertions, 20 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 | 569 | out: | |
| 566 | error: | 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 | */ |
| 991 | static void keyring_revoke(struct key *keyring) | 992 | static 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 | ||
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 1bc38587adc4..ac49c8aacbf0 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
| @@ -94,7 +94,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | /* attach the auth key to the session keyring */ | 96 | /* attach the auth key to the session keyring */ |
| 97 | ret = __key_link(keyring, authkey); | 97 | ret = key_link(keyring, authkey); |
| 98 | if (ret < 0) | 98 | if (ret < 0) |
| 99 | goto error_link; | 99 | goto error_link; |
| 100 | 100 | ||
