Quero determinar qual processo tem a outra extremidade de um soquete UNIX.
Especificamente, estou perguntando sobre um que foi criado socketpair()
, embora o problema seja o mesmo para qualquer soquete UNIX.
Eu tenho um programa parent
que cria a socketpair(AF_UNIX, SOCK_STREAM, 0, fds)
, e fork()
s. O processo pai fecha fds[1]
e continua fds[0]
se comunicando. A criança faz o contrário close(fds[0]); s=fds[1]
. Então a criança exec()
é outro programa child1
. Os dois podem se comunicar através desse par de soquetes.
Agora, digamos que eu sei quem parent
é, mas quero descobrir quem child1
é. Como eu faço isso?
Existem várias ferramentas à minha disposição, mas nenhuma pode me dizer qual processo está do outro lado do soquete. Eu tentei:
lsof -c progname
lsof -c parent -c child1
ls -l /proc/$(pidof server)/fd
cat /proc/net/unix
Basicamente, eu posso ver os dois soquetes e tudo sobre eles, mas não posso dizer que eles estão conectados. Estou tentando determinar qual DF no pai está se comunicando com qual processo filho.
fonte
socketpair
e as duas extremidades do soquete não estão correlacionadas, exceto pelosocketpair
método específico do tipo . Para soquetes unix, isso estáunix_socketpair
em `net / unix / af_unix.c . Seria bom ter essas informações também para tubos.Linux-3.3 e superior.
No Linux, desde a versão 3.3 do kernel (e desde que o
UNIX_DIAG
recurso seja construído no kernel), o par de um determinado soquete de domínio unix (incluindo pares de soquetes) pode ser obtido usando uma nova API baseada em netlink .lsof
desde a versão 4.89 pode fazer uso dessa API:Irá listar todos os soquetes de domínio Unix que possuem um processo cujo nome começa
Xorg
em cada extremidade em um formato semelhante a:Se a sua versão do
lsof
é muito antiga, existem mais algumas opções.O
ss
utilitário (fromiproute2
) faz uso dessa mesma API para recuperar e exibir informações na lista de soquetes de domínio unix no sistema, incluindo informações de pares.As tomadas são identificadas pelo seu número de inode . Observe que não está relacionado ao inode do sistema de arquivos do arquivo de soquete.
Por exemplo, em:
diz que o soquete 3435997 (que foi vinculado ao soquete ABSTRACT
/tmp/.X11-unix/X0
) está conectado ao soquete 3435996. A-p
opção pode informar quais processos estão com esse soquete aberto. Isso é feito com algumas açõesreadlink
ativadas/proc/$pid/fd/*
, portanto, isso só pode ser feito nos processos que você possui (a menos que estejaroot
). Por exemplo aqui:Para descobrir que processo (s) possui 3435996, você pode procurar sua própria entrada na saída de
ss -xp
:Você também pode usar esse script como um invólucro
lsof
para mostrar facilmente as informações relevantes:Por exemplo:
Antes do linux-3.3
A antiga API do Linux para recuperar informações do soquete unix é via
/proc/net/unix
arquivo de texto. Ele lista todos os soquetes de domínio Unix (incluindo socketpairs). O primeiro campo lá (se não oculta para não-superusuários com okernel.kptr_restrict
parâmetro sysctl) como já explicado por @Totor contém o endereço do kernel de umaunix_sock
estrutura que contém umpeer
apontador de campo para o correspondente de paresunix_sock
. Também é o quelsof
gera aDEVICE
coluna em um soquete Unix.Agora, obter o valor desse
peer
campo significa poder ler a memória do kernel e conhecer o deslocamento dessepeer
campo em relação aounix_sock
endereço.Vários
gdb
baseados esystemtap
baseados em soluções já foram dadas, mas eles exigemgdb
/systemtap
e Linux Kernel símbolos de depuração para o kernel em execução que está sendo instalado, que geralmente não é o caso em sistemas de produção.Codificar o offset não é realmente uma opção, pois isso varia com a versão do kernel.
Agora podemos usar uma abordagem heurística para determinar o deslocamento: nossa ferramenta cria um manequim
socketpair
(então sabemos o endereço de ambos os pares) e pesquisamos o endereço do ponto em torno da memória na outra extremidade para determinar o deslocamento.Aqui está um script de prova de conceito que faz exatamente isso
perl
(testado com sucesso com o kernel 2.4.27 e 2.6.32 no i386 e 3.13 e 3.16 no amd64). Como acima, ele funciona como um invólucrolsof
:Por exemplo:
Aqui está o script:
fonte
lsof
autor.ss
não fazer isso? É uma espécie de sobre a minha cabeça, masss -px
listas de um monte de sockets Unix com informações de pares como:users: ("nacl_helper",pid=18992,fd=6),("chrome",pid=18987,fd=6),("chrome",pid=18975,fd=5)) u_str ESTAB\t0\t0\t/run/dbus/system_bus_socket 8760\t\t* 15068
e os títulos das colunas são ...State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
lsof -c terminology
posso ver,terminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAM
mas sess -px | grep terminology
eu conseguir:u_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
Erkki Seppala realmente tem uma ferramenta que recupera essas informações do kernel do Linux com gdb. Está disponível aqui .
fonte
Desde o kernel 3.3
Agora você pode obter essas informações com :
ss
Agora você pode ver na
Peer
coluna um ID (número do inode) que corresponde a outro ID naLocal
coluna. Os IDs correspondentes são as duas extremidades de um soquete.Nota: A
UNIX_DIAG
opção deve estar ativada no seu kernel.Antes do kernel 3.3
O Linux não expôs essas informações à terra do usuário.
No entanto, olhando para a memória do kernel , podemos acessar essas informações.
Nota: Esta resposta faz isso usando
gdb
, no entanto, consulte a resposta de @ StéphaneChazelas, que é mais elaborada a esse respeito.Existem 2 tomadas diferentes, uma escuta e uma estabelecida. O número hexa é o endereço da
unix_sock
estrutura do kernel correspondente , tendo umpeer
atributo o endereço da outra extremidade do soquete (também umaunix_sock
instância da estrutura).Agora podemos usar
gdb
para encontrar apeer
memória interna do kernel:Aqui está, a outra extremidade do soquete é mantida pelo
mysql
PID 14815.Seu kernel deve ser compilado
KCORE_ELF
para ser usado/proc/kcore
. Além disso, você precisa de uma versão da sua imagem do kernel com símbolos de depuração. No Debian 7,apt-get install linux-image-3.2.0-4-amd64-dbg
irá fornecer este arquivo.Não há necessidade da imagem do kernel depurável ...
Se você não possui (ou não deseja manter) a imagem do kernel de depuração no sistema, pode dar
gdb
um deslocamento de memória para acessar "manualmente" opeer
valor. Esse valor de deslocamento geralmente difere com a versão ou arquitetura do kernel.No meu kernel, eu sei que o deslocamento é de 680 bytes, ou seja, 85 vezes 64 bits. Então eu posso fazer:
Voilà, mesmo resultado acima.
Se você possui o mesmo kernel em execução em várias máquinas, é mais fácil usar essa variante porque você não precisa da imagem de depuração, apenas do valor de deslocamento.
Para (facilmente) descobrir esse valor de deslocamento primeiro, você precisa da imagem de depuração:
Aqui, 680 bytes, são 85 x 64 bits ou 170 x 32 bits.
A maior parte do crédito para esta resposta é do MvG .
fonte
Se em um sistema Linux recente com um systemtap em funcionamento (1.8 ou mais recente), você pode usar o script abaixo para pós-processar a saída de
lsof
:Por exemplo:
(se você vir 0x0000000000000000 acima em vez de 0xffff ..., é porque o
kernel.kptr_restrict
parâmetro sysctl está definido no seu sistema, fazendo com que os ponteiros do kernel sejam ocultos de processos não privilegiados; nesse caso, você precisará executarlsof
como root para obter um resultado significativo).Este script não faz nenhuma tentativa de lidar com nomes de arquivos de soquete com caracteres de nova linha, mas também não
lsof
(nemlsof
com espaços em branco ou dois pontos).systemtap
aqui é usado para despejar o endereço e o endereço de mesmo nível de todas asunix_sock
estruturas nounix_socket_table
hash no kernel.Testado apenas no Linux 3.16 amd64 com systemtap 2.6 e 3.13 com 2.3.
fonte
parse error: unknown statistic operator @var
: estou esquecendo de algo?@var
foi adicionado no systemtap 1.8, 17/06/2012 (a versão mais recente é 2.7) #4.89 de lsof suporta a exibição de opções de terminal.
Citado em lsof.8:
Exemplo de saída:
fonte
Desde o Linux kernel 4.2, existe
CONFIG_UNIX_DIAG
, o que fornece informações extras sobre soquetes de domínio UNIX, ou seja, asVirtual File System
informações (VFS), que contêm as informações ausentes até agora para vincular o Inode do caminho ao processo. Ele já pode ser consultado usando ass
ferramenta iproute2, iniciando na versão v4.19.0 ~ 55 :O número do dispositivo e o caminho do Inode que você pode obter
ss
também suporta filtragem:mas lembre-se de que isso pode não listar o soquete certo para você, pois um processo maligno pode renomear o soquete original e substituí-lo pelo próprio mal:
lsof /tmp/socket
,fuser /tmp/socket
ess --processes --unix --all --extended 'sport = /tmp/socket'
todos listarão o processo original, não a substituição incorreta. Em vez disso, use algo como isto:Ou escreva seu próprio programa litte com base no modelo contido no man 7 sock_diag .
fonte