forked from mirrors/linux
		
	keys: Network namespace domain tag
Create key domain tags for network namespaces and make it possible to automatically tag keys that are used by networked services (e.g. AF_RXRPC, AFS, DNS) with the default network namespace if not set by the caller. This allows keys with the same description but in different namespaces to coexist within a keyring. Signed-off-by: David Howells <dhowells@redhat.com> cc: netdev@vger.kernel.org cc: linux-nfs@vger.kernel.org cc: linux-cifs@vger.kernel.org cc: linux-afs@lists.infradead.org
This commit is contained in:
		
							parent
							
								
									218e6424e7
								
							
						
					
					
						commit
						9b24261051
					
				
					 6 changed files with 35 additions and 1 deletions
				
			
		|  | @ -74,6 +74,9 @@ struct key_type { | |||
| 	 */ | ||||
| 	size_t def_datalen; | ||||
| 
 | ||||
| 	unsigned int flags; | ||||
| #define KEY_TYPE_NET_DOMAIN	0x00000001 /* Keys of this type have a net namespace domain */ | ||||
| 
 | ||||
| 	/* vet a description */ | ||||
| 	int (*vet_description)(const char *description); | ||||
| 
 | ||||
|  |  | |||
|  | @ -71,6 +71,9 @@ struct net { | |||
| 						 */ | ||||
| 	struct llist_node	cleanup_list;	/* namespaces on death row */ | ||||
| 
 | ||||
| #ifdef CONFIG_KEYS | ||||
| 	struct key_tag		*key_domain;	/* Key domain of operation tag */ | ||||
| #endif | ||||
| 	struct user_namespace   *user_ns;	/* Owning user namespace */ | ||||
| 	struct ucounts		*ucounts; | ||||
| 	spinlock_t		nsid_lock; | ||||
|  |  | |||
|  | @ -38,9 +38,16 @@ EXPORT_SYMBOL_GPL(net_namespace_list); | |||
| DECLARE_RWSEM(net_rwsem); | ||||
| EXPORT_SYMBOL_GPL(net_rwsem); | ||||
| 
 | ||||
| #ifdef CONFIG_KEYS | ||||
| static struct key_tag init_net_key_domain = { .usage = REFCOUNT_INIT(1) }; | ||||
| #endif | ||||
| 
 | ||||
| struct net init_net = { | ||||
| 	.count		= REFCOUNT_INIT(1), | ||||
| 	.dev_base_head	= LIST_HEAD_INIT(init_net.dev_base_head), | ||||
| #ifdef CONFIG_KEYS | ||||
| 	.key_domain	= &init_net_key_domain, | ||||
| #endif | ||||
| }; | ||||
| EXPORT_SYMBOL(init_net); | ||||
| 
 | ||||
|  | @ -386,10 +393,22 @@ static struct net *net_alloc(void) | |||
| 	if (!net) | ||||
| 		goto out_free; | ||||
| 
 | ||||
| #ifdef CONFIG_KEYS | ||||
| 	net->key_domain = kzalloc(sizeof(struct key_tag), GFP_KERNEL); | ||||
| 	if (!net->key_domain) | ||||
| 		goto out_free_2; | ||||
| 	refcount_set(&net->key_domain->usage, 1); | ||||
| #endif | ||||
| 
 | ||||
| 	rcu_assign_pointer(net->gen, ng); | ||||
| out: | ||||
| 	return net; | ||||
| 
 | ||||
| #ifdef CONFIG_KEYS | ||||
| out_free_2: | ||||
| 	kmem_cache_free(net_cachep, net); | ||||
| 	net = NULL; | ||||
| #endif | ||||
| out_free: | ||||
| 	kfree(ng); | ||||
| 	goto out; | ||||
|  | @ -566,6 +585,7 @@ static void cleanup_net(struct work_struct *work) | |||
| 	list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { | ||||
| 		list_del_init(&net->exit_list); | ||||
| 		dec_net_namespaces(net->ucounts); | ||||
| 		key_remove_domain(net->key_domain); | ||||
| 		put_user_ns(net->user_ns); | ||||
| 		net_drop_ns(net); | ||||
| 	} | ||||
|  |  | |||
|  | @ -314,6 +314,7 @@ static long dns_resolver_read(const struct key *key, | |||
| 
 | ||||
| struct key_type key_type_dns_resolver = { | ||||
| 	.name		= "dns_resolver", | ||||
| 	.flags		= KEY_TYPE_NET_DOMAIN, | ||||
| 	.preparse	= dns_resolver_preparse, | ||||
| 	.free_preparse	= dns_resolver_free_preparse, | ||||
| 	.instantiate	= generic_key_instantiate, | ||||
|  |  | |||
|  | @ -43,6 +43,7 @@ static long rxrpc_read(const struct key *, char __user *, size_t); | |||
|  */ | ||||
| struct key_type key_type_rxrpc = { | ||||
| 	.name		= "rxrpc", | ||||
| 	.flags		= KEY_TYPE_NET_DOMAIN, | ||||
| 	.preparse	= rxrpc_preparse, | ||||
| 	.free_preparse	= rxrpc_free_preparse, | ||||
| 	.instantiate	= generic_key_instantiate, | ||||
|  | @ -58,6 +59,7 @@ EXPORT_SYMBOL(key_type_rxrpc); | |||
|  */ | ||||
| struct key_type key_type_rxrpc_s = { | ||||
| 	.name		= "rxrpc_s", | ||||
| 	.flags		= KEY_TYPE_NET_DOMAIN, | ||||
| 	.vet_description = rxrpc_vet_description_s, | ||||
| 	.preparse	= rxrpc_preparse_s, | ||||
| 	.free_preparse	= rxrpc_free_preparse_s, | ||||
|  |  | |||
|  | @ -17,10 +17,12 @@ | |||
| #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" | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -220,7 +222,10 @@ void key_set_index_key(struct keyring_index_key *index_key) | |||
| 
 | ||||
| 	memcpy(index_key->desc, index_key->description, n); | ||||
| 
 | ||||
| 	index_key->domain_tag = &default_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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 David Howells
						David Howells