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 2182be9e930..ccde17aff61 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -1,6 +1,6 @@ /* key.c: basic authentication token and access key management * - * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/security.h> #include <linux/workqueue.h> #include <linux/err.h> #include "internal.h" @@ -253,6 +254,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, struct key_user *user = NULL; struct key *key; size_t desclen, quotalen; + int ret; key = ERR_PTR(-EINVAL); if (!desc || !*desc) @@ -305,6 +307,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->flags = 0; key->expiry = 0; key->payload.data = NULL; + key->security = NULL; if (!not_in_quota) key->flags |= 1 << KEY_FLAG_IN_QUOTA; @@ -315,16 +318,34 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->magic = KEY_DEBUG_MAGIC; #endif + /* let the security module know about the key */ + ret = security_key_alloc(key); + if (ret < 0) + goto security_error; + /* publish the key by giving it a serial number */ atomic_inc(&user->nkeys); key_alloc_serial(key); - error: +error: return key; - no_memory_3: +security_error: + kfree(key->description); + kmem_cache_free(key_jar, key); + if (!not_in_quota) { + spin_lock(&user->lock); + user->qnkeys--; + user->qnbytes -= quotalen; + spin_unlock(&user->lock); + } + key_user_put(user); + key = ERR_PTR(ret); + goto error; + +no_memory_3: kmem_cache_free(key_jar, key); - no_memory_2: +no_memory_2: if (!not_in_quota) { spin_lock(&user->lock); user->qnkeys--; @@ -332,11 +353,11 @@ struct key *key_alloc(struct key_type *type, const char *desc, spin_unlock(&user->lock); } key_user_put(user); - no_memory_1: +no_memory_1: key = ERR_PTR(-ENOMEM); goto error; - no_quota: +no_quota: spin_unlock(&user->lock); key_user_put(user); key = ERR_PTR(-EDQUOT); @@ -556,6 +577,8 @@ static void key_cleanup(void *data) key_check(key); + security_key_free(key); + /* deal with the user's key tracking and quota */ if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { spin_lock(&key->user->lock); @@ -700,8 +723,8 @@ static inline key_ref_t __key_update(key_ref_t key_ref, int ret; /* need write permission on the key to update it */ - ret = -EACCES; - if (!key_permission(key_ref, KEY_WRITE)) + ret = key_permission(key_ref, KEY_WRITE); + if (ret < 0) goto error; ret = -EEXIST; @@ -711,7 +734,6 @@ static inline key_ref_t __key_update(key_ref_t key_ref, down_write(&key->sem); ret = key->type->update(key, payload, plen); - if (ret == 0) /* updating a negative key instantiates it */ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); @@ -768,9 +790,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, /* if we're going to allocate a new key, we're going to have * to modify the keyring */ - key_ref = ERR_PTR(-EACCES); - if (!key_permission(keyring_ref, KEY_WRITE)) + ret = key_permission(keyring_ref, KEY_WRITE); + if (ret < 0) { + key_ref = ERR_PTR(ret); goto error_3; + } /* search for an existing key of the same type and description in the * destination keyring @@ -780,8 +804,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, goto found_matching_key; /* decide on the permissions we want */ - perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK; - perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK; + perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; + perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR; if (ktype->read) 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) key_check(key); /* the key must be writable */ - ret = -EACCES; - if (!key_permission(key_ref, KEY_WRITE)) + ret = key_permission(key_ref, KEY_WRITE); + if (ret < 0) goto error; /* attempt to update it if supported */ ret = -EOPNOTSUPP; if (key->type->update) { down_write(&key->sem); - ret = key->type->update(key, payload, plen); + ret = key->type->update(key, payload, plen); if (ret == 0) /* updating a negative key instantiates it */ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |