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; | 	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 */ | 	/* vet a description */ | ||||||
| 	int (*vet_description)(const char *description); | 	int (*vet_description)(const char *description); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -71,6 +71,9 @@ struct net { | ||||||
| 						 */ | 						 */ | ||||||
| 	struct llist_node	cleanup_list;	/* namespaces on death row */ | 	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 user_namespace   *user_ns;	/* Owning user namespace */ | ||||||
| 	struct ucounts		*ucounts; | 	struct ucounts		*ucounts; | ||||||
| 	spinlock_t		nsid_lock; | 	spinlock_t		nsid_lock; | ||||||
|  |  | ||||||
|  | @ -38,9 +38,16 @@ EXPORT_SYMBOL_GPL(net_namespace_list); | ||||||
| DECLARE_RWSEM(net_rwsem); | DECLARE_RWSEM(net_rwsem); | ||||||
| EXPORT_SYMBOL_GPL(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 = { | struct net init_net = { | ||||||
| 	.count		= REFCOUNT_INIT(1), | 	.count		= REFCOUNT_INIT(1), | ||||||
| 	.dev_base_head	= LIST_HEAD_INIT(init_net.dev_base_head), | 	.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); | EXPORT_SYMBOL(init_net); | ||||||
| 
 | 
 | ||||||
|  | @ -386,10 +393,22 @@ static struct net *net_alloc(void) | ||||||
| 	if (!net) | 	if (!net) | ||||||
| 		goto out_free; | 		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); | 	rcu_assign_pointer(net->gen, ng); | ||||||
| out: | out: | ||||||
| 	return net; | 	return net; | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_KEYS | ||||||
|  | out_free_2: | ||||||
|  | 	kmem_cache_free(net_cachep, net); | ||||||
|  | 	net = NULL; | ||||||
|  | #endif | ||||||
| out_free: | out_free: | ||||||
| 	kfree(ng); | 	kfree(ng); | ||||||
| 	goto out; | 	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_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { | ||||||
| 		list_del_init(&net->exit_list); | 		list_del_init(&net->exit_list); | ||||||
| 		dec_net_namespaces(net->ucounts); | 		dec_net_namespaces(net->ucounts); | ||||||
|  | 		key_remove_domain(net->key_domain); | ||||||
| 		put_user_ns(net->user_ns); | 		put_user_ns(net->user_ns); | ||||||
| 		net_drop_ns(net); | 		net_drop_ns(net); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -314,6 +314,7 @@ static long dns_resolver_read(const struct key *key, | ||||||
| 
 | 
 | ||||||
| struct key_type key_type_dns_resolver = { | struct key_type key_type_dns_resolver = { | ||||||
| 	.name		= "dns_resolver", | 	.name		= "dns_resolver", | ||||||
|  | 	.flags		= KEY_TYPE_NET_DOMAIN, | ||||||
| 	.preparse	= dns_resolver_preparse, | 	.preparse	= dns_resolver_preparse, | ||||||
| 	.free_preparse	= dns_resolver_free_preparse, | 	.free_preparse	= dns_resolver_free_preparse, | ||||||
| 	.instantiate	= generic_key_instantiate, | 	.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 = { | struct key_type key_type_rxrpc = { | ||||||
| 	.name		= "rxrpc", | 	.name		= "rxrpc", | ||||||
|  | 	.flags		= KEY_TYPE_NET_DOMAIN, | ||||||
| 	.preparse	= rxrpc_preparse, | 	.preparse	= rxrpc_preparse, | ||||||
| 	.free_preparse	= rxrpc_free_preparse, | 	.free_preparse	= rxrpc_free_preparse, | ||||||
| 	.instantiate	= generic_key_instantiate, | 	.instantiate	= generic_key_instantiate, | ||||||
|  | @ -58,6 +59,7 @@ EXPORT_SYMBOL(key_type_rxrpc); | ||||||
|  */ |  */ | ||||||
| struct key_type key_type_rxrpc_s = { | struct key_type key_type_rxrpc_s = { | ||||||
| 	.name		= "rxrpc_s", | 	.name		= "rxrpc_s", | ||||||
|  | 	.flags		= KEY_TYPE_NET_DOMAIN, | ||||||
| 	.vet_description = rxrpc_vet_description_s, | 	.vet_description = rxrpc_vet_description_s, | ||||||
| 	.preparse	= rxrpc_preparse_s, | 	.preparse	= rxrpc_preparse_s, | ||||||
| 	.free_preparse	= rxrpc_free_preparse_s, | 	.free_preparse	= rxrpc_free_preparse_s, | ||||||
|  |  | ||||||
|  | @ -17,10 +17,12 @@ | ||||||
| #include <linux/seq_file.h> | #include <linux/seq_file.h> | ||||||
| #include <linux/err.h> | #include <linux/err.h> | ||||||
| #include <linux/user_namespace.h> | #include <linux/user_namespace.h> | ||||||
|  | #include <linux/nsproxy.h> | ||||||
| #include <keys/keyring-type.h> | #include <keys/keyring-type.h> | ||||||
| #include <keys/user-type.h> | #include <keys/user-type.h> | ||||||
| #include <linux/assoc_array_priv.h> | #include <linux/assoc_array_priv.h> | ||||||
| #include <linux/uaccess.h> | #include <linux/uaccess.h> | ||||||
|  | #include <net/net_namespace.h> | ||||||
| #include "internal.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); | 	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); | 	hash_key_type_and_desc(index_key); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 David Howells
						David Howells