.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* Basic authentication token and access key management |
---|
2 | 3 | * |
---|
3 | 4 | * Copyright (C) 2004-2008 Red Hat, Inc. All Rights Reserved. |
---|
4 | 5 | * Written by David Howells (dhowells@redhat.com) |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or |
---|
7 | | - * modify it under the terms of the GNU General Public License |
---|
8 | | - * as published by the Free Software Foundation; either version |
---|
9 | | - * 2 of the License, or (at your option) any later version. |
---|
10 | 6 | */ |
---|
11 | 7 | |
---|
12 | | -#include <linux/module.h> |
---|
| 8 | +#include <linux/export.h> |
---|
13 | 9 | #include <linux/init.h> |
---|
14 | 10 | #include <linux/poison.h> |
---|
15 | 11 | #include <linux/sched.h> |
---|
.. | .. |
---|
17 | 13 | #include <linux/security.h> |
---|
18 | 14 | #include <linux/workqueue.h> |
---|
19 | 15 | #include <linux/random.h> |
---|
| 16 | +#include <linux/ima.h> |
---|
20 | 17 | #include <linux/err.h> |
---|
21 | 18 | #include "internal.h" |
---|
22 | 19 | |
---|
.. | .. |
---|
285 | 282 | key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL); |
---|
286 | 283 | if (!key->index_key.description) |
---|
287 | 284 | goto no_memory_3; |
---|
| 285 | + key->index_key.type = type; |
---|
| 286 | + key_set_index_key(&key->index_key); |
---|
288 | 287 | |
---|
289 | 288 | refcount_set(&key->usage, 1); |
---|
290 | 289 | init_rwsem(&key->sem); |
---|
291 | 290 | lockdep_set_class(&key->sem, &type->lock_class); |
---|
292 | | - key->index_key.type = type; |
---|
293 | 291 | key->user = user; |
---|
294 | 292 | key->quotalen = quotalen; |
---|
295 | 293 | key->datalen = type->def_datalen; |
---|
.. | .. |
---|
318 | 316 | goto security_error; |
---|
319 | 317 | |
---|
320 | 318 | /* publish the key by giving it a serial number */ |
---|
| 319 | + refcount_inc(&key->domain_tag->usage); |
---|
321 | 320 | atomic_inc(&user->nkeys); |
---|
322 | 321 | key_alloc_serial(key); |
---|
323 | 322 | |
---|
.. | .. |
---|
447 | 446 | /* mark the key as being instantiated */ |
---|
448 | 447 | atomic_inc(&key->user->nikeys); |
---|
449 | 448 | mark_key_instantiated(key, 0); |
---|
| 449 | + notify_key(key, NOTIFY_KEY_INSTANTIATED, 0); |
---|
450 | 450 | |
---|
451 | 451 | if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) |
---|
452 | 452 | awaken = 1; |
---|
.. | .. |
---|
456 | 456 | if (test_bit(KEY_FLAG_KEEP, &keyring->flags)) |
---|
457 | 457 | set_bit(KEY_FLAG_KEEP, &key->flags); |
---|
458 | 458 | |
---|
459 | | - __key_link(key, _edit); |
---|
| 459 | + __key_link(keyring, key, _edit); |
---|
460 | 460 | } |
---|
461 | 461 | |
---|
462 | 462 | /* disable the authorisation key */ |
---|
463 | 463 | if (authkey) |
---|
464 | | - key_revoke(authkey); |
---|
| 464 | + key_invalidate(authkey); |
---|
465 | 465 | |
---|
466 | 466 | if (prep->expiry != TIME64_MAX) { |
---|
467 | 467 | key->expiry = prep->expiry; |
---|
.. | .. |
---|
502 | 502 | struct key *authkey) |
---|
503 | 503 | { |
---|
504 | 504 | struct key_preparsed_payload prep; |
---|
505 | | - struct assoc_array_edit *edit; |
---|
| 505 | + struct assoc_array_edit *edit = NULL; |
---|
506 | 506 | int ret; |
---|
507 | 507 | |
---|
508 | 508 | memset(&prep, 0, sizeof(prep)); |
---|
.. | .. |
---|
517 | 517 | } |
---|
518 | 518 | |
---|
519 | 519 | if (keyring) { |
---|
520 | | - ret = __key_link_begin(keyring, &key->index_key, &edit); |
---|
| 520 | + ret = __key_link_lock(keyring, &key->index_key); |
---|
521 | 521 | if (ret < 0) |
---|
522 | 522 | goto error; |
---|
| 523 | + |
---|
| 524 | + ret = __key_link_begin(keyring, &key->index_key, &edit); |
---|
| 525 | + if (ret < 0) |
---|
| 526 | + goto error_link_end; |
---|
523 | 527 | |
---|
524 | 528 | if (keyring->restrict_link && keyring->restrict_link->check) { |
---|
525 | 529 | struct key_restriction *keyres = keyring->restrict_link; |
---|
.. | .. |
---|
572 | 576 | struct key *keyring, |
---|
573 | 577 | struct key *authkey) |
---|
574 | 578 | { |
---|
575 | | - struct assoc_array_edit *edit; |
---|
| 579 | + struct assoc_array_edit *edit = NULL; |
---|
576 | 580 | int ret, awaken, link_ret = 0; |
---|
577 | 581 | |
---|
578 | 582 | key_check(key); |
---|
.. | .. |
---|
585 | 589 | if (keyring->restrict_link) |
---|
586 | 590 | return -EPERM; |
---|
587 | 591 | |
---|
588 | | - link_ret = __key_link_begin(keyring, &key->index_key, &edit); |
---|
| 592 | + link_ret = __key_link_lock(keyring, &key->index_key); |
---|
| 593 | + if (link_ret == 0) { |
---|
| 594 | + link_ret = __key_link_begin(keyring, &key->index_key, &edit); |
---|
| 595 | + if (link_ret < 0) |
---|
| 596 | + __key_link_end(keyring, &key->index_key, edit); |
---|
| 597 | + } |
---|
589 | 598 | } |
---|
590 | 599 | |
---|
591 | 600 | mutex_lock(&key_construction_mutex); |
---|
.. | .. |
---|
595 | 604 | /* mark the key as being negatively instantiated */ |
---|
596 | 605 | atomic_inc(&key->user->nikeys); |
---|
597 | 606 | mark_key_instantiated(key, -error); |
---|
| 607 | + notify_key(key, NOTIFY_KEY_INSTANTIATED, -error); |
---|
598 | 608 | key->expiry = ktime_get_real_seconds() + timeout; |
---|
599 | 609 | key_schedule_gc(key->expiry + key_gc_delay); |
---|
600 | 610 | |
---|
.. | .. |
---|
605 | 615 | |
---|
606 | 616 | /* and link it into the destination keyring */ |
---|
607 | 617 | if (keyring && link_ret == 0) |
---|
608 | | - __key_link(key, &edit); |
---|
| 618 | + __key_link(keyring, key, &edit); |
---|
609 | 619 | |
---|
610 | 620 | /* disable the authorisation key */ |
---|
611 | 621 | if (authkey) |
---|
612 | | - key_revoke(authkey); |
---|
| 622 | + key_invalidate(authkey); |
---|
613 | 623 | } |
---|
614 | 624 | |
---|
615 | 625 | mutex_unlock(&key_construction_mutex); |
---|
.. | .. |
---|
758 | 768 | down_write(&key->sem); |
---|
759 | 769 | |
---|
760 | 770 | ret = key->type->update(key, prep); |
---|
761 | | - if (ret == 0) |
---|
| 771 | + if (ret == 0) { |
---|
762 | 772 | /* Updating a negative key positively instantiates it */ |
---|
763 | 773 | mark_key_instantiated(key, 0); |
---|
| 774 | + notify_key(key, NOTIFY_KEY_UPDATED, 0); |
---|
| 775 | + } |
---|
764 | 776 | |
---|
765 | 777 | up_write(&key->sem); |
---|
766 | 778 | |
---|
.. | .. |
---|
812 | 824 | .description = description, |
---|
813 | 825 | }; |
---|
814 | 826 | struct key_preparsed_payload prep; |
---|
815 | | - struct assoc_array_edit *edit; |
---|
| 827 | + struct assoc_array_edit *edit = NULL; |
---|
816 | 828 | const struct cred *cred = current_cred(); |
---|
817 | 829 | struct key *keyring, *key = NULL; |
---|
818 | 830 | key_ref_t key_ref; |
---|
.. | .. |
---|
861 | 873 | goto error_free_prep; |
---|
862 | 874 | } |
---|
863 | 875 | index_key.desc_len = strlen(index_key.description); |
---|
| 876 | + key_set_index_key(&index_key); |
---|
| 877 | + |
---|
| 878 | + ret = __key_link_lock(keyring, &index_key); |
---|
| 879 | + if (ret < 0) { |
---|
| 880 | + key_ref = ERR_PTR(ret); |
---|
| 881 | + goto error_free_prep; |
---|
| 882 | + } |
---|
864 | 883 | |
---|
865 | 884 | ret = __key_link_begin(keyring, &index_key, &edit); |
---|
866 | 885 | if (ret < 0) { |
---|
867 | 886 | key_ref = ERR_PTR(ret); |
---|
868 | | - goto error_free_prep; |
---|
| 887 | + goto error_link_end; |
---|
869 | 888 | } |
---|
870 | 889 | |
---|
871 | 890 | if (restrict_link && restrict_link->check) { |
---|
.. | .. |
---|
924 | 943 | goto error_link_end; |
---|
925 | 944 | } |
---|
926 | 945 | |
---|
| 946 | + ima_post_key_create_or_update(keyring, key, payload, plen, |
---|
| 947 | + flags, true); |
---|
| 948 | + |
---|
927 | 949 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); |
---|
928 | 950 | |
---|
929 | 951 | error_link_end: |
---|
.. | .. |
---|
953 | 975 | } |
---|
954 | 976 | |
---|
955 | 977 | key_ref = __key_update(key_ref, &prep); |
---|
| 978 | + |
---|
| 979 | + if (!IS_ERR(key_ref)) |
---|
| 980 | + ima_post_key_create_or_update(keyring, key, |
---|
| 981 | + payload, plen, |
---|
| 982 | + flags, false); |
---|
| 983 | + |
---|
956 | 984 | goto error_free_prep; |
---|
957 | 985 | } |
---|
958 | 986 | EXPORT_SYMBOL(key_create_or_update); |
---|
.. | .. |
---|
1001 | 1029 | down_write(&key->sem); |
---|
1002 | 1030 | |
---|
1003 | 1031 | ret = key->type->update(key, &prep); |
---|
1004 | | - if (ret == 0) |
---|
| 1032 | + if (ret == 0) { |
---|
1005 | 1033 | /* Updating a negative key positively instantiates it */ |
---|
1006 | 1034 | mark_key_instantiated(key, 0); |
---|
| 1035 | + notify_key(key, NOTIFY_KEY_UPDATED, 0); |
---|
| 1036 | + } |
---|
1007 | 1037 | |
---|
1008 | 1038 | up_write(&key->sem); |
---|
1009 | 1039 | |
---|
.. | .. |
---|
1035 | 1065 | * instantiated |
---|
1036 | 1066 | */ |
---|
1037 | 1067 | down_write_nested(&key->sem, 1); |
---|
1038 | | - if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags) && |
---|
1039 | | - key->type->revoke) |
---|
1040 | | - key->type->revoke(key); |
---|
| 1068 | + if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags)) { |
---|
| 1069 | + notify_key(key, NOTIFY_KEY_REVOKED, 0); |
---|
| 1070 | + if (key->type->revoke) |
---|
| 1071 | + key->type->revoke(key); |
---|
1041 | 1072 | |
---|
1042 | | - /* set the death time to no more than the expiry time */ |
---|
1043 | | - time = ktime_get_real_seconds(); |
---|
1044 | | - if (key->revoked_at == 0 || key->revoked_at > time) { |
---|
1045 | | - key->revoked_at = time; |
---|
1046 | | - key_schedule_gc(key->revoked_at + key_gc_delay); |
---|
| 1073 | + /* set the death time to no more than the expiry time */ |
---|
| 1074 | + time = ktime_get_real_seconds(); |
---|
| 1075 | + if (key->revoked_at == 0 || key->revoked_at > time) { |
---|
| 1076 | + key->revoked_at = time; |
---|
| 1077 | + key_schedule_gc(key->revoked_at + key_gc_delay); |
---|
| 1078 | + } |
---|
1047 | 1079 | } |
---|
1048 | 1080 | |
---|
1049 | 1081 | up_write(&key->sem); |
---|
.. | .. |
---|
1065 | 1097 | |
---|
1066 | 1098 | if (!test_bit(KEY_FLAG_INVALIDATED, &key->flags)) { |
---|
1067 | 1099 | down_write_nested(&key->sem, 1); |
---|
1068 | | - if (!test_and_set_bit(KEY_FLAG_INVALIDATED, &key->flags)) |
---|
| 1100 | + if (!test_and_set_bit(KEY_FLAG_INVALIDATED, &key->flags)) { |
---|
| 1101 | + notify_key(key, NOTIFY_KEY_INVALIDATED, 0); |
---|
1069 | 1102 | key_schedule_gc_links(); |
---|
| 1103 | + } |
---|
1070 | 1104 | up_write(&key->sem); |
---|
1071 | 1105 | } |
---|
1072 | 1106 | } |
---|