Skip to content

Commit f2780d6

Browse files
Kirill Tkhaidavem330
authored andcommitted
tun: Add ioctl() SIOCGSKNS cmd to allow obtaining net ns of tun device
This patch adds possibility to get tun device's net namespace fd in the same way we allow to do that for sockets. Socket ioctl numbers do not intersect with tun-specific, and there is already SIOCSIFHWADDR used in tun code. So, SIOCGSKNS number is choosen instead of custom-made for this functionality. Note, that open_related_ns() uses plain get_net_ns() and it's safe (net can't be already dead at this moment): tun socket is allocated via sk_alloc() with zero last arg (kern = 0). So, each alive socket increments net::count, and the socket is definitely alive during ioctl syscall. Also, common variable net is introduced, so small cleanup in TUNSETIFF is made. Signed-off-by: Kirill Tkhai <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 24dce08 commit f2780d6

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

drivers/net/tun.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
#include <linux/mutex.h>
7979

8080
#include <linux/uaccess.h>
81+
#include <linux/proc_fs.h>
8182

8283
/* Uncomment to enable debugging */
8384
/* #define TUN_DEBUG 1 */
@@ -2793,6 +2794,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
27932794
struct tun_struct *tun;
27942795
void __user* argp = (void __user*)arg;
27952796
struct ifreq ifr;
2797+
struct net *net;
27962798
kuid_t owner;
27972799
kgid_t group;
27982800
int sndbuf;
@@ -2801,7 +2803,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
28012803
int le;
28022804
int ret;
28032805

2804-
if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == SOCK_IOC_TYPE) {
2806+
if (cmd == TUNSETIFF || cmd == TUNSETQUEUE ||
2807+
(_IOC_TYPE(cmd) == SOCK_IOC_TYPE && cmd != SIOCGSKNS)) {
28052808
if (copy_from_user(&ifr, argp, ifreq_len))
28062809
return -EFAULT;
28072810
} else {
@@ -2821,14 +2824,15 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
28212824
rtnl_lock();
28222825

28232826
tun = tun_get(tfile);
2827+
net = sock_net(&tfile->sk);
28242828
if (cmd == TUNSETIFF) {
28252829
ret = -EEXIST;
28262830
if (tun)
28272831
goto unlock;
28282832

28292833
ifr.ifr_name[IFNAMSIZ-1] = '\0';
28302834

2831-
ret = tun_set_iff(sock_net(&tfile->sk), file, &ifr);
2835+
ret = tun_set_iff(net, file, &ifr);
28322836

28332837
if (ret)
28342838
goto unlock;
@@ -2850,6 +2854,14 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
28502854
tfile->ifindex = ifindex;
28512855
goto unlock;
28522856
}
2857+
if (cmd == SIOCGSKNS) {
2858+
ret = -EPERM;
2859+
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2860+
goto unlock;
2861+
2862+
ret = open_related_ns(&net->ns, get_net_ns);
2863+
goto unlock;
2864+
}
28532865

28542866
ret = -EBADFD;
28552867
if (!tun)

0 commit comments

Comments
 (0)