Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

watch_queue: Add a key/keyring notification facility

Add a key/keyring change notification facility whereby notifications about
changes in key and keyring content and attributes can be received.

Firstly, an event queue needs to be created:

pipe2(fds, O_NOTIFICATION_PIPE);
ioctl(fds[1], IOC_WATCH_QUEUE_SET_SIZE, 256);

then a notification can be set up to report notifications via that queue:

struct watch_notification_filter filter = {
.nr_filters = 1,
.filters = {
[0] = {
.type = WATCH_TYPE_KEY_NOTIFY,
.subtype_filter[0] = UINT_MAX,
},
},
};
ioctl(fds[1], IOC_WATCH_QUEUE_SET_FILTER, &filter);
keyctl_watch_key(KEY_SPEC_SESSION_KEYRING, fds[1], 0x01);

After that, records will be placed into the queue when events occur in
which keys are changed in some way. Records are of the following format:

struct key_notification {
struct watch_notification watch;
__u32 key_id;
__u32 aux;
} *n;

Where:

n->watch.type will be WATCH_TYPE_KEY_NOTIFY.

n->watch.subtype will indicate the type of event, such as
NOTIFY_KEY_REVOKED.

n->watch.info & WATCH_INFO_LENGTH will indicate the length of the
record.

n->watch.info & WATCH_INFO_ID will be the second argument to
keyctl_watch_key(), shifted.

n->key will be the ID of the affected key.

n->aux will hold subtype-dependent information, such as the key
being linked into the keyring specified by n->key in the case of
NOTIFY_KEY_LINKED.

Note that it is permissible for event records to be of variable length -
or, at least, the length may be dependent on the subtype. Note also that
the queue can be shared between multiple notifications of various types.

Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: James Morris <jamorris@linux.microsoft.com>

