summaryrefslogtreecommitdiff
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-02-15 15:34:42 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-15 15:35:11 -0500
commitc402fb7e380c142f2ad3e94d4a1a096fc55b643f (patch)
tree379cb186c759641311ec2eed0c3e1aba9e30fa3c /drivers/net/tun.c
parentbdc8587ad75d9a42a8165f932c2dfff4d5b877e4 (diff)
parentf2780d6d74756bc1d7ba32ff3dd0de4afd7c7e1e (diff)
downloadlinux-c402fb7e380c142f2ad3e94d4a1a096fc55b643f.tar.gz
linux-c402fb7e380c142f2ad3e94d4a1a096fc55b643f.tar.xz
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: Kirill Tkhai <ktkhai@virtuozzo.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 81e6cc951e7f..8e9a0ac644d2 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -78,6 +78,7 @@
#include <linux/mutex.h>
#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
/* Uncomment to enable debugging */
/* #define TUN_DEBUG 1 */
@@ -2793,6 +2794,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
struct tun_struct *tun;
void __user* argp = (void __user*)arg;
struct ifreq ifr;
+ struct net *net;
kuid_t owner;
kgid_t group;
int sndbuf;
@@ -2801,7 +2803,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
int le;
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))
return -EFAULT;
} else {
@@ -2821,6 +2824,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
rtnl_lock();
tun = tun_get(tfile);
+ net = sock_net(&tfile->sk);
if (cmd == TUNSETIFF) {
ret = -EEXIST;
if (tun)
@@ -2828,7 +2832,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
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)
goto unlock;
@@ -2850,6 +2854,14 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
tfile->ifindex = ifindex;
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;
if (!tun)