Quem tem o outro lado desse soquete unix?


54

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 parentque 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.

Respostas:


27

Desde do kernel 3.3, é possível usar ssou lsof-4.89ou acima - veja a resposta de Stéphane Chazelas .

Nas versões mais antigas, segundo o autor de lsof, era impossível descobrir isso: o kernel do Linux não expõe essas informações. Fonte: thread de 2003 em comp.unix.admin .

O número mostrado em /proc/$pid/fd/$fdé o número do inode do soquete no sistema de arquivos do soquete virtual. Quando você cria um par de tubos ou soquetes, cada extremidade recebe sucessivamente um número de inode. Os números são atribuídos sequencialmente, portanto, há uma alta probabilidade de os números diferirem por 1, mas isso não é garantido (porque o primeiro soquete era N e N +1 já estava em uso devido ao empacotamento ou porque algum outro encadeamento foi agendada entre as duas alocações de inode e esse thread também criou alguns inodes).

Eu verifiquei a definição de socketpairno kernel 2.6.39 e as duas extremidades do soquete não estão correlacionadas, exceto pelo socketpairmétodo específico do tipo . Para soquetes unix, está unix_socketpairincluídonet/unix/af_unix.c .


2
Obrigado @Gillles. Lembro-me de ler algo sobre isso há algum tempo, mas não consegui encontrá-lo novamente. Talvez eu precise escrever um patch para / proc / net / unix.
Jonathon Reinhart

E sim, eu fiz essa observação com o crescente número de inodes, e atualmente é com isso que estou trabalhando. No entanto, como você observou, não é garantido. O processo que estou vendo tem pelo menos 40 soquetes unix abertos e vi uma instância em que o N + 1 não era verdadeiro. Vadio.
Jonathon Reinhart

