Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* keyring.c: keyring handling |
2 | * | |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | |
4 | * 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 | */ | |
11 | ||
12 | #include <linux/module.h> | |
13 | #include <linux/init.h> | |
14 | #include <linux/sched.h> | |
15 | #include <linux/slab.h> | |
16 | #include <linux/seq_file.h> | |
17 | #include <linux/err.h> | |
18 | #include <asm/uaccess.h> | |
19 | #include "internal.h" | |
20 | ||
21 | /* | |
22 | * when plumbing the depths of the key tree, this sets a hard limit set on how | |
23 | * deep we're willing to go | |
24 | */ | |
25 | #define KEYRING_SEARCH_MAX_DEPTH 6 | |
26 | ||
27 | /* | |
28 | * we keep all named keyrings in a hash to speed looking them up | |
29 | */ | |
30 | #define KEYRING_NAME_HASH_SIZE (1 << 5) | |
31 | ||
32 | static struct list_head keyring_name_hash[KEYRING_NAME_HASH_SIZE]; | |
33 | static DEFINE_RWLOCK(keyring_name_lock); | |
34 | ||
35 | static inline unsigned keyring_hash(const char *desc) | |
36 | { | |
37 | unsigned bucket = 0; | |
38 | ||
39 | for (; *desc; desc++) | |
40 | bucket += (unsigned char) *desc; | |
41 | ||
42 | return bucket & (KEYRING_NAME_HASH_SIZE - 1); | |
43 | } | |
44 | ||
45 | /* | |
46 | * the keyring type definition | |
47 | */ | |
48 | static int keyring_instantiate(struct key *keyring, | |
49 | const void *data, size_t datalen); | |
50 | static int keyring_duplicate(struct key *keyring, const struct key *source); | |
51 | static int keyring_match(const struct key *keyring, const void *criterion); | |
52 | static void keyring_destroy(struct key *keyring); | |
53 | static void keyring_describe(const struct key *keyring, struct seq_file *m); | |
54 | static long keyring_read(const struct key *keyring, | |
55 | char __user *buffer, size_t buflen); | |
56 | ||
57 | struct key_type key_type_keyring = { | |
58 | .name = "keyring", | |
59 | .def_datalen = sizeof(struct keyring_list), | |
60 | .instantiate = keyring_instantiate, | |
61 | .duplicate = keyring_duplicate, | |
62 | .match = keyring_match, | |
63 | .destroy = keyring_destroy, | |
64 | .describe = keyring_describe, | |
65 | .read = keyring_read, | |
66 | }; | |
67 | ||
68 | /* | |
69 | * semaphore to serialise link/link calls to prevent two link calls in parallel | |
70 | * introducing a cycle | |
71 | */ | |
72 | DECLARE_RWSEM(keyring_serialise_link_sem); | |
73 | ||
74 | /*****************************************************************************/ | |
75 | /* | |
76 | * publish the name of a keyring so that it can be found by name (if it has | |
77 | * one) | |
78 | */ | |
79 | void keyring_publish_name(struct key *keyring) | |
80 | { | |
81 | int bucket; | |
82 | ||
83 | if (keyring->description) { | |
84 | bucket = keyring_hash(keyring->description); | |
85 | ||
86 | write_lock(&keyring_name_lock); | |
87 | ||
88 | if (!keyring_name_hash[bucket].next) | |
89 | INIT_LIST_HEAD(&keyring_name_hash[bucket]); | |
90 | ||
91 | list_add_tail(&keyring->type_data.link, | |
92 | &keyring_name_hash[bucket]); | |
93 | ||
94 | write_unlock(&keyring_name_lock); | |
95 | } | |
96 | ||
97 | } /* end keyring_publish_name() */ | |
98 | ||
99 | /*****************************************************************************/ | |
100 | /* | |
101 | * initialise a keyring | |
102 | * - we object if we were given any data | |
103 | */ | |
104 | static int keyring_instantiate(struct key *keyring, | |
105 | const void *data, size_t datalen) | |
106 | { | |
107 | int ret; | |
108 | ||
109 | ret = -EINVAL; | |
110 | if (datalen == 0) { | |
111 | /* make the keyring available by name if it has one */ | |
112 | keyring_publish_name(keyring); | |
113 | ret = 0; | |
114 | } | |
115 | ||
116 | return ret; | |
117 | ||
118 | } /* end keyring_instantiate() */ | |
119 | ||
120 | /*****************************************************************************/ | |
121 | /* | |
122 | * duplicate the list of subscribed keys from a source keyring into this one | |
123 | */ | |
124 | static int keyring_duplicate(struct key *keyring, const struct key *source) | |
125 | { | |
126 | struct keyring_list *sklist, *klist; | |
127 | unsigned max; | |
128 | size_t size; | |
129 | int loop, ret; | |
130 | ||
131 | const unsigned limit = | |
132 | (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key); | |
133 | ||
134 | ret = 0; | |
135 | sklist = source->payload.subscriptions; | |
136 | ||
137 | if (sklist && sklist->nkeys > 0) { | |
138 | max = sklist->nkeys; | |
139 | BUG_ON(max > limit); | |
140 | ||
141 | max = (max + 3) & ~3; | |
142 | if (max > limit) | |
143 | max = limit; | |
144 | ||
145 | ret = -ENOMEM; | |
146 | size = sizeof(*klist) + sizeof(struct key) * max; | |
147 | klist = kmalloc(size, GFP_KERNEL); | |
148 | if (!klist) | |
149 | goto error; | |
150 | ||
151 | klist->maxkeys = max; | |
152 | klist->nkeys = sklist->nkeys; | |
153 | memcpy(klist->keys, | |
154 | sklist->keys, | |
155 | sklist->nkeys * sizeof(struct key)); | |
156 | ||
157 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | |
158 | atomic_inc(&klist->keys[loop]->usage); | |
159 | ||
160 | keyring->payload.subscriptions = klist; | |
161 | ret = 0; | |
162 | } | |
163 | ||
164 | error: | |
165 | return ret; | |
166 | ||
167 | } /* end keyring_duplicate() */ | |
168 | ||
169 | /*****************************************************************************/ | |
170 | /* | |
171 | * match keyrings on their name | |
172 | */ | |
173 | static int keyring_match(const struct key *keyring, const void *description) | |
174 | { | |
175 | return keyring->description && | |
176 | strcmp(keyring->description, description) == 0; | |
177 | ||
178 | } /* end keyring_match() */ | |
179 | ||
180 | /*****************************************************************************/ | |
181 | /* | |
182 | * dispose of the data dangling from the corpse of a keyring | |
183 | */ | |
184 | static void keyring_destroy(struct key *keyring) | |
185 | { | |
186 | struct keyring_list *klist; | |
187 | int loop; | |
188 | ||
189 | if (keyring->description) { | |
190 | write_lock(&keyring_name_lock); | |
191 | list_del(&keyring->type_data.link); | |
192 | write_unlock(&keyring_name_lock); | |
193 | } | |
194 | ||
195 | klist = keyring->payload.subscriptions; | |
196 | if (klist) { | |
197 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | |
198 | key_put(klist->keys[loop]); | |
199 | kfree(klist); | |
200 | } | |
201 | ||
202 | } /* end keyring_destroy() */ | |
203 | ||
204 | /*****************************************************************************/ | |
205 | /* | |
206 | * describe the keyring | |
207 | */ | |
208 | static void keyring_describe(const struct key *keyring, struct seq_file *m) | |
209 | { | |
210 | struct keyring_list *klist; | |
211 | ||
212 | if (keyring->description) { | |
213 | seq_puts(m, keyring->description); | |
214 | } | |
215 | else { | |
216 | seq_puts(m, "[anon]"); | |
217 | } | |
218 | ||
219 | klist = keyring->payload.subscriptions; | |
220 | if (klist) | |
221 | seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); | |
222 | else | |
223 | seq_puts(m, ": empty"); | |
224 | ||
225 | } /* end keyring_describe() */ | |
226 | ||
227 | /*****************************************************************************/ | |
228 | /* | |
229 | * read a list of key IDs from the keyring's contents | |
230 | */ | |
231 | static long keyring_read(const struct key *keyring, | |
232 | char __user *buffer, size_t buflen) | |
233 | { | |
234 | struct keyring_list *klist; | |
235 | struct key *key; | |
236 | size_t qty, tmp; | |
237 | int loop, ret; | |
238 | ||
239 | ret = 0; | |
240 | klist = keyring->payload.subscriptions; | |
241 | ||
242 | if (klist) { | |
243 | /* calculate how much data we could return */ | |
244 | qty = klist->nkeys * sizeof(key_serial_t); | |
245 | ||
246 | if (buffer && buflen > 0) { | |
247 | if (buflen > qty) | |
248 | buflen = qty; | |
249 | ||
250 | /* copy the IDs of the subscribed keys into the | |
251 | * buffer */ | |
252 | ret = -EFAULT; | |
253 | ||
254 | for (loop = 0; loop < klist->nkeys; loop++) { | |
255 | key = klist->keys[loop]; | |
256 | ||
257 | tmp = sizeof(key_serial_t); | |
258 | if (tmp > buflen) | |
259 | tmp = buflen; | |
260 | ||
261 | if (copy_to_user(buffer, | |
262 | &key->serial, | |
263 | tmp) != 0) | |
264 | goto error; | |
265 | ||
266 | buflen -= tmp; | |
267 | if (buflen == 0) | |
268 | break; | |
269 | buffer += tmp; | |
270 | } | |
271 | } | |
272 | ||
273 | ret = qty; | |
274 | } | |
275 | ||
276 | error: | |
277 | return ret; | |
278 | ||
279 | } /* end keyring_read() */ | |
280 | ||
281 | /*****************************************************************************/ | |
282 | /* | |
283 | * allocate a keyring and link into the destination keyring | |
284 | */ | |
285 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |
286 | int not_in_quota, struct key *dest) | |
287 | { | |
288 | struct key *keyring; | |
289 | int ret; | |
290 | ||
291 | keyring = key_alloc(&key_type_keyring, description, | |
292 | uid, gid, KEY_USR_ALL, not_in_quota); | |
293 | ||
294 | if (!IS_ERR(keyring)) { | |
295 | ret = key_instantiate_and_link(keyring, NULL, 0, dest); | |
296 | if (ret < 0) { | |
297 | key_put(keyring); | |
298 | keyring = ERR_PTR(ret); | |
299 | } | |
300 | } | |
301 | ||
302 | return keyring; | |
303 | ||
304 | } /* end keyring_alloc() */ | |
305 | ||
306 | /*****************************************************************************/ | |
307 | /* | |
308 | * search the supplied keyring tree for a key that matches the criterion | |
309 | * - perform a breadth-then-depth search up to the prescribed limit | |
310 | * - we only find keys on which we have search permission | |
311 | * - we use the supplied match function to see if the description (or other | |
312 | * feature of interest) matches | |
313 | * - we readlock the keyrings as we search down the tree | |
314 | * - we return -EAGAIN if we didn't find any matching key | |
315 | * - we return -ENOKEY if we only found negative matching keys | |
316 | */ | |
317 | struct key *keyring_search_aux(struct key *keyring, | |
318 | struct key_type *type, | |
319 | const void *description, | |
320 | key_match_func_t match) | |
321 | { | |
322 | struct { | |
323 | struct key *keyring; | |
324 | int kix; | |
325 | } stack[KEYRING_SEARCH_MAX_DEPTH]; | |
326 | ||
327 | struct keyring_list *keylist; | |
328 | struct timespec now; | |
329 | struct key *key; | |
330 | long err; | |
331 | int sp, psp, kix; | |
332 | ||
333 | key_check(keyring); | |
334 | ||
335 | /* top keyring must have search permission to begin the search */ | |
336 | key = ERR_PTR(-EACCES); | |
337 | if (!key_permission(keyring, KEY_SEARCH)) | |
338 | goto error; | |
339 | ||
340 | key = ERR_PTR(-ENOTDIR); | |
341 | if (keyring->type != &key_type_keyring) | |
342 | goto error; | |
343 | ||
344 | now = current_kernel_time(); | |
345 | err = -EAGAIN; | |
346 | sp = 0; | |
347 | ||
348 | /* start processing a new keyring */ | |
349 | descend: | |
350 | read_lock(&keyring->lock); | |
351 | if (keyring->flags & KEY_FLAG_REVOKED) | |
352 | goto not_this_keyring; | |
353 | ||
354 | keylist = keyring->payload.subscriptions; | |
355 | if (!keylist) | |
356 | goto not_this_keyring; | |
357 | ||
358 | /* iterate through the keys in this keyring first */ | |
359 | for (kix = 0; kix < keylist->nkeys; kix++) { | |
360 | key = keylist->keys[kix]; | |
361 | ||
362 | /* ignore keys not of this type */ | |
363 | if (key->type != type) | |
364 | continue; | |
365 | ||
366 | /* skip revoked keys and expired keys */ | |
367 | if (key->flags & KEY_FLAG_REVOKED) | |
368 | continue; | |
369 | ||
370 | if (key->expiry && now.tv_sec >= key->expiry) | |
371 | continue; | |
372 | ||
373 | /* keys that don't match */ | |
374 | if (!match(key, description)) | |
375 | continue; | |
376 | ||
377 | /* key must have search permissions */ | |
378 | if (!key_permission(key, KEY_SEARCH)) | |
379 | continue; | |
380 | ||
381 | /* we set a different error code if we find a negative key */ | |
382 | if (key->flags & KEY_FLAG_NEGATIVE) { | |
383 | err = -ENOKEY; | |
384 | continue; | |
385 | } | |
386 | ||
387 | goto found; | |
388 | } | |
389 | ||
390 | /* search through the keyrings nested in this one */ | |
391 | kix = 0; | |
392 | ascend: | |
393 | while (kix < keylist->nkeys) { | |
394 | key = keylist->keys[kix]; | |
395 | if (key->type != &key_type_keyring) | |
396 | goto next; | |
397 | ||
398 | /* recursively search nested keyrings | |
399 | * - only search keyrings for which we have search permission | |
400 | */ | |
401 | if (sp >= KEYRING_SEARCH_MAX_DEPTH) | |
402 | goto next; | |
403 | ||
404 | if (!key_permission(key, KEY_SEARCH)) | |
405 | goto next; | |
406 | ||
407 | /* evade loops in the keyring tree */ | |
408 | for (psp = 0; psp < sp; psp++) | |
409 | if (stack[psp].keyring == keyring) | |
410 | goto next; | |
411 | ||
412 | /* stack the current position */ | |
413 | stack[sp].keyring = keyring; | |
414 | stack[sp].kix = kix; | |
415 | sp++; | |
416 | ||
417 | /* begin again with the new keyring */ | |
418 | keyring = key; | |
419 | goto descend; | |
420 | ||
421 | next: | |
422 | kix++; | |
423 | } | |
424 | ||
425 | /* the keyring we're looking at was disqualified or didn't contain a | |
426 | * matching key */ | |
427 | not_this_keyring: | |
428 | read_unlock(&keyring->lock); | |
429 | ||
430 | if (sp > 0) { | |
431 | /* resume the processing of a keyring higher up in the tree */ | |
432 | sp--; | |
433 | keyring = stack[sp].keyring; | |
434 | keylist = keyring->payload.subscriptions; | |
435 | kix = stack[sp].kix + 1; | |
436 | goto ascend; | |
437 | } | |
438 | ||
439 | key = ERR_PTR(err); | |
440 | goto error; | |
441 | ||
442 | /* we found a viable match */ | |
443 | found: | |
444 | atomic_inc(&key->usage); | |
445 | read_unlock(&keyring->lock); | |
446 | ||
447 | /* unwind the keyring stack */ | |
448 | while (sp > 0) { | |
449 | sp--; | |
450 | read_unlock(&stack[sp].keyring->lock); | |
451 | } | |
452 | ||
453 | key_check(key); | |
454 | error: | |
455 | return key; | |
456 | ||
457 | } /* end keyring_search_aux() */ | |
458 | ||
459 | /*****************************************************************************/ | |
460 | /* | |
461 | * search the supplied keyring tree for a key that matches the criterion | |
462 | * - perform a breadth-then-depth search up to the prescribed limit | |
463 | * - we only find keys on which we have search permission | |
464 | * - we readlock the keyrings as we search down the tree | |
465 | * - we return -EAGAIN if we didn't find any matching key | |
466 | * - we return -ENOKEY if we only found negative matching keys | |
467 | */ | |
468 | struct key *keyring_search(struct key *keyring, | |
469 | struct key_type *type, | |
470 | const char *description) | |
471 | { | |
472 | return keyring_search_aux(keyring, type, description, type->match); | |
473 | ||
474 | } /* end keyring_search() */ | |
475 | ||
476 | EXPORT_SYMBOL(keyring_search); | |
477 | ||
478 | /*****************************************************************************/ | |
479 | /* | |
480 | * search the given keyring only (no recursion) | |
481 | * - keyring must be locked by caller | |
482 | */ | |
483 | struct key *__keyring_search_one(struct key *keyring, | |
484 | const struct key_type *ktype, | |
485 | const char *description, | |
486 | key_perm_t perm) | |
487 | { | |
488 | struct keyring_list *klist; | |
489 | struct key *key; | |
490 | int loop; | |
491 | ||
492 | klist = keyring->payload.subscriptions; | |
493 | if (klist) { | |
494 | for (loop = 0; loop < klist->nkeys; loop++) { | |
495 | key = klist->keys[loop]; | |
496 | ||
497 | if (key->type == ktype && | |
498 | key->type->match(key, description) && | |
499 | key_permission(key, perm) && | |
500 | !(key->flags & KEY_FLAG_REVOKED) | |
501 | ) | |
502 | goto found; | |
503 | } | |
504 | } | |
505 | ||
506 | key = ERR_PTR(-ENOKEY); | |
507 | goto error; | |
508 | ||
509 | found: | |
510 | atomic_inc(&key->usage); | |
511 | error: | |
512 | return key; | |
513 | ||
514 | } /* end __keyring_search_one() */ | |
515 | ||
516 | /*****************************************************************************/ | |
517 | /* | |
518 | * find a keyring with the specified name | |
519 | * - all named keyrings are searched | |
520 | * - only find keyrings with search permission for the process | |
521 | * - only find keyrings with a serial number greater than the one specified | |
522 | */ | |
523 | struct key *find_keyring_by_name(const char *name, key_serial_t bound) | |
524 | { | |
525 | struct key *keyring; | |
526 | int bucket; | |
527 | ||
528 | keyring = ERR_PTR(-EINVAL); | |
529 | if (!name) | |
530 | goto error; | |
531 | ||
532 | bucket = keyring_hash(name); | |
533 | ||
534 | read_lock(&keyring_name_lock); | |
535 | ||
536 | if (keyring_name_hash[bucket].next) { | |
537 | /* search this hash bucket for a keyring with a matching name | |
538 | * that's readable and that hasn't been revoked */ | |
539 | list_for_each_entry(keyring, | |
540 | &keyring_name_hash[bucket], | |
541 | type_data.link | |
542 | ) { | |
543 | if (keyring->flags & KEY_FLAG_REVOKED) | |
544 | continue; | |
545 | ||
546 | if (strcmp(keyring->description, name) != 0) | |
547 | continue; | |
548 | ||
549 | if (!key_permission(keyring, KEY_SEARCH)) | |
550 | continue; | |
551 | ||
552 | /* found a potential candidate, but we still need to | |
553 | * check the serial number */ | |
554 | if (keyring->serial <= bound) | |
555 | continue; | |
556 | ||
557 | /* we've got a match */ | |
558 | atomic_inc(&keyring->usage); | |
559 | read_unlock(&keyring_name_lock); | |
560 | goto error; | |
561 | } | |
562 | } | |
563 | ||
564 | read_unlock(&keyring_name_lock); | |
565 | keyring = ERR_PTR(-ENOKEY); | |
566 | ||
567 | error: | |
568 | return keyring; | |
569 | ||
570 | } /* end find_keyring_by_name() */ | |
571 | ||
572 | /*****************************************************************************/ | |
573 | /* | |
574 | * see if a cycle will will be created by inserting acyclic tree B in acyclic | |
575 | * tree A at the topmost level (ie: as a direct child of A) | |
576 | * - since we are adding B to A at the top level, checking for cycles should | |
577 | * just be a matter of seeing if node A is somewhere in tree B | |
578 | */ | |
579 | static int keyring_detect_cycle(struct key *A, struct key *B) | |
580 | { | |
581 | struct { | |
582 | struct key *subtree; | |
583 | int kix; | |
584 | } stack[KEYRING_SEARCH_MAX_DEPTH]; | |
585 | ||
586 | struct keyring_list *keylist; | |
587 | struct key *subtree, *key; | |
588 | int sp, kix, ret; | |
589 | ||
590 | ret = -EDEADLK; | |
591 | if (A == B) | |
592 | goto error; | |
593 | ||
594 | subtree = B; | |
595 | sp = 0; | |
596 | ||
597 | /* start processing a new keyring */ | |
598 | descend: | |
599 | read_lock(&subtree->lock); | |
600 | if (subtree->flags & KEY_FLAG_REVOKED) | |
601 | goto not_this_keyring; | |
602 | ||
603 | keylist = subtree->payload.subscriptions; | |
604 | if (!keylist) | |
605 | goto not_this_keyring; | |
606 | kix = 0; | |
607 | ||
608 | ascend: | |
609 | /* iterate through the remaining keys in this keyring */ | |
610 | for (; kix < keylist->nkeys; kix++) { | |
611 | key = keylist->keys[kix]; | |
612 | ||
613 | if (key == A) | |
614 | goto cycle_detected; | |
615 | ||
616 | /* recursively check nested keyrings */ | |
617 | if (key->type == &key_type_keyring) { | |
618 | if (sp >= KEYRING_SEARCH_MAX_DEPTH) | |
619 | goto too_deep; | |
620 | ||
621 | /* stack the current position */ | |
622 | stack[sp].subtree = subtree; | |
623 | stack[sp].kix = kix; | |
624 | sp++; | |
625 | ||
626 | /* begin again with the new keyring */ | |
627 | subtree = key; | |
628 | goto descend; | |
629 | } | |
630 | } | |
631 | ||
632 | /* the keyring we're looking at was disqualified or didn't contain a | |
633 | * matching key */ | |
634 | not_this_keyring: | |
635 | read_unlock(&subtree->lock); | |
636 | ||
637 | if (sp > 0) { | |
638 | /* resume the checking of a keyring higher up in the tree */ | |
639 | sp--; | |
640 | subtree = stack[sp].subtree; | |
641 | keylist = subtree->payload.subscriptions; | |
642 | kix = stack[sp].kix + 1; | |
643 | goto ascend; | |
644 | } | |
645 | ||
646 | ret = 0; /* no cycles detected */ | |
647 | ||
648 | error: | |
649 | return ret; | |
650 | ||
651 | too_deep: | |
652 | ret = -ELOOP; | |
653 | goto error_unwind; | |
654 | cycle_detected: | |
655 | ret = -EDEADLK; | |
656 | error_unwind: | |
657 | read_unlock(&subtree->lock); | |
658 | ||
659 | /* unwind the keyring stack */ | |
660 | while (sp > 0) { | |
661 | sp--; | |
662 | read_unlock(&stack[sp].subtree->lock); | |
663 | } | |
664 | ||
665 | goto error; | |
666 | ||
667 | } /* end keyring_detect_cycle() */ | |
668 | ||
669 | /*****************************************************************************/ | |
670 | /* | |
671 | * link a key into to a keyring | |
672 | * - must be called with the keyring's semaphore held | |
673 | */ | |
674 | int __key_link(struct key *keyring, struct key *key) | |
675 | { | |
676 | struct keyring_list *klist, *nklist; | |
677 | unsigned max; | |
678 | size_t size; | |
679 | int ret; | |
680 | ||
681 | ret = -EKEYREVOKED; | |
682 | if (keyring->flags & KEY_FLAG_REVOKED) | |
683 | goto error; | |
684 | ||
685 | ret = -ENOTDIR; | |
686 | if (keyring->type != &key_type_keyring) | |
687 | goto error; | |
688 | ||
689 | /* serialise link/link calls to prevent parallel calls causing a | |
690 | * cycle when applied to two keyring in opposite orders */ | |
691 | down_write(&keyring_serialise_link_sem); | |
692 | ||
693 | /* check that we aren't going to create a cycle adding one keyring to | |
694 | * another */ | |
695 | if (key->type == &key_type_keyring) { | |
696 | ret = keyring_detect_cycle(keyring, key); | |
697 | if (ret < 0) | |
698 | goto error2; | |
699 | } | |
700 | ||
701 | /* check that we aren't going to overrun the user's quota */ | |
702 | ret = key_payload_reserve(keyring, | |
703 | keyring->datalen + KEYQUOTA_LINK_BYTES); | |
704 | if (ret < 0) | |
705 | goto error2; | |
706 | ||
707 | klist = keyring->payload.subscriptions; | |
708 | ||
709 | if (klist && klist->nkeys < klist->maxkeys) { | |
710 | /* there's sufficient slack space to add directly */ | |
711 | atomic_inc(&key->usage); | |
712 | ||
713 | write_lock(&keyring->lock); | |
714 | klist->keys[klist->nkeys++] = key; | |
715 | write_unlock(&keyring->lock); | |
716 | ||
717 | ret = 0; | |
718 | } | |
719 | else { | |
720 | /* grow the key list */ | |
721 | max = 4; | |
722 | if (klist) | |
723 | max += klist->maxkeys; | |
724 | ||
725 | ret = -ENFILE; | |
726 | size = sizeof(*klist) + sizeof(*key) * max; | |
727 | if (size > PAGE_SIZE) | |
728 | goto error3; | |
729 | ||
730 | ret = -ENOMEM; | |
731 | nklist = kmalloc(size, GFP_KERNEL); | |
732 | if (!nklist) | |
733 | goto error3; | |
734 | nklist->maxkeys = max; | |
735 | nklist->nkeys = 0; | |
736 | ||
737 | if (klist) { | |
738 | nklist->nkeys = klist->nkeys; | |
739 | memcpy(nklist->keys, | |
740 | klist->keys, | |
741 | sizeof(struct key *) * klist->nkeys); | |
742 | } | |
743 | ||
744 | /* add the key into the new space */ | |
745 | atomic_inc(&key->usage); | |
746 | ||
747 | write_lock(&keyring->lock); | |
748 | keyring->payload.subscriptions = nklist; | |
749 | nklist->keys[nklist->nkeys++] = key; | |
750 | write_unlock(&keyring->lock); | |
751 | ||
752 | /* dispose of the old keyring list */ | |
753 | kfree(klist); | |
754 | ||
755 | ret = 0; | |
756 | } | |
757 | ||
758 | error2: | |
759 | up_write(&keyring_serialise_link_sem); | |
760 | error: | |
761 | return ret; | |
762 | ||
763 | error3: | |
764 | /* undo the quota changes */ | |
765 | key_payload_reserve(keyring, | |
766 | keyring->datalen - KEYQUOTA_LINK_BYTES); | |
767 | goto error2; | |
768 | ||
769 | } /* end __key_link() */ | |
770 | ||
771 | /*****************************************************************************/ | |
772 | /* | |
773 | * link a key to a keyring | |
774 | */ | |
775 | int key_link(struct key *keyring, struct key *key) | |
776 | { | |
777 | int ret; | |
778 | ||
779 | key_check(keyring); | |
780 | key_check(key); | |
781 | ||
782 | down_write(&keyring->sem); | |
783 | ret = __key_link(keyring, key); | |
784 | up_write(&keyring->sem); | |
785 | ||
786 | return ret; | |
787 | ||
788 | } /* end key_link() */ | |
789 | ||
790 | EXPORT_SYMBOL(key_link); | |
791 | ||
792 | /*****************************************************************************/ | |
793 | /* | |
794 | * unlink the first link to a key from a keyring | |
795 | */ | |
796 | int key_unlink(struct key *keyring, struct key *key) | |
797 | { | |
798 | struct keyring_list *klist; | |
799 | int loop, ret; | |
800 | ||
801 | key_check(keyring); | |
802 | key_check(key); | |
803 | ||
804 | ret = -ENOTDIR; | |
805 | if (keyring->type != &key_type_keyring) | |
806 | goto error; | |
807 | ||
808 | down_write(&keyring->sem); | |
809 | ||
810 | klist = keyring->payload.subscriptions; | |
811 | if (klist) { | |
812 | /* search the keyring for the key */ | |
813 | for (loop = 0; loop < klist->nkeys; loop++) | |
814 | if (klist->keys[loop] == key) | |
815 | goto key_is_present; | |
816 | } | |
817 | ||
818 | up_write(&keyring->sem); | |
819 | ret = -ENOENT; | |
820 | goto error; | |
821 | ||
822 | key_is_present: | |
823 | /* adjust the user's quota */ | |
824 | key_payload_reserve(keyring, | |
825 | keyring->datalen - KEYQUOTA_LINK_BYTES); | |
826 | ||
827 | /* shuffle down the key pointers | |
828 | * - it might be worth shrinking the allocated memory, but that runs | |
829 | * the risk of ENOMEM as we would have to copy | |
830 | */ | |
831 | write_lock(&keyring->lock); | |
832 | ||
833 | klist->nkeys--; | |
834 | if (loop < klist->nkeys) | |
835 | memcpy(&klist->keys[loop], | |
836 | &klist->keys[loop + 1], | |
837 | (klist->nkeys - loop) * sizeof(struct key *)); | |
838 | ||
839 | write_unlock(&keyring->lock); | |
840 | ||
841 | up_write(&keyring->sem); | |
842 | key_put(key); | |
843 | ret = 0; | |
844 | ||
845 | error: | |
846 | return ret; | |
847 | ||
848 | } /* end key_unlink() */ | |
849 | ||
850 | EXPORT_SYMBOL(key_unlink); | |
851 | ||
852 | /*****************************************************************************/ | |
853 | /* | |
854 | * clear the specified process keyring | |
855 | * - implements keyctl(KEYCTL_CLEAR) | |
856 | */ | |
857 | int keyring_clear(struct key *keyring) | |
858 | { | |
859 | struct keyring_list *klist; | |
860 | int loop, ret; | |
861 | ||
862 | ret = -ENOTDIR; | |
863 | if (keyring->type == &key_type_keyring) { | |
864 | /* detach the pointer block with the locks held */ | |
865 | down_write(&keyring->sem); | |
866 | ||
867 | klist = keyring->payload.subscriptions; | |
868 | if (klist) { | |
869 | /* adjust the quota */ | |
870 | key_payload_reserve(keyring, | |
871 | sizeof(struct keyring_list)); | |
872 | ||
873 | write_lock(&keyring->lock); | |
874 | keyring->payload.subscriptions = NULL; | |
875 | write_unlock(&keyring->lock); | |
876 | } | |
877 | ||
878 | up_write(&keyring->sem); | |
879 | ||
880 | /* free the keys after the locks have been dropped */ | |
881 | if (klist) { | |
882 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | |
883 | key_put(klist->keys[loop]); | |
884 | ||
885 | kfree(klist); | |
886 | } | |
887 | ||
888 | ret = 0; | |
889 | } | |
890 | ||
891 | return ret; | |
892 | ||
893 | } /* end keyring_clear() */ | |
894 | ||
895 | EXPORT_SYMBOL(keyring_clear); |