| /* Keyring handling | 
 |  * | 
 |  * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved. | 
 |  * Written by David Howells (dhowells@redhat.com) | 
 |  * | 
 |  * This program is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU General Public License | 
 |  * as published by the Free Software Foundation; either version | 
 |  * 2 of the License, or (at your option) any later version. | 
 |  */ | 
 |  | 
 | #include <linux/module.h> | 
 | #include <linux/init.h> | 
 | #include <linux/sched.h> | 
 | #include <linux/slab.h> | 
 | #include <linux/security.h> | 
 | #include <linux/seq_file.h> | 
 | #include <linux/err.h> | 
 | #include <keys/keyring-type.h> | 
 | #include <linux/uaccess.h> | 
 | #include "internal.h" | 
 |  | 
 | #define rcu_dereference_locked_keyring(keyring)				\ | 
 | 	(rcu_dereference_protected(					\ | 
 | 		(keyring)->payload.subscriptions,			\ | 
 | 		rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem))) | 
 |  | 
 | #define KEY_LINK_FIXQUOTA 1UL | 
 |  | 
 | /* | 
 |  * When plumbing the depths of the key tree, this sets a hard limit | 
 |  * set on how deep we're willing to go. | 
 |  */ | 
 | #define KEYRING_SEARCH_MAX_DEPTH 6 | 
 |  | 
 | /* | 
 |  * We keep all named keyrings in a hash to speed looking them up. | 
 |  */ | 
 | #define KEYRING_NAME_HASH_SIZE	(1 << 5) | 
 |  | 
 | static struct list_head	keyring_name_hash[KEYRING_NAME_HASH_SIZE]; | 
 | static DEFINE_RWLOCK(keyring_name_lock); | 
 |  | 
 | static inline unsigned keyring_hash(const char *desc) | 
 | { | 
 | 	unsigned bucket = 0; | 
 |  | 
 | 	for (; *desc; desc++) | 
 | 		bucket += (unsigned char)*desc; | 
 |  | 
 | 	return bucket & (KEYRING_NAME_HASH_SIZE - 1); | 
 | } | 
 |  | 
 | /* | 
 |  * The keyring key type definition.  Keyrings are simply keys of this type and | 
 |  * can be treated as ordinary keys in addition to having their own special | 
 |  * operations. | 
 |  */ | 
 | static int keyring_instantiate(struct key *keyring, | 
 | 			       const void *data, size_t datalen); | 
 | static int keyring_match(const struct key *keyring, const void *criterion); | 
 | static void keyring_revoke(struct key *keyring); | 
 | static void keyring_destroy(struct key *keyring); | 
 | static void keyring_describe(const struct key *keyring, struct seq_file *m); | 
 | static long keyring_read(const struct key *keyring, | 
 | 			 char __user *buffer, size_t buflen); | 
 |  | 
 | struct key_type key_type_keyring = { | 
 | 	.name		= "keyring", | 
 | 	.def_datalen	= sizeof(struct keyring_list), | 
 | 	.instantiate	= keyring_instantiate, | 
 | 	.match		= keyring_match, | 
 | 	.revoke		= keyring_revoke, | 
 | 	.destroy	= keyring_destroy, | 
 | 	.describe	= keyring_describe, | 
 | 	.read		= keyring_read, | 
 | }; | 
 | EXPORT_SYMBOL(key_type_keyring); | 
 |  | 
 | /* | 
 |  * Semaphore to serialise link/link calls to prevent two link calls in parallel | 
 |  * introducing a cycle. | 
 |  */ | 
 | static DECLARE_RWSEM(keyring_serialise_link_sem); | 
 |  | 
 | /* | 
 |  * Publish the name of a keyring so that it can be found by name (if it has | 
 |  * one). | 
 |  */ | 
 | static void keyring_publish_name(struct key *keyring) | 
 | { | 
 | 	int bucket; | 
 |  | 
 | 	if (keyring->description) { | 
 | 		bucket = keyring_hash(keyring->description); | 
 |  | 
 | 		write_lock(&keyring_name_lock); | 
 |  | 
 | 		if (!keyring_name_hash[bucket].next) | 
 | 			INIT_LIST_HEAD(&keyring_name_hash[bucket]); | 
 |  | 
 | 		list_add_tail(&keyring->type_data.link, | 
 | 			      &keyring_name_hash[bucket]); | 
 |  | 
 | 		write_unlock(&keyring_name_lock); | 
 | 	} | 
 | } | 
 |  | 
 | /* | 
 |  * Initialise a keyring. | 
 |  * | 
 |  * Returns 0 on success, -EINVAL if given any data. | 
 |  */ | 
 | static int keyring_instantiate(struct key *keyring, | 
 | 			       const void *data, size_t datalen) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	ret = -EINVAL; | 
 | 	if (datalen == 0) { | 
 | 		/* make the keyring available by name if it has one */ | 
 | 		keyring_publish_name(keyring); | 
 | 		ret = 0; | 
 | 	} | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | /* | 
 |  * Match keyrings on their name | 
 |  */ | 
 | static int keyring_match(const struct key *keyring, const void *description) | 
 | { | 
 | 	return keyring->description && | 
 | 		strcmp(keyring->description, description) == 0; | 
 | } | 
 |  | 
 | /* | 
 |  * Clean up a keyring when it is destroyed.  Unpublish its name if it had one | 
 |  * and dispose of its data. | 
 |  */ | 
 | static void keyring_destroy(struct key *keyring) | 
 | { | 
 | 	struct keyring_list *klist; | 
 | 	int loop; | 
 |  | 
 | 	if (keyring->description) { | 
 | 		write_lock(&keyring_name_lock); | 
 |  | 
 | 		if (keyring->type_data.link.next != NULL && | 
 | 		    !list_empty(&keyring->type_data.link)) | 
 | 			list_del(&keyring->type_data.link); | 
 |  | 
 | 		write_unlock(&keyring_name_lock); | 
 | 	} | 
 |  | 
 | 	klist = rcu_dereference_check(keyring->payload.subscriptions, | 
 | 				      atomic_read(&keyring->usage) == 0); | 
 | 	if (klist) { | 
 | 		for (loop = klist->nkeys - 1; loop >= 0; loop--) | 
 | 			key_put(klist->keys[loop]); | 
 | 		kfree(klist); | 
 | 	} | 
 | } | 
 |  | 
 | /* | 
 |  * Describe a keyring for /proc. | 
 |  */ | 
 | static void keyring_describe(const struct key *keyring, struct seq_file *m) | 
 | { | 
 | 	struct keyring_list *klist; | 
 |  | 
 | 	if (keyring->description) | 
 | 		seq_puts(m, keyring->description); | 
 | 	else | 
 | 		seq_puts(m, "[anon]"); | 
 |  | 
 | 	if (key_is_instantiated(keyring)) { | 
 | 		rcu_read_lock(); | 
 | 		klist = rcu_dereference(keyring->payload.subscriptions); | 
 | 		if (klist) | 
 | 			seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); | 
 | 		else | 
 | 			seq_puts(m, ": empty"); | 
 | 		rcu_read_unlock(); | 
 | 	} | 
 | } | 
 |  | 
 | /* | 
 |  * Read a list of key IDs from the keyring's contents in binary form | 
 |  * | 
 |  * The keyring's semaphore is read-locked by the caller. | 
 |  */ | 
 | static long keyring_read(const struct key *keyring, | 
 | 			 char __user *buffer, size_t buflen) | 
 | { | 
 | 	struct keyring_list *klist; | 
 | 	struct key *key; | 
 | 	size_t qty, tmp; | 
 | 	int loop, ret; | 
 |  | 
 | 	ret = 0; | 
 | 	klist = rcu_dereference_locked_keyring(keyring); | 
 | 	if (klist) { | 
 | 		/* calculate how much data we could return */ | 
 | 		qty = klist->nkeys * sizeof(key_serial_t); | 
 |  | 
 | 		if (buffer && buflen > 0) { | 
 | 			if (buflen > qty) | 
 | 				buflen = qty; | 
 |  | 
 | 			/* copy the IDs of the subscribed keys into the | 
 | 			 * buffer */ | 
 | 			ret = -EFAULT; | 
 |  | 
 | 			for (loop = 0; loop < klist->nkeys; loop++) { | 
 | 				key = klist->keys[loop]; | 
 |  | 
 | 				tmp = sizeof(key_serial_t); | 
 | 				if (tmp > buflen) | 
 | 					tmp = buflen; | 
 |  | 
 | 				if (copy_to_user(buffer, | 
 | 						 &key->serial, | 
 | 						 tmp) != 0) | 
 | 					goto error; | 
 |  | 
 | 				buflen -= tmp; | 
 | 				if (buflen == 0) | 
 | 					break; | 
 | 				buffer += tmp; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		ret = qty; | 
 | 	} | 
 |  | 
 | error: | 
 | 	return ret; | 
 | } | 
 |  | 
 | /* | 
 |  * Allocate a keyring and link into the destination keyring. | 
 |  */ | 
 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 
 | 			  const struct cred *cred, unsigned long flags, | 
 | 			  struct key *dest) | 
 | { | 
 | 	struct key *keyring; | 
 | 	int ret; | 
 |  | 
 | 	keyring = key_alloc(&key_type_keyring, description, | 
 | 			    uid, gid, cred, | 
 | 			    (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | 
 | 			    flags); | 
 |  | 
 | 	if (!IS_ERR(keyring)) { | 
 | 		ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); | 
 | 		if (ret < 0) { | 
 | 			key_put(keyring); | 
 | 			keyring = ERR_PTR(ret); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return keyring; | 
 | } | 
 |  | 
 | /** | 
 |  * keyring_search_aux - Search a keyring tree for a key matching some criteria | 
 |  * @keyring_ref: A pointer to the keyring with possession indicator. | 
 |  * @cred: The credentials to use for permissions checks. | 
 |  * @type: The type of key to search for. | 
 |  * @description: Parameter for @match. | 
 |  * @match: Function to rule on whether or not a key is the one required. | 
 |  * @no_state_check: Don't check if a matching key is bad | 
 |  * | 
 |  * Search the supplied keyring tree for a key that matches the criteria given. | 
 |  * The root keyring and any linked keyrings must grant Search permission to the | 
 |  * caller to be searchable and keys can only be found if they too grant Search | 
 |  * to the caller. The possession flag on the root keyring pointer controls use | 
 |  * of the possessor bits in permissions checking of the entire tree.  In | 
 |  * addition, the LSM gets to forbid keyring searches and key matches. | 
 |  * | 
 |  * The search is performed as a breadth-then-depth search up to the prescribed | 
 |  * limit (KEYRING_SEARCH_MAX_DEPTH). | 
 |  * | 
 |  * Keys are matched to the type provided and are then filtered by the match | 
 |  * function, which is given the description to use in any way it sees fit.  The | 
 |  * match function may use any attributes of a key that it wishes to to | 
 |  * determine the match.  Normally the match function from the key type would be | 
 |  * used. | 
 |  * | 
 |  * RCU is used to prevent the keyring key lists from disappearing without the | 
 |  * need to take lots of locks. | 
 |  * | 
 |  * Returns a pointer to the found key and increments the key usage count if | 
 |  * successful; -EAGAIN if no matching keys were found, or if expired or revoked | 
 |  * keys were found; -ENOKEY if only negative keys were found; -ENOTDIR if the | 
 |  * specified keyring wasn't a keyring. | 
 |  * | 
 |  * In the case of a successful return, the possession attribute from | 
 |  * @keyring_ref is propagated to the returned key reference. | 
 |  */ | 
 | key_ref_t keyring_search_aux(key_ref_t keyring_ref, | 
 | 			     const struct cred *cred, | 
 | 			     struct key_type *type, | 
 | 			     const void *description, | 
 | 			     key_match_func_t match, | 
 | 			     bool no_state_check) | 
 | { | 
 | 	struct { | 
 | 		struct keyring_list *keylist; | 
 | 		int kix; | 
 | 	} stack[KEYRING_SEARCH_MAX_DEPTH]; | 
 |  | 
 | 	struct keyring_list *keylist; | 
 | 	struct timespec now; | 
 | 	unsigned long possessed, kflags; | 
 | 	struct key *keyring, *key; | 
 | 	key_ref_t key_ref; | 
 | 	long err; | 
 | 	int sp, nkeys, kix; | 
 |  | 
 | 	keyring = key_ref_to_ptr(keyring_ref); | 
 | 	possessed = is_key_possessed(keyring_ref); | 
 | 	key_check(keyring); | 
 |  | 
 | 	/* top keyring must have search permission to begin the search */ | 
 | 	err = key_task_permission(keyring_ref, cred, KEY_SEARCH); | 
 | 	if (err < 0) { | 
 | 		key_ref = ERR_PTR(err); | 
 | 		goto error; | 
 | 	} | 
 |  | 
 | 	key_ref = ERR_PTR(-ENOTDIR); | 
 | 	if (keyring->type != &key_type_keyring) | 
 | 		goto error; | 
 |  | 
 | 	rcu_read_lock(); | 
 |  | 
 | 	now = current_kernel_time(); | 
 | 	err = -EAGAIN; | 
 | 	sp = 0; | 
 |  | 
 | 	/* firstly we should check to see if this top-level keyring is what we | 
 | 	 * are looking for */ | 
 | 	key_ref = ERR_PTR(-EAGAIN); | 
 | 	kflags = keyring->flags; | 
 | 	if (keyring->type == type && match(keyring, description)) { | 
 | 		key = keyring; | 
 | 		if (no_state_check) | 
 | 			goto found; | 
 |  | 
 | 		/* check it isn't negative and hasn't expired or been | 
 | 		 * revoked */ | 
 | 		if (kflags & (1 << KEY_FLAG_REVOKED)) | 
 | 			goto error_2; | 
 | 		if (key->expiry && now.tv_sec >= key->expiry) | 
 | 			goto error_2; | 
 | 		key_ref = ERR_PTR(key->type_data.reject_error); | 
 | 		if (kflags & (1 << KEY_FLAG_NEGATIVE)) | 
 | 			goto error_2; | 
 | 		goto found; | 
 | 	} | 
 |  | 
 | 	/* otherwise, the top keyring must not be revoked, expired, or | 
 | 	 * negatively instantiated if we are to search it */ | 
 | 	key_ref = ERR_PTR(-EAGAIN); | 
 | 	if (kflags & ((1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) || | 
 | 	    (keyring->expiry && now.tv_sec >= keyring->expiry)) | 
 | 		goto error_2; | 
 |  | 
 | 	/* start processing a new keyring */ | 
 | descend: | 
 | 	if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | 
 | 		goto not_this_keyring; | 
 |  | 
 | 	keylist = rcu_dereference(keyring->payload.subscriptions); | 
 | 	if (!keylist) | 
 | 		goto not_this_keyring; | 
 |  | 
 | 	/* iterate through the keys in this keyring first */ | 
 | 	nkeys = keylist->nkeys; | 
 | 	smp_rmb(); | 
 | 	for (kix = 0; kix < nkeys; kix++) { | 
 | 		key = keylist->keys[kix]; | 
 | 		kflags = key->flags; | 
 |  | 
 | 		/* ignore keys not of this type */ | 
 | 		if (key->type != type) | 
 | 			continue; | 
 |  | 
 | 		/* skip revoked keys and expired keys */ | 
 | 		if (!no_state_check) { | 
 | 			if (kflags & (1 << KEY_FLAG_REVOKED)) | 
 | 				continue; | 
 |  | 
 | 			if (key->expiry && now.tv_sec >= key->expiry) | 
 | 				continue; | 
 | 		} | 
 |  | 
 | 		/* keys that don't match */ | 
 | 		if (!match(key, description)) | 
 | 			continue; | 
 |  | 
 | 		/* key must have search permissions */ | 
 | 		if (key_task_permission(make_key_ref(key, possessed), | 
 | 					cred, KEY_SEARCH) < 0) | 
 | 			continue; | 
 |  | 
 | 		if (no_state_check) | 
 | 			goto found; | 
 |  | 
 | 		/* we set a different error code if we pass a negative key */ | 
 | 		if (kflags & (1 << KEY_FLAG_NEGATIVE)) { | 
 | 			err = key->type_data.reject_error; | 
 | 			continue; | 
 | 		} | 
 |  | 
 | 		goto found; | 
 | 	} | 
 |  | 
 | 	/* search through the keyrings nested in this one */ | 
 | 	kix = 0; | 
 | ascend: | 
 | 	nkeys = keylist->nkeys; | 
 | 	smp_rmb(); | 
 | 	for (; kix < nkeys; kix++) { | 
 | 		key = keylist->keys[kix]; | 
 | 		if (key->type != &key_type_keyring) | 
 | 			continue; | 
 |  | 
 | 		/* recursively search nested keyrings | 
 | 		 * - only search keyrings for which we have search permission | 
 | 		 */ | 
 | 		if (sp >= KEYRING_SEARCH_MAX_DEPTH) | 
 | 			continue; | 
 |  | 
 | 		if (key_task_permission(make_key_ref(key, possessed), | 
 | 					cred, KEY_SEARCH) < 0) | 
 | 			continue; | 
 |  | 
 | 		/* stack the current position */ | 
 | 		stack[sp].keylist = keylist; | 
 | 		stack[sp].kix = kix; | 
 | 		sp++; | 
 |  | 
 | 		/* begin again with the new keyring */ | 
 | 		keyring = key; | 
 | 		goto descend; | 
 | 	} | 
 |  | 
 | 	/* the keyring we're looking at was disqualified or didn't contain a | 
 | 	 * matching key */ | 
 | not_this_keyring: | 
 | 	if (sp > 0) { | 
 | 		/* resume the processing of a keyring higher up in the tree */ | 
 | 		sp--; | 
 | 		keylist = stack[sp].keylist; | 
 | 		kix = stack[sp].kix + 1; | 
 | 		goto ascend; | 
 | 	} | 
 |  | 
 | 	key_ref = ERR_PTR(err); | 
 | 	goto error_2; | 
 |  | 
 | 	/* we found a viable match */ | 
 | found: | 
 | 	atomic_inc(&key->usage); | 
 | 	key_check(key); | 
 | 	key_ref = make_key_ref(key, possessed); | 
 | error_2: | 
 | 	rcu_read_unlock(); | 
 | error: | 
 | 	return key_ref; | 
 | } | 
 |  | 
 | /** | 
 |  * keyring_search - Search the supplied keyring tree for a matching key | 
 |  * @keyring: The root of the keyring tree to be searched. | 
 |  * @type: The type of keyring we want to find. | 
 |  * @description: The name of the keyring we want to find. | 
 |  * | 
 |  * As keyring_search_aux() above, but using the current task's credentials and | 
 |  * type's default matching function. | 
 |  */ | 
 | key_ref_t keyring_search(key_ref_t keyring, | 
 | 			 struct key_type *type, | 
 | 			 const char *description) | 
 | { | 
 | 	if (!type->match) | 
 | 		return ERR_PTR(-ENOKEY); | 
 |  | 
 | 	return keyring_search_aux(keyring, current->cred, | 
 | 				  type, description, type->match, false); | 
 | } | 
 | EXPORT_SYMBOL(keyring_search); | 
 |  | 
 | /* | 
 |  * Search the given keyring only (no recursion). | 
 |  * | 
 |  * The caller must guarantee that the keyring is a keyring and that the | 
 |  * permission is granted to search the keyring as no check is made here. | 
 |  * | 
 |  * RCU is used to make it unnecessary to lock the keyring key list here. | 
 |  * | 
 |  * Returns a pointer to the found key with usage count incremented if | 
 |  * successful and returns -ENOKEY if not found.  Revoked keys and keys not | 
 |  * providing the requested permission are skipped over. | 
 |  * | 
 |  * If successful, the possession indicator is propagated from the keyring ref | 
 |  * to the returned key reference. | 
 |  */ | 
 | key_ref_t __keyring_search_one(key_ref_t keyring_ref, | 
 | 			       const struct key_type *ktype, | 
 | 			       const char *description, | 
 | 			       key_perm_t perm) | 
 | { | 
 | 	struct keyring_list *klist; | 
 | 	unsigned long possessed; | 
 | 	struct key *keyring, *key; | 
 | 	int nkeys, loop; | 
 |  | 
 | 	keyring = key_ref_to_ptr(keyring_ref); | 
 | 	possessed = is_key_possessed(keyring_ref); | 
 |  | 
 | 	rcu_read_lock(); | 
 |  | 
 | 	klist = rcu_dereference(keyring->payload.subscriptions); | 
 | 	if (klist) { | 
 | 		nkeys = klist->nkeys; | 
 | 		smp_rmb(); | 
 | 		for (loop = 0; loop < nkeys ; loop++) { | 
 | 			key = klist->keys[loop]; | 
 |  | 
 | 			if (key->type == ktype && | 
 | 			    (!key->type->match || | 
 | 			     key->type->match(key, description)) && | 
 | 			    key_permission(make_key_ref(key, possessed), | 
 | 					   perm) == 0 && | 
 | 			    !test_bit(KEY_FLAG_REVOKED, &key->flags) | 
 | 			    ) | 
 | 				goto found; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	rcu_read_unlock(); | 
 | 	return ERR_PTR(-ENOKEY); | 
 |  | 
 | found: | 
 | 	atomic_inc(&key->usage); | 
 | 	rcu_read_unlock(); | 
 | 	return make_key_ref(key, possessed); | 
 | } | 
 |  | 
 | /* | 
 |  * Find a keyring with the specified name. | 
 |  * | 
 |  * All named keyrings in the current user namespace are searched, provided they | 
 |  * grant Search permission directly to the caller (unless this check is | 
 |  * skipped).  Keyrings whose usage points have reached zero or who have been | 
 |  * revoked are skipped. | 
 |  * | 
 |  * Returns a pointer to the keyring with the keyring's refcount having being | 
 |  * incremented on success.  -ENOKEY is returned if a key could not be found. | 
 |  */ | 
 | struct key *find_keyring_by_name(const char *name, bool skip_perm_check) | 
 | { | 
 | 	struct key *keyring; | 
 | 	int bucket; | 
 |  | 
 | 	if (!name) | 
 | 		return ERR_PTR(-EINVAL); | 
 |  | 
 | 	bucket = keyring_hash(name); | 
 |  | 
 | 	read_lock(&keyring_name_lock); | 
 |  | 
 | 	if (keyring_name_hash[bucket].next) { | 
 | 		/* search this hash bucket for a keyring with a matching name | 
 | 		 * that's readable and that hasn't been revoked */ | 
 | 		list_for_each_entry(keyring, | 
 | 				    &keyring_name_hash[bucket], | 
 | 				    type_data.link | 
 | 				    ) { | 
 | 			if (keyring->user->user_ns != current_user_ns()) | 
 | 				continue; | 
 |  | 
 | 			if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | 
 | 				continue; | 
 |  | 
 | 			if (strcmp(keyring->description, name) != 0) | 
 | 				continue; | 
 |  | 
 | 			if (!skip_perm_check && | 
 | 			    key_permission(make_key_ref(keyring, 0), | 
 | 					   KEY_SEARCH) < 0) | 
 | 				continue; | 
 |  | 
 | 			/* we've got a match but we might end up racing with | 
 | 			 * key_cleanup() if the keyring is currently 'dead' | 
 | 			 * (ie. it has a zero usage count) */ | 
 | 			if (!atomic_inc_not_zero(&keyring->usage)) | 
 | 				continue; | 
 | 			goto out; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	keyring = ERR_PTR(-ENOKEY); | 
 | out: | 
 | 	read_unlock(&keyring_name_lock); | 
 | 	return keyring; | 
 | } | 
 |  | 
 | /* | 
 |  * See if a cycle will will be created by inserting acyclic tree B in acyclic | 
 |  * tree A at the topmost level (ie: as a direct child of A). | 
 |  * | 
 |  * Since we are adding B to A at the top level, checking for cycles should just | 
 |  * be a matter of seeing if node A is somewhere in tree B. | 
 |  */ | 
 | static int keyring_detect_cycle(struct key *A, struct key *B) | 
 | { | 
 | 	struct { | 
 | 		struct keyring_list *keylist; | 
 | 		int kix; | 
 | 	} stack[KEYRING_SEARCH_MAX_DEPTH]; | 
 |  | 
 | 	struct keyring_list *keylist; | 
 | 	struct key *subtree, *key; | 
 | 	int sp, nkeys, kix, ret; | 
 |  | 
 | 	rcu_read_lock(); | 
 |  | 
 | 	ret = -EDEADLK; | 
 | 	if (A == B) | 
 | 		goto cycle_detected; | 
 |  | 
 | 	subtree = B; | 
 | 	sp = 0; | 
 |  | 
 | 	/* start processing a new keyring */ | 
 | descend: | 
 | 	if (test_bit(KEY_FLAG_REVOKED, &subtree->flags)) | 
 | 		goto not_this_keyring; | 
 |  | 
 | 	keylist = rcu_dereference(subtree->payload.subscriptions); | 
 | 	if (!keylist) | 
 | 		goto not_this_keyring; | 
 | 	kix = 0; | 
 |  | 
 | ascend: | 
 | 	/* iterate through the remaining keys in this keyring */ | 
 | 	nkeys = keylist->nkeys; | 
 | 	smp_rmb(); | 
 | 	for (; kix < nkeys; kix++) { | 
 | 		key = keylist->keys[kix]; | 
 |  | 
 | 		if (key == A) | 
 | 			goto cycle_detected; | 
 |  | 
 | 		/* recursively check nested keyrings */ | 
 | 		if (key->type == &key_type_keyring) { | 
 | 			if (sp >= KEYRING_SEARCH_MAX_DEPTH) | 
 | 				goto too_deep; | 
 |  | 
 | 			/* stack the current position */ | 
 | 			stack[sp].keylist = keylist; | 
 | 			stack[sp].kix = kix; | 
 | 			sp++; | 
 |  | 
 | 			/* begin again with the new keyring */ | 
 | 			subtree = key; | 
 | 			goto descend; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	/* the keyring we're looking at was disqualified or didn't contain a | 
 | 	 * matching key */ | 
 | not_this_keyring: | 
 | 	if (sp > 0) { | 
 | 		/* resume the checking of a keyring higher up in the tree */ | 
 | 		sp--; | 
 | 		keylist = stack[sp].keylist; | 
 | 		kix = stack[sp].kix + 1; | 
 | 		goto ascend; | 
 | 	} | 
 |  | 
 | 	ret = 0; /* no cycles detected */ | 
 |  | 
 | error: | 
 | 	rcu_read_unlock(); | 
 | 	return ret; | 
 |  | 
 | too_deep: | 
 | 	ret = -ELOOP; | 
 | 	goto error; | 
 |  | 
 | cycle_detected: | 
 | 	ret = -EDEADLK; | 
 | 	goto error; | 
 | } | 
 |  | 
 | /* | 
 |  * 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); | 
 |  | 
 | 	if (klist->delkey != USHRT_MAX) | 
 | 		key_put(klist->keys[klist->delkey]); | 
 | 	kfree(klist); | 
 | } | 
 |  | 
 | /* | 
 |  * Preallocate memory so that a key can be linked into to a keyring. | 
 |  */ | 
 | int __key_link_begin(struct key *keyring, const struct key_type *type, | 
 | 		     const char *description, unsigned long *_prealloc) | 
 | 	__acquires(&keyring->sem) | 
 | { | 
 | 	struct keyring_list *klist, *nklist; | 
 | 	unsigned long prealloc; | 
 | 	unsigned max; | 
 | 	size_t size; | 
 | 	int loop, ret; | 
 |  | 
 | 	kenter("%d,%s,%s,", key_serial(keyring), type->name, description); | 
 |  | 
 | 	if (keyring->type != &key_type_keyring) | 
 | 		return -ENOTDIR; | 
 |  | 
 | 	down_write(&keyring->sem); | 
 |  | 
 | 	ret = -EKEYREVOKED; | 
 | 	if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | 
 | 		goto error_krsem; | 
 |  | 
 | 	/* serialise link/link calls to prevent parallel calls causing a cycle | 
 | 	 * when linking two keyring in opposite orders */ | 
 | 	if (type == &key_type_keyring) | 
 | 		down_write(&keyring_serialise_link_sem); | 
 |  | 
 | 	klist = rcu_dereference_locked_keyring(keyring); | 
 |  | 
 | 	/* see if there's a matching key we can displace */ | 
 | 	if (klist && klist->nkeys > 0) { | 
 | 		for (loop = klist->nkeys - 1; loop >= 0; loop--) { | 
 | 			if (klist->keys[loop]->type == type && | 
 | 			    strcmp(klist->keys[loop]->description, | 
 | 				   description) == 0 | 
 | 			    ) { | 
 | 				/* found a match - we'll replace this one with | 
 | 				 * the new key */ | 
 | 				size = sizeof(struct key *) * klist->maxkeys; | 
 | 				size += sizeof(*klist); | 
 | 				BUG_ON(size > PAGE_SIZE); | 
 |  | 
 | 				ret = -ENOMEM; | 
 | 				nklist = kmemdup(klist, size, GFP_KERNEL); | 
 | 				if (!nklist) | 
 | 					goto error_sem; | 
 |  | 
 | 				/* note replacement slot */ | 
 | 				klist->delkey = nklist->delkey = loop; | 
 | 				prealloc = (unsigned long)nklist; | 
 | 				goto done; | 
 | 			} | 
 | 		} | 
 | 	} | 
 |  | 
 | 	/* check that we aren't going to overrun the user's quota */ | 
 | 	ret = key_payload_reserve(keyring, | 
 | 				  keyring->datalen + KEYQUOTA_LINK_BYTES); | 
 | 	if (ret < 0) | 
 | 		goto error_sem; | 
 |  | 
 | 	if (klist && klist->nkeys < klist->maxkeys) { | 
 | 		/* there's sufficient slack space to append directly */ | 
 | 		nklist = NULL; | 
 | 		prealloc = KEY_LINK_FIXQUOTA; | 
 | 	} else { | 
 | 		/* grow the key list */ | 
 | 		max = 4; | 
 | 		if (klist) | 
 | 			max += klist->maxkeys; | 
 |  | 
 | 		ret = -ENFILE; | 
 | 		if (max > USHRT_MAX - 1) | 
 | 			goto error_quota; | 
 | 		size = sizeof(*klist) + sizeof(struct key *) * max; | 
 | 		if (size > PAGE_SIZE) | 
 | 			goto error_quota; | 
 |  | 
 | 		ret = -ENOMEM; | 
 | 		nklist = kmalloc(size, GFP_KERNEL); | 
 | 		if (!nklist) | 
 | 			goto error_quota; | 
 |  | 
 | 		nklist->maxkeys = max; | 
 | 		if (klist) { | 
 | 			memcpy(nklist->keys, klist->keys, | 
 | 			       sizeof(struct key *) * klist->nkeys); | 
 | 			nklist->delkey = klist->nkeys; | 
 | 			nklist->nkeys = klist->nkeys + 1; | 
 | 			klist->delkey = USHRT_MAX; | 
 | 		} else { | 
 | 			nklist->nkeys = 1; | 
 | 			nklist->delkey = 0; | 
 | 		} | 
 |  | 
 | 		/* add the key into the new space */ | 
 | 		nklist->keys[nklist->delkey] = NULL; | 
 | 	} | 
 |  | 
 | 	prealloc = (unsigned long)nklist | KEY_LINK_FIXQUOTA; | 
 | done: | 
 | 	*_prealloc = prealloc; | 
 | 	kleave(" = 0"); | 
 | 	return 0; | 
 |  | 
 | error_quota: | 
 | 	/* undo the quota changes */ | 
 | 	key_payload_reserve(keyring, | 
 | 			    keyring->datalen - KEYQUOTA_LINK_BYTES); | 
 | error_sem: | 
 | 	if (type == &key_type_keyring) | 
 | 		up_write(&keyring_serialise_link_sem); | 
 | error_krsem: | 
 | 	up_write(&keyring->sem); | 
 | 	kleave(" = %d", ret); | 
 | 	return ret; | 
 | } | 
 |  | 
 | /* | 
 |  * Check already instantiated keys aren't going to be a problem. | 
 |  * | 
 |  * The caller must have called __key_link_begin(). Don't need to call this for | 
 |  * keys that were created since __key_link_begin() was called. | 
 |  */ | 
 | int __key_link_check_live_key(struct key *keyring, struct key *key) | 
 | { | 
 | 	if (key->type == &key_type_keyring) | 
 | 		/* check that we aren't going to create a cycle by linking one | 
 | 		 * keyring to another */ | 
 | 		return keyring_detect_cycle(keyring, key); | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* | 
 |  * Link a key into to a keyring. | 
 |  * | 
 |  * Must be called with __key_link_begin() having being called.  Discards any | 
 |  * already extant link to matching key if there is one, so that each keyring | 
 |  * holds at most one link to any given key of a particular type+description | 
 |  * combination. | 
 |  */ | 
 | void __key_link(struct key *keyring, struct key *key, | 
 | 		unsigned long *_prealloc) | 
 | { | 
 | 	struct keyring_list *klist, *nklist; | 
 |  | 
 | 	nklist = (struct keyring_list *)(*_prealloc & ~KEY_LINK_FIXQUOTA); | 
 | 	*_prealloc = 0; | 
 |  | 
 | 	kenter("%d,%d,%p", keyring->serial, key->serial, nklist); | 
 |  | 
 | 	klist = rcu_dereference_locked_keyring(keyring); | 
 |  | 
 | 	atomic_inc(&key->usage); | 
 |  | 
 | 	/* there's a matching key we can displace or an empty slot in a newly | 
 | 	 * allocated list we can fill */ | 
 | 	if (nklist) { | 
 | 		kdebug("replace %hu/%hu/%hu", | 
 | 		       nklist->delkey, nklist->nkeys, nklist->maxkeys); | 
 |  | 
 | 		nklist->keys[nklist->delkey] = key; | 
 |  | 
 | 		rcu_assign_pointer(keyring->payload.subscriptions, nklist); | 
 |  | 
 | 		/* dispose of the old keyring list and, if there was one, the | 
 | 		 * displaced key */ | 
 | 		if (klist) { | 
 | 			kdebug("dispose %hu/%hu/%hu", | 
 | 			       klist->delkey, klist->nkeys, klist->maxkeys); | 
 | 			call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); | 
 | 		} | 
 | 	} else { | 
 | 		/* there's sufficient slack space to append directly */ | 
 | 		klist->keys[klist->nkeys] = key; | 
 | 		smp_wmb(); | 
 | 		klist->nkeys++; | 
 | 	} | 
 | } | 
 |  | 
 | /* | 
 |  * Finish linking a key into to a keyring. | 
 |  * | 
 |  * Must be called with __key_link_begin() having being called. | 
 |  */ | 
 | void __key_link_end(struct key *keyring, struct key_type *type, | 
 | 		    unsigned long prealloc) | 
 | 	__releases(&keyring->sem) | 
 | { | 
 | 	BUG_ON(type == NULL); | 
 | 	BUG_ON(type->name == NULL); | 
 | 	kenter("%d,%s,%lx", keyring->serial, type->name, prealloc); | 
 |  | 
 | 	if (type == &key_type_keyring) | 
 | 		up_write(&keyring_serialise_link_sem); | 
 |  | 
 | 	if (prealloc) { | 
 | 		if (prealloc & KEY_LINK_FIXQUOTA) | 
 | 			key_payload_reserve(keyring, | 
 | 					    keyring->datalen - | 
 | 					    KEYQUOTA_LINK_BYTES); | 
 | 		kfree((struct keyring_list *)(prealloc & ~KEY_LINK_FIXQUOTA)); | 
 | 	} | 
 | 	up_write(&keyring->sem); | 
 | } | 
 |  | 
 | /** | 
 |  * key_link - Link a key to a keyring | 
 |  * @keyring: The keyring to make the link in. | 
 |  * @key: The key to link to. | 
 |  * | 
 |  * Make a link in a keyring to a key, such that the keyring holds a reference | 
 |  * on that key and the key can potentially be found by searching that keyring. | 
 |  * | 
 |  * This function will write-lock the keyring's semaphore and will consume some | 
 |  * of the user's key data quota to hold the link. | 
 |  * | 
 |  * Returns 0 if successful, -ENOTDIR if the keyring isn't a keyring, | 
 |  * -EKEYREVOKED if the keyring has been revoked, -ENFILE if the keyring is | 
 |  * full, -EDQUOT if there is insufficient key data quota remaining to add | 
 |  * another link or -ENOMEM if there's insufficient memory. | 
 |  * | 
 |  * It is assumed that the caller has checked that it is permitted for a link to | 
 |  * be made (the keyring should have Write permission and the key Link | 
 |  * permission). | 
 |  */ | 
 | int key_link(struct key *keyring, struct key *key) | 
 | { | 
 | 	unsigned long prealloc; | 
 | 	int ret; | 
 |  | 
 | 	key_check(keyring); | 
 | 	key_check(key); | 
 |  | 
 | 	ret = __key_link_begin(keyring, key->type, key->description, &prealloc); | 
 | 	if (ret == 0) { | 
 | 		ret = __key_link_check_live_key(keyring, key); | 
 | 		if (ret == 0) | 
 | 			__key_link(keyring, key, &prealloc); | 
 | 		__key_link_end(keyring, key->type, prealloc); | 
 | 	} | 
 |  | 
 | 	return ret; | 
 | } | 
 | EXPORT_SYMBOL(key_link); | 
 |  | 
 | /** | 
 |  * key_unlink - Unlink the first link to a key from a keyring. | 
 |  * @keyring: The keyring to remove the link from. | 
 |  * @key: The key the link is to. | 
 |  * | 
 |  * Remove a link from a keyring to a key. | 
 |  * | 
 |  * This function will write-lock the keyring's semaphore. | 
 |  * | 
 |  * Returns 0 if successful, -ENOTDIR if the keyring isn't a keyring, -ENOENT if | 
 |  * the key isn't linked to by the keyring or -ENOMEM if there's insufficient | 
 |  * memory. | 
 |  * | 
 |  * It is assumed that the caller has checked that it is permitted for a link to | 
 |  * be removed (the keyring should have Write permission; no permissions are | 
 |  * required on the key). | 
 |  */ | 
 | int key_unlink(struct key *keyring, struct key *key) | 
 | { | 
 | 	struct keyring_list *klist, *nklist; | 
 | 	int loop, ret; | 
 |  | 
 | 	key_check(keyring); | 
 | 	key_check(key); | 
 |  | 
 | 	ret = -ENOTDIR; | 
 | 	if (keyring->type != &key_type_keyring) | 
 | 		goto error; | 
 |  | 
 | 	down_write(&keyring->sem); | 
 |  | 
 | 	klist = rcu_dereference_locked_keyring(keyring); | 
 | 	if (klist) { | 
 | 		/* search the keyring for the key */ | 
 | 		for (loop = 0; loop < klist->nkeys; loop++) | 
 | 			if (klist->keys[loop] == key) | 
 | 				goto key_is_present; | 
 | 	} | 
 |  | 
 | 	up_write(&keyring->sem); | 
 | 	ret = -ENOENT; | 
 | 	goto error; | 
 |  | 
 | key_is_present: | 
 | 	/* we need to copy the key list for RCU purposes */ | 
 | 	nklist = kmalloc(sizeof(*klist) + | 
 | 			 sizeof(struct key *) * klist->maxkeys, | 
 | 			 GFP_KERNEL); | 
 | 	if (!nklist) | 
 | 		goto nomem; | 
 | 	nklist->maxkeys = klist->maxkeys; | 
 | 	nklist->nkeys = klist->nkeys - 1; | 
 |  | 
 | 	if (loop > 0) | 
 | 		memcpy(&nklist->keys[0], | 
 | 		       &klist->keys[0], | 
 | 		       loop * sizeof(struct key *)); | 
 |  | 
 | 	if (loop < nklist->nkeys) | 
 | 		memcpy(&nklist->keys[loop], | 
 | 		       &klist->keys[loop + 1], | 
 | 		       (nklist->nkeys - loop) * sizeof(struct key *)); | 
 |  | 
 | 	/* adjust the user's quota */ | 
 | 	key_payload_reserve(keyring, | 
 | 			    keyring->datalen - KEYQUOTA_LINK_BYTES); | 
 |  | 
 | 	rcu_assign_pointer(keyring->payload.subscriptions, nklist); | 
 |  | 
 | 	up_write(&keyring->sem); | 
 |  | 
 | 	/* schedule for later cleanup */ | 
 | 	klist->delkey = loop; | 
 | 	call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); | 
 |  | 
 | 	ret = 0; | 
 |  | 
 | error: | 
 | 	return ret; | 
 | nomem: | 
 | 	ret = -ENOMEM; | 
 | 	up_write(&keyring->sem); | 
 | 	goto error; | 
 | } | 
 | EXPORT_SYMBOL(key_unlink); | 
 |  | 
 | /* | 
 |  * Dispose of a keyring list after the RCU grace period, releasing the keys it | 
 |  * links to. | 
 |  */ | 
 | static void keyring_clear_rcu_disposal(struct rcu_head *rcu) | 
 | { | 
 | 	struct keyring_list *klist; | 
 | 	int loop; | 
 |  | 
 | 	klist = container_of(rcu, struct keyring_list, rcu); | 
 |  | 
 | 	for (loop = klist->nkeys - 1; loop >= 0; loop--) | 
 | 		key_put(klist->keys[loop]); | 
 |  | 
 | 	kfree(klist); | 
 | } | 
 |  | 
 | /** | 
 |  * keyring_clear - Clear a keyring | 
 |  * @keyring: The keyring to clear. | 
 |  * | 
 |  * Clear the contents of the specified keyring. | 
 |  * | 
 |  * Returns 0 if successful or -ENOTDIR if the keyring isn't a keyring. | 
 |  */ | 
 | int keyring_clear(struct key *keyring) | 
 | { | 
 | 	struct keyring_list *klist; | 
 | 	int ret; | 
 |  | 
 | 	ret = -ENOTDIR; | 
 | 	if (keyring->type == &key_type_keyring) { | 
 | 		/* detach the pointer block with the locks held */ | 
 | 		down_write(&keyring->sem); | 
 |  | 
 | 		klist = rcu_dereference_locked_keyring(keyring); | 
 | 		if (klist) { | 
 | 			/* adjust the quota */ | 
 | 			key_payload_reserve(keyring, | 
 | 					    sizeof(struct keyring_list)); | 
 |  | 
 | 			rcu_assign_pointer(keyring->payload.subscriptions, | 
 | 					   NULL); | 
 | 		} | 
 |  | 
 | 		up_write(&keyring->sem); | 
 |  | 
 | 		/* free the keys after the locks have been dropped */ | 
 | 		if (klist) | 
 | 			call_rcu(&klist->rcu, keyring_clear_rcu_disposal); | 
 |  | 
 | 		ret = 0; | 
 | 	} | 
 |  | 
 | 	return ret; | 
 | } | 
 | EXPORT_SYMBOL(keyring_clear); | 
 |  | 
 | /* | 
 |  * Dispose of the links from a revoked keyring. | 
 |  * | 
 |  * This is called with the key sem write-locked. | 
 |  */ | 
 | static void keyring_revoke(struct key *keyring) | 
 | { | 
 | 	struct keyring_list *klist; | 
 |  | 
 | 	klist = rcu_dereference_locked_keyring(keyring); | 
 |  | 
 | 	/* adjust the quota */ | 
 | 	key_payload_reserve(keyring, 0); | 
 |  | 
 | 	if (klist) { | 
 | 		rcu_assign_pointer(keyring->payload.subscriptions, NULL); | 
 | 		call_rcu(&klist->rcu, keyring_clear_rcu_disposal); | 
 | 	} | 
 | } | 
 |  | 
 | /* | 
 |  * Determine whether a key is dead. | 
 |  */ | 
 | static bool key_is_dead(struct key *key, time_t limit) | 
 | { | 
 | 	return test_bit(KEY_FLAG_DEAD, &key->flags) || | 
 | 		(key->expiry > 0 && key->expiry <= limit); | 
 | } | 
 |  | 
 | /* | 
 |  * Collect garbage from the contents of a keyring, replacing the old list with | 
 |  * a new one with the pointers all shuffled down. | 
 |  * | 
 |  * Dead keys are classed as oned that are flagged as being dead or are revoked, | 
 |  * expired or negative keys that were revoked or expired before the specified | 
 |  * limit. | 
 |  */ | 
 | void keyring_gc(struct key *keyring, time_t limit) | 
 | { | 
 | 	struct keyring_list *klist, *new; | 
 | 	struct key *key; | 
 | 	int loop, keep, max; | 
 |  | 
 | 	kenter("{%x,%s}", key_serial(keyring), keyring->description); | 
 |  | 
 | 	down_write(&keyring->sem); | 
 |  | 
 | 	klist = rcu_dereference_locked_keyring(keyring); | 
 | 	if (!klist) | 
 | 		goto no_klist; | 
 |  | 
 | 	/* work out how many subscriptions we're keeping */ | 
 | 	keep = 0; | 
 | 	for (loop = klist->nkeys - 1; loop >= 0; loop--) | 
 | 		if (!key_is_dead(klist->keys[loop], limit)) | 
 | 			keep++; | 
 |  | 
 | 	if (keep == klist->nkeys) | 
 | 		goto just_return; | 
 |  | 
 | 	/* allocate a new keyring payload */ | 
 | 	max = roundup(keep, 4); | 
 | 	new = kmalloc(sizeof(struct keyring_list) + max * sizeof(struct key *), | 
 | 		      GFP_KERNEL); | 
 | 	if (!new) | 
 | 		goto nomem; | 
 | 	new->maxkeys = max; | 
 | 	new->nkeys = 0; | 
 | 	new->delkey = 0; | 
 |  | 
 | 	/* install the live keys | 
 | 	 * - must take care as expired keys may be updated back to life | 
 | 	 */ | 
 | 	keep = 0; | 
 | 	for (loop = klist->nkeys - 1; loop >= 0; loop--) { | 
 | 		key = klist->keys[loop]; | 
 | 		if (!key_is_dead(key, limit)) { | 
 | 			if (keep >= max) | 
 | 				goto discard_new; | 
 | 			new->keys[keep++] = key_get(key); | 
 | 		} | 
 | 	} | 
 | 	new->nkeys = keep; | 
 |  | 
 | 	/* adjust the quota */ | 
 | 	key_payload_reserve(keyring, | 
 | 			    sizeof(struct keyring_list) + | 
 | 			    KEYQUOTA_LINK_BYTES * keep); | 
 |  | 
 | 	if (keep == 0) { | 
 | 		rcu_assign_pointer(keyring->payload.subscriptions, NULL); | 
 | 		kfree(new); | 
 | 	} else { | 
 | 		rcu_assign_pointer(keyring->payload.subscriptions, new); | 
 | 	} | 
 |  | 
 | 	up_write(&keyring->sem); | 
 |  | 
 | 	call_rcu(&klist->rcu, keyring_clear_rcu_disposal); | 
 | 	kleave(" [yes]"); | 
 | 	return; | 
 |  | 
 | discard_new: | 
 | 	new->nkeys = keep; | 
 | 	keyring_clear_rcu_disposal(&new->rcu); | 
 | 	up_write(&keyring->sem); | 
 | 	kleave(" [discard]"); | 
 | 	return; | 
 |  | 
 | just_return: | 
 | 	up_write(&keyring->sem); | 
 | 	kleave(" [no dead]"); | 
 | 	return; | 
 |  | 
 | no_klist: | 
 | 	up_write(&keyring->sem); | 
 | 	kleave(" [no_klist]"); | 
 | 	return; | 
 |  | 
 | nomem: | 
 | 	up_write(&keyring->sem); | 
 | 	kleave(" [oom]"); | 
 | } |