mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
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_AF_SPEC,
|
||||
IFLA_GROUP, /* Group the device belongs to */
|
||||
IFLA_NET_NS_FD,
|
||||
__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 net *get_net_ns_by_pid(pid_t pid);
|
||||
extern struct net *get_net_ns_by_fd(int pid);
|
||||
|
||||
#ifdef CONFIG_NET_NS
|
||||
extern void __put_net(struct net *net);
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <linux/idr.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/file.h>
|
||||
#include <net/net_namespace.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);
|
||||
|
||||
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)
|
||||
{
|
||||
struct net_generic *ng;
|
||||
|
@ -577,10 +601,15 @@ EXPORT_SYMBOL_GPL(unregister_pernet_device);
|
|||
#ifdef CONFIG_NET_NS
|
||||
static void *netns_get(struct task_struct *task)
|
||||
{
|
||||
struct net *net;
|
||||
struct net *net = NULL;
|
||||
struct nsproxy *nsproxy;
|
||||
|
||||
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();
|
||||
|
||||
return net;
|
||||
}
|
||||
|
||||
|
|
|
@ -1043,6 +1043,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
|
|||
[IFLA_LINKMODE] = { .type = NLA_U8 },
|
||||
[IFLA_LINKINFO] = { .type = NLA_NESTED },
|
||||
[IFLA_NET_NS_PID] = { .type = NLA_U32 },
|
||||
[IFLA_NET_NS_FD] = { .type = NLA_U32 },
|
||||
[IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 },
|
||||
[IFLA_VFINFO_LIST] = {. 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])
|
||||
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
|
||||
net = get_net(src_net);
|
||||
return net;
|
||||
|
@ -1221,7 +1224,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
|
|||
int send_addr_notify = 0;
|
||||
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);
|
||||
if (IS_ERR(net)) {
|
||||
err = PTR_ERR(net);
|
||||
|
|
Loading…
Reference in a new issue