aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/gc.c2
-rw-r--r--security/keys/keyring.c95
2 files changed, 57 insertions, 40 deletions
diff --git a/security/keys/gc.c b/security/keys/gc.c
index 27610bf72195..adddaa258d50 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -148,7 +148,7 @@ static void key_gc_keyring(struct key *keyring, time_t limit)
148 loop = klist->nkeys; 148 loop = klist->nkeys;
149 smp_rmb(); 149 smp_rmb();
150 for (loop--; loop >= 0; loop--) { 150 for (loop--; loop >= 0; loop--) {
151 key = klist->keys[loop]; 151 key = rcu_dereference(klist->keys[loop]);
152 if (test_bit(KEY_FLAG_DEAD, &key->flags) || 152 if (test_bit(KEY_FLAG_DEAD, &key->flags) ||
153 (key->expiry > 0 && key->expiry <= limit)) 153 (key->expiry > 0 && key->expiry <= limit))
154 goto do_gc; 154 goto do_gc;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index d605f75292e4..459b3cc347f2 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -25,6 +25,11 @@
25 (keyring)->payload.subscriptions, \ 25 (keyring)->payload.subscriptions, \
26 rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem))) 26 rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem)))
27 27
28#define rcu_deref_link_locked(klist, index, keyring) \
29 (rcu_dereference_protected( \
30 (klist)->keys[index], \
31 rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem)))
32
28#define KEY_LINK_FIXQUOTA 1UL 33#define KEY_LINK_FIXQUOTA 1UL
29 34
30/* 35/*
@@ -138,6 +143,11 @@ static int keyring_match(const struct key *keyring, const void *description)
138/* 143/*
139 * Clean up a keyring when it is destroyed. Unpublish its name if it had one 144 * Clean up a keyring when it is destroyed. Unpublish its name if it had one
140 * and dispose of its data. 145 * and dispose of its data.
146 *
147 * The garbage collector detects the final key_put(), removes the keyring from
148 * the serial number tree and then does RCU synchronisation before coming here,
149 * so we shouldn't need to worry about code poking around here with the RCU
150 * readlock held by this time.
141 */ 151 */
142static void keyring_destroy(struct key *keyring) 152static void keyring_destroy(struct key *keyring)
143{ 153{
@@ -154,11 +164,10 @@ static void keyring_destroy(struct key *keyring)
154 write_unlock(&keyring_name_lock); 164 write_unlock(&keyring_name_lock);
155 } 165 }
156 166
157 klist = rcu_dereference_check(keyring->payload.subscriptions, 167 klist = rcu_access_pointer(keyring->payload.subscriptions);
158 atomic_read(&keyring->usage) == 0);
159 if (klist) { 168 if (klist) {
160 for (loop = klist->nkeys - 1; loop >= 0; loop--) 169 for (loop = klist->nkeys - 1; loop >= 0; loop--)
161 key_put(klist->keys[loop]); 170 key_put(rcu_access_pointer(klist->keys[loop]));
162 kfree(klist); 171 kfree(klist);
163 } 172 }
164} 173}
@@ -214,7 +223,8 @@ static long keyring_read(const struct key *keyring,
214 ret = -EFAULT; 223 ret = -EFAULT;
215 224
216 for (loop = 0; loop < klist->nkeys; loop++) { 225 for (loop = 0; loop < klist->nkeys; loop++) {
217 key = klist->keys[loop]; 226 key = rcu_deref_link_locked(klist, loop,
227 keyring);
218 228
219 tmp = sizeof(key_serial_t); 229 tmp = sizeof(key_serial_t);
220 if (tmp > buflen) 230 if (tmp > buflen)
@@ -383,7 +393,7 @@ descend:
383 nkeys = keylist->nkeys; 393 nkeys = keylist->nkeys;
384 smp_rmb(); 394 smp_rmb();
385 for (kix = 0; kix < nkeys; kix++) { 395 for (kix = 0; kix < nkeys; kix++) {
386 key = keylist->keys[kix]; 396 key = rcu_dereference(keylist->keys[kix]);
387 kflags = key->flags; 397 kflags = key->flags;
388 398
389 /* ignore keys not of this type */ 399 /* ignore keys not of this type */
@@ -426,7 +436,7 @@ ascend:
426 nkeys = keylist->nkeys; 436 nkeys = keylist->nkeys;
427 smp_rmb(); 437 smp_rmb();
428 for (; kix < nkeys; kix++) { 438 for (; kix < nkeys; kix++) {
429 key = keylist->keys[kix]; 439 key = rcu_dereference(keylist->keys[kix]);
430 if (key->type != &key_type_keyring) 440 if (key->type != &key_type_keyring)
431 continue; 441 continue;
432 442
@@ -531,8 +541,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
531 nkeys = klist->nkeys; 541 nkeys = klist->nkeys;
532 smp_rmb(); 542 smp_rmb();
533 for (loop = 0; loop < nkeys ; loop++) { 543 for (loop = 0; loop < nkeys ; loop++) {
534 key = klist->keys[loop]; 544 key = rcu_dereference(klist->keys[loop]);
535
536 if (key->type == ktype && 545 if (key->type == ktype &&
537 (!key->type->match || 546 (!key->type->match ||
538 key->type->match(key, description)) && 547 key->type->match(key, description)) &&
@@ -654,7 +663,7 @@ ascend:
654 nkeys = keylist->nkeys; 663 nkeys = keylist->nkeys;
655 smp_rmb(); 664 smp_rmb();
656 for (; kix < nkeys; kix++) { 665 for (; kix < nkeys; kix++) {
657 key = keylist->keys[kix]; 666 key = rcu_dereference(keylist->keys[kix]);
658 667
659 if (key == A) 668 if (key == A)
660 goto cycle_detected; 669 goto cycle_detected;
@@ -711,7 +720,7 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
711 container_of(rcu, struct keyring_list, rcu); 720 container_of(rcu, struct keyring_list, rcu);
712 721
713 if (klist->delkey != USHRT_MAX) 722 if (klist->delkey != USHRT_MAX)
714 key_put(klist->keys[klist->delkey]); 723 key_put(rcu_access_pointer(klist->keys[klist->delkey]));
715 kfree(klist); 724 kfree(klist);
716} 725}
717 726
@@ -749,24 +758,16 @@ int __key_link_begin(struct key *keyring, const struct key_type *type,
749 /* see if there's a matching key we can displace */ 758 /* see if there's a matching key we can displace */
750 if (klist && klist->nkeys > 0) { 759 if (klist && klist->nkeys > 0) {
751 for (loop = klist->nkeys - 1; loop >= 0; loop--) { 760 for (loop = klist->nkeys - 1; loop >= 0; loop--) {
752 if (klist->keys[loop]->type == type && 761 struct key *key = rcu_deref_link_locked(klist, loop,
753 strcmp(klist->keys[loop]->description, 762 keyring);
754 description) == 0 763 if (key->type == type &&
755 ) { 764 strcmp(key->description, description) == 0) {
756 /* found a match - we'll replace this one with 765 /* Found a match - we'll replace the link with
757 * the new key */ 766 * one to the new key. We record the slot
758 size = sizeof(struct key *) * klist->maxkeys; 767 * position.
759 size += sizeof(*klist); 768 */
760 BUG_ON(size > PAGE_SIZE); 769 klist->delkey = loop;
761 770 prealloc = 0;
762 ret = -ENOMEM;
763 nklist = kmemdup(klist, size, GFP_KERNEL);
764 if (!nklist)
765 goto error_sem;
766
767 /* note replacement slot */
768 klist->delkey = nklist->delkey = loop;
769 prealloc = (unsigned long)nklist;
770 goto done; 771 goto done;
771 } 772 }
772 } 773 }
@@ -780,7 +781,7 @@ int __key_link_begin(struct key *keyring, const struct key_type *type,
780 781
781 if (klist && klist->nkeys < klist->maxkeys) { 782 if (klist && klist->nkeys < klist->maxkeys) {
782 /* there's sufficient slack space to append directly */ 783 /* there's sufficient slack space to append directly */
783 nklist = NULL; 784 klist->delkey = klist->nkeys;
784 prealloc = KEY_LINK_FIXQUOTA; 785 prealloc = KEY_LINK_FIXQUOTA;
785 } else { 786 } else {
786 /* grow the key list */ 787 /* grow the key list */
@@ -813,10 +814,10 @@ int __key_link_begin(struct key *keyring, const struct key_type *type,
813 } 814 }
814 815
815 /* add the key into the new space */ 816 /* add the key into the new space */
816 nklist->keys[nklist->delkey] = NULL; 817 RCU_INIT_POINTER(nklist->keys[nklist->delkey], NULL);
818 prealloc = (unsigned long)nklist | KEY_LINK_FIXQUOTA;
817 } 819 }
818 820
819 prealloc = (unsigned long)nklist | KEY_LINK_FIXQUOTA;
820done: 821done:
821 *_prealloc = prealloc; 822 *_prealloc = prealloc;
822 kleave(" = 0"); 823 kleave(" = 0");
@@ -862,6 +863,7 @@ void __key_link(struct key *keyring, struct key *key,
862 unsigned long *_prealloc) 863 unsigned long *_prealloc)
863{ 864{
864 struct keyring_list *klist, *nklist; 865 struct keyring_list *klist, *nklist;
866 struct key *discard;
865 867
866 nklist = (struct keyring_list *)(*_prealloc & ~KEY_LINK_FIXQUOTA); 868 nklist = (struct keyring_list *)(*_prealloc & ~KEY_LINK_FIXQUOTA);
867 *_prealloc = 0; 869 *_prealloc = 0;
@@ -875,10 +877,10 @@ void __key_link(struct key *keyring, struct key *key,
875 /* there's a matching key we can displace or an empty slot in a newly 877 /* there's a matching key we can displace or an empty slot in a newly
876 * allocated list we can fill */ 878 * allocated list we can fill */
877 if (nklist) { 879 if (nklist) {
878 kdebug("replace %hu/%hu/%hu", 880 kdebug("reissue %hu/%hu/%hu",
879 nklist->delkey, nklist->nkeys, nklist->maxkeys); 881 nklist->delkey, nklist->nkeys, nklist->maxkeys);
880 882
881 nklist->keys[nklist->delkey] = key; 883 RCU_INIT_POINTER(nklist->keys[nklist->delkey], key);
882 884
883 rcu_assign_pointer(keyring->payload.subscriptions, nklist); 885 rcu_assign_pointer(keyring->payload.subscriptions, nklist);
884 886
@@ -889,9 +891,23 @@ void __key_link(struct key *keyring, struct key *key,
889 klist->delkey, klist->nkeys, klist->maxkeys); 891 klist->delkey, klist->nkeys, klist->maxkeys);
890 call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); 892 call_rcu(&klist->rcu, keyring_unlink_rcu_disposal);
891 } 893 }
894 } else if (klist->delkey < klist->nkeys) {
895 kdebug("replace %hu/%hu/%hu",
896 klist->delkey, klist->nkeys, klist->maxkeys);
897
898 discard = rcu_dereference_protected(
899 klist->keys[klist->delkey],
900 rwsem_is_locked(&keyring->sem));
901 rcu_assign_pointer(klist->keys[klist->delkey], key);
902 /* The garbage collector will take care of RCU
903 * synchronisation */
904 key_put(discard);
892 } else { 905 } else {
893 /* there's sufficient slack space to append directly */ 906 /* there's sufficient slack space to append directly */
894 klist->keys[klist->nkeys] = key; 907 kdebug("append %hu/%hu/%hu",
908 klist->delkey, klist->nkeys, klist->maxkeys);
909
910 RCU_INIT_POINTER(klist->keys[klist->delkey], key);
895 smp_wmb(); 911 smp_wmb();
896 klist->nkeys++; 912 klist->nkeys++;
897 } 913 }
@@ -998,7 +1014,7 @@ int key_unlink(struct key *keyring, struct key *key)
998 if (klist) { 1014 if (klist) {
999 /* search the keyring for the key */ 1015 /* search the keyring for the key */
1000 for (loop = 0; loop < klist->nkeys; loop++) 1016 for (loop = 0; loop < klist->nkeys; loop++)
1001 if (klist->keys[loop] == key) 1017 if (rcu_access_pointer(klist->keys[loop]) == key)
1002 goto key_is_present; 1018 goto key_is_present;
1003 } 1019 }
1004 1020
@@ -1061,7 +1077,7 @@ static void keyring_clear_rcu_disposal(struct rcu_head *rcu)
1061 klist = container_of(rcu, struct keyring_list, rcu); 1077 klist = container_of(rcu, struct keyring_list, rcu);
1062 1078
1063 for (loop = klist->nkeys - 1; loop >= 0; loop--) 1079 for (loop = klist->nkeys - 1; loop >= 0; loop--)
1064 key_put(klist->keys[loop]); 1080 key_put(rcu_access_pointer(klist->keys[loop]));
1065 1081
1066 kfree(klist); 1082 kfree(klist);
1067} 1083}
@@ -1161,7 +1177,8 @@ void keyring_gc(struct key *keyring, time_t limit)
1161 /* work out how many subscriptions we're keeping */ 1177 /* work out how many subscriptions we're keeping */
1162 keep = 0; 1178 keep = 0;
1163 for (loop = klist->nkeys - 1; loop >= 0; loop--) 1179 for (loop = klist->nkeys - 1; loop >= 0; loop--)
1164 if (!key_is_dead(klist->keys[loop], limit)) 1180 if (!key_is_dead(rcu_deref_link_locked(klist, loop, keyring),
1181 limit))
1165 keep++; 1182 keep++;
1166 1183
1167 if (keep == klist->nkeys) 1184 if (keep == klist->nkeys)
@@ -1182,11 +1199,11 @@ void keyring_gc(struct key *keyring, time_t limit)
1182 */ 1199 */
1183 keep = 0; 1200 keep = 0;
1184 for (loop = klist->nkeys - 1; loop >= 0; loop--) { 1201 for (loop = klist->nkeys - 1; loop >= 0; loop--) {
1185 key = klist->keys[loop]; 1202 key = rcu_deref_link_locked(klist, loop, keyring);
1186 if (!key_is_dead(key, limit)) { 1203 if (!key_is_dead(key, limit)) {
1187 if (keep >= max) 1204 if (keep >= max)
1188 goto discard_new; 1205 goto discard_new;
1189 new->keys[keep++] = key_get(key); 1206 RCU_INIT_POINTER(new->keys[keep++], key_get(key));
1190 } 1207 }
1191 } 1208 }
1192 new->nkeys = keep; 1209 new->nkeys = keep;