forked from mirrors/linux
		
	net: Allow setting the network namespace by fd
Take advantage of the new abstraction and allow network devices to be placed in any network namespace that we have a fd to talk about. Acked-by: David S. Miller <davem@davemloft.net> Acked-by: Daniel Lezcano <daniel.lezcano@free.fr> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
This commit is contained in:
		
							parent
							
								
									a00eaf11a2
								
							
						
					
					
						commit
						f063052947
					
				
					 4 changed files with 37 additions and 3 deletions
				
			
		|  | @ -136,6 +136,7 @@ enum { | ||||||
| 	IFLA_PORT_SELF, | 	IFLA_PORT_SELF, | ||||||
| 	IFLA_AF_SPEC, | 	IFLA_AF_SPEC, | ||||||
| 	IFLA_GROUP,		/* Group the device belongs to */ | 	IFLA_GROUP,		/* Group the device belongs to */ | ||||||
|  | 	IFLA_NET_NS_FD, | ||||||
| 	__IFLA_MAX | 	__IFLA_MAX | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -119,6 +119,7 @@ static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns) | ||||||
| extern struct list_head net_namespace_list; | extern struct list_head net_namespace_list; | ||||||
| 
 | 
 | ||||||
| extern struct net *get_net_ns_by_pid(pid_t pid); | extern struct net *get_net_ns_by_pid(pid_t pid); | ||||||
|  | extern struct net *get_net_ns_by_fd(int pid); | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_NET_NS | #ifdef CONFIG_NET_NS | ||||||
| extern void __put_net(struct net *net); | extern void __put_net(struct net *net); | ||||||
|  |  | ||||||
|  | @ -8,6 +8,8 @@ | ||||||
| #include <linux/idr.h> | #include <linux/idr.h> | ||||||
| #include <linux/rculist.h> | #include <linux/rculist.h> | ||||||
| #include <linux/nsproxy.h> | #include <linux/nsproxy.h> | ||||||
|  | #include <linux/proc_fs.h> | ||||||
|  | #include <linux/file.h> | ||||||
| #include <net/net_namespace.h> | #include <net/net_namespace.h> | ||||||
| #include <net/netns/generic.h> | #include <net/netns/generic.h> | ||||||
| 
 | 
 | ||||||
|  | @ -343,6 +345,28 @@ struct net *get_net_ns_by_pid(pid_t pid) | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(get_net_ns_by_pid); | EXPORT_SYMBOL_GPL(get_net_ns_by_pid); | ||||||
| 
 | 
 | ||||||
|  | struct net *get_net_ns_by_fd(int fd) | ||||||
|  | { | ||||||
|  | 	struct proc_inode *ei; | ||||||
|  | 	struct file *file; | ||||||
|  | 	struct net *net; | ||||||
|  | 
 | ||||||
|  | 	net = ERR_PTR(-EINVAL); | ||||||
|  | 	file = proc_ns_fget(fd); | ||||||
|  | 	if (!file) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	ei = PROC_I(file->f_dentry->d_inode); | ||||||
|  | 	if (ei->ns_ops != &netns_operations) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	net = get_net(ei->ns); | ||||||
|  | out: | ||||||
|  | 	if (file) | ||||||
|  | 		fput(file); | ||||||
|  | 	return net; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int __init net_ns_init(void) | static int __init net_ns_init(void) | ||||||
| { | { | ||||||
| 	struct net_generic *ng; | 	struct net_generic *ng; | ||||||
|  | @ -577,10 +601,15 @@ EXPORT_SYMBOL_GPL(unregister_pernet_device); | ||||||
| #ifdef CONFIG_NET_NS | #ifdef CONFIG_NET_NS | ||||||
| static void *netns_get(struct task_struct *task) | static void *netns_get(struct task_struct *task) | ||||||
| { | { | ||||||
| 	struct net *net; | 	struct net *net = NULL; | ||||||
|  | 	struct nsproxy *nsproxy; | ||||||
|  | 
 | ||||||
| 	rcu_read_lock(); | 	rcu_read_lock(); | ||||||
| 	net = get_net(task->nsproxy->net_ns); | 	nsproxy = task_nsproxy(task); | ||||||
|  | 	if (nsproxy) | ||||||
|  | 		net = get_net(nsproxy->net_ns); | ||||||
| 	rcu_read_unlock(); | 	rcu_read_unlock(); | ||||||
|  | 
 | ||||||
| 	return net; | 	return net; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1043,6 +1043,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | ||||||
| 	[IFLA_LINKMODE]		= { .type = NLA_U8 }, | 	[IFLA_LINKMODE]		= { .type = NLA_U8 }, | ||||||
| 	[IFLA_LINKINFO]		= { .type = NLA_NESTED }, | 	[IFLA_LINKINFO]		= { .type = NLA_NESTED }, | ||||||
| 	[IFLA_NET_NS_PID]	= { .type = NLA_U32 }, | 	[IFLA_NET_NS_PID]	= { .type = NLA_U32 }, | ||||||
|  | 	[IFLA_NET_NS_FD]	= { .type = NLA_U32 }, | ||||||
| 	[IFLA_IFALIAS]	        = { .type = NLA_STRING, .len = IFALIASZ-1 }, | 	[IFLA_IFALIAS]	        = { .type = NLA_STRING, .len = IFALIASZ-1 }, | ||||||
| 	[IFLA_VFINFO_LIST]	= {. type = NLA_NESTED }, | 	[IFLA_VFINFO_LIST]	= {. type = NLA_NESTED }, | ||||||
| 	[IFLA_VF_PORTS]		= { .type = NLA_NESTED }, | 	[IFLA_VF_PORTS]		= { .type = NLA_NESTED }, | ||||||
|  | @ -1091,6 +1092,8 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) | ||||||
| 	 */ | 	 */ | ||||||
| 	if (tb[IFLA_NET_NS_PID]) | 	if (tb[IFLA_NET_NS_PID]) | ||||||
| 		net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); | 		net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); | ||||||
|  | 	else if (tb[IFLA_NET_NS_FD]) | ||||||
|  | 		net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD])); | ||||||
| 	else | 	else | ||||||
| 		net = get_net(src_net); | 		net = get_net(src_net); | ||||||
| 	return net; | 	return net; | ||||||
|  | @ -1221,7 +1224,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | ||||||
| 	int send_addr_notify = 0; | 	int send_addr_notify = 0; | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
| 	if (tb[IFLA_NET_NS_PID]) { | 	if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) { | ||||||
| 		struct net *net = rtnl_link_get_net(dev_net(dev), tb); | 		struct net *net = rtnl_link_get_net(dev_net(dev), tb); | ||||||
| 		if (IS_ERR(net)) { | 		if (IS_ERR(net)) { | ||||||
| 			err = PTR_ERR(net); | 			err = PTR_ERR(net); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Eric W. Biederman
						Eric W. Biederman