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 <ktkhai@virtuozzo.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
24dce0800b
Коммит
f2780d6d74
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче