diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /security/keys/keyring.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r-- | security/keys/keyring.c | 895 |
1 files changed, 895 insertions, 0 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c new file mode 100644 index 000000000000..e2ab4f8e7481 --- /dev/null +++ b/security/keys/keyring.c | |||
@@ -0,0 +1,895 @@ | |||
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); | ||