+ /* 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;
+ }
+ }
+ }
+