A entrada iff:
que poderia ter uma resposta foi adicionado no kernel 3.14 com o commit tun: add device name(iff) field to proc fdinfo entry
, por isso não está disponível em kernel 3.13 ou antes, eg com o Ubuntu 14.04LTS.
Neste caso, embora não seja possível pedir ao kernel para fornecer as informações, ainda é possível pedir ao processo real para fornecer essas informações, rastreando-as com um depurador.
Há um ioctl disponível desde o Linux 2.6.27 para solicitar informações sobre uma interface tuntap configurada : TUNGETIFF
. Seu uso é para um processo que herda um fd para poder consultar o fd para receber o nome e o tipo da interface ( ifr_name
e ifr_flags
) ou para saber que o dispositivo tuntap ainda não foi configurado ( EBADFD
) e que deveria fazê-lo.
Portanto, embora seja possível usar gdb
, é um pouco complicado, porque se nenhum ambiente de desenvolvimento estiver disponível, um poucos parâmetros e valores necessários precisam ser conhecidos ou ajustados (e podem mudar no futuro ou com arquiteturas). Estas informações e ajustes onde necessário aqui:
- definindo
$malloc
para sistemas 64bits para manipular o tamanho correto para o endereço de memória retornado: o crédito vai para este comentário do SO. -
$malloc(64)
:struct ifreq
parece ser 40 bytes em 64bits, vamos usar 64 para se manter seguro. -
0x800454d2
==TUNGETIFF
. - resultado
ifr_name
está no deslocamento 0.
Aqui está um shell script preparando o caminho para cada tuntap fd encontrado para chamar gdb
, junto com o próprio script do gdb:
tungetiff.sh
:
#!/bin/sh
[ $# -gt 0 ] || exit 1
SCRIPTGDB="$1"; shift
for pid in "$@"; 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 "%s\n",$1
set logging off
call free($1)
quit
Exemplo típico de execução (provavelmente funcionará apenas como root, mesmo o usuário libvirt-qemu não parece ser capaz de 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