11
@JonathonReinhart Verifiquei a definição desocketpair e as duas extremidades do soquete não estão correlacionadas, exceto pelo socketpairmétodo específico do tipo . Para soquetes unix, isso está unix_socketpairem `net / unix / af_unix.c . Seria bom ter essas informações também para tubos.
Gilles 'SO- stop be evil'

36

Nota : Agora mantenho um lsofwrapper que combina as duas abordagens descritas aqui e também adiciona informações para pares de conexões TCP de loopback em https://github.com/stephane-chazelas/misc-scripts/blob/master/lsofc

Linux-3.3 e superior.

No Linux, desde a versão 3.3 do kernel (e desde que o UNIX_DIAGrecurso 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:

lsof +E -aUc Xorg

Irá listar todos os soquetes de domínio Unix que possuem um processo cujo nome começa Xorgem cada extremidade em um formato semelhante a:

Xorg       2777       root   56u  unix 0xffff8802419a7c00      0t0   34036 @/tmp/.X11-unix/X0 type=STREAM ->INO=33273 4120,xterm,3u

Se a sua versão do lsofé muito antiga, existem mais algumas opções.

O ssutilitário (from iproute2) 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:

$ ss -x
[...]
u_str  ESTAB    0    0   @/tmp/.X11-unix/X0 3435997     * 3435996

diz que o soquete 3435997 (que foi vinculado ao soquete ABSTRACT /tmp/.X11-unix/X0) está conectado ao soquete 3435996. A -popção pode informar quais processos estão com esse soquete aberto. Isso é feito com algumas ações readlinkativadas /proc/$pid/fd/*, portanto, isso só pode ser feito nos processos que você possui (a menos que esteja root). Por exemplo aqui:

$ sudo ss -xp
[...]
u_str  ESTAB  0  0  @/tmp/.X11-unix/X0 3435997 * 3435996 users:(("Xorg",pid=3080,fd=83))
[...]
$ sudo ls -l /proc/3080/fd/23
lrwx------ 1 root root 64 Mar 12 16:34 /proc/3080/fd/83 -> socket:[3435997]

Para descobrir que processo (s) possui 3435996, você pode procurar sua própria entrada na saída de ss -xp:

$ ss -xp | awk '$6 == 3435996'
u_str  ESTAB  0  0  * 3435996  * 3435997 users:(("xterm",pid=29215,fd=3))

Você também pode usar esse script como um invólucro lsofpara mostrar facilmente as informações relevantes:

#! /usr/bin/perl
# lsof wrapper to add peer information for unix domain socket.
# Needs Linux 3.3 or above and CONFIG_UNIX_DIAG enabled.

# retrieve peer and direction information from ss
my (%peer, %dir);
open SS, '-|', 'ss', '-nexa';
while (<SS>) {
  if (/\s(\d+)\s+\*\s+(\d+) ([<-]-[->])$/) {
    $peer{$1} = $2;
    $dir{$1} = $3;
  }
}
close SS;

# Now get info about processes tied to sockets using lsof
my (%fields, %proc);
open LSOF, '-|', 'lsof', '-nPUFpcfin';
while (<LSOF>) {
  if (/(.)(.*)/) {
    $fields{$1} = $2;
    if ($1 eq 'n') {
      $proc{$fields{i}}->{"$fields{c},$fields{p}" .
      ($fields{n} =~ m{^([@/].*?)( type=\w+)?$} ? ",$1" : "")} = "";
    }
  }
}
close LSOF;

# and finally process the lsof output
open LSOF, '-|', 'lsof', @ARGV;
while (<LSOF>) {
  chomp;
  if (/\sunix\s+\S+\s+\S+\s+(\d+)\s/) {
    my $peer = $peer{$1};
    if (defined($peer)) {
      $_ .= $peer ?
            " ${dir{$1}} $peer\[" . (join("|", keys%{$proc{$peer}})||"?") . "]" :
            "[LISTENING]";
    }
  }
  print "$_\n";
}
close LSOF or exit(1);

Por exemplo:

$ sudo that-lsof-wrapper -ad3 -p 29215
COMANDO PID USUÁRIO FD TIPO DISPOSITIVO TAMANHO / DESLIGADO NOME DO NÓ
xterm 29215 stephane 3u unix 0xffff8800a07da4c0 0t0 3435996 tipo = STREAM <-> 3435997 [Xorg, 3080, @ / tmp / .X11-unix / X0]

Antes do linux-3.3

A antiga API do Linux para recuperar informações do soquete unix é via /proc/net/unixarquivo 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 o kernel.kptr_restrictparâmetro sysctl) como já explicado por @Totor contém o endereço do kernel de uma unix_sockestrutura que contém um peerapontador de campo para o correspondente de pares unix_sock . Também é o que lsofgera a DEVICEcoluna em um soquete Unix.

Agora, obter o valor desse peercampo significa poder ler a memória do kernel e conhecer o deslocamento desse peercampo em relação ao unix_sockendereço.

Vários gdbbaseados e systemtapbaseados em soluções já foram dadas, mas eles exigem gdb/ systemtape 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ólucro lsof:

Por exemplo:

$ that-lsof-wrapper -aUc nm-applet
COMANDO PID USUÁRIO FD TIPO DISPOSITIVO TAMANHO / DESLIGADO NOME DO NÓ
nm-applet 4183 stephane 4u UNIX 0xffff8800a055eb40 0t0 36,888 type = STREAM -> 0xffff8800a055e7c0 [dbugs-daemon, 4190, @ / tmp / dbugs-AiBCXOnuP6] 
nm-applet 4183 stephane 7u UNIX 0xffff8800a055e440 0t0 36,890 type = STREAM -> 0xffff8800a055e0c0 [Xorg, 3080, @ / tmp / .X11-UNIX / X0] 
nm-applet 4183 stephane 8u UNIX 0xffff8800a05c1040 0t0 36201 tipo = STREAM -> 0xffff8800a05c13c0 [dbugs-daemon, 4118, @ / tmp / dbugs-yxxNr1NkYC] 
nm-applet 4183 stephane 11u Unix 0xffff8800a055d080 0t0 36,219 type = STREAM -> 0xffff8800a055d400 [dbugs-daemon, 4118, @ / tmp / dbugs-yxxNr1NkYC] 
nm-applet 4183 stephane 12u UNIX 0xffff88022e0dfb80 0t0 36,221 type = STREAM -> 0xffff88022e0df800 [dbugs-daemon, 2268, / var / run / dbus / system_bus_socket]
nm-applet 4183 stephane 13u unix 0xffff88022e0f80c0 0t0 37025 type = STREAM -> 0xffff88022e29ec00 [dbus-daemon, 2268, / var / run / dbus / system_bus_socket]

Aqui está o script:

#! /usr/bin/perl
# wrapper around lsof to add peer information for Unix
# domain sockets. needs lsof, and superuser privileges.
# Copyright Stephane Chazelas 2015, public domain.
# example: sudo this-lsof-wrapper -aUc Xorg
use Socket;

open K, "<", "/proc/kcore" or die "open kcore: $!";
read K, $h, 8192 # should be more than enough
 or die "read kcore: $!";

# parse ELF header
my ($t,$o,$n) = unpack("x4Cx[C19L!]L!x[L!C8]S", $h);
$t = $t == 1 ? "L3x4Lx12" : "Lx4QQx8Qx16"; # program header ELF32 or ELF64
my @headers = unpack("x$o($t)$n",$h);

# read data from kcore at given address (obtaining file offset from ELF
# @headers)
sub readaddr {
  my @h = @headers;
  my ($addr, $length) = @_;
  my $offset;
  while (my ($t, $o, $v, $s) = splice @h, 0, 4) {
    if ($addr >= $v && $addr < $v + $s) {
      $offset = $o + $addr - $v;
      if ($addr + $length - $v > $s) {
        $length = $s - ($addr - $v);
      }
      last;
    }
  }
  return undef unless defined($offset);
  seek K, $offset, 0 or die "seek kcore: $!";
  my $ret;
  read K, $ret, $length or die "read($length) kcore \@$offset: $!";
  return $ret;
}

# create a dummy socketpair to try find the offset in the
# kernel structure
socketpair(Rdr, Wtr, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
 or die "socketpair: $!";
$r = readlink("/proc/self/fd/" . fileno(Rdr)) or die "readlink Rdr: $!";
$r =~ /\[(\d+)/; $r = $1;
$w = readlink("/proc/self/fd/" . fileno(Wtr)) or die "readlink Wtr: $!";
$w =~ /\[(\d+)/; $w = $1;
# now $r and $w contain the socket inodes of both ends of the socketpair
die "Can't determine peer offset" unless $r && $w;

# get the inode->address mapping
open U, "<", "/proc/net/unix" or die "open unix: $!";
while (<U>) {
  if (/^([0-9a-f]+):(?:\s+\S+){5}\s+(\d+)/) {
    $addr{$2} = hex $1;
  }
}
close U;

die "Can't determine peer offset" unless $addr{$r} && $addr{$w};

# read 2048 bytes starting at the address of Rdr and hope to find
# the address of Wtr referenced somewhere in there.
$around = readaddr $addr{$r}, 2048;
my $offset = 0;
my $ptr_size = length(pack("L!",0));
my $found;
for (unpack("L!*", $around)) {
  if ($_ == $addr{$w}) {
    $found = 1;
    last;
  }
  $offset += $ptr_size;
}
die "Can't determine peer offset" unless $found;

my %peer;
# now retrieve peer for each socket
for my $inode (keys %addr) {
  $peer{$addr{$inode}} = unpack("L!", readaddr($addr{$inode}+$offset,$ptr_size));
}
close K;

# Now get info about processes tied to sockets using lsof
my (%fields, %proc);
open LSOF, '-|', 'lsof', '-nPUFpcfdn';
while (<LSOF>) {
  if (/(.)(.*)/) {
    $fields{$1} = $2;
    if ($1 eq 'n') {
      $proc{hex($fields{d})}->{"$fields{c},$fields{p}" .
      ($fields{n} =~ m{^([@/].*?)( type=\w+)?$} ? ",$1" : "")} = "";
    }
  }
}
close LSOF;

# and finally process the lsof output
open LSOF, '-|', 'lsof', @ARGV;
while (<LSOF>) {
  chomp;
  for my $addr (/0x[0-9a-f]+/g) {
    $addr = hex $addr;
    my $peer = $peer{$addr};
    if (defined($peer)) {
      $_ .= $peer ?
            sprintf(" -> 0x%x[", $peer) . join("|", keys%{$proc{$peer}}) . "]" :
            "[LISTENING]";
      last;
    }
  }
  print "$_\n";
}
close LSOF or exit(1);

11
@ MikeServ, esse é um acompanhamento desse comentário . Não ser capaz de encontrar a outra extremidade dos soquetes unix é algo que sempre me incomodou (muitas vezes ao tentar encontrar clientes X e havia uma pergunta recente sobre isso ). Vou tentar ver se uma abordagem semelhante pode ser usada para pseudo-terminais e sugerir isso ao lsofautor.
Stéphane Chazelas 17/03/2015

11
Ainda não acredito que isso não seja fornecido pelo próprio kernel! Eu realmente deveria enviar um patch, se não fosse por nada além de descobrir por que ele ainda não existe.
Jonathon Reinhart

11
que ssnão fazer isso? É uma espécie de sobre a minha cabeça, mas ss -pxlistas 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* 15068e os títulos das colunas são ...State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
mikeserv

11
Além disso, se eu lsof -c terminologyposso ver, terminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAMmas se ss -px | grep terminologyeu conseguir:u_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
mikeserv

11
@ MikeServ, parece que sim! Parece que tenho
perdido


8

Desde o kernel 3.3

Agora você pode obter essas informações com :ss

# ss -xp

Agora você pode ver na Peercoluna um ID (número do inode) que corresponde a outro ID na Localcoluna. Os IDs correspondentes são as duas extremidades de um soquete.

Nota: A UNIX_DIAGopçã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.

# lsof | grep whatever
mysqld 14450 (...) unix 0xffff8801011e8280 (...) /var/run/mysqld/mysqld.sock
mysqld 14450 (...) unix 0xffff8801011e9600 (...) /var/run/mysqld/mysqld.sock

Existem 2 tomadas diferentes, uma escuta e uma estabelecida. O número hexa é o endereço da unix_sockestrutura do kernel correspondente , tendo um peeratributo o endereço da outra extremidade do soquete (também uma unix_sockinstância da estrutura).

Agora podemos usar gdbpara encontrar a peermemória interna do kernel:

# gdb /usr/lib/debug/boot/vmlinux-3.2.0-4-amd64 /proc/kcore
(gdb) print ((struct unix_sock*)0xffff8801011e9600)->peer
$1 = (struct sock *) 0xffff880171f078c0

# lsof | grep 0xffff880171f078c0
mysql 14815 (...) unix 0xffff880171f078c0 (...) socket

Aqui está, a outra extremidade do soquete é mantida pelo mysqlPID 14815.

Seu kernel deve ser compilado KCORE_ELFpara 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-dbgirá 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 gdbum deslocamento de memória para acessar "manualmente" o peervalor. 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:

# gdb /boot/vmlinux-3.2.0-4-amd64 /proc/kcore
(gdb) print ((void**)0xffff8801011e9600)[85]
$1 = (void *) 0xffff880171f078c0

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:

$ pahole -C unix_sock /usr/lib/debug/boot/vmlinux-3.2.0-4-amd64
struct unix_sock {
  (...)
  struct sock *              peer;                 /*   680     8 */
  (...)
}

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 .


2
Outra abordagem para recuperar o deslocamento poderia ser criar um par de soquetes, identificar as entradas correspondentes em / proc / net / unix com base nos números de inode dos links de leitura em / proc / pif / fd / * e verificar a memória em torno do endereço de um soquete para o endereço do outro. Isso poderia criar um ambiente razoavelmente portátil (entre versões e arquiteturas do Linux) que poderia ser implementado pelo próprio lsof. Vou tentar criar um PoC.
Stéphane Chazelas 13/03/2015

2
Agora adicionei um PoC que parece funcionar bem nos sistemas que testei.
Stéphane Chazelas 17/03/2015

5

Essa solução, embora funcione, é de interesse limitado, pois se você possui uma seção de sistema suficientemente recente, é provável que tenha um kernel recente o suficiente para usar abordagens ssbaseadas e, se estiver em um kernel antigo, esse outro solução , embora mais hacky funcione e não exija software adicional.

Ainda é útil como uma demonstração de como usar systemtappara esse tipo de tarefa.

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:

$ lsof -aUc nm-applet | sudo esse script
COMANDO PID USUÁRIO FD TIPO DISPOSITIVO TAMANHO / DESLIGADO NOME DO NÓ
nm-applet 4183 stephane 4u UNIX 0xffff8800a055eb40 0t0 36,888 type = STREAM -> 0xffff8800a055e7c0 [dbugs-daemon, 4190, @ / tmp / dbugs-AiBCXOnuP6] 
nm-applet 4183 stephane 7u UNIX 0xffff8800a055e440 0t0 36,890 type = STREAM -> 0xffff8800a055e0c0 [Xorg, 3080, @ / tmp / .X11-UNIX / X0] 
nm-applet 4183 stephane 8u UNIX 0xffff8800a05c1040 0t0 36201 tipo = STREAM -> 0xffff8800a05c13c0 [dbugs-daemon, 4118, @ / tmp / dbugs-yxxNr1NkYC] 
nm-applet 4183 stephane 11u Unix 0xffff8800a055d080 0t0 36,219 type = STREAM -> 0xffff8800a055d400 [dbugs-daemon, 4118, @ / tmp / dbugs-yxxNr1NkYC] 
nm-applet 4183 stephane 12u UNIX 0xffff88022e0dfb80 0t0 36,221 type = STREAM -> 0xffff88022e0df800 [dbugs-daemon, 2268, / var / run / dbus / system_bus_socket]
nm-applet 4183 stephane 13u unix 0xffff88022e0f80c0 0t0 37025 type = STREAM -> 0xffff88022e29ec00 [dbus-daemon, 2268, / var / run / dbus / system_bus_socket]

(se você vir 0x0000000000000000 acima em vez de 0xffff ..., é porque o kernel.kptr_restrictparâ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á executar lsofcomo 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(nem lsofcom espaços em branco ou dois pontos).

systemtapaqui é usado para despejar o endereço e o endereço de mesmo nível de todas as unix_sockestruturas no unix_socket_tablehash no kernel.

Testado apenas no Linux 3.16 amd64 com systemtap 2.6 e 3.13 com 2.3.

#! /usr/bin/perl
# meant to process lsof output to try and find the peer of a given
# unix domain socket. Needs a working systemtap, lsof, and superuser
# privileges. Copyright Stephane Chazelas 2015, public domain.
# Example: lsof -aUc X | sudo this-script
open STAP, '-|', 'stap', '-e', q{
  probe begin {
    offset = &@cast(0, "struct sock")->__sk_common->skc_node;
    for (i = 0; i < 512; i++) 
      for (p = @var("unix_socket_table@net/unix/af_unix.c")[i]->first;
           p;
           p=@cast(p, "struct hlist_node")->next
          ) {
        sock = p - offset;
        printf("%p %p\n", sock, @cast(sock, "struct unix_sock")->peer);
    }
    exit()
  }
};  
my %peer;
while (<STAP>) {
  chomp;
  my ($a, $b) = split;
  $peer{$a} = $b;
}
close STAP;

my %f, %addr;
open LSOF, '-|', 'lsof', '-nPUFpcfdn';
while (<LSOF>) {
  if (/(.)(.*)/) {
    $f{$1} = $2;
    if ($1 eq 'n') {
      $addr{$f{d}}->{"$f{c},$f{p}" . ($f{n} =~ m{^([@/].*?)( type=\w+)?$} ? ",$1" : "")} = "";
    }
  }
}
close LSOF;

while (<>) {
  chomp;
  for my $addr (/0x[0-9a-f]+/g) {
    my $peer = $peer{$addr};
    if (defined($peer)) {
      $_ .= $peer eq '0x0' ?
            "[LISTENING]" :
            " -> $peer\[" . join("|", keys%{$addr{$peer}}) . "]";
      last;
    }
  }
  print "$_\n";
}

parse error: unknown statistic operator @var: estou esquecendo de algo?
Totor

@Totor, @varfoi adicionado no systemtap 1.8, 17/06/2012 (a versão mais recente é 2.7) #
Stéphane Chazelas

2

4.89 de lsof suporta a exibição de opções de terminal.

Citado em lsof.8:

+|-E +E specifies that process intercommunication channels should be
     displayed with endpoint information and the channels
     of the endpoints should also be displayed.  Currently
     only pipe on Linux is implemented.

     Endpoint information is displayed in the NAME column
     in the form "PID,cmd,FDmode".  PID is the endpoint
     process ID; cmd is the endpoint process command; FD is
     the endpoint file's descriptor; and mode is the
     endpoint file's access mode.  Multiple occurrences of
     this information can appear in a file's NAME column.

     -E specfies that Linux pipe files should only be
     displayed with endpoint information.

Exemplo de saída:

mozStorag 21535 22254  yamato    6u     unix 0xf...       0t0     348924 type=STREAM pino=351122 4249,dbus-daem,55u
mozStorag 21535 22254  yamato   10u     unix 0xf...       0t0     356193 type=STREAM pino=356194 21535,gdbus,11u
mozStorag 21535 22254  yamato   11u     unix 0xf...       0t0     356194 type=STREAM pino=356193 21535,gdbus,10u
mozStorag 21535 22254  yamato   21u     unix 0xf...       0t0     355141 type=STREAM pino=357544 4249,dbus-daem,60u
mozStorag 21535 22254  yamato   26u     unix 0xf...       0t0     351134 type=STREAM pino=355142 5015,gdbus,17u
mozStorag 21535 22254  yamato   69u     unix 0xf...       0t0     469354 type=STREAM pino=468160 4545,alsa-sink,21u
mozStorag 21535 22254  yamato   82u     unix 0xf...       0t0     449383 type=STREAM pino=449384 12257,Chrome_Ch,3u
mozStorag 21535 22254  yamato   86u     unix 0xf...       0t0     355174 type=SEQPACKET pino=355175 21535,gdbus,95u
mozStorag 21535 22254  yamato   95u     unix 0xf...       0t0     355175 type=SEQPACKET pino=355174 21535,gdbus,86u 12257,Chrome_Ch,4u
mozStorag 21535 22254  yamato  100u     unix 0xf...       0t0     449389 type=STREAM pino=456453 3614,Xorg,38u
mozStorag 21535 22254  yamato  105u     unix 0xf...       0t0     582613 type=STREAM pino=586261
obexd     22163        yamato    1u     unix 0xf...       0t0     361859 type=STREAM pino=365931
obexd     22163        yamato    2u     unix 0xf...       0t0     361860 type=STREAM pino=365934
obexd     22163        yamato    3u     unix 0xf...       0t0     361241 type=DGRAM pino=10028
obexd     22163        yamato    6u     unix 0xf...       0t0     361242 type=STREAM pino=361864 4249,dbus-daem,70u

2

Desde o Linux kernel 4.2, existe CONFIG_UNIX_DIAG, o que fornece informações extras sobre soquetes de domínio UNIX, ou seja, as Virtual File Systeminformaçõ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 a ssferramenta iproute2, iniciando na versão v4.19.0 ~ 55 :

$ ss --processes --unix --all --extened
...
Netid  State   Recv-Q  Send-Q  Local Address:Port      Peer Address:Port
u_str  LISTEN  0       5         /tmp/socket 13381347             * 0     users:(("nc",pid=12550,fd=3)) <-> ino:1569897 dev:0/65025 peers:

O número do dispositivo e o caminho do Inode que você pode obter

$ stat -c 'ino:%i dev:0/%d' /tmp/socket
ino:1569946 dev:0/65025

ss também suporta filtragem:

 ss --processes --unix --all --extended 'sport = /tmp/socket'

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:

mv /tmp/socket /tmp/socket.orig
nc -U -l /tmp/socket.evil &
mv /tmp/socket.evil /tmp/socket

lsof /tmp/socket, fuser /tmp/sockete ss --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:

id=$(stat -c 'ino:%i dev:0/%d' /tmp/socket)
ss --processes --unix --all --extended | grep -F "$id"

Ou escreva seu próprio programa litte com base no modelo contido no man 7 sock_diag .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.