From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kirill Tkhai Subject: [PATCH net-next v2 3/3] tun: Add ioctl() SIOCGSKNS cmd to allow obtaining net ns of tun device Date: Wed, 14 Feb 2018 16:40:14 +0300 Message-ID: <151861561482.9376.13227400968104818367.stgit@localhost.localdomain> References: <151861548493.9376.6162694167471967.stgit@localhost.localdomain> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit To: davem@davemloft.net, jasowang@redhat.com, edumazet@google.com, xiyou.wangcong@gmail.com, willemb@google.com, peterpenkov96@gmail.com, linyu.yuan@alcatel-sbell.com.cn, kstewart@linuxfoundation.org, aviadye@mellanox.com, gregkh@linuxfoundation.org, ktkhai@virtuozzo.com, davejwatson@fb.com, netdev@vger.kernel.org Return-path: Received: from mail-he1eur01on0137.outbound.protection.outlook.com ([104.47.0.137]:5568 "EHLO EUR01-HE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1030314AbeBNNkW (ORCPT ); Wed, 14 Feb 2018 08:40:22 -0500 In-Reply-To: <151861548493.9376.6162694167471967.stgit@localhost.localdomain> Sender: netdev-owner@vger.kernel.org List-ID: 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 --- drivers/net/tun.c | 16 ++++++++++++++-- 1 file 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 #include +#include /* 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)