| /* keyring.c: keyring handling | 
 |  * | 
 |  * Copyright (C) 2004-5 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 <asm/uaccess.h> | 
 | #include "internal.h" | 
 |  | 
 | /* | 
 |  * 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 type definition | 
 |  */ | 
 | 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) | 
 |  */ | 
 | 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); | 
 | 	} | 
 |  | 
 | } /* end keyring_publish_name() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * initialise a keyring | 
 |  * - we object if we were 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; | 
 |  | 
 | } /* end keyring_instantiate() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * match keyrings on their name | 
 |  */ | 
 | static int keyring_match(const struct key *keyring, const void *description) | 
 | { | 
 | 	return keyring->description && | 
 | 		strcmp(keyring->description, description) == 0; | 
 |  | 
 | } /* end keyring_match() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * dispose of the data dangling from the corpse of a keyring | 
 |  */ | 
 | 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(keyring->payload.subscriptions); | 
 | 	if (klist) { | 
 | 		for (loop = klist->nkeys - 1; loop >= 0; loop--) | 
 | 			key_put(klist->keys[loop]); | 
 | 		kfree(klist); | 
 | 	} | 
 |  | 
 | } /* end keyring_destroy() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * describe the keyring | 
 |  */ | 
 | 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]"); | 
 | 	} | 
 |  | 
 | 	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(); | 
 |  | 
 | } /* end keyring_describe() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * read a list of key IDs from the keyring's contents | 
 |  * - the keyring's semaphore is read-locked | 
 |  */ | 
 | 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(keyring->payload.subscriptions); | 
 |  | 
 | 	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; | 
 |  | 
 | } /* end keyring_read() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * allocate a keyring and link into the destination keyring | 
 |  */ | 
 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 
 | 			  struct task_struct *ctx, unsigned long flags, | 
 | 			  struct key *dest) | 
 | { | 
 | 	struct key *keyring; | 
 | 	int ret; | 
 |  | 
 | 	keyring = key_alloc(&key_type_keyring, description, | 
 | 			    uid, gid, ctx, | 
 | 			    (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; | 
 |  | 
 | } /* end keyring_alloc() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * search the supplied keyring tree for a key that matches the criterion | 
 |  * - perform a breadth-then-depth search up to the prescribed limit | 
 |  * - we only find keys on which we have search permission | 
 |  * - we use the supplied match function to see if the description (or other | 
 |  *   feature of interest) matches | 
 |  * - we rely on RCU to prevent the keyring lists from disappearing on us | 
 |  * - we return -EAGAIN if we didn't find any matching key | 
 |  * - we return -ENOKEY if we only found negative matching keys | 
 |  * - we propagate the possession attribute from the keyring ref to the key ref | 
 |  */ | 
 | key_ref_t keyring_search_aux(key_ref_t keyring_ref, | 
 | 			     struct task_struct *context, | 
 | 			     struct key_type *type, | 
 | 			     const void *description, | 
 | 			     key_match_func_t match) | 
 | { | 
 | 	struct { | 
 | 		struct keyring_list *keylist; | 
 | 		int kix; | 
 | 	} stack[KEYRING_SEARCH_MAX_DEPTH]; | 
 |  | 
 | 	struct keyring_list *keylist; | 
 | 	struct timespec now; | 
 | 	unsigned long possessed; | 
 | 	struct key *keyring, *key; | 
 | 	key_ref_t key_ref; | 
 | 	long err; | 
 | 	int sp, 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, context, 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; | 
 |  | 
 | 	/* 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 */ | 
 | 	for (kix = 0; kix < keylist->nkeys; kix++) { | 
 | 		key = keylist->keys[kix]; | 
 |  | 
 | 		/* ignore keys not of this type */ | 
 | 		if (key->type != type) | 
 | 			continue; | 
 |  | 
 | 		/* skip revoked keys and expired keys */ | 
 | 		if (test_bit(KEY_FLAG_REVOKED, &key->flags)) | 
 | 			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), | 
 | 					context, KEY_SEARCH) < 0) | 
 | 			continue; | 
 |  | 
 | 		/* we set a different error code if we find a negative key */ | 
 | 		if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { | 
 | 			err = -ENOKEY; | 
 | 			continue; | 
 | 		} | 
 |  | 
 | 		goto found; | 
 | 	} | 
 |  | 
 | 	/* search through the keyrings nested in this one */ | 
 | 	kix = 0; | 
 | ascend: | 
 | 	for (; kix < keylist->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), | 
 | 					context, 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; | 
 |  | 
 | } /* end keyring_search_aux() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * search the supplied keyring tree for a key that matches the criterion | 
 |  * - perform a breadth-then-depth search up to the prescribed limit | 
 |  * - we only find keys on which we have search permission | 
 |  * - we readlock the keyrings as we search down the tree | 
 |  * - we return -EAGAIN if we didn't find any matching key | 
 |  * - we return -ENOKEY if we only found negative matching keys | 
 |  */ | 
 | 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, | 
 | 				  type, description, type->match); | 
 |  | 
 | } /* end keyring_search() */ | 
 |  | 
 | EXPORT_SYMBOL(keyring_search); | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * search the given keyring only (no recursion) | 
 |  * - keyring must be locked by caller | 
 |  * - caller must guarantee that the keyring is a keyring | 
 |  */ | 
 | 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 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) { | 
 | 		for (loop = 0; loop < klist->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); | 
 |  | 
 | } /* end __keyring_search_one() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * find a keyring with the specified name | 
 |  * - all named keyrings are searched | 
 |  * - only find keyrings with search permission for the process | 
 |  * - only find keyrings with a serial number greater than the one specified | 
 |  */ | 
 | struct key *find_keyring_by_name(const char *name, key_serial_t bound) | 
 | { | 
 | 	struct key *keyring; | 
 | 	int bucket; | 
 |  | 
 | 	keyring = ERR_PTR(-EINVAL); | 
 | 	if (!name) | 
 | 		goto error; | 
 |  | 
 | 	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 (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | 
 | 				continue; | 
 |  | 
 | 			if (strcmp(keyring->description, name) != 0) | 
 | 				continue; | 
 |  | 
 | 			if (key_permission(make_key_ref(keyring, 0), | 
 | 					   KEY_SEARCH) < 0) | 
 | 				continue; | 
 |  | 
 | 			/* found a potential candidate, but we still need to | 
 | 			 * check the serial number */ | 
 | 			if (keyring->serial <= bound) | 
 | 				continue; | 
 |  | 
 | 			/* we've got a match */ | 
 | 			atomic_inc(&keyring->usage); | 
 | 			read_unlock(&keyring_name_lock); | 
 | 			goto error; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	read_unlock(&keyring_name_lock); | 
 | 	keyring = ERR_PTR(-ENOKEY); | 
 |  | 
 |  error: | 
 | 	return keyring; | 
 |  | 
 | } /* end find_keyring_by_name() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * 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, 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 */ | 
 | 	for (; kix < keylist->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; | 
 |  | 
 | } /* end keyring_detect_cycle() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * dispose of a keyring list after the RCU grace period | 
 |  */ | 
 | static void keyring_link_rcu_disposal(struct rcu_head *rcu) | 
 | { | 
 | 	struct keyring_list *klist = | 
 | 		container_of(rcu, struct keyring_list, rcu); | 
 |  | 
 | 	kfree(klist); | 
 |  | 
 | } /* 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 loop, ret; | 
 |  | 
 | 	ret = -EKEYREVOKED; | 
 | 	if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | 
 | 		goto error; | 
 |  | 
 | 	ret = -ENOTDIR; | 
 | 	if (keyring->type != &key_type_keyring) | 
 | 		goto error; | 
 |  | 
 | 	/* serialise link/link calls to prevent parallel calls causing a | 
 | 	 * cycle when applied to two keyring in opposite orders */ | 
 | 	down_write(&keyring_serialise_link_sem); | 
 |  | 
 | 	/* check that we aren't going to create a cycle adding one keyring to | 
 | 	 * another */ | 
 | 	if (key->type == &key_type_keyring) { | 
 | 		ret = keyring_detect_cycle(keyring, key); | 
 | 		if (ret < 0) | 
 | 			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 = kmemdup(klist, size, GFP_KERNEL); | 
 | 				if (!nklist) | 
 | 					goto error2; | 
 |  | 
 | 				/* 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); | 
 | 	if (ret < 0) | 
 | 		goto error2; | 
 |  | 
 | 	klist = keyring->payload.subscriptions; | 
 |  | 
 | 	if (klist && klist->nkeys < klist->maxkeys) { | 
 | 		/* there's sufficient slack space to add directly */ | 
 | 		atomic_inc(&key->usage); | 
 |  | 
 | 		klist->keys[klist->nkeys] = key; | 
 | 		smp_wmb(); | 
 | 		klist->nkeys++; | 
 | 		smp_wmb(); | 
 | 	} | 
 | 	else { | 
 | 		/* grow the key list */ | 
 | 		max = 4; | 
 | 		if (klist) | 
 | 			max += klist->maxkeys; | 
 |  | 
 | 		ret = -ENFILE; | 
 | 		if (max > 65535) | 
 | 			goto error3; | 
 | 		size = sizeof(*klist) + sizeof(struct key *) * max; | 
 | 		if (size > PAGE_SIZE) | 
 | 			goto error3; | 
 |  | 
 | 		ret = -ENOMEM; | 
 | 		nklist = kmalloc(size, GFP_KERNEL); | 
 | 		if (!nklist) | 
 | 			goto error3; | 
 | 		nklist->maxkeys = max; | 
 | 		nklist->nkeys = 0; | 
 |  | 
 | 		if (klist) { | 
 | 			nklist->nkeys = klist->nkeys; | 
 | 			memcpy(nklist->keys, | 
 | 			       klist->keys, | 
 | 			       sizeof(struct key *) * klist->nkeys); | 
 | 		} | 
 |  | 
 | 		/* add the key into the new space */ | 
 | 		atomic_inc(&key->usage); | 
 | 		nklist->keys[nklist->nkeys++] = key; | 
 |  | 
 | 		rcu_assign_pointer(keyring->payload.subscriptions, nklist); | 
 |  | 
 | 		/* dispose of the old keyring list */ | 
 | 		if (klist) | 
 | 			call_rcu(&klist->rcu, keyring_link_rcu_disposal); | 
 | 	} | 
 |  | 
 | done: | 
 | 	ret = 0; | 
 | error2: | 
 | 	up_write(&keyring_serialise_link_sem); | 
 | error: | 
 | 	return ret; | 
 |  | 
 | error3: | 
 | 	/* undo the quota changes */ | 
 | 	key_payload_reserve(keyring, | 
 | 			    keyring->datalen - KEYQUOTA_LINK_BYTES); | 
 | 	goto error2; | 
 |  | 
 | } /* end __key_link() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * link a key to a keyring | 
 |  */ | 
 | int key_link(struct key *keyring, struct key *key) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	key_check(keyring); | 
 | 	key_check(key); | 
 |  | 
 | 	down_write(&keyring->sem); | 
 | 	ret = __key_link(keyring, key); | 
 | 	up_write(&keyring->sem); | 
 |  | 
 | 	return ret; | 
 |  | 
 | } /* end key_link() */ | 
 |  | 
 | EXPORT_SYMBOL(key_link); | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * unlink the first link to a key from a keyring | 
 |  */ | 
 | 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 = keyring->payload.subscriptions; | 
 | 	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; | 
 |  | 
 | } /* end key_unlink() */ | 
 |  | 
 | 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); | 
 |  | 
 | } /* end keyring_clear_rcu_disposal() */ | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * clear the specified process keyring | 
 |  * - implements keyctl(KEYCTL_CLEAR) | 
 |  */ | 
 | 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 = keyring->payload.subscriptions; | 
 | 		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; | 
 |  | 
 | } /* end keyring_clear() */ | 
 |  | 
 | EXPORT_SYMBOL(keyring_clear); | 
 |  | 
 | /*****************************************************************************/ | 
 | /* | 
 |  * dispose of the links from a revoked keyring | 
 |  * - called with the key sem write-locked | 
 |  */ | 
 | static void keyring_revoke(struct key *keyring) | 
 | { | 
 | 	struct keyring_list *klist = keyring->payload.subscriptions; | 
 |  | 
 | 	/* 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); | 
 | 	} | 
 |  | 
 | } /* end keyring_revoke() */ |