This is a first for me to appear on the Linux kernel netdev list, so please 
bear with me while killing me...

For diagnosing Linux virtual networking I need to relate TAP/TUN network 
interfacces to the user space processes they are served by. I'm aware of Kirill 
Tkhai's TUN SIOCGSKNS ioctl patches. My usecase is that my diagnosis software 
is a process different from a TAP/TUN serving process, so issuing the ioctl() 
is not really possible to outside processes (without resorting to gorilla 
tactics like attaching to the serving process, pausing it, and then injecting 
ioctl() calls). For my usecase, /proc/$PID/fdinfo/$FD is an easy-to-use source 
of the information I need for diagnosis.

At the moment, fdinfo for a TAP/TUN device unfortunately only returns the name 
of the TAP/TUN network interface the fd is connected to for serving. 
Unfortunately, this does not allow for unambiguous identification in such 
system configurations where there are multiple TAP/TUN network interfaces of 
the same ifname, but in different network namespaces. In addition to the 
ifname, a network namespace reference is necessary where the TAP/TUN network 
interface is currently living in. Together, these two nuggets of information 
allow to unambiguously relate TAP/TUN serving processes with the correct 
TAP/TUN network interfaces.

To achieve this, I would like you to give feedback on potential additional 
information in fdinfo for TAP/TUN, please see the following patch for 
discussion. I'm also providing a "test" script at 
https://gist.github.com/TheDiveO/d0834baacc92a7ab25300fd8c7468b61 that creates 
two identically named TAP/TUN network interfaces, but in different network 
namespaces, with a dummy serving process living in a third network namespace. 
This requires a dummy TAP serving process tapclient.c to also to be found here 
in the same GitHub gist: 
https://gist.github.com/TheDiveO/d0834baacc92a7ab25300fd8c7468b61.

About my potential patch:

- adds two new keys "iffnetns:" and "devnetns:".

- "iffnetns:" references the network namespace where the TAP/TUN network 
interface (if created) is located in. The format is the same as if readlink() a 
network namespace fd, such as in "$readlink /proc/self/ns/net". In particular, 
the textual representation is "net:[%u]", where %u is the inode number of the 
specific network namespace.

- "devnetns:" references the network namespace where the control fd would 
create new TAP/TUN network interfaces; please note that this can be different 
from the network namespace where the currently created TAP/TUN network 
interface is currently located in. Again, this reference is in the same textual 
format as for the "iffnetns:" key.

- at the moment I'm at a loss as to whether this additional information needs 
to be subjected to CAP_NET?


diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 53f4f37b0ffd..1ddc22b35d0a 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -3440,22 +3440,37 @@ static int tun_chr_close(struct inode *inode, struct 
file *file)
 #ifdef CONFIG_PROC_FS
 static void tun_chr_show_fdinfo(struct seq_file *m, struct file *file)
 {
-       struct tun_file *tfile = file->private_data;
-       struct tun_struct *tun;
-       struct ifreq ifr;
-
-       memset(&ifr, 0, sizeof(ifr));
-
-       rtnl_lock();
-       tun = tun_get(tfile);
-       if (tun)
-               tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
-       rtnl_unlock();
-
-       if (tun)
-               tun_put(tun);
-
-       seq_printf(m, "iff:\t%s\n", ifr.ifr_name);
+    struct tun_file *tfile = file->private_data;
+    struct tun_struct *tun;
+    struct ifreq ifr;
+    unsigned int iffnetnsinum = 0; /* netns of TAP/TUN nif */
+    unsigned int tnetnsinum = 0; /* netns captured when opening /dev/net/tun */
+
+    memset(&ifr, 0, sizeof(ifr));
+
+    rtnl_lock();
+    tun = tun_get(tfile);
+    if (tun) {
+        tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
+               /* network namespace where this /dev/net/tun char device fd 
reference
+                * will create new TAP/TUN network interfaces.
+                */
+        tnetnsinum = sock_net(&tfile->sk)->ns.inum;
+               /* network namespace where the TAP/TUN network interface
+                * currently is located in.
+                */
+        iffnetnsinum = dev_net(tun->dev)->ns.inum;
+    }
+    rtnl_unlock();
+
+    if (tun)
+        tun_put(tun);
+
+    seq_printf(m, "iff:\t%s\n", ifr.ifr_name);
+    if (iffnetnsinum)
+        seq_printf(m, "iffnetns:\tnet:[%u]\n", iffnetnsinum);
+    if (tnetnsinum)
+        seq_printf(m, "devnetns:\tnet:[%u]\n", tnetnsinum);
 }
 #endif

Harald

Reply via email to