diff options
Diffstat (limited to 'security/keys/key.c')
-rw-r--r-- | security/keys/key.c | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index 2182be9e9309..ccde17aff616 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* key.c: basic authentication token and access key management | 1 | /* key.c: basic authentication token and access key management |
2 | * | 2 | * |
3 | * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004 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 |
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/security.h> | ||
16 | #include <linux/workqueue.h> | 17 | #include <linux/workqueue.h> |
17 | #include <linux/err.h> | 18 | #include <linux/err.h> |
18 | #include "internal.h" | 19 | #include "internal.h" |
@@ -253,6 +254,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
253 | struct key_user *user = NULL; | 254 | struct key_user *user = NULL; |
254 | struct key *key; | 255 | struct key *key; |
255 | size_t desclen, quotalen; | 256 | size_t desclen, quotalen; |
257 | int ret; | ||
256 | 258 | ||
257 | key = ERR_PTR(-EINVAL); | 259 | key = ERR_PTR(-EINVAL); |
258 | if (!desc || !*desc) | 260 | if (!desc || !*desc) |
@@ -305,6 +307,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
305 | key->flags = 0; | 307 | key->flags = 0; |
306 | key->expiry = 0; | 308 | key->expiry = 0; |
307 | key->payload.data = NULL; | 309 | key->payload.data = NULL; |
310 | key->security = NULL; | ||
308 | 311 | ||
309 | if (!not_in_quota) | 312 | if (!not_in_quota) |
310 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; | 313 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; |
@@ -315,16 +318,34 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
315 | key->magic = KEY_DEBUG_MAGIC; | 318 | key->magic = KEY_DEBUG_MAGIC; |
316 | #endif | 319 | #endif |
317 | 320 | ||
321 | /* let the security module know about the key */ | ||
322 | ret = security_key_alloc(key); | ||
323 | if (ret < 0) | ||
324 | goto security_error; | ||
325 | |||
318 | /* publish the key by giving it a serial number */ | 326 | /* publish the key by giving it a serial number */ |
319 | atomic_inc(&user->nkeys); | 327 | atomic_inc(&user->nkeys); |
320 | key_alloc_serial(key); | 328 | key_alloc_serial(key); |
321 | 329 | ||
322 | error: | 330 | error: |
323 | return key; | 331 | return key; |
324 | 332 | ||
325 | no_memory_3: | 333 | security_error: |
334 | kfree(key->description); | ||
335 | kmem_cache_free(key_jar, key); | ||
336 | if (!not_in_quota) { | ||
337 | spin_lock(&user->lock); | ||
338 | user->qnkeys--; | ||
339 | user->qnbytes -= quotalen; | ||
340 | spin_unlock(&user->lock); | ||
341 | } | ||
342 | key_user_put(user); | ||
343 | key = ERR_PTR(ret); | ||
344 | goto error; | ||
345 | |||
346 | no_memory_3: | ||
326 | kmem_cache_free(key_jar, key); | 347 | kmem_cache_free(key_jar, key); |
327 | no_memory_2: | 348 | no_memory_2: |
328 | if (!not_in_quota) { | 349 | if (!not_in_quota) { |
329 | spin_lock(&user->lock); | 350 | spin_lock(&user->lock); |
330 | user->qnkeys--; | 351 | user->qnkeys--; |
@@ -332,11 +353,11 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
332 | spin_unlock(&user->lock); | 353 | spin_unlock(&user->lock); |
333 | } | 354 | } |
334 | key_user_put(user); | 355 | key_user_put(user); |
335 | no_memory_1: | 356 | no_memory_1: |
336 | key = ERR_PTR(-ENOMEM); | 357 | key = ERR_PTR(-ENOMEM); |
337 | goto error; | 358 | goto error; |
338 | 359 | ||
339 | no_quota: | 360 | no_quota: |
340 | spin_unlock(&user->lock); | 361 | spin_unlock(&user->lock); |
341 | key_user_put(user); | 362 | key_user_put(user); |
342 | key = ERR_PTR(-EDQUOT); | 363 | key = ERR_PTR(-EDQUOT); |
@@ -556,6 +577,8 @@ static void key_cleanup(void *data) | |||
556 | 577 | ||
557 | key_check(key); | 578 | key_check(key); |
558 | 579 | ||
580 | security_key_free(key); | ||
581 | |||
559 | /* deal with the user's key tracking and quota */ | 582 | /* deal with the user's key tracking and quota */ |
560 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { | 583 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
561 | spin_lock(&key->user->lock); | 584 | spin_lock(&key->user->lock); |
@@ -700,8 +723,8 @@ static inline key_ref_t __key_update(key_ref_t key_ref, | |||
700 | int ret; | 723 | int ret; |
701 | 724 | ||
702 | /* need write permission on the key to update it */ | 725 | /* need write permission on the key to update it */ |
703 | ret = -EACCES; | 726 | ret = key_permission(key_ref, KEY_WRITE); |
704 | if (!key_permission(key_ref, KEY_WRITE)) | 727 | if (ret < 0) |
705 | goto error; | 728 | goto error; |
706 | 729 | ||
707 | ret = -EEXIST; | 730 | ret = -EEXIST; |
@@ -711,7 +734,6 @@ static inline key_ref_t __key_update(key_ref_t key_ref, | |||
711 | down_write(&key->sem); | 734 | down_write(&key->sem); |
712 | 735 | ||
713 | ret = key->type->update(key, payload, plen); | 736 | ret = key->type->update(key, payload, plen); |
714 | |||
715 | if (ret == 0) | 737 | if (ret == 0) |
716 | /* updating a negative key instantiates it */ | 738 | /* updating a negative key instantiates it */ |
717 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | 739 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |
@@ -768,9 +790,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
768 | 790 | ||
769 | /* if we're going to allocate a new key, we're going to have | 791 | /* if we're going to allocate a new key, we're going to have |
770 | * to modify the keyring */ | 792 | * to modify the keyring */ |
771 | key_ref = ERR_PTR(-EACCES); | 793 | ret = key_permission(keyring_ref, KEY_WRITE); |
772 | if (!key_permission(keyring_ref, KEY_WRITE)) | 794 | if (ret < 0) { |
795 | key_ref = ERR_PTR(ret); | ||
773 | goto error_3; | 796 | goto error_3; |
797 | } | ||
774 | 798 | ||
775 | /* search for an existing key of the same type and description in the | 799 | /* search for an existing key of the same type and description in the |
776 | * destination keyring | 800 | * destination keyring |
@@ -780,8 +804,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
780 | goto found_matching_key; | 804 | goto found_matching_key; |
781 | 805 | ||
782 | /* decide on the permissions we want */ | 806 | /* decide on the permissions we want */ |
783 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK; | 807 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; |
784 | perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK; | 808 | perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR; |
785 | 809 | ||
786 | if (ktype->read) | 810 | if (ktype->read) |
787 | perm |= KEY_POS_READ | KEY_USR_READ; | 811 | perm |= KEY_POS_READ | KEY_USR_READ; |
@@ -840,16 +864,16 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) | |||
840 | key_check(key); | 864 | key_check(key); |
841 | 865 | ||
842 | /* the key must be writable */ | 866 | /* the key must be writable */ |
843 | ret = -EACCES; | 867 | ret = key_permission(key_ref, KEY_WRITE); |
844 | if (!key_permission(key_ref, KEY_WRITE)) | 868 | if (ret < 0) |
845 | goto error; | 869 | goto error; |
846 | 870 | ||
847 | /* attempt to update it if supported */ | 871 | /* attempt to update it if supported */ |
848 | ret = -EOPNOTSUPP; | 872 | ret = -EOPNOTSUPP; |
849 | if (key->type->update) { | 873 | if (key->type->update) { |
850 | down_write(&key->sem); | 874 | down_write(&key->sem); |
851 | ret = key->type->update(key, payload, plen); | ||
852 | 875 | ||
876 | ret = key->type->update(key, payload, plen); | ||
853 | if (ret == 0) | 877 | if (ret == 0) |
854 | /* updating a negative key instantiates it */ | 878 | /* updating a negative key instantiates it */ |
855 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | 879 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |