kconfig: fix default value for choice input
[pandora-kernel.git] / security / keys / keyring.c
index 5d22c03..d65a180 100644 (file)
@@ -479,51 +479,6 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
 
 } /* end __keyring_search_one() */
 
-/*****************************************************************************/
-/*
- * search for an instantiation authorisation key matching a target key
- * - the RCU read lock must be held by the caller
- * - a target_id of zero specifies any valid token
- */
-struct key *keyring_search_instkey(struct key *keyring,
-                                  key_serial_t target_id)
-{
-       struct request_key_auth *rka;
-       struct keyring_list *klist;
-       struct key *instkey;
-       int loop;
-
-       klist = rcu_dereference(keyring->payload.subscriptions);
-       if (klist) {
-               for (loop = 0; loop < klist->nkeys; loop++) {
-                       instkey = klist->keys[loop];
-
-                       if (instkey->type != &key_type_request_key_auth)
-                               continue;
-
-                       rka = instkey->payload.data;
-                       if (target_id && rka->target_key->serial != target_id)
-                               continue;
-
-                       /* the auth key is revoked during instantiation */
-                       if (!test_bit(KEY_FLAG_REVOKED, &instkey->flags))
-                               goto found;
-
-                       instkey = ERR_PTR(-EKEYREVOKED);
-                       goto error;
-               }
-       }
-
-       instkey = ERR_PTR(-EACCES);
-       goto error;
-
-found:
-       atomic_inc(&instkey->usage);
-error:
-       return instkey;
-
-} /* end keyring_search_instkey() */
-
 /*****************************************************************************/
 /*
  * find a keyring with the specified name
@@ -682,17 +637,33 @@ static void keyring_link_rcu_disposal(struct rcu_head *rcu)
 
 } /* end keyring_link_rcu_disposal() */
 
+/*****************************************************************************/
+/*
+ * dispose of a keyring list after the RCU grace period, freeing the unlinked
+ * key
+ */
+static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
+{
+       struct keyring_list *klist =
+               container_of(rcu, struct keyring_list, rcu);
+
+       key_put(klist->keys[klist->delkey]);
+       kfree(klist);
+
+} /* end keyring_unlink_rcu_disposal() */
+
 /*****************************************************************************/
 /*
  * link a key into to a keyring
  * - must be called with the keyring's semaphore write-locked
+ * - discard already extant link to matching key if there is one
  */
 int __key_link(struct key *keyring, struct key *key)
 {
        struct keyring_list *klist, *nklist;
        unsigned max;
        size_t size;
-       int ret;
+       int loop, ret;
 
        ret = -EKEYREVOKED;
        if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
@@ -714,6 +685,48 @@ int __key_link(struct key *keyring, struct key *key)
                        goto error2;
        }
 
+       /* see if there's a matching key we can displace */
+       klist = keyring->payload.subscriptions;
+
+       if (klist && klist->nkeys > 0) {
+               struct key_type *type = key->type;
+
+               for (loop = klist->nkeys - 1; loop >= 0; loop--) {
+                       if (klist->keys[loop]->type == type &&
+                           strcmp(klist->keys[loop]->description,
+                                  key->description) == 0
+                           ) {
+                               /* found a match - replace with new key */
+                               size = sizeof(struct key *) * klist->maxkeys;
+                               size += sizeof(*klist);
+                               BUG_ON(size > PAGE_SIZE);
+
+                               ret = -ENOMEM;
+                               nklist = kmalloc(size, GFP_KERNEL);
+                               if (!nklist)
+                                       goto error2;
+
+                               memcpy(nklist, klist, size);
+
+                               /* replace matched key */
+                               atomic_inc(&key->usage);
+                               nklist->keys[loop] = key;
+
+                               rcu_assign_pointer(
+                                       keyring->payload.subscriptions,
+                                       nklist);
+
+                               /* dispose of the old keyring list and the
+                                * displaced key */
+                               klist->delkey = loop;
+                               call_rcu(&klist->rcu,
+                                        keyring_unlink_rcu_disposal);
+
+                               goto done;
+                       }
+               }
+       }
+
        /* check that we aren't going to overrun the user's quota */
        ret = key_payload_reserve(keyring,
                                  keyring->datalen + KEYQUOTA_LINK_BYTES);
@@ -730,8 +743,6 @@ int __key_link(struct key *keyring, struct key *key)
                smp_wmb();
                klist->nkeys++;
                smp_wmb();
-
-               ret = 0;
        }
        else {
                /* grow the key list */
@@ -769,16 +780,16 @@ int __key_link(struct key *keyring, struct key *key)
                /* dispose of the old keyring list */
                if (klist)
                        call_rcu(&klist->rcu, keyring_link_rcu_disposal);
-
-               ret = 0;
        }
 
- error2:
+done:
+       ret = 0;
+error2:
        up_write(&keyring_serialise_link_sem);
- error:
+error:
        return ret;
 
- error3:
+error3:
        /* undo the quota changes */
        key_payload_reserve(keyring,
                            keyring->datalen - KEYQUOTA_LINK_BYTES);
@@ -807,21 +818,6 @@ int key_link(struct key *keyring, struct key *key)
 
 EXPORT_SYMBOL(key_link);
 
-/*****************************************************************************/
-/*
- * dispose of a keyring list after the RCU grace period, freeing the unlinked
- * key
- */
-static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
-{
-       struct keyring_list *klist =
-               container_of(rcu, struct keyring_list, rcu);
-
-       key_put(klist->keys[klist->delkey]);
-       kfree(klist);
-
-} /* end keyring_unlink_rcu_disposal() */
-
 /*****************************************************************************/
 /*
  * unlink the first link to a key from a keyring