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>
This commit is contained in:
David S. Miller 2018-02-15 15:34:42 -05:00
commit c402fb7e38
4 changed files with 19 additions and 3 deletions

View file

@ -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)

View file

@ -184,6 +184,7 @@ int open_related_ns(struct ns_common *ns,
return fd;
}
EXPORT_SYMBOL_GPL(open_related_ns);
static long ns_ioctl(struct file *filp, unsigned int ioctl,
unsigned long arg)

View file

@ -353,4 +353,6 @@ extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen
unsigned int flags, struct timespec *timeout);
extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
unsigned int vlen, unsigned int flags);
extern struct ns_common *get_net_ns(struct ns_common *ns);
#endif /* _LINUX_SOCKET_H */

View file

@ -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.
*/
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;
}
EXPORT_SYMBOL_GPL(get_net_ns);
static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{