1800 lines · 47.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* Keyring handling * * Copyright (C) 2004-2005, 2008, 2013 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) */ #include <linux/export.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 <linux/user_namespace.h>#include <linux/nsproxy.h>#include <keys/keyring-type.h>#include <keys/user-type.h>#include <linux/assoc_array_priv.h>#include <linux/uaccess.h>#include <net/net_namespace.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 mark pointers we pass to the associative array with bit 1 set if * they're keyrings and clear otherwise. */#define KEYRING_PTR_SUBTYPE	0x2UL static inline bool keyring_ptr_is_keyring(const struct assoc_array_ptr *x){	return (unsigned long)x & KEYRING_PTR_SUBTYPE;}static inline struct key *keyring_ptr_to_key(const struct assoc_array_ptr *x){	void *object = assoc_array_ptr_to_leaf(x);	return (struct key *)((unsigned long)object & ~KEYRING_PTR_SUBTYPE);}static inline void *keyring_key_to_ptr(struct key *key){	if (key->type == &key_type_keyring)		return (void *)((unsigned long)key | KEYRING_PTR_SUBTYPE);	return key;} static DEFINE_RWLOCK(keyring_name_lock); /* * Clean up the bits of user_namespace that belong to us. */void key_free_user_ns(struct user_namespace *ns){	write_lock(&keyring_name_lock);	list_del_init(&ns->keyring_name_list);	write_unlock(&keyring_name_lock); 	key_put(ns->user_keyring_register);#ifdef CONFIG_PERSISTENT_KEYRINGS	key_put(ns->persistent_keyring_register);#endif} /* * 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_preparse(struct key_preparsed_payload *prep);static void keyring_free_preparse(struct key_preparsed_payload *prep);static int keyring_instantiate(struct key *keyring,			       struct key_preparsed_payload *prep);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 *buffer, size_t buflen); struct key_type key_type_keyring = {	.name		= "keyring",	.def_datalen	= 0,	.preparse	= keyring_preparse,	.free_preparse	= keyring_free_preparse,	.instantiate	= keyring_instantiate,	.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 DEFINE_MUTEX(keyring_serialise_link_lock); /* * Publish the name of a keyring so that it can be found by name (if it has * one and it doesn't begin with a dot). */static void keyring_publish_name(struct key *keyring){	struct user_namespace *ns = current_user_ns(); 	if (keyring->description &&	    keyring->description[0] &&	    keyring->description[0] != '.') {		write_lock(&keyring_name_lock);		list_add_tail(&keyring->name_link, &ns->keyring_name_list);		write_unlock(&keyring_name_lock);	}} /* * Preparse a keyring payload */static int keyring_preparse(struct key_preparsed_payload *prep){	return prep->datalen != 0 ? -EINVAL : 0;} /* * Free a preparse of a user defined key payload */static void keyring_free_preparse(struct key_preparsed_payload *prep){} /* * Initialise a keyring. * * Returns 0 on success, -EINVAL if given any data. */static int keyring_instantiate(struct key *keyring,			       struct key_preparsed_payload *prep){	assoc_array_init(&keyring->keys);	/* make the keyring available by name if it has one */	keyring_publish_name(keyring);	return 0;} /* * Multiply 64-bits by 32-bits to 96-bits and fold back to 64-bit.  Ideally we'd * fold the carry back too, but that requires inline asm. */static u64 mult_64x32_and_fold(u64 x, u32 y){	u64 hi = (u64)(u32)(x >> 32) * y;	u64 lo = (u64)(u32)(x) * y;	return lo + ((u64)(u32)hi << 32) + (u32)(hi >> 32);} /* * Hash a key type and description. */static void hash_key_type_and_desc(struct keyring_index_key *index_key){	const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP;	const unsigned long fan_mask = ASSOC_ARRAY_FAN_MASK;	const char *description = index_key->description;	unsigned long hash, type;	u32 piece;	u64 acc;	int n, desc_len = index_key->desc_len; 	type = (unsigned long)index_key->type;	acc = mult_64x32_and_fold(type, desc_len + 13);	acc = mult_64x32_and_fold(acc, 9207);	piece = (unsigned long)index_key->domain_tag;	acc = mult_64x32_and_fold(acc, piece);	acc = mult_64x32_and_fold(acc, 9207); 	for (;;) {		n = desc_len;		if (n <= 0)			break;		if (n > 4)			n = 4;		piece = 0;		memcpy(&piece, description, n);		description += n;		desc_len -= n;		acc = mult_64x32_and_fold(acc, piece);		acc = mult_64x32_and_fold(acc, 9207);	} 	/* Fold the hash down to 32 bits if need be. */	hash = acc;	if (ASSOC_ARRAY_KEY_CHUNK_SIZE == 32)		hash ^= acc >> 32; 	/* Squidge all the keyrings into a separate part of the tree to	 * ordinary keys by making sure the lowest level segment in the hash is	 * zero for keyrings and non-zero otherwise.	 */	if (index_key->type != &key_type_keyring && (hash & fan_mask) == 0)		hash |= (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1;	else if (index_key->type == &key_type_keyring && (hash & fan_mask) != 0)		hash = (hash + (hash << level_shift)) & ~fan_mask;	index_key->hash = hash;} /* * Finalise an index key to include a part of the description actually in the * index key, to set the domain tag and to calculate the hash. */void key_set_index_key(struct keyring_index_key *index_key){	static struct key_tag default_domain_tag = { .usage = REFCOUNT_INIT(1), };	size_t n = min_t(size_t, index_key->desc_len, sizeof(index_key->desc)); 	memcpy(index_key->desc, index_key->description, n); 	if (!index_key->domain_tag) {		if (index_key->type->flags & KEY_TYPE_NET_DOMAIN)			index_key->domain_tag = current->nsproxy->net_ns->key_domain;		else			index_key->domain_tag = &default_domain_tag;	} 	hash_key_type_and_desc(index_key);} /** * key_put_tag - Release a ref on a tag. * @tag: The tag to release. * * This releases a reference the given tag and returns true if that ref was the * last one. */bool key_put_tag(struct key_tag *tag){	if (refcount_dec_and_test(&tag->usage)) {		kfree_rcu(tag, rcu);		return true;	} 	return false;} /** * key_remove_domain - Kill off a key domain and gc its keys * @domain_tag: The domain tag to release. * * This marks a domain tag as being dead and releases a ref on it.  If that * wasn't the last reference, the garbage collector is poked to try and delete * all keys that were in the domain. */void key_remove_domain(struct key_tag *domain_tag){	domain_tag->removed = true;	if (!key_put_tag(domain_tag))		key_schedule_gc_links();} /* * Build the next index key chunk. * * We return it one word-sized chunk at a time. */static unsigned long keyring_get_key_chunk(const void *data, int level){	const struct keyring_index_key *index_key = data;	unsigned long chunk = 0;	const u8 *d;	int desc_len = index_key->desc_len, n = sizeof(chunk);	unsigned int offset; 	level /= ASSOC_ARRAY_KEY_CHUNK_SIZE;	switch (level) {	case 0:		return index_key->hash;	case 1:		return index_key->x;	case 2:		return (unsigned long)index_key->type;	case 3:		return (unsigned long)index_key->domain_tag;	default:		level -= 4;		offset = sizeof(index_key->desc) + level * sizeof(long);		if (desc_len <= offset)			return 0; 		d = index_key->description + offset;		desc_len -= offset;		if (desc_len > n)			desc_len = n;		d += desc_len;		do {			chunk <<= 8;			chunk |= *--d;		} while (--desc_len > 0);		return chunk;	}} static unsigned long keyring_get_object_key_chunk(const void *object, int level){	const struct key *key = keyring_ptr_to_key(object);	return keyring_get_key_chunk(&key->index_key, level);} static bool keyring_compare_object(const void *object, const void *data){	const struct keyring_index_key *index_key = data;	const struct key *key = keyring_ptr_to_key(object); 	return key->index_key.type == index_key->type &&		key->index_key.domain_tag == index_key->domain_tag &&		key->index_key.desc_len == index_key->desc_len &&		memcmp(key->index_key.description, index_key->description,		       index_key->desc_len) == 0;} /* * Compare the index keys of a pair of objects and determine the bit position * at which they differ - if they differ. */static int keyring_diff_objects(const void *object, const void *data){	const struct key *key_a = keyring_ptr_to_key(object);	const struct keyring_index_key *a = &key_a->index_key;	const struct keyring_index_key *b = data;	unsigned long seg_a, seg_b;	int level, i; 	level = 0;	seg_a = a->hash;	seg_b = b->hash;	if ((seg_a ^ seg_b) != 0)		goto differ;	level += ASSOC_ARRAY_KEY_CHUNK_SIZE / 8; 	/* The number of bits contributed by the hash is controlled by a	 * constant in the assoc_array headers.  Everything else thereafter we	 * can deal with as being machine word-size dependent.	 */	seg_a = a->x;	seg_b = b->x;	if ((seg_a ^ seg_b) != 0)		goto differ;	level += sizeof(unsigned long); 	/* The next bit may not work on big endian */	seg_a = (unsigned long)a->type;	seg_b = (unsigned long)b->type;	if ((seg_a ^ seg_b) != 0)		goto differ;	level += sizeof(unsigned long); 	seg_a = (unsigned long)a->domain_tag;	seg_b = (unsigned long)b->domain_tag;	if ((seg_a ^ seg_b) != 0)		goto differ;	level += sizeof(unsigned long); 	i = sizeof(a->desc);	if (a->desc_len <= i)		goto same; 	for (; i < a->desc_len; i++) {		seg_a = *(unsigned char *)(a->description + i);		seg_b = *(unsigned char *)(b->description + i);		if ((seg_a ^ seg_b) != 0)			goto differ_plus_i;	} same:	return -1; differ_plus_i:	level += i - (int)sizeof(a->desc);differ:	i = level * 8 + __ffs(seg_a ^ seg_b);	return i;} /* * Free an object after stripping the keyring flag off of the pointer. */static void keyring_free_object(void *object){	key_put(keyring_ptr_to_key(object));} /* * Operations for keyring management by the index-tree routines. */static const struct assoc_array_ops keyring_assoc_array_ops = {	.get_key_chunk		= keyring_get_key_chunk,	.get_object_key_chunk	= keyring_get_object_key_chunk,	.compare_object		= keyring_compare_object,	.diff_objects		= keyring_diff_objects,	.free_object		= keyring_free_object,}; /* * Clean up a keyring when it is destroyed.  Unpublish its name if it had one * and dispose of its data. * * The garbage collector detects the final key_put(), removes the keyring from * the serial number tree and then does RCU synchronisation before coming here, * so we shouldn't need to worry about code poking around here with the RCU * readlock held by this time. */static void keyring_destroy(struct key *keyring){	if (keyring->description) {		write_lock(&keyring_name_lock); 		if (keyring->name_link.next != NULL &&		    !list_empty(&keyring->name_link))			list_del(&keyring->name_link); 		write_unlock(&keyring_name_lock);	} 	if (keyring->restrict_link) {		struct key_restriction *keyres = keyring->restrict_link; 		key_put(keyres->key);		kfree(keyres);	} 	assoc_array_destroy(&keyring->keys, &keyring_assoc_array_ops);} /* * Describe a keyring for /proc. */static void keyring_describe(const struct key *keyring, struct seq_file *m){	if (keyring->description)		seq_puts(m, keyring->description);	else		seq_puts(m, "[anon]"); 	if (key_is_positive(keyring)) {		if (keyring->keys.nr_leaves_on_tree != 0)			seq_printf(m, ": %lu", keyring->keys.nr_leaves_on_tree);		else			seq_puts(m, ": empty");	}} struct keyring_read_iterator_context {	size_t			buflen;	size_t			count;	key_serial_t		*buffer;}; static int keyring_read_iterator(const void *object, void *data){	struct keyring_read_iterator_context *ctx = data;	const struct key *key = keyring_ptr_to_key(object); 	kenter("{%s,%d},,{%zu/%zu}",	       key->type->name, key->serial, ctx->count, ctx->buflen); 	if (ctx->count >= ctx->buflen)		return 1; 	*ctx->buffer++ = key->serial;	ctx->count += sizeof(key->serial);	return 0;} /* * Read a list of key IDs from the keyring's contents in binary form * * The keyring's semaphore is read-locked by the caller.  This prevents someone * from modifying it under us - which could cause us to read key IDs multiple * times. */static long keyring_read(const struct key *keyring,			 char *buffer, size_t buflen){	struct keyring_read_iterator_context ctx;	long ret; 	kenter("{%d},,%zu", key_serial(keyring), buflen); 	if (buflen & (sizeof(key_serial_t) - 1))		return -EINVAL; 	/* Copy as many key IDs as fit into the buffer */	if (buffer && buflen) {		ctx.buffer = (key_serial_t *)buffer;		ctx.buflen = buflen;		ctx.count = 0;		ret = assoc_array_iterate(&keyring->keys,					  keyring_read_iterator, &ctx);

Lines 1–500 of 1800.