How to find the connection between tap interface and its file descriptor?

I have a qemu VM started by an orchestration script, which creates transient tap interfaces. When I inspect the command line arguments of the qemu-system-x86_64 process, then I can see, that the process connects to already opened tap interface with the file descriptor 27:

-netdev tap,fd=27,id=hostnet1,vhost=on,vhostfd=28

According to ls -l /proc/<qemu-system-x86_64_PID>/fd/27 it points to /dev/net/tun.

Does it work somehow in a way that tap interface name (for example vnet99) is passed to /dev/net/tun with ioctl() and this returns the correct fd? Or in general, how can I find out which tap interface in my host machine has file descriptor 27?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

The iff: entry which could have given an answer was added in kernel 3.14 with the commit tun: add device name(iff) field to proc fdinfo entry, so is not available on kernel 3.13 or before, eg with Ubuntu 14.04LTS.

In this case, while it’s not possible to ask the kernel to give the information, it’s still possible to ask the actual process to give this information, by tracing it with a debugger.

There’s an ioctl available since Linux 2.6.27 to ask informations about a configured tuntap interface: TUNGETIFF. Its use is for a process inheriting an fd to be able to query the fd to receive interface’s name and type (ifr_name and ifr_flags) or to know the tuntap device was not configured yet (EBADFD) and that it should do it.

So while it’s possible using gdb, it’s a bit tricky because if no development environment is available, a few needed parameter and values have to be known or adjusted (and might change in the future or with architectures). These informations and adjustments where needed here:

  • defining $malloc for 64bits systems to handle the correct size for the returned memory address: credit goes to this comment from SO.
  • $malloc(64): struct ifreq appears to be 40 bytes on 64bits, let’s use 64 to stay safe.
  • 0x800454d2 == TUNGETIFF.
  • result ifr_name is at offset 0.

Here are a shell script preparing the way for each tuntap fd found to call gdb, along with gdb’s own script:

tungetiff.sh:

#!/bin/sh

[ $# -gt 0 ] || exit 1
SCRIPTGDB="$1"; shift

for pid in "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1e3a5e">[email protected]</a>"; do
    for procfd in /proc/$pid/fd/*; do
        if [ "$(readlink $procfd)" = "/dev/net/tun" ]; then
            fd=$(basename $procfd)
            printf 'pid=%d fd=%d ifname=' $pid $fd
            gdb -batch-silent --pid=$pid -ex 'set $fd'=$fd -x "$SCRIPTGDB"
        fi
    done
done

tungetiff.gdb:

set $malloc=(void *(*)(long long)) malloc
p $malloc(64)
p ioctl($fd, 0x800454d2, $1)
set *((char *)($1+16))=0
set logging file /dev/stdout
set logging on
printf "%sn",$1
set logging off
call free($1)
quit

Typical example of execution (will probably only work as root, even user libvirt-qemu doesn’t appear to be able to ptrace qemu-system):

# ./tungetiff.sh tungetiff.gdb $(pgrep qemu-system-)
pid=22281 fd=26 ifname=vnet1
pid=22281 fd=30 ifname=vnet2
pid=27109 fd=26 ifname=vnet0

Method 2

With the file descriptor 27 known you’d walk the /proc under the QEMU’s process:

 $ ls /proc/<qemu-system-x86_64_PID>/fd/27

At the same level as the fd directory is another directory fdinfo which contains details such as this:

$ cat /proc/<qemu-system-x86_64_PID>/fdinfo/27
pos:    0
flags:  0104002
mnt_id: 18
iff:    tap0123acdc-66

The iff entry in this file is the tap device.

References


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x