Commit c402fb7e authored by David S. Miller's avatar David S. Miller

Merge branch 'tunchr-get-netns'

Kirill Tkhai says:

====================
net: Add ioctl() SIOCGSKNS cmd to allow obtaining net ns of tun device

Currently, it's not possible to get or check net namespace,
which was used to create tun socket. User may have two tun
devices with the same names in different nets, and there
is no way to differ them each other.

The patchset adds support for ioctl() cmd SIOCGSKNS for tun
devices. It will allow people to obtain net namespace file
descriptor like we allow to do that for sockets in general.

v2: Add new patch [2/3] to export open_related_ns().
====================
Signed-off-by: default avatarKirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents bdc8587a f2780d6d
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/proc_fs.h>
/* Uncomment to enable debugging */ /* Uncomment to enable debugging */
/* #define TUN_DEBUG 1 */ /* #define TUN_DEBUG 1 */
...@@ -2793,6 +2794,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ...@@ -2793,6 +2794,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
struct tun_struct *tun; struct tun_struct *tun;
void __user* argp = (void __user*)arg; void __user* argp = (void __user*)arg;
struct ifreq ifr; struct ifreq ifr;
struct net *net;
kuid_t owner; kuid_t owner;
kgid_t group; kgid_t group;
int sndbuf; int sndbuf;
...@@ -2801,7 +2803,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ...@@ -2801,7 +2803,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
int le; int le;
int ret; int ret;
if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == SOCK_IOC_TYPE) { if (cmd == TUNSETIFF || cmd == TUNSETQUEUE ||
(_IOC_TYPE(cmd) == SOCK_IOC_TYPE && cmd != SIOCGSKNS)) {
if (copy_from_user(&ifr, argp, ifreq_len)) if (copy_from_user(&ifr, argp, ifreq_len))
return -EFAULT; return -EFAULT;
} else { } else {
...@@ -2821,6 +2824,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ...@@ -2821,6 +2824,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
rtnl_lock(); rtnl_lock();
tun = tun_get(tfile); tun = tun_get(tfile);
net = sock_net(&tfile->sk);
if (cmd == TUNSETIFF) { if (cmd == TUNSETIFF) {
ret = -EEXIST; ret = -EEXIST;
if (tun) if (tun)
...@@ -2828,7 +2832,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ...@@ -2828,7 +2832,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
ifr.ifr_name[IFNAMSIZ-1] = '\0'; ifr.ifr_name[IFNAMSIZ-1] = '\0';
ret = tun_set_iff(sock_net(&tfile->sk), file, &ifr); ret = tun_set_iff(net, file, &ifr);
if (ret) if (ret)
goto unlock; goto unlock;
...@@ -2850,6 +2854,14 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ...@@ -2850,6 +2854,14 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
tfile->ifindex = ifindex; tfile->ifindex = ifindex;
goto unlock; goto unlock;
} }
if (cmd == SIOCGSKNS) {
ret = -EPERM;
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto unlock;
ret = open_related_ns(&net->ns, get_net_ns);
goto unlock;
}
ret = -EBADFD; ret = -EBADFD;
if (!tun) if (!tun)
......
...@@ -184,6 +184,7 @@ int open_related_ns(struct ns_common *ns, ...@@ -184,6 +184,7 @@ int open_related_ns(struct ns_common *ns,
return fd; return fd;
} }
EXPORT_SYMBOL_GPL(open_related_ns);
static long ns_ioctl(struct file *filp, unsigned int ioctl, static long ns_ioctl(struct file *filp, unsigned int ioctl,
unsigned long arg) unsigned long arg)
......
...@@ -353,4 +353,6 @@ extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen ...@@ -353,4 +353,6 @@ extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen
unsigned int flags, struct timespec *timeout); unsigned int flags, struct timespec *timeout);
extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
unsigned int vlen, unsigned int flags); unsigned int vlen, unsigned int flags);
extern struct ns_common *get_net_ns(struct ns_common *ns);
#endif /* _LINUX_SOCKET_H */ #endif /* _LINUX_SOCKET_H */
...@@ -990,10 +990,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock, ...@@ -990,10 +990,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
* what to do with it - that's up to the protocol still. * what to do with it - that's up to the protocol still.
*/ */
static struct ns_common *get_net_ns(struct ns_common *ns) struct ns_common *get_net_ns(struct ns_common *ns)
{ {
return &get_net(container_of(ns, struct net, ns))->ns; return &get_net(container_of(ns, struct net, ns))->ns;
} }
EXPORT_SYMBOL_GPL(get_net_ns);
static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment