Merge branch 'for_paulus' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc
[cascardo/linux.git] / security / keys / key.c
index 01bcfec..b6061fa 100644 (file)
@@ -1,6 +1,6 @@
 /* key.c: basic authentication token and access key management
  *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -36,7 +36,7 @@ static DECLARE_WORK(key_cleanup_task, key_cleanup, NULL);
 DECLARE_RWSEM(key_construction_sem);
 
 /* any key who's type gets unegistered will be re-typed to this */
-struct key_type key_type_dead = {
+static struct key_type key_type_dead = {
        .name           = "dead",
 };
 
@@ -240,9 +240,9 @@ static inline void key_alloc_serial(struct key *key)
 /*
  * allocate a key of the specified type
  * - update the user's quota to reflect the existence of the key
- * - called from a key-type operation with key_types_sem read-locked by either
- *   key_create_or_update() or by key_duplicate(); this prevents unregistration
- *   of the key type
+ * - called from a key-type operation with key_types_sem read-locked by
+ *   key_create_or_update()
+ *   - this prevents unregistration of the key type
  * - upon return the key is as yet uninstantiated; the caller needs to either
  *   instantiate the key or discard it before returning
  */
@@ -271,7 +271,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
         * its description */
        if (!not_in_quota) {
                spin_lock(&user->lock);
-               if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS &&
+               if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
                    user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
                    )
                        goto no_quota;
@@ -785,6 +785,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 
        key_check(keyring);
 
+       key_ref = ERR_PTR(-ENOTDIR);
+       if (keyring->type != &key_type_keyring)
+               goto error_2;
+
        down_write(&keyring->sem);
 
        /* if we're going to allocate a new key, we're going to have
@@ -795,12 +799,16 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
                goto error_3;
        }
 
-       /* search for an existing key of the same type and description in the
-        * destination keyring
+       /* if it's possible to update this type of key, search for an existing
+        * key of the same type and description in the destination keyring and
+        * update that instead if possible
         */
-       key_ref = __keyring_search_one(keyring_ref, ktype, description, 0);
-       if (!IS_ERR(key_ref))
-               goto found_matching_key;
+       if (ktype->update) {
+               key_ref = __keyring_search_one(keyring_ref, ktype, description,
+                                              0);
+               if (!IS_ERR(key_ref))
+                       goto found_matching_key;
+       }
 
        /* decide on the permissions we want */
        perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
@@ -887,56 +895,6 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
 
 EXPORT_SYMBOL(key_update);
 
-/*****************************************************************************/
-/*
- * duplicate a key, potentially with a revised description
- * - must be supported by the keytype (keyrings for instance can be duplicated)
- */
-struct key *key_duplicate(struct key *source, const char *desc)
-{
-       struct key *key;
-       int ret;
-
-       key_check(source);
-
-       if (!desc)
-               desc = source->description;
-
-       down_read(&key_types_sem);
-
-       ret = -EINVAL;
-       if (!source->type->duplicate)
-               goto error;
-
-       /* allocate and instantiate a key */
-       key = key_alloc(source->type, desc, current->fsuid, current->fsgid,
-                       source->perm, 0);
-       if (IS_ERR(key))
-               goto error_k;
-
-       down_read(&source->sem);
-       ret = key->type->duplicate(key, source);
-       up_read(&source->sem);
-       if (ret < 0)
-               goto error2;
-
-       atomic_inc(&key->user->nikeys);
-       set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
-
- error_k:
-       up_read(&key_types_sem);
- out:
-       return key;
-
- error2:
-       key_put(key);
- error:
-       up_read(&key_types_sem);
-       key = ERR_PTR(ret);
-       goto out;
-
-} /* end key_duplicate() */
-
 /*****************************************************************************/
 /*
  * revoke a key