diff options
Diffstat (limited to 'security/keys/key.c')
-rw-r--r-- | security/keys/key.c | 94 |
1 files changed, 42 insertions, 52 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index 59402c843203..1fdfccb3fe43 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -294,7 +294,6 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
294 | } | 294 | } |
295 | 295 | ||
296 | atomic_set(&key->usage, 1); | 296 | atomic_set(&key->usage, 1); |
297 | rwlock_init(&key->lock); | ||
298 | init_rwsem(&key->sem); | 297 | init_rwsem(&key->sem); |
299 | key->type = type; | 298 | key->type = type; |
300 | key->user = user; | 299 | key->user = user; |
@@ -308,7 +307,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
308 | key->payload.data = NULL; | 307 | key->payload.data = NULL; |
309 | 308 | ||
310 | if (!not_in_quota) | 309 | if (!not_in_quota) |
311 | key->flags |= KEY_FLAG_IN_QUOTA; | 310 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; |
312 | 311 | ||
313 | memset(&key->type_data, 0, sizeof(key->type_data)); | 312 | memset(&key->type_data, 0, sizeof(key->type_data)); |
314 | 313 | ||
@@ -359,7 +358,7 @@ int key_payload_reserve(struct key *key, size_t datalen) | |||
359 | key_check(key); | 358 | key_check(key); |
360 | 359 | ||
361 | /* contemplate the quota adjustment */ | 360 | /* contemplate the quota adjustment */ |
362 | if (delta != 0 && key->flags & KEY_FLAG_IN_QUOTA) { | 361 | if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
363 | spin_lock(&key->user->lock); | 362 | spin_lock(&key->user->lock); |
364 | 363 | ||
365 | if (delta > 0 && | 364 | if (delta > 0 && |
@@ -405,23 +404,17 @@ static int __key_instantiate_and_link(struct key *key, | |||
405 | down_write(&key_construction_sem); | 404 | down_write(&key_construction_sem); |
406 | 405 | ||
407 | /* can't instantiate twice */ | 406 | /* can't instantiate twice */ |
408 | if (!(key->flags & KEY_FLAG_INSTANTIATED)) { | 407 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
409 | /* instantiate the key */ | 408 | /* instantiate the key */ |
410 | ret = key->type->instantiate(key, data, datalen); | 409 | ret = key->type->instantiate(key, data, datalen); |
411 | 410 | ||
412 | if (ret == 0) { | 411 | if (ret == 0) { |
413 | /* mark the key as being instantiated */ | 412 | /* mark the key as being instantiated */ |
414 | write_lock(&key->lock); | ||
415 | |||
416 | atomic_inc(&key->user->nikeys); | 413 | atomic_inc(&key->user->nikeys); |
417 | key->flags |= KEY_FLAG_INSTANTIATED; | 414 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); |
418 | 415 | ||
419 | if (key->flags & KEY_FLAG_USER_CONSTRUCT) { | 416 | if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) |
420 | key->flags &= ~KEY_FLAG_USER_CONSTRUCT; | ||
421 | awaken = 1; | 417 | awaken = 1; |
422 | } | ||
423 | |||
424 | write_unlock(&key->lock); | ||
425 | 418 | ||
426 | /* and link it into the destination keyring */ | 419 | /* and link it into the destination keyring */ |
427 | if (keyring) | 420 | if (keyring) |
@@ -486,21 +479,17 @@ int key_negate_and_link(struct key *key, | |||
486 | down_write(&key_construction_sem); | 479 | down_write(&key_construction_sem); |
487 | 480 | ||
488 | /* can't instantiate twice */ | 481 | /* can't instantiate twice */ |
489 | if (!(key->flags & KEY_FLAG_INSTANTIATED)) { | 482 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
490 | /* mark the key as being negatively instantiated */ | 483 | /* mark the key as being negatively instantiated */ |
491 | write_lock(&key->lock); | ||
492 | |||
493 | atomic_inc(&key->user->nikeys); | 484 | atomic_inc(&key->user->nikeys); |
494 | key->flags |= KEY_FLAG_INSTANTIATED | KEY_FLAG_NEGATIVE; | 485 | set_bit(KEY_FLAG_NEGATIVE, &key->flags); |
486 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); | ||
495 | now = current_kernel_time(); | 487 | now = current_kernel_time(); |
496 | key->expiry = now.tv_sec + timeout; | 488 | key->expiry = now.tv_sec + timeout; |
497 | 489 | ||
498 | if (key->flags & KEY_FLAG_USER_CONSTRUCT) { | 490 | if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) |
499 | key->flags &= ~KEY_FLAG_USER_CONSTRUCT; | ||
500 | awaken = 1; | 491 | awaken = 1; |
501 | } | ||
502 | 492 | ||
503 | write_unlock(&key->lock); | ||
504 | ret = 0; | 493 | ret = 0; |
505 | 494 | ||
506 | /* and link it into the destination keyring */ | 495 | /* and link it into the destination keyring */ |
@@ -553,8 +542,10 @@ static void key_cleanup(void *data) | |||
553 | rb_erase(&key->serial_node, &key_serial_tree); | 542 | rb_erase(&key->serial_node, &key_serial_tree); |
554 | spin_unlock(&key_serial_lock); | 543 | spin_unlock(&key_serial_lock); |
555 | 544 | ||
545 | key_check(key); | ||
546 | |||
556 | /* deal with the user's key tracking and quota */ | 547 | /* deal with the user's key tracking and quota */ |
557 | if (key->flags & KEY_FLAG_IN_QUOTA) { | 548 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
558 | spin_lock(&key->user->lock); | 549 | spin_lock(&key->user->lock); |
559 | key->user->qnkeys--; | 550 | key->user->qnkeys--; |
560 | key->user->qnbytes -= key->quotalen; | 551 | key->user->qnbytes -= key->quotalen; |
@@ -562,7 +553,7 @@ static void key_cleanup(void *data) | |||
562 | } | 553 | } |
563 | 554 | ||
564 | atomic_dec(&key->user->nkeys); | 555 | atomic_dec(&key->user->nkeys); |
565 | if (key->flags & KEY_FLAG_INSTANTIATED) | 556 | if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) |
566 | atomic_dec(&key->user->nikeys); | 557 | atomic_dec(&key->user->nikeys); |
567 | 558 | ||
568 | key_user_put(key->user); | 559 | key_user_put(key->user); |
@@ -631,9 +622,9 @@ struct key *key_lookup(key_serial_t id) | |||
631 | goto error; | 622 | goto error; |
632 | 623 | ||
633 | found: | 624 | found: |
634 | /* pretent doesn't exist if it's dead */ | 625 | /* pretend it doesn't exist if it's dead */ |
635 | if (atomic_read(&key->usage) == 0 || | 626 | if (atomic_read(&key->usage) == 0 || |
636 | (key->flags & KEY_FLAG_DEAD) || | 627 | test_bit(KEY_FLAG_DEAD, &key->flags) || |
637 | key->type == &key_type_dead) | 628 | key->type == &key_type_dead) |
638 | goto not_found; | 629 | goto not_found; |
639 | 630 | ||
@@ -708,12 +699,9 @@ static inline struct key *__key_update(struct key *key, const void *payload, | |||
708 | 699 | ||
709 | ret = key->type->update(key, payload, plen); | 700 | ret = key->type->update(key, payload, plen); |
710 | 701 | ||
711 | if (ret == 0) { | 702 | if (ret == 0) |
712 | /* updating a negative key instantiates it */ | 703 | /* updating a negative key instantiates it */ |
713 | write_lock(&key->lock); | 704 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |
714 | key->flags &= ~KEY_FLAG_NEGATIVE; | ||
715 | write_unlock(&key->lock); | ||
716 | } | ||
717 | 705 | ||
718 | up_write(&key->sem); | 706 | up_write(&key->sem); |
719 | 707 | ||
@@ -841,12 +829,9 @@ int key_update(struct key *key, const void *payload, size_t plen) | |||
841 | down_write(&key->sem); | 829 | down_write(&key->sem); |
842 | ret = key->type->update(key, payload, plen); | 830 | ret = key->type->update(key, payload, plen); |
843 | 831 | ||
844 | if (ret == 0) { | 832 | if (ret == 0) |
845 | /* updating a negative key instantiates it */ | 833 | /* updating a negative key instantiates it */ |
846 | write_lock(&key->lock); | 834 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |
847 | key->flags &= ~KEY_FLAG_NEGATIVE; | ||
848 | write_unlock(&key->lock); | ||
849 | } | ||
850 | 835 | ||
851 | up_write(&key->sem); | 836 | up_write(&key->sem); |
852 | } | 837 | } |
@@ -892,10 +877,7 @@ struct key *key_duplicate(struct key *source, const char *desc) | |||
892 | goto error2; | 877 | goto error2; |
893 | 878 | ||
894 | atomic_inc(&key->user->nikeys); | 879 | atomic_inc(&key->user->nikeys); |
895 | 880 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); | |
896 | write_lock(&key->lock); | ||
897 | key->flags |= KEY_FLAG_INSTANTIATED; | ||
898 | write_unlock(&key->lock); | ||
899 | 881 | ||
900 | error_k: | 882 | error_k: |
901 | up_read(&key_types_sem); | 883 | up_read(&key_types_sem); |
@@ -922,9 +904,7 @@ void key_revoke(struct key *key) | |||
922 | /* make sure no one's trying to change or use the key when we mark | 904 | /* make sure no one's trying to change or use the key when we mark |
923 | * it */ | 905 | * it */ |
924 | down_write(&key->sem); | 906 | down_write(&key->sem); |
925 | write_lock(&key->lock); | 907 | set_bit(KEY_FLAG_REVOKED, &key->flags); |
926 | key->flags |= KEY_FLAG_REVOKED; | ||
927 | write_unlock(&key->lock); | ||
928 | up_write(&key->sem); | 908 | up_write(&key->sem); |
929 | 909 | ||
930 | } /* end key_revoke() */ | 910 | } /* end key_revoke() */ |
@@ -975,24 +955,33 @@ void unregister_key_type(struct key_type *ktype) | |||
975 | /* withdraw the key type */ | 955 | /* withdraw the key type */ |
976 | list_del_init(&ktype->link); | 956 | list_del_init(&ktype->link); |
977 | 957 | ||
978 | /* need to withdraw all keys of this type */ | 958 | /* mark all the keys of this type dead */ |
979 | spin_lock(&key_serial_lock); | 959 | spin_lock(&key_serial_lock); |
980 | 960 | ||
981 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { | 961 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { |
982 | key = rb_entry(_n, struct key, serial_node); | 962 | key = rb_entry(_n, struct key, serial_node); |
983 | 963 | ||
984 | if (key->type != ktype) | 964 | if (key->type == ktype) |
985 | continue; | 965 | key->type = &key_type_dead; |
966 | } | ||
967 | |||
968 | spin_unlock(&key_serial_lock); | ||
969 | |||
970 | /* make sure everyone revalidates their keys */ | ||
971 | synchronize_kernel(); | ||
972 | |||
973 | /* we should now be able to destroy the payloads of all the keys of | ||
974 | * this type with impunity */ | ||
975 | spin_lock(&key_serial_lock); | ||
986 | 976 | ||
987 | write_lock(&key->lock); | 977 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { |
988 | key->type = &key_type_dead; | 978 | key = rb_entry(_n, struct key, serial_node); |
989 | write_unlock(&key->lock); | ||
990 | 979 | ||
991 | /* there shouldn't be anyone looking at the description or | 980 | if (key->type == ktype) { |
992 | * payload now */ | 981 | if (ktype->destroy) |
993 | if (ktype->destroy) | 982 | ktype->destroy(key); |
994 | ktype->destroy(key); | 983 | memset(&key->payload, 0xbd, sizeof(key->payload)); |
995 | memset(&key->payload, 0xbd, sizeof(key->payload)); | 984 | } |
996 | } | 985 | } |
997 | 986 | ||
998 | spin_unlock(&key_serial_lock); | 987 | spin_unlock(&key_serial_lock); |
@@ -1037,4 +1026,5 @@ void __init key_init(void) | |||
1037 | 1026 | ||
1038 | /* link the two root keyrings together */ | 1027 | /* link the two root keyrings together */ |
1039 | key_link(&root_session_keyring, &root_user_keyring); | 1028 | key_link(&root_session_keyring, &root_user_keyring); |
1029 | |||
1040 | } /* end key_init() */ | 1030 | } /* end key_init() */ |