History

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.

David Howells committed 6 years ago

Commit f7e47671 parent 998f50412 files · +270 −28Browse files

Unified · Split

12 files
  1. Documentation/security/keys/core.rst +57 −0
  2. include/linux/key.h +3 −0
  3. include/uapi/linux/keyctl.h +2 −0
  4. include/uapi/linux/watch_queue.h +27 −1
  5. security/keys/Kconfig +9 −0
  6. security/keys/compat.c +3 −0
  7. security/keys/gc.c +5 −0
  8. security/keys/internal.h +29 −1
  9. security/keys/key.c +24 −14
  10. security/keys/keyctl.c +96 −3
  11. security/keys/keyring.c +13 −7
  12. security/keys/request_key.c +2 −2
Documentation/security/keys/core.rst+57−0
@@ -1026,6 +1026,63 @@ The keyctl syscall functions are: · 1025 unmodified lines
10261026 written into the output buffer. Verification returns 0 on success.
10271027
10281028
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+
10291086 Kernel Services
10301087 ===============
10311088
include/linux/key.h+3−0
@@ -176,6 +176,9 @@ struct key { · 175 unmodified lines
176176 struct list_head graveyard_link;
177177 struct rb_node serial_node;
178178 };
179+#ifdef CONFIG_KEY_NOTIFICATIONS
180+ struct watch_list *watchers; /* Entities watching this key for changes */
181+#endif
179182 struct rw_semaphore sem; /* change vs change sem */
180183 struct key_user *user; /* owner of this key */
181184 void *security; /* security data for this key */
include/uapi/linux/keyctl.h+2−0
@@ -69,6 +69,7 @@ · 68 unmodified lines
6969 #define KEYCTL_RESTRICT_KEYRING 29 /* Restrict keys allowed to link to a keyring */
7070 #define KEYCTL_MOVE 30 /* Move keys between keyrings */
7171 #define KEYCTL_CAPABILITIES 31 /* Find capabilities of keyrings subsystem */
72+#define KEYCTL_WATCH_KEY 32 /* Watch a key or ring of keys for changes */
7273
7374 /* keyctl structures */
7475 struct keyctl_dh_params {
@@ -130,5 +131,6 @@ struct keyctl_pkey_params { · 55 unmodified lines
130131 #define KEYCTL_CAPS0_MOVE 0x80 /* KEYCTL_MOVE supported */
131132 #define KEYCTL_CAPS1_NS_KEYRING_NAME 0x01 /* Keyring names are per-user_namespace */
132133 #define KEYCTL_CAPS1_NS_KEY_TAG 0x02 /* Key indexing can include a namespace tag */
134+#define KEYCTL_CAPS1_NOTIFICATIONS 0x04 /* Keys generate watchable notifications */
133135
134136 #endif /* _LINUX_KEYCTL_H */
include/uapi/linux/watch_queue.h+27−1
@@ -13,7 +13,8 @@ · 12 unmodified lines
1313
1414 enum watch_notification_type {
1515 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
1718 };
1819
1920 enum watch_meta_notification_subtype {
@@ -75,4 +76,29 @@ struct watch_notification_removal { · 55 unmodified lines
7576 __u64 id; /* Type-dependent identifier */
7677 };
7778
79+/*
80+ * Type of key/keyring change notification.
81+ */
82+enum key_notification_subtype {
83+ NOTIFY_KEY_INSTANTIATED = 0, /* Key was instantiated (aux is error code) */
84+ NOTIFY_KEY_UPDATED = 1, /* Key was updated */
85+ NOTIFY_KEY_LINKED = 2, /* Key (aux) was added to watched keyring */
86+ NOTIFY_KEY_UNLINKED = 3, /* Key (aux) was removed from watched keyring */
87+ NOTIFY_KEY_CLEARED = 4, /* Keyring was cleared */
88+ NOTIFY_KEY_REVOKED = 5, /* Key was revoked */
89+ NOTIFY_KEY_INVALIDATED = 6, /* Key was invalidated */
90+ NOTIFY_KEY_SETATTR = 7, /* Key's attributes got changed */
91+};
92+
93+/*
94+ * Key/keyring notification record.
95+ * - watch.type = WATCH_TYPE_KEY_NOTIFY
96+ * - watch.subtype = enum key_notification_type
97+ */
98+struct key_notification {
99+ struct watch_notification watch;
100+ __u32 key_id; /* The key/keyring affected */
101+ __u32 aux; /* Per-type auxiliary data */
102+};
103+
78104 #endif /* _UAPI_LINUX_WATCH_QUEUE_H */
security/keys/Kconfig+9−0
@@ -116,3 +116,12 @@ config KEY_DH_OPERATIONS · 115 unmodified lines
116116 in the kernel.
117117
118118 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.
security/keys/compat.c+3−0
@@ -156,6 +156,9 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option, · 155 unmodified lines
156156 case KEYCTL_CAPABILITIES:
157157 return keyctl_capabilities(compat_ptr(arg2), arg3);
158158
159+ case KEYCTL_WATCH_KEY:
160+ return keyctl_watch_key(arg2, arg3, arg4);
161+
159162 default:
160163 return -EOPNOTSUPP;
161164 }
security/keys/gc.c+5−0
@@ -131,6 +131,11 @@ static noinline void key_gc_unused_keys(struct list_head *keys) · 130 unmodified lines
131131 kdebug("- %u", key->serial);
132132 key_check(key);
133133
134+#ifdef CONFIG_KEY_NOTIFICATIONS
135+ remove_watch_list(key->watchers, key->serial);
136+ key->watchers = NULL;
137+#endif
138+
134139 /* Throw away the key data if the key is instantiated */
135140 if (state == KEY_IS_POSITIVE && key->type->destroy)
136141 key->type->destroy(key);
security/keys/internal.h+29−1
@@ -15,6 +15,7 @@ · 14 unmodified lines
1515 #include <linux/task_work.h>
1616 #include <linux/keyctl.h>
1717 #include <linux/refcount.h>
18+#include <linux/watch_queue.h>
1819 #include <linux/compat.h>
1920 #include <linux/mm.h>
2021 #include <linux/vmalloc.h>
@@ -99,7 +100,8 @@ extern int __key_link_begin(struct key *keyring, · 78 unmodified lines
99100 const struct keyring_index_key *index_key,
100101 struct assoc_array_edit **_edit);
101102 extern int __key_link_check_live_key(struct key *keyring, struct key *key);
102−extern void __key_link(struct key *key, struct assoc_array_edit **_edit);
103+extern void __key_link(struct key *keyring, struct key *key,
104+ struct assoc_array_edit **_edit);
103105 extern void __key_link_end(struct key *keyring,
104106 const struct keyring_index_key *index_key,
105107 struct assoc_array_edit *edit);
@@ -183,6 +185,23 @@ extern int key_task_permission(const key_ref_t key_ref, · 77 unmodified lines
183185 const struct cred *cred,
184186 key_perm_t perm);
185187
188+static inline void notify_key(struct key *key,
189+ enum key_notification_subtype subtype, u32 aux)
190+{
191+#ifdef CONFIG_KEY_NOTIFICATIONS
192+ struct key_notification n = {
193+ .watch.type = WATCH_TYPE_KEY_NOTIFY,
194+ .watch.subtype = subtype,
195+ .watch.info = watch_sizeof(n),
196+ .key_id = key_serial(key),
197+ .aux = aux,
198+ };
199+
200+ post_watch_notification(key->watchers, &n.watch, current_cred(),
201+ n.key_id);
202+#endif
203+}
204+
186205 /*
187206 * Check to see whether permission is granted to use a key in the desired way.
188207 */
@@ -333,6 +352,15 @@ static inline long keyctl_pkey_e_d_s(int op, · 144 unmodified lines
333352
334353 extern long keyctl_capabilities(unsigned char __user *_buffer, size_t buflen);
335354
355+#ifdef CONFIG_KEY_NOTIFICATIONS
356+extern long keyctl_watch_key(key_serial_t, int, int);
357+#else
358+static inline long keyctl_watch_key(key_serial_t key_id, int watch_fd, int watch_id)
359+{
360+ return -EOPNOTSUPP;
361+}
362+#endif
363+
336364 /*
337365 * Debugging key validation
338366 */
security/keys/key.c+24−14
@@ -444,6 +444,7 @@ static int __key_instantiate_and_link(struct key *key, · 443 unmodified lines
444444 /* mark the key as being instantiated */
445445 atomic_inc(&key->user->nikeys);
446446 mark_key_instantiated(key, 0);
447+ notify_key(key, NOTIFY_KEY_INSTANTIATED, 0);
447448
448449 if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
449450 awaken = 1;
@@ -453,7 +454,7 @@ static int __key_instantiate_and_link(struct key *key, · 3 unmodified lines
453454 if (test_bit(KEY_FLAG_KEEP, &keyring->flags))
454455 set_bit(KEY_FLAG_KEEP, &key->flags);
455456
456− __key_link(key, _edit);
457+ __key_link(keyring, key, _edit);
457458 }
458459
459460 /* disable the authorisation key */
@@ -601,6 +602,7 @@ int key_reject_and_link(struct key *key, · 141 unmodified lines
601602 /* mark the key as being negatively instantiated */
602603 atomic_inc(&key->user->nikeys);
603604 mark_key_instantiated(key, -error);
605+ notify_key(key, NOTIFY_KEY_INSTANTIATED, -error);
604606 key->expiry = ktime_get_real_seconds() + timeout;
605607 key_schedule_gc(key->expiry + key_gc_delay);
606608
@@ -611,7 +613,7 @@ int key_reject_and_link(struct key *key, · 4 unmodified lines
611613
612614 /* and link it into the destination keyring */
613615 if (keyring && link_ret == 0)
614− __key_link(key, &edit);
616+ __key_link(keyring, key, &edit);
615617
616618 /* disable the authorisation key */
617619 if (authkey)
@@ -764,9 +766,11 @@ static inline key_ref_t __key_update(key_ref_t key_ref, · 146 unmodified lines
764766 down_write(&key->sem);
765767
766768 ret = key->type->update(key, prep);
767− if (ret == 0)
769+ if (ret == 0) {
768770 /* Updating a negative key positively instantiates it */
769771 mark_key_instantiated(key, 0);
772+ notify_key(key, NOTIFY_KEY_UPDATED, 0);
773+ }
770774
771775 up_write(&key->sem);
772776
@@ -1023,9 +1027,11 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) · 250 unmodified lines
10231027 down_write(&key->sem);
10241028
10251029 ret = key->type->update(key, &prep);
1026− if (ret == 0)
1030+ if (ret == 0) {
10271031 /* Updating a negative key positively instantiates it */
10281032 mark_key_instantiated(key, 0);
1033+ notify_key(key, NOTIFY_KEY_UPDATED, 0);
1034+ }
10291035
10301036 up_write(&key->sem);
10311037
@@ -1057,15 +1063,17 @@ void key_revoke(struct key *key) · 25 unmodified lines
10571063 * instantiated
10581064 */
10591065 down_write_nested(&key->sem, 1);
1060− if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags) &&
1061− key->type->revoke)
1062− key->type->revoke(key);
1063−
1064− /* set the death time to no more than the expiry time */
1065− time = ktime_get_real_seconds();
1066− if (key->revoked_at == 0 || key->revoked_at > time) {
1067− key->revoked_at = time;
1068− key_schedule_gc(key->revoked_at + key_gc_delay);
1066+ if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags)) {
1067+ notify_key(key, NOTIFY_KEY_REVOKED, 0);
1068+ if (key->type->revoke)
1069+ key->type->revoke(key);
1070+
1071+ /* set the death time to no more than the expiry time */
1072+ time = ktime_get_real_seconds();
1073+ if (key->revoked_at == 0 || key->revoked_at > time) {
1074+ key->revoked_at = time;
1075+ key_schedule_gc(key->revoked_at + key_gc_delay);
1076+ }
10691077 }
10701078
10711079 up_write(&key->sem);
@@ -1087,8 +1095,10 @@ void key_invalidate(struct key *key) · 15 unmodified lines
10871095
10881096 if (!test_bit(KEY_FLAG_INVALIDATED, &key->flags)) {
10891097 down_write_nested(&key->sem, 1);
1090− if (!test_and_set_bit(KEY_FLAG_INVALIDATED, &key->flags))
1098+ if (!test_and_set_bit(KEY_FLAG_INVALIDATED, &key->flags)) {
1099+ notify_key(key, NOTIFY_KEY_INVALIDATED, 0);
10911100 key_schedule_gc_links();
1101+ }
10921102 up_write(&key->sem);
10931103 }
10941104 }
security/keys/keyctl.c+96−3
@@ -37,7 +37,9 @@ static const unsigned char keyrings_capabilities[2] = { · 36 unmodified lines
3737 KEYCTL_CAPS0_MOVE
3838 ),
3939 [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+ ),
4143 };
4244
4345 static int key_get_type_from_user(char *type,
@@ -1039,6 +1041,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) · 995 unmodified lines
10391041 if (group != (gid_t) -1)
10401042 key->gid = gid;
10411043
1044+ notify_key(key, NOTIFY_KEY_SETATTR, 0);
10421045 ret = 0;
10431046
10441047 error_put:
@@ -1089,6 +1092,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) · 44 unmodified lines
10891092 /* if we're not the sysadmin, we can only change a key that we own */
10901093 if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid())) {
10911094 key->perm = perm;
1095+ notify_key(key, NOTIFY_KEY_SETATTR, 0);
10921096 ret = 0;
10931097 }
10941098
@@ -1480,10 +1484,12 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout) · 385 unmodified lines
14801484 okay:
14811485 key = key_ref_to_ptr(key_ref);
14821486 ret = 0;
1483− if (test_bit(KEY_FLAG_KEEP, &key->flags))
1487+ if (test_bit(KEY_FLAG_KEEP, &key->flags)) {
14841488 ret = -EPERM;
1485− else
1489+ } else {
14861490 key_set_timeout(key, timeout);
1491+ notify_key(key, NOTIFY_KEY_SETATTR, 0);
1492+ }
14871493 key_put(key);
14881494
14891495 error:
@@ -1757,6 +1763,90 @@ error: · 267 unmodified lines
17571763 return ret;
17581764 }
17591765
1766+#ifdef CONFIG_KEY_NOTIFICATIONS
1767+/*
1768+ * Watch for changes to a key.
1769+ *
1770+ * The caller must have View permission to watch a key or keyring.
1771+ */
1772+long keyctl_watch_key(key_serial_t id, int watch_queue_fd, int watch_id)
1773+{
1774+ struct watch_queue *wqueue;
1775+ struct watch_list *wlist = NULL;
1776+ struct watch *watch = NULL;
1777+ struct key *key;
1778+ key_ref_t key_ref;
1779+ long ret;
1780+
1781+ if (watch_id < -1 || watch_id > 0xff)
1782+ return -EINVAL;
1783+
1784+ key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_NEED_VIEW);
1785+ if (IS_ERR(key_ref))
1786+ return PTR_ERR(key_ref);
1787+ key = key_ref_to_ptr(key_ref);
1788+
1789+ wqueue = get_watch_queue(watch_queue_fd);
1790+ if (IS_ERR(wqueue)) {
1791+ ret = PTR_ERR(wqueue);
1792+ goto err_key;
1793+ }
1794+
1795+ if (watch_id >= 0) {
1796+ ret = -ENOMEM;
1797+ if (!key->watchers) {
1798+ wlist = kzalloc(sizeof(*wlist), GFP_KERNEL);
1799+ if (!wlist)
1800+ goto err_wqueue;
1801+ init_watch_list(wlist, NULL);
1802+ }
1803+
1804+ watch = kzalloc(sizeof(*watch), GFP_KERNEL);
1805+ if (!watch)
1806+ goto err_wlist;
1807+
1808+ init_watch(watch, wqueue);
1809+ watch->id = key->serial;
1810+ watch->info_id = (u32)watch_id << WATCH_INFO_ID__SHIFT;
1811+
1812+ ret = security_watch_key(key);
1813+ if (ret < 0)
1814+ goto err_watch;
1815+
1816+ down_write(&key->sem);
1817+ if (!key->watchers) {
1818+ key->watchers = wlist;
1819+ wlist = NULL;
1820+ }
1821+
1822+ ret = add_watch_to_object(watch, key->watchers);
1823+ up_write(&key->sem);
1824+
1825+ if (ret == 0)
1826+ watch = NULL;
1827+ } else {
1828+ ret = -EBADSLT;
1829+ if (key->watchers) {
1830+ down_write(&key->sem);
1831+ ret = remove_watch_from_object(key->watchers,
1832+ wqueue, key_serial(key),
1833+ false);
1834+ up_write(&key->sem);
1835+ }
1836+ }
1837+
1838+err_watch:
1839+ kfree(watch);
1840+err_wlist:
1841+ kfree(wlist);
1842+err_wqueue:
1843+ put_watch_queue(wqueue);
1844+err_key:
1845+ key_put(key);
1846+ return ret;
1847+}
1848+#endif /* CONFIG_KEY_NOTIFICATIONS */
1849+
17601850 /*
17611851 * Get keyrings subsystem capabilities.
17621852 */
@@ -1926,6 +2016,9 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, · 163 unmodified lines
19262016 case KEYCTL_CAPABILITIES:
19272017 return keyctl_capabilities((unsigned char __user *)arg2, (size_t)arg3);
19282018
2019+ case KEYCTL_WATCH_KEY:
2020+ return keyctl_watch_key((key_serial_t)arg2, (int)arg3, (int)arg4);
2021+
19292022 default:
19302023 return -EOPNOTSUPP;
19312024 }
security/keys/keyring.c+13−7
@@ -1056,12 +1056,14 @@ int keyring_restrict(key_ref_t keyring_ref, const char *type, · 1055 unmodified lines
10561056 down_write(&keyring->sem);
10571057 down_write(&keyring_serialise_restrict_sem);
10581058
1059− if (keyring->restrict_link)
1059+ if (keyring->restrict_link) {
10601060 ret = -EEXIST;
1061− else if (keyring_detect_restriction_cycle(keyring, restrict_link))
1061+ } else if (keyring_detect_restriction_cycle(keyring, restrict_link)) {
10621062 ret = -EDEADLK;
1063− else
1063+ } else {
10641064 keyring->restrict_link = restrict_link;
1065+ notify_key(keyring, NOTIFY_KEY_SETATTR, 0);
1066+ }
10651067
10661068 up_write(&keyring_serialise_restrict_sem);
10671069 up_write(&keyring->sem);
@@ -1362,12 +1364,14 @@ int __key_link_check_live_key(struct key *keyring, struct key *key) · 294 unmodified lines
13621364 * holds at most one link to any given key of a particular type+description
13631365 * combination.
13641366 */
1365−void __key_link(struct key *key, struct assoc_array_edit **_edit)
1367+void __key_link(struct key *keyring, struct key *key,
1368+ struct assoc_array_edit **_edit)
13661369 {
13671370 __key_get(key);
13681371 assoc_array_insert_set_object(*_edit, keyring_key_to_ptr(key));
13691372 assoc_array_apply_edit(*_edit);
13701373 *_edit = NULL;
1374+ notify_key(keyring, NOTIFY_KEY_LINKED, key_serial(key));
13711375 }
13721376
13731377 /*
@@ -1451,7 +1455,7 @@ int key_link(struct key *keyring, struct key *key) · 77 unmodified lines
14511455 if (ret == 0)
14521456 ret = __key_link_check_live_key(keyring, key);
14531457 if (ret == 0)
1454− __key_link(key, &edit);
1458+ __key_link(keyring, key, &edit);
14551459
14561460 error_end:
14571461 __key_link_end(keyring, &key->index_key, edit);
@@ -1483,7 +1487,7 @@ static int __key_unlink_begin(struct key *keyring, struct key *key, · 25 unmodified lines
14831487 struct assoc_array_edit *edit;
14841488
14851489 BUG_ON(*_edit != NULL);
1486−
1490+
14871491 edit = assoc_array_delete(&keyring->keys, &keyring_assoc_array_ops,
14881492 &key->index_key);
14891493 if (IS_ERR(edit))
@@ -1503,6 +1507,7 @@ static void __key_unlink(struct key *keyring, struct key *key, · 13 unmodified lines
15031507 struct assoc_array_edit **_edit)
15041508 {
15051509 assoc_array_apply_edit(*_edit);
1510+ notify_key(keyring, NOTIFY_KEY_UNLINKED, key_serial(key));
15061511 *_edit = NULL;
15071512 key_payload_reserve(keyring, keyring->datalen - KEYQUOTA_LINK_BYTES);
15081513 }
@@ -1621,7 +1626,7 @@ int key_move(struct key *key, · 112 unmodified lines
16211626 goto error;
16221627
16231628 __key_unlink(from_keyring, key, &from_edit);
1624− __key_link(key, &to_edit);
1629+ __key_link(to_keyring, key, &to_edit);
16251630 error:
16261631 __key_link_end(to_keyring, &key->index_key, to_edit);
16271632 __key_unlink_end(from_keyring, key, from_edit);
@@ -1655,6 +1660,7 @@ int keyring_clear(struct key *keyring) · 27 unmodified lines
16551660 } else {
16561661 if (edit)
16571662 assoc_array_apply_edit(edit);
1663+ notify_key(keyring, NOTIFY_KEY_CLEARED, 0);
16581664 key_payload_reserve(keyring, 0);
16591665 ret = 0;
16601666 }
security/keys/request_key.c+2−2
@@ -418,7 +418,7 @@ static int construct_alloc_key(struct keyring_search_context *ctx, · 417 unmodified lines
418418 goto key_already_present;
419419
420420 if (dest_keyring)
421− __key_link(key, &edit);
421+ __key_link(dest_keyring, key, &edit);
422422
423423 mutex_unlock(&key_construction_mutex);
424424 if (dest_keyring)
@@ -437,7 +437,7 @@ key_already_present: · 12 unmodified lines
437437 if (dest_keyring) {
438438 ret = __key_link_check_live_key(dest_keyring, key);
439439 if (ret == 0)
440− __key_link(key, &edit);
440+ __key_link(dest_keyring, key, &edit);
441441 __key_link_end(dest_keyring, &ctx->index_key, edit);
442442 if (ret < 0)
443443 goto link_check_failed;