Como encontrar a conexão entre a interface de toque e seu descritor de arquivo?

2

Eu tenho uma qemu VM iniciada por um script de orquestração, que cria interfaces tap transitórias. Quando inspeciono os argumentos da linha de comando do processo qemu-system-x86_64 , posso ver que o processo se conecta à interface tap já aberta com o descritor de arquivo 27 :

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

De acordo com ls -l /proc/<qemu-system-x86_64_PID>/fd/27 , ele aponta para /dev/net/tun .

Funciona de alguma forma de forma que tap nome da interface (por exemplo vnet99 ) seja passado para /dev/net/tun com ioctl() e isso retorne o fd correto? Ou, em geral, como posso descobrir qual tap interface na minha máquina host possui o descritor de arquivo 27?

    
por Martin 12.08.2018 / 22:03

2 respostas

1

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
    
por 15.08.2018 / 12:52
3

Com o descritor de arquivo 27, você sabia que andaria com o /proc no processo do QEMU:

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

No mesmo nível em que o diretório fd é outro diretório fdinfo que contém detalhes como este:

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

A entrada iff neste arquivo é o dispositivo de toque.

Referências

por 13.08.2018 / 04:09