diff options
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r-- | security/keys/keyring.c | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 88292e3dee96..a9ab8affc092 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* keyring.c: keyring handling | 1 | /* Keyring handling |
2 | * | 2 | * |
3 | * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -79,7 +79,7 @@ static DECLARE_RWSEM(keyring_serialise_link_sem); | |||
79 | * publish the name of a keyring so that it can be found by name (if it has | 79 | * publish the name of a keyring so that it can be found by name (if it has |
80 | * one) | 80 | * one) |
81 | */ | 81 | */ |
82 | void keyring_publish_name(struct key *keyring) | 82 | static void keyring_publish_name(struct key *keyring) |
83 | { | 83 | { |
84 | int bucket; | 84 | int bucket; |
85 | 85 | ||
@@ -292,7 +292,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
292 | 292 | ||
293 | struct keyring_list *keylist; | 293 | struct keyring_list *keylist; |
294 | struct timespec now; | 294 | struct timespec now; |
295 | unsigned long possessed; | 295 | unsigned long possessed, kflags; |
296 | struct key *keyring, *key; | 296 | struct key *keyring, *key; |
297 | key_ref_t key_ref; | 297 | key_ref_t key_ref; |
298 | long err; | 298 | long err; |
@@ -319,6 +319,32 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
319 | err = -EAGAIN; | 319 | err = -EAGAIN; |
320 | sp = 0; | 320 | sp = 0; |
321 | 321 | ||
322 | /* firstly we should check to see if this top-level keyring is what we | ||
323 | * are looking for */ | ||
324 | key_ref = ERR_PTR(-EAGAIN); | ||
325 | kflags = keyring->flags; | ||
326 | if (keyring->type == type && match(keyring, description)) { | ||
327 | key = keyring; | ||
328 | |||
329 | /* check it isn't negative and hasn't expired or been | ||
330 | * revoked */ | ||
331 | if (kflags & (1 << KEY_FLAG_REVOKED)) | ||
332 | goto error_2; | ||
333 | if (key->expiry && now.tv_sec >= key->expiry) | ||
334 | goto error_2; | ||
335 | key_ref = ERR_PTR(-ENOKEY); | ||
336 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) | ||
337 | goto error_2; | ||
338 | goto found; | ||
339 | } | ||
340 | |||
341 | /* otherwise, the top keyring must not be revoked, expired, or | ||
342 | * negatively instantiated if we are to search it */ | ||
343 | key_ref = ERR_PTR(-EAGAIN); | ||
344 | if (kflags & ((1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) || | ||
345 | (keyring->expiry && now.tv_sec >= keyring->expiry)) | ||
346 | goto error_2; | ||
347 | |||
322 | /* start processing a new keyring */ | 348 | /* start processing a new keyring */ |
323 | descend: | 349 | descend: |
324 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | 350 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
@@ -331,13 +357,14 @@ descend: | |||
331 | /* iterate through the keys in this keyring first */ | 357 | /* iterate through the keys in this keyring first */ |
332 | for (kix = 0; kix < keylist->nkeys; kix++) { | 358 | for (kix = 0; kix < keylist->nkeys; kix++) { |
333 | key = keylist->keys[kix]; | 359 | key = keylist->keys[kix]; |
360 | kflags = key->flags; | ||
334 | 361 | ||
335 | /* ignore keys not of this type */ | 362 | /* ignore keys not of this type */ |
336 | if (key->type != type) | 363 | if (key->type != type) |
337 | continue; | 364 | continue; |
338 | 365 | ||
339 | /* skip revoked keys and expired keys */ | 366 | /* skip revoked keys and expired keys */ |
340 | if (test_bit(KEY_FLAG_REVOKED, &key->flags)) | 367 | if (kflags & (1 << KEY_FLAG_REVOKED)) |
341 | continue; | 368 | continue; |
342 | 369 | ||
343 | if (key->expiry && now.tv_sec >= key->expiry) | 370 | if (key->expiry && now.tv_sec >= key->expiry) |
@@ -352,8 +379,8 @@ descend: | |||
352 | context, KEY_SEARCH) < 0) | 379 | context, KEY_SEARCH) < 0) |
353 | continue; | 380 | continue; |
354 | 381 | ||
355 | /* we set a different error code if we find a negative key */ | 382 | /* we set a different error code if we pass a negative key */ |
356 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { | 383 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) { |
357 | err = -ENOKEY; | 384 | err = -ENOKEY; |
358 | continue; | 385 | continue; |
359 | } | 386 | } |
@@ -489,10 +516,9 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, | |||
489 | /* | 516 | /* |
490 | * find a keyring with the specified name | 517 | * find a keyring with the specified name |
491 | * - all named keyrings are searched | 518 | * - all named keyrings are searched |
492 | * - only find keyrings with search permission for the process | 519 | * - normally only finds keyrings with search permission for the current process |
493 | * - only find keyrings with a serial number greater than the one specified | ||
494 | */ | 520 | */ |
495 | struct key *find_keyring_by_name(const char *name, key_serial_t bound) | 521 | struct key *find_keyring_by_name(const char *name, bool skip_perm_check) |
496 | { | 522 | { |
497 | struct key *keyring; | 523 | struct key *keyring; |
498 | int bucket; | 524 | int bucket; |
@@ -518,15 +544,11 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound) | |||
518 | if (strcmp(keyring->description, name) != 0) | 544 | if (strcmp(keyring->description, name) != 0) |
519 | continue; | 545 | continue; |
520 | 546 | ||
521 | if (key_permission(make_key_ref(keyring, 0), | 547 | if (!skip_perm_check && |
548 | key_permission(make_key_ref(keyring, 0), | ||
522 | KEY_SEARCH) < 0) | 549 | KEY_SEARCH) < 0) |
523 | continue; | 550 | continue; |
524 | 551 | ||
525 | /* found a potential candidate, but we still need to | ||
526 | * check the serial number */ | ||
527 | if (keyring->serial <= bound) | ||
528 | continue; | ||
529 | |||
530 | /* we've got a match */ | 552 | /* we've got a match */ |
531 | atomic_inc(&keyring->usage); | 553 | atomic_inc(&keyring->usage); |
532 | read_unlock(&keyring_name_lock); | 554 | read_unlock(&keyring_name_lock); |