.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* Keyring handling |
---|
2 | 3 | * |
---|
3 | 4 | * Copyright (C) 2004-2005, 2008, 2013 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/sched.h> |
---|
15 | 11 | #include <linux/slab.h> |
---|
16 | 12 | #include <linux/security.h> |
---|
17 | 13 | #include <linux/seq_file.h> |
---|
18 | 14 | #include <linux/err.h> |
---|
| 15 | +#include <linux/user_namespace.h> |
---|
| 16 | +#include <linux/nsproxy.h> |
---|
19 | 17 | #include <keys/keyring-type.h> |
---|
20 | 18 | #include <keys/user-type.h> |
---|
21 | 19 | #include <linux/assoc_array_priv.h> |
---|
22 | 20 | #include <linux/uaccess.h> |
---|
| 21 | +#include <net/net_namespace.h> |
---|
23 | 22 | #include "internal.h" |
---|
24 | 23 | |
---|
25 | 24 | /* |
---|
.. | .. |
---|
27 | 26 | * set on how deep we're willing to go. |
---|
28 | 27 | */ |
---|
29 | 28 | #define KEYRING_SEARCH_MAX_DEPTH 6 |
---|
30 | | - |
---|
31 | | -/* |
---|
32 | | - * We keep all named keyrings in a hash to speed looking them up. |
---|
33 | | - */ |
---|
34 | | -#define KEYRING_NAME_HASH_SIZE (1 << 5) |
---|
35 | 29 | |
---|
36 | 30 | /* |
---|
37 | 31 | * We mark pointers we pass to the associative array with bit 1 set if |
---|
.. | .. |
---|
55 | 49 | return key; |
---|
56 | 50 | } |
---|
57 | 51 | |
---|
58 | | -static struct list_head keyring_name_hash[KEYRING_NAME_HASH_SIZE]; |
---|
59 | 52 | static DEFINE_RWLOCK(keyring_name_lock); |
---|
60 | 53 | |
---|
61 | | -static inline unsigned keyring_hash(const char *desc) |
---|
| 54 | +/* |
---|
| 55 | + * Clean up the bits of user_namespace that belong to us. |
---|
| 56 | + */ |
---|
| 57 | +void key_free_user_ns(struct user_namespace *ns) |
---|
62 | 58 | { |
---|
63 | | - unsigned bucket = 0; |
---|
| 59 | + write_lock(&keyring_name_lock); |
---|
| 60 | + list_del_init(&ns->keyring_name_list); |
---|
| 61 | + write_unlock(&keyring_name_lock); |
---|
64 | 62 | |
---|
65 | | - for (; *desc; desc++) |
---|
66 | | - bucket += (unsigned char)*desc; |
---|
67 | | - |
---|
68 | | - return bucket & (KEYRING_NAME_HASH_SIZE - 1); |
---|
| 63 | + key_put(ns->user_keyring_register); |
---|
| 64 | +#ifdef CONFIG_PERSISTENT_KEYRINGS |
---|
| 65 | + key_put(ns->persistent_keyring_register); |
---|
| 66 | +#endif |
---|
69 | 67 | } |
---|
70 | 68 | |
---|
71 | 69 | /* |
---|
.. | .. |
---|
100 | 98 | * Semaphore to serialise link/link calls to prevent two link calls in parallel |
---|
101 | 99 | * introducing a cycle. |
---|
102 | 100 | */ |
---|
103 | | -static DECLARE_RWSEM(keyring_serialise_link_sem); |
---|
| 101 | +static DEFINE_MUTEX(keyring_serialise_link_lock); |
---|
104 | 102 | |
---|
105 | 103 | /* |
---|
106 | 104 | * Publish the name of a keyring so that it can be found by name (if it has |
---|
107 | | - * one). |
---|
| 105 | + * one and it doesn't begin with a dot). |
---|
108 | 106 | */ |
---|
109 | 107 | static void keyring_publish_name(struct key *keyring) |
---|
110 | 108 | { |
---|
111 | | - int bucket; |
---|
| 109 | + struct user_namespace *ns = current_user_ns(); |
---|
112 | 110 | |
---|
113 | | - if (keyring->description) { |
---|
114 | | - bucket = keyring_hash(keyring->description); |
---|
115 | | - |
---|
| 111 | + if (keyring->description && |
---|
| 112 | + keyring->description[0] && |
---|
| 113 | + keyring->description[0] != '.') { |
---|
116 | 114 | write_lock(&keyring_name_lock); |
---|
117 | | - |
---|
118 | | - if (!keyring_name_hash[bucket].next) |
---|
119 | | - INIT_LIST_HEAD(&keyring_name_hash[bucket]); |
---|
120 | | - |
---|
121 | | - list_add_tail(&keyring->name_link, |
---|
122 | | - &keyring_name_hash[bucket]); |
---|
123 | | - |
---|
| 115 | + list_add_tail(&keyring->name_link, &ns->keyring_name_list); |
---|
124 | 116 | write_unlock(&keyring_name_lock); |
---|
125 | 117 | } |
---|
126 | 118 | } |
---|
.. | .. |
---|
168 | 160 | /* |
---|
169 | 161 | * Hash a key type and description. |
---|
170 | 162 | */ |
---|
171 | | -static unsigned long hash_key_type_and_desc(const struct keyring_index_key *index_key) |
---|
| 163 | +static void hash_key_type_and_desc(struct keyring_index_key *index_key) |
---|
172 | 164 | { |
---|
173 | 165 | const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP; |
---|
174 | 166 | const unsigned long fan_mask = ASSOC_ARRAY_FAN_MASK; |
---|
.. | .. |
---|
179 | 171 | int n, desc_len = index_key->desc_len; |
---|
180 | 172 | |
---|
181 | 173 | type = (unsigned long)index_key->type; |
---|
182 | | - |
---|
183 | 174 | acc = mult_64x32_and_fold(type, desc_len + 13); |
---|
184 | 175 | acc = mult_64x32_and_fold(acc, 9207); |
---|
| 176 | + piece = (unsigned long)index_key->domain_tag; |
---|
| 177 | + acc = mult_64x32_and_fold(acc, piece); |
---|
| 178 | + acc = mult_64x32_and_fold(acc, 9207); |
---|
| 179 | + |
---|
185 | 180 | for (;;) { |
---|
186 | 181 | n = desc_len; |
---|
187 | 182 | if (n <= 0) |
---|
.. | .. |
---|
206 | 201 | * zero for keyrings and non-zero otherwise. |
---|
207 | 202 | */ |
---|
208 | 203 | if (index_key->type != &key_type_keyring && (hash & fan_mask) == 0) |
---|
209 | | - return hash | (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1; |
---|
210 | | - if (index_key->type == &key_type_keyring && (hash & fan_mask) != 0) |
---|
211 | | - return (hash + (hash << level_shift)) & ~fan_mask; |
---|
212 | | - return hash; |
---|
| 204 | + hash |= (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1; |
---|
| 205 | + else if (index_key->type == &key_type_keyring && (hash & fan_mask) != 0) |
---|
| 206 | + hash = (hash + (hash << level_shift)) & ~fan_mask; |
---|
| 207 | + index_key->hash = hash; |
---|
| 208 | +} |
---|
| 209 | + |
---|
| 210 | +/* |
---|
| 211 | + * Finalise an index key to include a part of the description actually in the |
---|
| 212 | + * index key, to set the domain tag and to calculate the hash. |
---|
| 213 | + */ |
---|
| 214 | +void key_set_index_key(struct keyring_index_key *index_key) |
---|
| 215 | +{ |
---|
| 216 | + static struct key_tag default_domain_tag = { .usage = REFCOUNT_INIT(1), }; |
---|
| 217 | + size_t n = min_t(size_t, index_key->desc_len, sizeof(index_key->desc)); |
---|
| 218 | + |
---|
| 219 | + memcpy(index_key->desc, index_key->description, n); |
---|
| 220 | + |
---|
| 221 | + if (!index_key->domain_tag) { |
---|
| 222 | + if (index_key->type->flags & KEY_TYPE_NET_DOMAIN) |
---|
| 223 | + index_key->domain_tag = current->nsproxy->net_ns->key_domain; |
---|
| 224 | + else |
---|
| 225 | + index_key->domain_tag = &default_domain_tag; |
---|
| 226 | + } |
---|
| 227 | + |
---|
| 228 | + hash_key_type_and_desc(index_key); |
---|
| 229 | +} |
---|
| 230 | + |
---|
| 231 | +/** |
---|
| 232 | + * key_put_tag - Release a ref on a tag. |
---|
| 233 | + * @tag: The tag to release. |
---|
| 234 | + * |
---|
| 235 | + * This releases a reference the given tag and returns true if that ref was the |
---|
| 236 | + * last one. |
---|
| 237 | + */ |
---|
| 238 | +bool key_put_tag(struct key_tag *tag) |
---|
| 239 | +{ |
---|
| 240 | + if (refcount_dec_and_test(&tag->usage)) { |
---|
| 241 | + kfree_rcu(tag, rcu); |
---|
| 242 | + return true; |
---|
| 243 | + } |
---|
| 244 | + |
---|
| 245 | + return false; |
---|
| 246 | +} |
---|
| 247 | + |
---|
| 248 | +/** |
---|
| 249 | + * key_remove_domain - Kill off a key domain and gc its keys |
---|
| 250 | + * @domain_tag: The domain tag to release. |
---|
| 251 | + * |
---|
| 252 | + * This marks a domain tag as being dead and releases a ref on it. If that |
---|
| 253 | + * wasn't the last reference, the garbage collector is poked to try and delete |
---|
| 254 | + * all keys that were in the domain. |
---|
| 255 | + */ |
---|
| 256 | +void key_remove_domain(struct key_tag *domain_tag) |
---|
| 257 | +{ |
---|
| 258 | + domain_tag->removed = true; |
---|
| 259 | + if (!key_put_tag(domain_tag)) |
---|
| 260 | + key_schedule_gc_links(); |
---|
213 | 261 | } |
---|
214 | 262 | |
---|
215 | 263 | /* |
---|
216 | 264 | * Build the next index key chunk. |
---|
217 | | - * |
---|
218 | | - * On 32-bit systems the index key is laid out as: |
---|
219 | | - * |
---|
220 | | - * 0 4 5 9... |
---|
221 | | - * hash desclen typeptr desc[] |
---|
222 | | - * |
---|
223 | | - * On 64-bit systems: |
---|
224 | | - * |
---|
225 | | - * 0 8 9 17... |
---|
226 | | - * hash desclen typeptr desc[] |
---|
227 | 265 | * |
---|
228 | 266 | * We return it one word-sized chunk at a time. |
---|
229 | 267 | */ |
---|
.. | .. |
---|
231 | 269 | { |
---|
232 | 270 | const struct keyring_index_key *index_key = data; |
---|
233 | 271 | unsigned long chunk = 0; |
---|
234 | | - long offset = 0; |
---|
| 272 | + const u8 *d; |
---|
235 | 273 | int desc_len = index_key->desc_len, n = sizeof(chunk); |
---|
236 | 274 | |
---|
237 | 275 | level /= ASSOC_ARRAY_KEY_CHUNK_SIZE; |
---|
238 | 276 | switch (level) { |
---|
239 | 277 | case 0: |
---|
240 | | - return hash_key_type_and_desc(index_key); |
---|
| 278 | + return index_key->hash; |
---|
241 | 279 | case 1: |
---|
242 | | - return ((unsigned long)index_key->type << 8) | desc_len; |
---|
| 280 | + return index_key->x; |
---|
243 | 281 | case 2: |
---|
244 | | - if (desc_len == 0) |
---|
245 | | - return (u8)((unsigned long)index_key->type >> |
---|
246 | | - (ASSOC_ARRAY_KEY_CHUNK_SIZE - 8)); |
---|
247 | | - n--; |
---|
248 | | - offset = 1; |
---|
| 282 | + return (unsigned long)index_key->type; |
---|
| 283 | + case 3: |
---|
| 284 | + return (unsigned long)index_key->domain_tag; |
---|
249 | 285 | default: |
---|
250 | | - offset += sizeof(chunk) - 1; |
---|
251 | | - offset += (level - 3) * sizeof(chunk); |
---|
252 | | - if (offset >= desc_len) |
---|
| 286 | + level -= 4; |
---|
| 287 | + if (desc_len <= sizeof(index_key->desc)) |
---|
253 | 288 | return 0; |
---|
254 | | - desc_len -= offset; |
---|
| 289 | + |
---|
| 290 | + d = index_key->description + sizeof(index_key->desc); |
---|
| 291 | + d += level * sizeof(long); |
---|
| 292 | + desc_len -= sizeof(index_key->desc); |
---|
255 | 293 | if (desc_len > n) |
---|
256 | 294 | desc_len = n; |
---|
257 | | - offset += desc_len; |
---|
258 | 295 | do { |
---|
259 | 296 | chunk <<= 8; |
---|
260 | | - chunk |= ((u8*)index_key->description)[--offset]; |
---|
| 297 | + chunk |= *d++; |
---|
261 | 298 | } while (--desc_len > 0); |
---|
262 | | - |
---|
263 | | - if (level == 2) { |
---|
264 | | - chunk <<= 8; |
---|
265 | | - chunk |= (u8)((unsigned long)index_key->type >> |
---|
266 | | - (ASSOC_ARRAY_KEY_CHUNK_SIZE - 8)); |
---|
267 | | - } |
---|
268 | 299 | return chunk; |
---|
269 | 300 | } |
---|
270 | 301 | } |
---|
.. | .. |
---|
281 | 312 | const struct key *key = keyring_ptr_to_key(object); |
---|
282 | 313 | |
---|
283 | 314 | return key->index_key.type == index_key->type && |
---|
| 315 | + key->index_key.domain_tag == index_key->domain_tag && |
---|
284 | 316 | key->index_key.desc_len == index_key->desc_len && |
---|
285 | 317 | memcmp(key->index_key.description, index_key->description, |
---|
286 | 318 | index_key->desc_len) == 0; |
---|
.. | .. |
---|
299 | 331 | int level, i; |
---|
300 | 332 | |
---|
301 | 333 | level = 0; |
---|
302 | | - seg_a = hash_key_type_and_desc(a); |
---|
303 | | - seg_b = hash_key_type_and_desc(b); |
---|
| 334 | + seg_a = a->hash; |
---|
| 335 | + seg_b = b->hash; |
---|
304 | 336 | if ((seg_a ^ seg_b) != 0) |
---|
305 | 337 | goto differ; |
---|
| 338 | + level += ASSOC_ARRAY_KEY_CHUNK_SIZE / 8; |
---|
306 | 339 | |
---|
307 | 340 | /* The number of bits contributed by the hash is controlled by a |
---|
308 | 341 | * constant in the assoc_array headers. Everything else thereafter we |
---|
309 | 342 | * can deal with as being machine word-size dependent. |
---|
310 | 343 | */ |
---|
311 | | - level += ASSOC_ARRAY_KEY_CHUNK_SIZE / 8; |
---|
312 | | - seg_a = a->desc_len; |
---|
313 | | - seg_b = b->desc_len; |
---|
| 344 | + seg_a = a->x; |
---|
| 345 | + seg_b = b->x; |
---|
314 | 346 | if ((seg_a ^ seg_b) != 0) |
---|
315 | 347 | goto differ; |
---|
| 348 | + level += sizeof(unsigned long); |
---|
316 | 349 | |
---|
317 | 350 | /* The next bit may not work on big endian */ |
---|
318 | | - level++; |
---|
319 | 351 | seg_a = (unsigned long)a->type; |
---|
320 | 352 | seg_b = (unsigned long)b->type; |
---|
321 | 353 | if ((seg_a ^ seg_b) != 0) |
---|
322 | 354 | goto differ; |
---|
323 | | - |
---|
324 | 355 | level += sizeof(unsigned long); |
---|
325 | | - if (a->desc_len == 0) |
---|
326 | | - goto same; |
---|
327 | 356 | |
---|
328 | | - i = 0; |
---|
329 | | - if (((unsigned long)a->description | (unsigned long)b->description) & |
---|
330 | | - (sizeof(unsigned long) - 1)) { |
---|
331 | | - do { |
---|
332 | | - seg_a = *(unsigned long *)(a->description + i); |
---|
333 | | - seg_b = *(unsigned long *)(b->description + i); |
---|
334 | | - if ((seg_a ^ seg_b) != 0) |
---|
335 | | - goto differ_plus_i; |
---|
336 | | - i += sizeof(unsigned long); |
---|
337 | | - } while (i < (a->desc_len & (sizeof(unsigned long) - 1))); |
---|
338 | | - } |
---|
| 357 | + seg_a = (unsigned long)a->domain_tag; |
---|
| 358 | + seg_b = (unsigned long)b->domain_tag; |
---|
| 359 | + if ((seg_a ^ seg_b) != 0) |
---|
| 360 | + goto differ; |
---|
| 361 | + level += sizeof(unsigned long); |
---|
| 362 | + |
---|
| 363 | + i = sizeof(a->desc); |
---|
| 364 | + if (a->desc_len <= i) |
---|
| 365 | + goto same; |
---|
339 | 366 | |
---|
340 | 367 | for (; i < a->desc_len; i++) { |
---|
341 | 368 | seg_a = *(unsigned char *)(a->description + i); |
---|
.. | .. |
---|
515 | 542 | * @keyring: The keyring being added to. |
---|
516 | 543 | * @type: The type of key being added. |
---|
517 | 544 | * @payload: The payload of the key intended to be added. |
---|
518 | | - * @data: Additional data for evaluating restriction. |
---|
| 545 | + * @restriction_key: Keys providing additional data for evaluating restriction. |
---|
519 | 546 | * |
---|
520 | 547 | * Reject the addition of any links to a keyring. It can be overridden by |
---|
521 | 548 | * passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when |
---|
.. | .. |
---|
657 | 684 | BUG_ON((ctx->flags & STATE_CHECKS) == 0 || |
---|
658 | 685 | (ctx->flags & STATE_CHECKS) == STATE_CHECKS); |
---|
659 | 686 | |
---|
| 687 | + if (ctx->index_key.description) |
---|
| 688 | + key_set_index_key(&ctx->index_key); |
---|
| 689 | + |
---|
660 | 690 | /* Check to see if this top-level keyring is what we are looking for |
---|
661 | 691 | * and whether it is valid or not. |
---|
662 | 692 | */ |
---|
.. | .. |
---|
696 | 726 | * Non-keyrings avoid the leftmost branch of the root entirely (root |
---|
697 | 727 | * slots 1-15). |
---|
698 | 728 | */ |
---|
| 729 | + if (!(ctx->flags & KEYRING_SEARCH_RECURSE)) |
---|
| 730 | + goto not_this_keyring; |
---|
| 731 | + |
---|
699 | 732 | ptr = READ_ONCE(keyring->keys.root); |
---|
700 | 733 | if (!ptr) |
---|
701 | 734 | goto not_this_keyring; |
---|
.. | .. |
---|
830 | 863 | } |
---|
831 | 864 | |
---|
832 | 865 | /** |
---|
833 | | - * keyring_search_aux - Search a keyring tree for a key matching some criteria |
---|
| 866 | + * keyring_search_rcu - Search a keyring tree for a matching key under RCU |
---|
834 | 867 | * @keyring_ref: A pointer to the keyring with possession indicator. |
---|
835 | 868 | * @ctx: The keyring search context. |
---|
836 | 869 | * |
---|
.. | .. |
---|
842 | 875 | * addition, the LSM gets to forbid keyring searches and key matches. |
---|
843 | 876 | * |
---|
844 | 877 | * The search is performed as a breadth-then-depth search up to the prescribed |
---|
845 | | - * limit (KEYRING_SEARCH_MAX_DEPTH). |
---|
| 878 | + * limit (KEYRING_SEARCH_MAX_DEPTH). The caller must hold the RCU read lock to |
---|
| 879 | + * prevent keyrings from being destroyed or rearranged whilst they are being |
---|
| 880 | + * searched. |
---|
846 | 881 | * |
---|
847 | 882 | * Keys are matched to the type provided and are then filtered by the match |
---|
848 | 883 | * function, which is given the description to use in any way it sees fit. The |
---|
.. | .. |
---|
861 | 896 | * In the case of a successful return, the possession attribute from |
---|
862 | 897 | * @keyring_ref is propagated to the returned key reference. |
---|
863 | 898 | */ |
---|
864 | | -key_ref_t keyring_search_aux(key_ref_t keyring_ref, |
---|
| 899 | +key_ref_t keyring_search_rcu(key_ref_t keyring_ref, |
---|
865 | 900 | struct keyring_search_context *ctx) |
---|
866 | 901 | { |
---|
867 | 902 | struct key *keyring; |
---|
.. | .. |
---|
883 | 918 | return ERR_PTR(err); |
---|
884 | 919 | } |
---|
885 | 920 | |
---|
886 | | - rcu_read_lock(); |
---|
887 | 921 | ctx->now = ktime_get_real_seconds(); |
---|
888 | 922 | if (search_nested_keyrings(keyring, ctx)) |
---|
889 | 923 | __key_get(key_ref_to_ptr(ctx->result)); |
---|
890 | | - rcu_read_unlock(); |
---|
891 | 924 | return ctx->result; |
---|
892 | 925 | } |
---|
893 | 926 | |
---|
.. | .. |
---|
896 | 929 | * @keyring: The root of the keyring tree to be searched. |
---|
897 | 930 | * @type: The type of keyring we want to find. |
---|
898 | 931 | * @description: The name of the keyring we want to find. |
---|
| 932 | + * @recurse: True to search the children of @keyring also |
---|
899 | 933 | * |
---|
900 | | - * As keyring_search_aux() above, but using the current task's credentials and |
---|
| 934 | + * As keyring_search_rcu() above, but using the current task's credentials and |
---|
901 | 935 | * type's default matching function and preferred search method. |
---|
902 | 936 | */ |
---|
903 | 937 | key_ref_t keyring_search(key_ref_t keyring, |
---|
904 | 938 | struct key_type *type, |
---|
905 | | - const char *description) |
---|
| 939 | + const char *description, |
---|
| 940 | + bool recurse) |
---|
906 | 941 | { |
---|
907 | 942 | struct keyring_search_context ctx = { |
---|
908 | 943 | .index_key.type = type, |
---|
.. | .. |
---|
917 | 952 | key_ref_t key; |
---|
918 | 953 | int ret; |
---|
919 | 954 | |
---|
| 955 | + if (recurse) |
---|
| 956 | + ctx.flags |= KEYRING_SEARCH_RECURSE; |
---|
920 | 957 | if (type->match_preparse) { |
---|
921 | 958 | ret = type->match_preparse(&ctx.match_data); |
---|
922 | 959 | if (ret < 0) |
---|
923 | 960 | return ERR_PTR(ret); |
---|
924 | 961 | } |
---|
925 | 962 | |
---|
926 | | - key = keyring_search_aux(keyring, &ctx); |
---|
| 963 | + rcu_read_lock(); |
---|
| 964 | + key = keyring_search_rcu(keyring, &ctx); |
---|
| 965 | + rcu_read_unlock(); |
---|
927 | 966 | |
---|
928 | 967 | if (type->match_free) |
---|
929 | 968 | type->match_free(&ctx.match_data); |
---|
.. | .. |
---|
971 | 1010 | |
---|
972 | 1011 | /** |
---|
973 | 1012 | * keyring_restrict - Look up and apply a restriction to a keyring |
---|
974 | | - * |
---|
975 | | - * @keyring: The keyring to be restricted |
---|
| 1013 | + * @keyring_ref: The keyring to be restricted |
---|
| 1014 | + * @type: The key type that will provide the restriction checker. |
---|
976 | 1015 | * @restriction: The restriction options to apply to the keyring |
---|
| 1016 | + * |
---|
| 1017 | + * Look up a keyring and apply a restriction to it. The restriction is managed |
---|
| 1018 | + * by the specific key type, but can be configured by the options specified in |
---|
| 1019 | + * the restriction string. |
---|
977 | 1020 | */ |
---|
978 | 1021 | int keyring_restrict(key_ref_t keyring_ref, const char *type, |
---|
979 | 1022 | const char *restriction) |
---|
.. | .. |
---|
1013 | 1056 | down_write(&keyring->sem); |
---|
1014 | 1057 | down_write(&keyring_serialise_restrict_sem); |
---|
1015 | 1058 | |
---|
1016 | | - if (keyring->restrict_link) |
---|
| 1059 | + if (keyring->restrict_link) { |
---|
1017 | 1060 | ret = -EEXIST; |
---|
1018 | | - else if (keyring_detect_restriction_cycle(keyring, restrict_link)) |
---|
| 1061 | + } else if (keyring_detect_restriction_cycle(keyring, restrict_link)) { |
---|
1019 | 1062 | ret = -EDEADLK; |
---|
1020 | | - else |
---|
| 1063 | + } else { |
---|
1021 | 1064 | keyring->restrict_link = restrict_link; |
---|
| 1065 | + notify_key(keyring, NOTIFY_KEY_SETATTR, 0); |
---|
| 1066 | + } |
---|
1022 | 1067 | |
---|
1023 | 1068 | up_write(&keyring_serialise_restrict_sem); |
---|
1024 | 1069 | up_write(&keyring->sem); |
---|
.. | .. |
---|
1095 | 1140 | */ |
---|
1096 | 1141 | struct key *find_keyring_by_name(const char *name, bool uid_keyring) |
---|
1097 | 1142 | { |
---|
| 1143 | + struct user_namespace *ns = current_user_ns(); |
---|
1098 | 1144 | struct key *keyring; |
---|
1099 | | - int bucket; |
---|
1100 | 1145 | |
---|
1101 | 1146 | if (!name) |
---|
1102 | 1147 | return ERR_PTR(-EINVAL); |
---|
1103 | 1148 | |
---|
1104 | | - bucket = keyring_hash(name); |
---|
1105 | | - |
---|
1106 | 1149 | read_lock(&keyring_name_lock); |
---|
1107 | 1150 | |
---|
1108 | | - if (keyring_name_hash[bucket].next) { |
---|
1109 | | - /* search this hash bucket for a keyring with a matching name |
---|
1110 | | - * that's readable and that hasn't been revoked */ |
---|
1111 | | - list_for_each_entry(keyring, |
---|
1112 | | - &keyring_name_hash[bucket], |
---|
1113 | | - name_link |
---|
1114 | | - ) { |
---|
1115 | | - if (!kuid_has_mapping(current_user_ns(), keyring->user->uid)) |
---|
1116 | | - continue; |
---|
| 1151 | + /* Search this hash bucket for a keyring with a matching name that |
---|
| 1152 | + * grants Search permission and that hasn't been revoked |
---|
| 1153 | + */ |
---|
| 1154 | + list_for_each_entry(keyring, &ns->keyring_name_list, name_link) { |
---|
| 1155 | + if (!kuid_has_mapping(ns, keyring->user->uid)) |
---|
| 1156 | + continue; |
---|
1117 | 1157 | |
---|
1118 | | - if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
---|
1119 | | - continue; |
---|
| 1158 | + if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
---|
| 1159 | + continue; |
---|
1120 | 1160 | |
---|
1121 | | - if (strcmp(keyring->description, name) != 0) |
---|
1122 | | - continue; |
---|
| 1161 | + if (strcmp(keyring->description, name) != 0) |
---|
| 1162 | + continue; |
---|
1123 | 1163 | |
---|
1124 | | - if (uid_keyring) { |
---|
1125 | | - if (!test_bit(KEY_FLAG_UID_KEYRING, |
---|
1126 | | - &keyring->flags)) |
---|
1127 | | - continue; |
---|
1128 | | - } else { |
---|
1129 | | - if (key_permission(make_key_ref(keyring, 0), |
---|
1130 | | - KEY_NEED_SEARCH) < 0) |
---|
1131 | | - continue; |
---|
1132 | | - } |
---|
1133 | | - |
---|
1134 | | - /* we've got a match but we might end up racing with |
---|
1135 | | - * key_cleanup() if the keyring is currently 'dead' |
---|
1136 | | - * (ie. it has a zero usage count) */ |
---|
1137 | | - if (!refcount_inc_not_zero(&keyring->usage)) |
---|
| 1164 | + if (uid_keyring) { |
---|
| 1165 | + if (!test_bit(KEY_FLAG_UID_KEYRING, |
---|
| 1166 | + &keyring->flags)) |
---|
1138 | 1167 | continue; |
---|
1139 | | - keyring->last_used_at = ktime_get_real_seconds(); |
---|
1140 | | - goto out; |
---|
| 1168 | + } else { |
---|
| 1169 | + if (key_permission(make_key_ref(keyring, 0), |
---|
| 1170 | + KEY_NEED_SEARCH) < 0) |
---|
| 1171 | + continue; |
---|
1141 | 1172 | } |
---|
| 1173 | + |
---|
| 1174 | + /* we've got a match but we might end up racing with |
---|
| 1175 | + * key_cleanup() if the keyring is currently 'dead' |
---|
| 1176 | + * (ie. it has a zero usage count) */ |
---|
| 1177 | + if (!refcount_inc_not_zero(&keyring->usage)) |
---|
| 1178 | + continue; |
---|
| 1179 | + keyring->last_used_at = ktime_get_real_seconds(); |
---|
| 1180 | + goto out; |
---|
1142 | 1181 | } |
---|
1143 | 1182 | |
---|
1144 | 1183 | keyring = ERR_PTR(-ENOKEY); |
---|
.. | .. |
---|
1181 | 1220 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | |
---|
1182 | 1221 | KEYRING_SEARCH_NO_UPDATE_TIME | |
---|
1183 | 1222 | KEYRING_SEARCH_NO_CHECK_PERM | |
---|
1184 | | - KEYRING_SEARCH_DETECT_TOO_DEEP), |
---|
| 1223 | + KEYRING_SEARCH_DETECT_TOO_DEEP | |
---|
| 1224 | + KEYRING_SEARCH_RECURSE), |
---|
1185 | 1225 | }; |
---|
1186 | 1226 | |
---|
1187 | 1227 | rcu_read_lock(); |
---|
.. | .. |
---|
1191 | 1231 | } |
---|
1192 | 1232 | |
---|
1193 | 1233 | /* |
---|
| 1234 | + * Lock keyring for link. |
---|
| 1235 | + */ |
---|
| 1236 | +int __key_link_lock(struct key *keyring, |
---|
| 1237 | + const struct keyring_index_key *index_key) |
---|
| 1238 | + __acquires(&keyring->sem) |
---|
| 1239 | + __acquires(&keyring_serialise_link_lock) |
---|
| 1240 | +{ |
---|
| 1241 | + if (keyring->type != &key_type_keyring) |
---|
| 1242 | + return -ENOTDIR; |
---|
| 1243 | + |
---|
| 1244 | + down_write(&keyring->sem); |
---|
| 1245 | + |
---|
| 1246 | + /* Serialise link/link calls to prevent parallel calls causing a cycle |
---|
| 1247 | + * when linking two keyring in opposite orders. |
---|
| 1248 | + */ |
---|
| 1249 | + if (index_key->type == &key_type_keyring) |
---|
| 1250 | + mutex_lock(&keyring_serialise_link_lock); |
---|
| 1251 | + |
---|
| 1252 | + return 0; |
---|
| 1253 | +} |
---|
| 1254 | + |
---|
| 1255 | +/* |
---|
| 1256 | + * Lock keyrings for move (link/unlink combination). |
---|
| 1257 | + */ |
---|
| 1258 | +int __key_move_lock(struct key *l_keyring, struct key *u_keyring, |
---|
| 1259 | + const struct keyring_index_key *index_key) |
---|
| 1260 | + __acquires(&l_keyring->sem) |
---|
| 1261 | + __acquires(&u_keyring->sem) |
---|
| 1262 | + __acquires(&keyring_serialise_link_lock) |
---|
| 1263 | +{ |
---|
| 1264 | + if (l_keyring->type != &key_type_keyring || |
---|
| 1265 | + u_keyring->type != &key_type_keyring) |
---|
| 1266 | + return -ENOTDIR; |
---|
| 1267 | + |
---|
| 1268 | + /* We have to be very careful here to take the keyring locks in the |
---|
| 1269 | + * right order, lest we open ourselves to deadlocking against another |
---|
| 1270 | + * move operation. |
---|
| 1271 | + */ |
---|
| 1272 | + if (l_keyring < u_keyring) { |
---|
| 1273 | + down_write(&l_keyring->sem); |
---|
| 1274 | + down_write_nested(&u_keyring->sem, 1); |
---|
| 1275 | + } else { |
---|
| 1276 | + down_write(&u_keyring->sem); |
---|
| 1277 | + down_write_nested(&l_keyring->sem, 1); |
---|
| 1278 | + } |
---|
| 1279 | + |
---|
| 1280 | + /* Serialise link/link calls to prevent parallel calls causing a cycle |
---|
| 1281 | + * when linking two keyring in opposite orders. |
---|
| 1282 | + */ |
---|
| 1283 | + if (index_key->type == &key_type_keyring) |
---|
| 1284 | + mutex_lock(&keyring_serialise_link_lock); |
---|
| 1285 | + |
---|
| 1286 | + return 0; |
---|
| 1287 | +} |
---|
| 1288 | + |
---|
| 1289 | +/* |
---|
1194 | 1290 | * Preallocate memory so that a key can be linked into to a keyring. |
---|
1195 | 1291 | */ |
---|
1196 | 1292 | int __key_link_begin(struct key *keyring, |
---|
1197 | 1293 | const struct keyring_index_key *index_key, |
---|
1198 | 1294 | struct assoc_array_edit **_edit) |
---|
1199 | | - __acquires(&keyring->sem) |
---|
1200 | | - __acquires(&keyring_serialise_link_sem) |
---|
1201 | 1295 | { |
---|
1202 | 1296 | struct assoc_array_edit *edit; |
---|
1203 | 1297 | int ret; |
---|
.. | .. |
---|
1206 | 1300 | keyring->serial, index_key->type->name, index_key->description); |
---|
1207 | 1301 | |
---|
1208 | 1302 | BUG_ON(index_key->desc_len == 0); |
---|
| 1303 | + BUG_ON(*_edit != NULL); |
---|
1209 | 1304 | |
---|
1210 | | - if (keyring->type != &key_type_keyring) |
---|
1211 | | - return -ENOTDIR; |
---|
1212 | | - |
---|
1213 | | - down_write(&keyring->sem); |
---|
| 1305 | + *_edit = NULL; |
---|
1214 | 1306 | |
---|
1215 | 1307 | ret = -EKEYREVOKED; |
---|
1216 | 1308 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
---|
1217 | | - goto error_krsem; |
---|
1218 | | - |
---|
1219 | | - /* serialise link/link calls to prevent parallel calls causing a cycle |
---|
1220 | | - * when linking two keyring in opposite orders */ |
---|
1221 | | - if (index_key->type == &key_type_keyring) |
---|
1222 | | - down_write(&keyring_serialise_link_sem); |
---|
| 1309 | + goto error; |
---|
1223 | 1310 | |
---|
1224 | 1311 | /* Create an edit script that will insert/replace the key in the |
---|
1225 | 1312 | * keyring tree. |
---|
.. | .. |
---|
1230 | 1317 | NULL); |
---|
1231 | 1318 | if (IS_ERR(edit)) { |
---|
1232 | 1319 | ret = PTR_ERR(edit); |
---|
1233 | | - goto error_sem; |
---|
| 1320 | + goto error; |
---|
1234 | 1321 | } |
---|
1235 | 1322 | |
---|
1236 | 1323 | /* If we're not replacing a link in-place then we're going to need some |
---|
.. | .. |
---|
1249 | 1336 | |
---|
1250 | 1337 | error_cancel: |
---|
1251 | 1338 | assoc_array_cancel_edit(edit); |
---|
1252 | | -error_sem: |
---|
1253 | | - if (index_key->type == &key_type_keyring) |
---|
1254 | | - up_write(&keyring_serialise_link_sem); |
---|
1255 | | -error_krsem: |
---|
1256 | | - up_write(&keyring->sem); |
---|
| 1339 | +error: |
---|
1257 | 1340 | kleave(" = %d", ret); |
---|
1258 | 1341 | return ret; |
---|
1259 | 1342 | } |
---|
.. | .. |
---|
1281 | 1364 | * holds at most one link to any given key of a particular type+description |
---|
1282 | 1365 | * combination. |
---|
1283 | 1366 | */ |
---|
1284 | | -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) |
---|
1285 | 1369 | { |
---|
1286 | 1370 | __key_get(key); |
---|
1287 | 1371 | assoc_array_insert_set_object(*_edit, keyring_key_to_ptr(key)); |
---|
1288 | 1372 | assoc_array_apply_edit(*_edit); |
---|
1289 | 1373 | *_edit = NULL; |
---|
| 1374 | + notify_key(keyring, NOTIFY_KEY_LINKED, key_serial(key)); |
---|
1290 | 1375 | } |
---|
1291 | 1376 | |
---|
1292 | 1377 | /* |
---|
.. | .. |
---|
1298 | 1383 | const struct keyring_index_key *index_key, |
---|
1299 | 1384 | struct assoc_array_edit *edit) |
---|
1300 | 1385 | __releases(&keyring->sem) |
---|
1301 | | - __releases(&keyring_serialise_link_sem) |
---|
| 1386 | + __releases(&keyring_serialise_link_lock) |
---|
1302 | 1387 | { |
---|
1303 | 1388 | BUG_ON(index_key->type == NULL); |
---|
1304 | 1389 | kenter("%d,%s,", keyring->serial, index_key->type->name); |
---|
1305 | | - |
---|
1306 | | - if (index_key->type == &key_type_keyring) |
---|
1307 | | - up_write(&keyring_serialise_link_sem); |
---|
1308 | 1390 | |
---|
1309 | 1391 | if (edit) { |
---|
1310 | 1392 | if (!edit->dead_leaf) { |
---|
.. | .. |
---|
1314 | 1396 | assoc_array_cancel_edit(edit); |
---|
1315 | 1397 | } |
---|
1316 | 1398 | up_write(&keyring->sem); |
---|
| 1399 | + |
---|
| 1400 | + if (index_key->type == &key_type_keyring) |
---|
| 1401 | + mutex_unlock(&keyring_serialise_link_lock); |
---|
1317 | 1402 | } |
---|
1318 | 1403 | |
---|
1319 | 1404 | /* |
---|
.. | .. |
---|
1349 | 1434 | */ |
---|
1350 | 1435 | int key_link(struct key *keyring, struct key *key) |
---|
1351 | 1436 | { |
---|
1352 | | - struct assoc_array_edit *edit; |
---|
| 1437 | + struct assoc_array_edit *edit = NULL; |
---|
1353 | 1438 | int ret; |
---|
1354 | 1439 | |
---|
1355 | 1440 | kenter("{%d,%d}", keyring->serial, refcount_read(&keyring->usage)); |
---|
.. | .. |
---|
1357 | 1442 | key_check(keyring); |
---|
1358 | 1443 | key_check(key); |
---|
1359 | 1444 | |
---|
1360 | | - ret = __key_link_begin(keyring, &key->index_key, &edit); |
---|
1361 | | - if (ret == 0) { |
---|
1362 | | - kdebug("begun {%d,%d}", keyring->serial, refcount_read(&keyring->usage)); |
---|
1363 | | - ret = __key_link_check_restriction(keyring, key); |
---|
1364 | | - if (ret == 0) |
---|
1365 | | - ret = __key_link_check_live_key(keyring, key); |
---|
1366 | | - if (ret == 0) |
---|
1367 | | - __key_link(key, &edit); |
---|
1368 | | - __key_link_end(keyring, &key->index_key, edit); |
---|
1369 | | - } |
---|
| 1445 | + ret = __key_link_lock(keyring, &key->index_key); |
---|
| 1446 | + if (ret < 0) |
---|
| 1447 | + goto error; |
---|
1370 | 1448 | |
---|
| 1449 | + ret = __key_link_begin(keyring, &key->index_key, &edit); |
---|
| 1450 | + if (ret < 0) |
---|
| 1451 | + goto error_end; |
---|
| 1452 | + |
---|
| 1453 | + kdebug("begun {%d,%d}", keyring->serial, refcount_read(&keyring->usage)); |
---|
| 1454 | + ret = __key_link_check_restriction(keyring, key); |
---|
| 1455 | + if (ret == 0) |
---|
| 1456 | + ret = __key_link_check_live_key(keyring, key); |
---|
| 1457 | + if (ret == 0) |
---|
| 1458 | + __key_link(keyring, key, &edit); |
---|
| 1459 | + |
---|
| 1460 | +error_end: |
---|
| 1461 | + __key_link_end(keyring, &key->index_key, edit); |
---|
| 1462 | +error: |
---|
1371 | 1463 | kleave(" = %d {%d,%d}", ret, keyring->serial, refcount_read(&keyring->usage)); |
---|
1372 | 1464 | return ret; |
---|
1373 | 1465 | } |
---|
1374 | 1466 | EXPORT_SYMBOL(key_link); |
---|
| 1467 | + |
---|
| 1468 | +/* |
---|
| 1469 | + * Lock a keyring for unlink. |
---|
| 1470 | + */ |
---|
| 1471 | +static int __key_unlink_lock(struct key *keyring) |
---|
| 1472 | + __acquires(&keyring->sem) |
---|
| 1473 | +{ |
---|
| 1474 | + if (keyring->type != &key_type_keyring) |
---|
| 1475 | + return -ENOTDIR; |
---|
| 1476 | + |
---|
| 1477 | + down_write(&keyring->sem); |
---|
| 1478 | + return 0; |
---|
| 1479 | +} |
---|
| 1480 | + |
---|
| 1481 | +/* |
---|
| 1482 | + * Begin the process of unlinking a key from a keyring. |
---|
| 1483 | + */ |
---|
| 1484 | +static int __key_unlink_begin(struct key *keyring, struct key *key, |
---|
| 1485 | + struct assoc_array_edit **_edit) |
---|
| 1486 | +{ |
---|
| 1487 | + struct assoc_array_edit *edit; |
---|
| 1488 | + |
---|
| 1489 | + BUG_ON(*_edit != NULL); |
---|
| 1490 | + |
---|
| 1491 | + edit = assoc_array_delete(&keyring->keys, &keyring_assoc_array_ops, |
---|
| 1492 | + &key->index_key); |
---|
| 1493 | + if (IS_ERR(edit)) |
---|
| 1494 | + return PTR_ERR(edit); |
---|
| 1495 | + |
---|
| 1496 | + if (!edit) |
---|
| 1497 | + return -ENOENT; |
---|
| 1498 | + |
---|
| 1499 | + *_edit = edit; |
---|
| 1500 | + return 0; |
---|
| 1501 | +} |
---|
| 1502 | + |
---|
| 1503 | +/* |
---|
| 1504 | + * Apply an unlink change. |
---|
| 1505 | + */ |
---|
| 1506 | +static void __key_unlink(struct key *keyring, struct key *key, |
---|
| 1507 | + struct assoc_array_edit **_edit) |
---|
| 1508 | +{ |
---|
| 1509 | + assoc_array_apply_edit(*_edit); |
---|
| 1510 | + notify_key(keyring, NOTIFY_KEY_UNLINKED, key_serial(key)); |
---|
| 1511 | + *_edit = NULL; |
---|
| 1512 | + key_payload_reserve(keyring, keyring->datalen - KEYQUOTA_LINK_BYTES); |
---|
| 1513 | +} |
---|
| 1514 | + |
---|
| 1515 | +/* |
---|
| 1516 | + * Finish unlinking a key from to a keyring. |
---|
| 1517 | + */ |
---|
| 1518 | +static void __key_unlink_end(struct key *keyring, |
---|
| 1519 | + struct key *key, |
---|
| 1520 | + struct assoc_array_edit *edit) |
---|
| 1521 | + __releases(&keyring->sem) |
---|
| 1522 | +{ |
---|
| 1523 | + if (edit) |
---|
| 1524 | + assoc_array_cancel_edit(edit); |
---|
| 1525 | + up_write(&keyring->sem); |
---|
| 1526 | +} |
---|
1375 | 1527 | |
---|
1376 | 1528 | /** |
---|
1377 | 1529 | * key_unlink - Unlink the first link to a key from a keyring. |
---|
.. | .. |
---|
1392 | 1544 | */ |
---|
1393 | 1545 | int key_unlink(struct key *keyring, struct key *key) |
---|
1394 | 1546 | { |
---|
1395 | | - struct assoc_array_edit *edit; |
---|
| 1547 | + struct assoc_array_edit *edit = NULL; |
---|
1396 | 1548 | int ret; |
---|
1397 | 1549 | |
---|
1398 | 1550 | key_check(keyring); |
---|
1399 | 1551 | key_check(key); |
---|
1400 | 1552 | |
---|
1401 | | - if (keyring->type != &key_type_keyring) |
---|
1402 | | - return -ENOTDIR; |
---|
| 1553 | + ret = __key_unlink_lock(keyring); |
---|
| 1554 | + if (ret < 0) |
---|
| 1555 | + return ret; |
---|
1403 | 1556 | |
---|
1404 | | - down_write(&keyring->sem); |
---|
1405 | | - |
---|
1406 | | - edit = assoc_array_delete(&keyring->keys, &keyring_assoc_array_ops, |
---|
1407 | | - &key->index_key); |
---|
1408 | | - if (IS_ERR(edit)) { |
---|
1409 | | - ret = PTR_ERR(edit); |
---|
1410 | | - goto error; |
---|
1411 | | - } |
---|
1412 | | - ret = -ENOENT; |
---|
1413 | | - if (edit == NULL) |
---|
1414 | | - goto error; |
---|
1415 | | - |
---|
1416 | | - assoc_array_apply_edit(edit); |
---|
1417 | | - key_payload_reserve(keyring, keyring->datalen - KEYQUOTA_LINK_BYTES); |
---|
1418 | | - ret = 0; |
---|
1419 | | - |
---|
1420 | | -error: |
---|
1421 | | - up_write(&keyring->sem); |
---|
| 1557 | + ret = __key_unlink_begin(keyring, key, &edit); |
---|
| 1558 | + if (ret == 0) |
---|
| 1559 | + __key_unlink(keyring, key, &edit); |
---|
| 1560 | + __key_unlink_end(keyring, key, edit); |
---|
1422 | 1561 | return ret; |
---|
1423 | 1562 | } |
---|
1424 | 1563 | EXPORT_SYMBOL(key_unlink); |
---|
| 1564 | + |
---|
| 1565 | +/** |
---|
| 1566 | + * key_move - Move a key from one keyring to another |
---|
| 1567 | + * @key: The key to move |
---|
| 1568 | + * @from_keyring: The keyring to remove the link from. |
---|
| 1569 | + * @to_keyring: The keyring to make the link in. |
---|
| 1570 | + * @flags: Qualifying flags, such as KEYCTL_MOVE_EXCL. |
---|
| 1571 | + * |
---|
| 1572 | + * Make a link in @to_keyring to a key, such that the keyring holds a reference |
---|
| 1573 | + * on that key and the key can potentially be found by searching that keyring |
---|
| 1574 | + * whilst simultaneously removing a link to the key from @from_keyring. |
---|
| 1575 | + * |
---|
| 1576 | + * This function will write-lock both keyring's semaphores and will consume |
---|
| 1577 | + * some of the user's key data quota to hold the link on @to_keyring. |
---|
| 1578 | + * |
---|
| 1579 | + * Returns 0 if successful, -ENOTDIR if either keyring isn't a keyring, |
---|
| 1580 | + * -EKEYREVOKED if either keyring has been revoked, -ENFILE if the second |
---|
| 1581 | + * keyring is full, -EDQUOT if there is insufficient key data quota remaining |
---|
| 1582 | + * to add another link or -ENOMEM if there's insufficient memory. If |
---|
| 1583 | + * KEYCTL_MOVE_EXCL is set, then -EEXIST will be returned if there's already a |
---|
| 1584 | + * matching key in @to_keyring. |
---|
| 1585 | + * |
---|
| 1586 | + * It is assumed that the caller has checked that it is permitted for a link to |
---|
| 1587 | + * be made (the keyring should have Write permission and the key Link |
---|
| 1588 | + * permission). |
---|
| 1589 | + */ |
---|
| 1590 | +int key_move(struct key *key, |
---|
| 1591 | + struct key *from_keyring, |
---|
| 1592 | + struct key *to_keyring, |
---|
| 1593 | + unsigned int flags) |
---|
| 1594 | +{ |
---|
| 1595 | + struct assoc_array_edit *from_edit = NULL, *to_edit = NULL; |
---|
| 1596 | + int ret; |
---|
| 1597 | + |
---|
| 1598 | + kenter("%d,%d,%d", key->serial, from_keyring->serial, to_keyring->serial); |
---|
| 1599 | + |
---|
| 1600 | + if (from_keyring == to_keyring) |
---|
| 1601 | + return 0; |
---|
| 1602 | + |
---|
| 1603 | + key_check(key); |
---|
| 1604 | + key_check(from_keyring); |
---|
| 1605 | + key_check(to_keyring); |
---|
| 1606 | + |
---|
| 1607 | + ret = __key_move_lock(from_keyring, to_keyring, &key->index_key); |
---|
| 1608 | + if (ret < 0) |
---|
| 1609 | + goto out; |
---|
| 1610 | + ret = __key_unlink_begin(from_keyring, key, &from_edit); |
---|
| 1611 | + if (ret < 0) |
---|
| 1612 | + goto error; |
---|
| 1613 | + ret = __key_link_begin(to_keyring, &key->index_key, &to_edit); |
---|
| 1614 | + if (ret < 0) |
---|
| 1615 | + goto error; |
---|
| 1616 | + |
---|
| 1617 | + ret = -EEXIST; |
---|
| 1618 | + if (to_edit->dead_leaf && (flags & KEYCTL_MOVE_EXCL)) |
---|
| 1619 | + goto error; |
---|
| 1620 | + |
---|
| 1621 | + ret = __key_link_check_restriction(to_keyring, key); |
---|
| 1622 | + if (ret < 0) |
---|
| 1623 | + goto error; |
---|
| 1624 | + ret = __key_link_check_live_key(to_keyring, key); |
---|
| 1625 | + if (ret < 0) |
---|
| 1626 | + goto error; |
---|
| 1627 | + |
---|
| 1628 | + __key_unlink(from_keyring, key, &from_edit); |
---|
| 1629 | + __key_link(to_keyring, key, &to_edit); |
---|
| 1630 | +error: |
---|
| 1631 | + __key_link_end(to_keyring, &key->index_key, to_edit); |
---|
| 1632 | + __key_unlink_end(from_keyring, key, from_edit); |
---|
| 1633 | +out: |
---|
| 1634 | + kleave(" = %d", ret); |
---|
| 1635 | + return ret; |
---|
| 1636 | +} |
---|
| 1637 | +EXPORT_SYMBOL(key_move); |
---|
1425 | 1638 | |
---|
1426 | 1639 | /** |
---|
1427 | 1640 | * keyring_clear - Clear a keyring |
---|
.. | .. |
---|
1447 | 1660 | } else { |
---|
1448 | 1661 | if (edit) |
---|
1449 | 1662 | assoc_array_apply_edit(edit); |
---|
| 1663 | + notify_key(keyring, NOTIFY_KEY_CLEARED, 0); |
---|
1450 | 1664 | key_payload_reserve(keyring, 0); |
---|
1451 | 1665 | ret = 0; |
---|
1452 | 1666 | } |
---|