+269 -27
+57
Documentation/security/keys/core.rst
··· 1026 1026 written into the output buffer. Verification returns 0 on success. 1027 1027 1028 1028 1029 + * Watch a key or keyring for changes:: 1030 + 1031 + long keyctl(KEYCTL_WATCH_KEY, key_serial_t key, int queue_fd, 1032 + const struct watch_notification_filter *filter); 1033 + 1034 + This will set or remove a watch for changes on the specified key or 1035 + keyring. 1036 + 1037 + "key" is the ID of the key to be watched. 1038 + 1039 + "queue_fd" is a file descriptor referring to an open "/dev/watch_queue" 1040 + which manages the buffer into which notifications will be delivered. 1041 + 1042 + "filter" is either NULL to remove a watch or a filter specification to 1043 + indicate what events are required from the key. 1044 + 1045 + See Documentation/watch_queue.rst for more information. 1046 + 1047 + Note that only one watch may be emplaced for any particular { key, 1048 + queue_fd } combination. 1049 + 1050 + Notification records look like:: 1051 + 1052 + struct key_notification { 1053 + struct watch_notification watch; 1054 + __u32 key_id; 1055 + __u32 aux; 1056 + }; 1057 + 1058 + In this, watch::type will be "WATCH_TYPE_KEY_NOTIFY" and subtype will be 1059 + one of:: 1060 + 1061 + NOTIFY_KEY_INSTANTIATED 1062 + NOTIFY_KEY_UPDATED 1063 + NOTIFY_KEY_LINKED 1064 + NOTIFY_KEY_UNLINKED 1065 + NOTIFY_KEY_CLEARED 1066 + NOTIFY_KEY_REVOKED 1067 + NOTIFY_KEY_INVALIDATED 1068 + NOTIFY_KEY_SETATTR 1069 + 1070 + Where these indicate a key being instantiated/rejected, updated, a link 1071 + being made in a keyring, a link being removed from a keyring, a keyring 1072 + being cleared, a key being revoked, a key being invalidated or a key 1073 + having one of its attributes changed (user, group, perm, timeout, 1074 + restriction). 1075 + 1076 + If a watched key is deleted, a basic watch_notification will be issued 1077 + with "type" set to WATCH_TYPE_META and "subtype" set to 1078 + watch_meta_removal_notification. The watchpoint ID will be set in the 1079 + "info" field. 1080 + 1081 + This needs to be configured by enabling: 1082 + 1083 + "Provide key/keyring change notifications" (KEY_NOTIFICATIONS) 1084 + 1085 + 1029 1086 Kernel Services 1030 1087 =============== 1031 1088
+3
include/linux/key.h
··· 176 176 struct list_head graveyard_link; 177 177 struct rb_node serial_node; 178 178 }; 179 + #ifdef CONFIG_KEY_NOTIFICATIONS 180 + struct watch_list *watchers; /* Entities watching this key for changes */ 181 + #endif 179 182 struct rw_semaphore sem; /* change vs change sem */ 180 183 struct key_user *user; /* owner of this key */ 181 184 void *security; /* security data for this key */
+2
include/uapi/linux/keyctl.h
··· 69 69 #define KEYCTL_RESTRICT_KEYRING 29 /* Restrict keys allowed to link to a keyring */ 70 70 #define KEYCTL_MOVE 30 /* Move keys between keyrings */ 71 71 #define KEYCTL_CAPABILITIES 31 /* Find capabilities of keyrings subsystem */ 72 + #define KEYCTL_WATCH_KEY 32 /* Watch a key or ring of keys for changes */ 72 73 73 74 /* keyctl structures */ 74 75 struct keyctl_dh_params { ··· 131 130 #define KEYCTL_CAPS0_MOVE 0x80 /* KEYCTL_MOVE supported */ 132 131 #define KEYCTL_CAPS1_NS_KEYRING_NAME 0x01 /* Keyring names are per-user_namespace */ 133 132 #define KEYCTL_CAPS1_NS_KEY_TAG 0x02 /* Key indexing can include a namespace tag */ 133 + #define KEYCTL_CAPS1_NOTIFICATIONS 0x04 /* Keys generate watchable notifications */ 134 134 135 135 #endif /* _LINUX_KEYCTL_H */
+27 -1
include/uapi/linux/watch_queue.h
··· 13 13 14 14 enum watch_notification_type { 15 15 WATCH_TYPE_META = 0, /* Special record */ 16 - WATCH_TYPE__NR = 1 16 + WATCH_TYPE_KEY_NOTIFY = 1, /* Key change event notification */ 17 + WATCH_TYPE__NR = 2 17 18 }; 18 19 19 20 enum watch_meta_notification_subtype { ··· 74 73 struct watch_notification_removal { 75 74 struct watch_notification watch; 76 75 __u64 id; /* Type-dependent identifier */ 76 + }; 77 + 78 + /* 79 + * Type of key/keyring change notification. 80 + */ 81 + enum key_notification_subtype { 82 + NOTIFY_KEY_INSTANTIATED = 0, /* Key was instantiated (aux is error code) */ 83 + NOTIFY_KEY_UPDATED = 1, /* Key was updated */ 84 + NOTIFY_KEY_LINKED = 2, /* Key (aux) was added to watched keyring */ 85 + NOTIFY_KEY_UNLINKED = 3, /* Key (aux) was removed from watched keyring */ 86 + NOTIFY_KEY_CLEARED = 4, /* Keyring was cleared */ 87 + NOTIFY_KEY_REVOKED = 5, /* Key was revoked */ 88 + NOTIFY_KEY_INVALIDATED = 6, /* Key was invalidated */ 89 + NOTIFY_KEY_SETATTR = 7, /* Key's attributes got changed */ 90 + }; 91 + 92 + /* 93 + * Key/keyring notification record. 94 + * - watch.type = WATCH_TYPE_KEY_NOTIFY 95 + * - watch.subtype = enum key_notification_type 96 + */ 97 + struct key_notification { 98 + struct watch_notification watch; 99 + __u32 key_id; /* The key/keyring affected */ 100 + __u32 aux; /* Per-type auxiliary data */ 77 101 }; 78 102 79 103 #endif /* _UAPI_LINUX_WATCH_QUEUE_H */
+9
security/keys/Kconfig
··· 116 116 in the kernel. 117 117 118 118 If you are unsure as to whether this is required, answer N. 119 + 120 + config KEY_NOTIFICATIONS 121 + bool "Provide key/keyring change notifications" 122 + depends on KEYS && WATCH_QUEUE 123 + help 124 + This option provides support for getting change notifications on keys 125 + and keyrings on which the caller has View permission. This makes use 126 + of the /dev/watch_queue misc device to handle the notification 127 + buffer and provides KEYCTL_WATCH_KEY to enable/disable watches.
+3
security/keys/compat.c
··· 156 156 case KEYCTL_CAPABILITIES: 157 157 return keyctl_capabilities(compat_ptr(arg2), arg3); 158 158 159 + case KEYCTL_WATCH_KEY: 160 + return keyctl_watch_key(arg2, arg3, arg4); 161 + 159 162 default: 160 163 return -EOPNOTSUPP; 161 164 }
+5
security/keys/gc.c
··· 131 131 kdebug("- %u", key->serial); 132 132 key_check(key); 133 133 134 + #ifdef CONFIG_KEY_NOTIFICATIONS 135 + remove_watch_list(key->watchers, key->serial); 136 + key->watchers = NULL; 137 + #endif 138 + 134 139 /* Throw away the key data if the key is instantiated */ 135 140 if (state == KEY_IS_POSITIVE && key->type->destroy) 136 141 key->type->destroy(key);
+29 -1
security/keys/internal.h
··· 15 15 #include <linux/task_work.h> 16 16 #include <linux/keyctl.h> 17 17 #include <linux/refcount.h> 18 + #include <linux/watch_queue.h> 18 19 #include <linux/compat.h> 19 20 #include <linux/mm.h> 20 21 #include <linux/vmalloc.h> ··· 100 99 const struct keyring_index_key *index_key, 101 100 struct assoc_array_edit **_edit); 102 101 extern int __key_link_check_live_key(struct key *keyring, struct key *key); 103 - extern void __key_link(struct key *key, struct assoc_array_edit **_edit); 102 + extern void __key_link(struct key *keyring, struct key *key, 103 + struct assoc_array_edit **_edit); 104 104 extern void __key_link_end(struct key *keyring, 105 105 const struct keyring_index_key *index_key, 106 106 struct assoc_array_edit *edit); ··· 184 182 extern int key_task_permission(const key_ref_t key_ref, 185 183 const struct cred *cred, 186 184 key_perm_t perm); 185 + 186 + static inline void notify_key(struct key *key, 187 + enum key_notification_subtype subtype, u32 aux) 188 + { 189 + #ifdef CONFIG_KEY_NOTIFICATIONS 190 + struct key_notification n = { 191 + .watch.type = WATCH_TYPE_KEY_NOTIFY, 192 + .watch.subtype = subtype, 193 + .watch.info = watch_sizeof(n), 194 + .key_id = key_serial(key), 195 + .aux = aux, 196 + }; 197 + 198 + post_watch_notification(key->watchers, &n.watch, current_cred(), 199 + n.key_id); 200 + #endif 201 + } 187 202 188 203 /* 189 204 * Check to see whether permission is granted to use a key in the desired way. ··· 351 332 #endif 352 333 353 334 extern long keyctl_capabilities(unsigned char __user *_buffer, size_t buflen); 335 + 336 + #ifdef CONFIG_KEY_NOTIFICATIONS 337 + extern long keyctl_watch_key(key_serial_t, int, int); 338 + #else 339 + static inline long keyctl_watch_key(key_serial_t key_id, int watch_fd, int watch_id) 340 + { 341 + return -EOPNOTSUPP; 342 + } 343 + #endif 354 344 355 345 /* 356 346 * Debugging key validation
+23 -13
security/keys/key.c
··· 444 444 /* mark the key as being instantiated */ 445 445 atomic_inc(&key->user->nikeys); 446 446 mark_key_instantiated(key, 0); 447 + notify_key(key, NOTIFY_KEY_INSTANTIATED, 0); 447 448 448 449 if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) 449 450 awaken = 1; ··· 454 453 if (test_bit(KEY_FLAG_KEEP, &keyring->flags)) 455 454 set_bit(KEY_FLAG_KEEP, &key->flags); 456 455 457 - __key_link(key, _edit); 456 + __key_link(keyring, key, _edit); 458 457 } 459 458 460 459 /* disable the authorisation key */ ··· 602 601 /* mark the key as being negatively instantiated */ 603 602 atomic_inc(&key->user->nikeys); 604 603 mark_key_instantiated(key, -error); 604 + notify_key(key, NOTIFY_KEY_INSTANTIATED, -error); 605 605 key->expiry = ktime_get_real_seconds() + timeout; 606 606 key_schedule_gc(key->expiry + key_gc_delay); 607 607 ··· 613 611 614 612 /* and link it into the destination keyring */ 615 613 if (keyring && link_ret == 0) 616 - __key_link(key, &edit); 614 + __key_link(keyring, key, &edit); 617 615 618 616 /* disable the authorisation key */ 619 617 if (authkey) ··· 766 764 down_write(&key->sem); 767 765 768 766 ret = key->type->update(key, prep); 769 - if (ret == 0) 767 + if (ret == 0) { 770 768 /* Updating a negative key positively instantiates it */ 771 769 mark_key_instantiated(key, 0); 770 + notify_key(key, NOTIFY_KEY_UPDATED, 0); 771 + } 772 772 773 773 up_write(&key->sem); 774 774 ··· 1027 1023 down_write(&key->sem); 1028 1024 1029 1025 ret = key->type->update(key, &prep); 1030 - if (ret == 0) 1026 + if (ret == 0) { 1031 1027 /* Updating a negative key positively instantiates it */ 1032 1028 mark_key_instantiated(key, 0); 1029 + notify_key(key, NOTIFY_KEY_UPDATED, 0); 1030 + } 1033 1031 1034 1032 up_write(&key->sem); 1035 1033 ··· 1063 1057 * instantiated 1064 1058 */ 1065 1059 down_write_nested(&key->sem, 1); 1066 - if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags) && 1067 - key->type->revoke) 1068 - key->type->revoke(key); 1060 + if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags)) { 1061 + notify_key(key, NOTIFY_KEY_REVOKED, 0); 1062 + if (key->type->revoke) 1063 + key->type->revoke(key); 1069 1064 1070 - /* set the death time to no more than the expiry time */ 1071 - time = ktime_get_real_seconds(); 1072 - if (key->revoked_at == 0 || key->revoked_at > time) { 1073 - key->revoked_at = time; 1074 - key_schedule_gc(key->revoked_at + key_gc_delay); 1065 + /* set the death time to no more than the expiry time */ 1066 + time = ktime_get_real_seconds(); 1067 + if (key->revoked_at == 0 || key->revoked_at > time) { 1068 + key->revoked_at = time; 1069 + key_schedule_gc(key->revoked_at + key_gc_delay); 1070 + } 1075 1071 } 1076 1072 1077 1073 up_write(&key->sem); ··· 1095 1087 1096 1088 if (!test_bit(KEY_FLAG_INVALIDATED, &key->flags)) { 1097 1089 down_write_nested(&key->sem, 1); 1098 - if (!test_and_set_bit(KEY_FLAG_INVALIDATED, &key->flags)) 1090 + if (!test_and_set_bit(KEY_FLAG_INVALIDATED, &key->flags)) { 1091 + notify_key(key, NOTIFY_KEY_INVALIDATED, 0); 1099 1092 key_schedule_gc_links(); 1093 + } 1100 1094 up_write(&key->sem); 1101 1095 } 1102 1096 }
+96 -3
security/keys/keyctl.c
··· 37 37 KEYCTL_CAPS0_MOVE 38 38 ), 39 39 [1] = (KEYCTL_CAPS1_NS_KEYRING_NAME | 40 - KEYCTL_CAPS1_NS_KEY_TAG), 40 + KEYCTL_CAPS1_NS_KEY_TAG | 41 + (IS_ENABLED(CONFIG_KEY_NOTIFICATIONS) ? KEYCTL_CAPS1_NOTIFICATIONS : 0) 42 + ), 41 43 }; 42 44 43 45 static int key_get_type_from_user(char *type, ··· 1041 1039 if (group != (gid_t) -1) 1042 1040 key->gid = gid; 1043 1041 1042 + notify_key(key, NOTIFY_KEY_SETATTR, 0); 1044 1043 ret = 0; 1045 1044 1046 1045 error_put: ··· 1092 1089 /* if we're not the sysadmin, we can only change a key that we own */ 1093 1090 if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid())) { 1094 1091 key->perm = perm; 1092 + notify_key(key, NOTIFY_KEY_SETATTR, 0); 1095 1093 ret = 0; 1096 1094 } 1097 1095 ··· 1484 1480 okay: 1485 1481 key = key_ref_to_ptr(key_ref); 1486 1482 ret = 0; 1487 - if (test_bit(KEY_FLAG_KEEP, &key->flags)) 1483 + if (test_bit(KEY_FLAG_KEEP, &key->flags)) { 1488 1484 ret = -EPERM; 1489 - else 1485 + } else { 1490 1486 key_set_timeout(key, timeout); 1487 + notify_key(key, NOTIFY_KEY_SETATTR, 0); 1488 + } 1491 1489 key_put(key); 1492 1490 1493 1491 error: ··· 1763 1757 return ret; 1764 1758 } 1765 1759 1760 + #ifdef CONFIG_KEY_NOTIFICATIONS 1761 + /* 1762 + * Watch for changes to a key. 1763 + * 1764 + * The caller must have View permission to watch a key or keyring. 1765 + */ 1766 + long keyctl_watch_key(key_serial_t id, int watch_queue_fd, int watch_id) 1767 + { 1768 + struct watch_queue *wqueue; 1769 + struct watch_list *wlist = NULL; 1770 + struct watch *watch = NULL; 1771 + struct key *key; 1772 + key_ref_t key_ref; 1773 + long ret; 1774 + 1775 + if (watch_id < -1 || watch_id > 0xff) 1776 + return -EINVAL; 1777 + 1778 + key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_NEED_VIEW); 1779 + if (IS_ERR(key_ref)) 1780 + return PTR_ERR(key_ref); 1781 + key = key_ref_to_ptr(key_ref); 1782 + 1783 + wqueue = get_watch_queue(watch_queue_fd); 1784 + if (IS_ERR(wqueue)) { 1785 + ret = PTR_ERR(wqueue); 1786 + goto err_key; 1787 + } 1788 + 1789 + if (watch_id >= 0) { 1790 + ret = -ENOMEM; 1791 + if (!key->watchers) { 1792 + wlist = kzalloc(sizeof(*wlist), GFP_KERNEL); 1793 + if (!wlist) 1794 + goto err_wqueue; 1795 + init_watch_list(wlist, NULL); 1796 + } 1797 + 1798 + watch = kzalloc(sizeof(*watch), GFP_KERNEL); 1799 + if (!watch) 1800 + goto err_wlist; 1801 + 1802 + init_watch(watch, wqueue); 1803 + watch->id = key->serial; 1804 + watch->info_id = (u32)watch_id << WATCH_INFO_ID__SHIFT; 1805 + 1806 + ret = security_watch_key(key); 1807 + if (ret < 0) 1808 + goto err_watch; 1809 + 1810 + down_write(&key->sem); 1811 + if (!key->watchers) { 1812 + key->watchers = wlist; 1813 + wlist = NULL; 1814 + } 1815 + 1816 + ret = add_watch_to_object(watch, key->watchers); 1817 + up_write(&key->sem); 1818 + 1819 + if (ret == 0) 1820 + watch = NULL; 1821 + } else { 1822 + ret = -EBADSLT; 1823 + if (key->watchers) { 1824 + down_write(&key->sem); 1825 + ret = remove_watch_from_object(key->watchers, 1826 + wqueue, key_serial(key), 1827 + false); 1828 + up_write(&key->sem); 1829 + } 1830 + } 1831 + 1832 + err_watch: 1833 + kfree(watch); 1834 + err_wlist: 1835 + kfree(wlist); 1836 + err_wqueue: 1837 + put_watch_queue(wqueue); 1838 + err_key: 1839 + key_put(key); 1840 + return ret; 1841 + } 1842 + #endif /* CONFIG_KEY_NOTIFICATIONS */ 1843 + 1766 1844 /* 1767 1845 * Get keyrings subsystem capabilities. 1768 1846 */ ··· 2015 1925 2016 1926 case KEYCTL_CAPABILITIES: 2017 1927 return keyctl_capabilities((unsigned char __user *)arg2, (size_t)arg3); 1928 + 1929 + case KEYCTL_WATCH_KEY: 1930 + return keyctl_watch_key((key_serial_t)arg2, (int)arg3, (int)arg4); 2018 1931 2019 1932 default: 2020 1933 return -EOPNOTSUPP;
+13 -7
security/keys/keyring.c
··· 1056 1056 down_write(&keyring->sem); 1057 1057 down_write(&keyring_serialise_restrict_sem); 1058 1058 1059 - if (keyring->restrict_link) 1059 + if (keyring->restrict_link) { 1060 1060 ret = -EEXIST; 1061 - else if (keyring_detect_restriction_cycle(keyring, restrict_link)) 1061 + } else if (keyring_detect_restriction_cycle(keyring, restrict_link)) { 1062 1062 ret = -EDEADLK; 1063 - else 1063 + } else { 1064 1064 keyring->restrict_link = restrict_link; 1065 + notify_key(keyring, NOTIFY_KEY_SETATTR, 0); 1066 + } 1065 1067 1066 1068 up_write(&keyring_serialise_restrict_sem); 1067 1069 up_write(&keyring->sem); ··· 1364 1362 * holds at most one link to any given key of a particular type+description 1365 1363 * combination. 1366 1364 */ 1367 - void __key_link(struct key *key, struct assoc_array_edit **_edit) 1365 + void __key_link(struct key *keyring, struct key *key, 1366 + struct assoc_array_edit **_edit) 1368 1367 { 1369 1368 __key_get(key); 1370 1369 assoc_array_insert_set_object(*_edit, keyring_key_to_ptr(key)); 1371 1370 assoc_array_apply_edit(*_edit); 1372 1371 *_edit = NULL; 1372 + notify_key(keyring, NOTIFY_KEY_LINKED, key_serial(key)); 1373 1373 } 1374 1374 1375 1375 /* ··· 1455 1451 if (ret == 0) 1456 1452 ret = __key_link_check_live_key(keyring, key); 1457 1453 if (ret == 0) 1458 - __key_link(key, &edit); 1454 + __key_link(keyring, key, &edit); 1459 1455 1460 1456 error_end: 1461 1457 __key_link_end(keyring, &key->index_key, edit); ··· 1487 1483 struct assoc_array_edit *edit; 1488 1484 1489 1485 BUG_ON(*_edit != NULL); 1490 - 1486 + 1491 1487 edit = assoc_array_delete(&keyring->keys, &keyring_assoc_array_ops, 1492 1488 &key->index_key); 1493 1489 if (IS_ERR(edit)) ··· 1507 1503 struct assoc_array_edit **_edit) 1508 1504 { 1509 1505 assoc_array_apply_edit(*_edit); 1506 + notify_key(keyring, NOTIFY_KEY_UNLINKED, key_serial(key)); 1510 1507 *_edit = NULL; 1511 1508 key_payload_reserve(keyring, keyring->datalen - KEYQUOTA_LINK_BYTES); 1512 1509 } ··· 1626 1621 goto error; 1627 1622 1628 1623 __key_unlink(from_keyring, key, &from_edit); 1629 - __key_link(key, &to_edit); 1624 + __key_link(to_keyring, key, &to_edit); 1630 1625 error: 1631 1626 __key_link_end(to_keyring, &key->index_key, to_edit); 1632 1627 __key_unlink_end(from_keyring, key, from_edit); ··· 1660 1655 } else { 1661 1656 if (edit) 1662 1657 assoc_array_apply_edit(edit); 1658 + notify_key(keyring, NOTIFY_KEY_CLEARED, 0); 1663 1659 key_payload_reserve(keyring, 0); 1664 1660 ret = 0; 1665 1661 }
+2 -2
security/keys/request_key.c
··· 418 418 goto key_already_present; 419 419 420 420 if (dest_keyring) 421 - __key_link(key, &edit); 421 + __key_link(dest_keyring, key, &edit); 422 422 423 423 mutex_unlock(&key_construction_mutex); 424 424 if (dest_keyring) ··· 437 437 if (dest_keyring) { 438 438 ret = __key_link_check_live_key(dest_keyring, key); 439 439 if (ret == 0) 440 - __key_link(key, &edit); 440 + __key_link(dest_keyring, key, &edit); 441 441 __key_link_end(dest_keyring, &ctx->index_key, edit); 442 442 if (ret < 0) 443 443 goto link_check_failed;