Skip to content

Commit

Permalink
Merge branch 'tunchr-get-netns'
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Feb 15, 2018
2 parents bdc8587 + f2780d6 commit c402fb7
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 3 deletions.
16 changes: 14 additions & 2 deletions drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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 {
Expand All @@ -2821,14 +2824,15 @@ 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)
goto unlock;

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;
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions fs/nsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions include/linux/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
3 changes: 2 additions & 1 deletion net/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down

0 comments on commit c402fb7

Please sign in to comment.