Chi ha l'altra estremità di questa socketpair unix?


54

Voglio determinare quale processo ha l'altra estremità di un socket UNIX.

In particolare, sto chiedendo di uno con cui è stato creato socketpair(), anche se il problema è lo stesso per qualsiasi socket UNIX.

Ho un programma parentche crea a socketpair(AF_UNIX, SOCK_STREAM, 0, fds), e fork()s. Il processo genitore si chiude fds[1]e continua fds[0]a comunicare. Il bambino fa il contrario, close(fds[0]); s=fds[1]. Quindi il bambino exec()è un altro programma child1,. I due possono comunicare avanti e indietro tramite questo socketpair.

Ora, diciamo che so chi parentè, ma voglio capire chi child1è. Come faccio a fare questo?

Ci sono diversi strumenti a mia disposizione, ma nessuno può dirmi quale processo si trova all'altra estremità del socket. Ho provato:

  • lsof -c progname
  • lsof -c parent -c child1
  • ls -l /proc/$(pidof server)/fd
  • cat /proc/net/unix

Fondamentalmente, posso vedere le due prese e tutto ciò che le riguarda, ma non posso dire che siano collegate. Sto cercando di determinare quale FD nel genitore sta comunicando con quale processo figlio.

Risposte:


27

Dal kernel 3.3, è possibile utilizzare sso lsof-4.89o superiore - vedi la risposta di Stéphane Chazelas .

Nelle versioni precedenti, secondo l'autore di lsof, era impossibile scoprirlo: il kernel Linux non espone queste informazioni. Fonte: thread 2003 su comp.unix.admin .

Il numero mostrato in /proc/$pid/fd/$fdè il numero di inode del socket nel filesystem del socket virtuale. Quando si crea una coppia di pipe o socket, ciascuna estremità riceve successivamente un numero di inode. I numeri sono attribuiti in sequenza, quindi c'è un'alta probabilità che i numeri differiscano di 1, ma questo non è garantito (o perché il primo socket era N e N +1 era già in uso a causa del wrapping, o perché qualche altro thread era programmato tra le due allocazioni degli inode e quel thread ha creato anche alcuni inode).

Ho verificato la definizione socketpairnel kernel 2.6.39 e le due estremità del socket non sono correlate se non con il socketpairmetodo specifico del tipo . Per i socket Unix, che è unix_socketpairinnet/unix/af_unix.c .


2
Grazie @Gillles. Ricordo di aver letto qualcosa a riguardo qualche tempo fa, ma non sono riuscito a ritrovarlo. Potrei semplicemente andare a scrivere una patch per / proc / net / unix.
Jonathon Reinhart,

E sì, avevo fatto quell'osservazione con il crescente numero di inode, e attualmente è quello con cui sto lavorando. Tuttavia, come hai notato, non è garantito. Il processo che sto guardando ha almeno 40 socket unix aperti e ho visto un'istanza in cui N + 1 non era vero. Bummer.
Jonathon Reinhart,

1
@JonathonReinhart Ho verificato la definizione disocketpair e le due estremità del socket non sono correlate se non con il socketpairmetodo specifico del tipo . Per i socket unix, si trova unix_socketpairin `net / unix / af_unix.c . Sarebbe bello avere queste informazioni anche per le pipe.
Gilles 'SO- smetti di essere malvagio' il

36

Nota : ora mantengo un lsofwrapper che combina entrambi gli approcci descritti qui e aggiunge anche informazioni per i peer delle connessioni TCP loopback su https://github.com/stephane-chazelas/misc-scripts/blob/master/lsofc

Linux-3.3 e versioni successive.

Su Linux, dalla versione 3.3 del kernel (e purché la UNIX_DIAGfunzionalità sia integrata nel kernel), il peer di un determinato socket di dominio unix (include socketpairs) può essere ottenuto usando una nuova API basata su netlink .

lsof dalla versione 4.89 può utilizzare quell'API:

lsof +E -aUc Xorg

Elencherà tutti i socket di dominio Unix che hanno un processo il cui nome inizia Xorgalle estremità in un formato simile a:

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

Se la tua versione di lsofè troppo vecchia, ci sono alcune altre opzioni.

L' ssutilità (da iproute2) utilizza la stessa API per recuperare e visualizzare informazioni sull'elenco dei socket di dominio unix sul sistema, comprese le informazioni sui peer.

I socket sono identificati dal loro numero di inode . Si noti che non è correlato all'inode del filesystem del file socket.

Ad esempio in:

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

dice che il socket 3435997 (che era associato al socket ABSTRACT /tmp/.X11-unix/X0) è collegato al socket 3435996. L' -popzione può dirti quale processo (i) ha quel socket aperto. Lo fa facendo alcuni readlinksecondi /proc/$pid/fd/*, quindi può farlo solo sui processi che possiedi (a meno che tu non lo sia root). Ad esempio qui:

$ 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]

Per scoprire quale processo (i) ha 3435996, puoi cercare la sua voce nell'output di ss -xp:

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

Puoi anche usare questo script come wrapper lsofper mostrare facilmente le informazioni rilevanti lì:

#! /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);

Per esempio:

$ sudo that-lsof-wrapper -ad3 -p 29215
COMANDO PID UTENTE TIPO FD MISURA DISPOSITIVO / OFF NOME NOME
xterm 29215 stephane 3u unix 0xffff8800a07da4c0 0t0 3435996 type = STREAM <-> 3435997 [Xorg, 3080, @ / tmp / .X11-unix / X0]

Prima di Linux-3.3

La vecchia API Linux per recuperare le informazioni sui socket unix è tramite il /proc/net/unixfile di testo. Elenca tutti i socket di dominio Unix (inclusi socketpairs). Il primo campo lì dentro (se non nascosto ai non superutenti con il kernel.kptr_restrictparametro sysctl) come già spiegato da @Totor contiene l'indirizzo del kernel di una unix_sockstruttura che contiene un peercampo che punta al peer corrispondente unix_sock. È anche ciò che lsofgenera la DEVICEcolonna su un socket Unix.

Ora ottenere il valore di quel peercampo significa poter leggere la memoria del kernel e conoscere l'offset di quel peercampo rispetto unix_sockall'indirizzo.

Sono già state fornite diverse soluzioni basate gdbsu e systemtapbasate ma richiedono gdb/ systemtape simboli di debug del kernel Linux per il kernel in esecuzione che non è generalmente il caso dei sistemi di produzione.

L'hardcoding dell'offset non è in realtà un'opzione in quanto varia con la versione del kernel.

Ora possiamo usare un approccio euristico per determinare l'offset: chiedi al nostro strumento di creare un manichino socketpair(quindi conosciamo l'indirizzo di entrambi i peer) e cercare l'indirizzo del peer attorno alla memoria all'altra estremità per determinare l'offset.

Ecco uno script di prova di concetto che fa proprio questo usando perl(testato con successo con i kernel 2.4.27 e 2.6.32 su i386 e 3.13 e 3.16 su amd64). Come sopra, funziona come un wrapper lsof:

Per esempio:

$ that-lsof-wrapper -aUc nm-applet
COMANDO PID UTENTE TIPO FD MISURA DISPOSITIVO / OFF NOME NOME
nm-applet 4183 stephane 4u unix 0xffff8800a055eb40 0T0 36888 type = STREAM -> 0xffff8800a055e7c0 [dbus-daemon, 4190, @ / tmp / dbus-AiBCXOnuP6] 
nm-applet 4183 stephane 7u unix 0xffff8800a055e440 0T0 36890 type = STREAM -> 0xffff8800a055e0c0 [Xorg, 3080, @ / tmp / .X11-unix / X0] 
nm-applet 4183 stephane 8u unix 0xffff8800a05c1040 0t0 36201 type = STREAM -> 0xffff8800a05c13c0 [dbus-daemon, 4118, @ / tmp / dbus- 
yxxNr3nC1nYnc1kY unix 0xffff8800a055d080 0T0 36219 type = STREAM -> 0xffff8800a055d400 [dbus-daemon, 4118, @ / tmp / dbus-yxxNr1NkYC] 
nm-applet 4183 stephane 12u unix 0xffff88022e0dfb80 0T0 36221 type = STREAM -> 0xffff88022e0df800 [dbus-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]

Ecco la sceneggiatura:

#! /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);

1
@mikeserv, questo è il seguito di quel commento . Non riuscire a trovare l'altra estremità dei socket unix è qualcosa che mi ha sempre infastidito (spesso quando cercavo di trovare client X e c'era una domanda recente a riguardo ). Proverò a vedere se un simile approccio può essere usato per gli pseudo-terminali e suggerirò quelli lsofall'autore.
Stéphane Chazelas,

1
Non riesco ancora a credere che questo non sia fornito dal kernel stesso! Dovrei davvero inviare una patch, se non altro per scoprire perché non esiste già.
Jonathon Reinhart,

1
non sslo fa? È un po 'sopra la mia testa, ma ss -pxelenca un sacco di socket unix con informazioni sui pari come: 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 le intestazioni di colonna sono ...State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
mikeserv

1
Inoltre, se lo faccio lsof -c terminologyposso vedere terminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAMma se lo faccio ss -px | grep terminologyottengo:u_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
mikeserv

1
@mikeserv, sembra proprio così! Sembra che ultimamente stia perdendo molto tempo ...
Stéphane Chazelas,


8

Dal kernel 3.3

È possibile ora ottenere queste informazioni con ss:

# ss -xp

Ora puoi vedere nella Peercolonna un ID (numero di inode) che corrisponde a un altro ID nella Localcolonna. Gli ID corrispondenti sono le due estremità di un socket.

Nota: l' UNIX_DIAGopzione deve essere abilitata nel kernel.

Prima del kernel 3.3

Linux non ha esposto queste informazioni a userland.

Tuttavia, esaminando la memoria del kernel , possiamo accedere a queste informazioni.

Nota: questa risposta lo fa usando gdb, tuttavia, vedere la risposta di @ StéphaneChazelas che è più elaborata al riguardo.

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

Vi sono 2 prese diverse, 1 in ascolto e 1 stabilita. Il numero hexa è l'indirizzo della corrispondente unix_sockstruttura del kernel , con un peerattributo che è l'indirizzo dell'altra estremità del socket (anche unix_sockun'istanza di struttura).

Ora possiamo usare gdbper trovare la peermemoria del 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

Ecco qua, l'altra estremità del socket è trattenuta da mysql, PID 14815.

Il tuo kernel deve essere compilato con KCORE_ELFper usare /proc/kcore. Inoltre, è necessaria una versione dell'immagine del kernel con simboli di debug. Su Debian 7, apt-get install linux-image-3.2.0-4-amd64-dbgfornirà questo file.

Non è necessaria l'immagine del kernel debuggable ...

Se non si dispone (o non si desidera conservare) l'immagine del kernel di debug sul sistema, è possibile assegnare gdball'offset di memoria l'accesso "manuale" al peervalore. Questo valore di offset di solito differisce con la versione o l'architettura del kernel.

Sul mio kernel, so che l'offset è di 680 byte, ovvero 85 volte 64 bit. Quindi posso fare:

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

Voilà, stesso risultato di cui sopra.

Se hai lo stesso kernel in esecuzione su più macchine, è più facile usare questa variante perché non hai bisogno dell'immagine di debug, ma solo del valore di offset.

Per scoprire (facilmente) questo valore di offset all'inizio, è necessaria l'immagine di debug:

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

Ecco qua, 680 byte, 85 x 64 bit o 170 x 32 bit.

Gran parte del merito di questa risposta va a MvG .


2
Un altro approccio per recuperare l'offset potrebbe essere quello di creare un socketpair, identificare le voci corrispondenti in / proc / net / unix in base ai numeri di inode dai collegamenti read su / proc / pif / fd / * e scansionare la memoria attorno all'indirizzo di un socket per l'indirizzo dell'altro. Ciò potrebbe essere ragionevolmente portabile (attraverso versioni e architetture Linux) che potrebbe essere implementato da lsof stesso. Proverò a inventare un PoC.
Stéphane Chazelas,

2
Ora ho aggiunto un simile PoC che sembra funzionare bene sui sistemi che ho testato.
Stéphane Chazelas,

5

Questa soluzione, sebbene funzionante, è di scarso interesse poiché se si dispone di un systemtap abbastanza recente, è probabile che si disponga di un kernel abbastanza recente in cui è possibile utilizzare approcci ssbasati e, se si utilizza un kernel più vecchio, quell'altro soluzione , anche se più hacky ha maggiori probabilità di funzionare e non richiede software aggiuntivo.

Ancora utile come dimostrazione di come utilizzare systemtapper questo tipo di attività.

Se su un recente sistema Linux con un systemtap funzionante (1.8 o successivo), è possibile utilizzare lo script seguente per post-elaborare l'output di lsof:

Per esempio:

$ lsof -aUc nm-applet | sudo quel-script
COMANDO PID UTENTE TIPO FD MISURA DISPOSITIVO / OFF NOME NOME
nm-applet 4183 stephane 4u unix 0xffff8800a055eb40 0T0 36888 type = STREAM -> 0xffff8800a055e7c0 [dbus-daemon, 4190, @ / tmp / dbus-AiBCXOnuP6] 
nm-applet 4183 stephane 7u unix 0xffff8800a055e440 0T0 36890 type = STREAM -> 0xffff8800a055e0c0 [Xorg, 3080, @ / tmp / .X11-unix / X0] 
nm-applet 4183 stephane 8u unix 0xffff8800a05c1040 0t0 36201 type = STREAM -> 0xffff8800a05c13c0 [dbus-daemon, 4118, @ / tmp / dbus- 
yxxNr3nC1nYnc1kY unix 0xffff8800a055d080 0T0 36219 type = STREAM -> 0xffff8800a055d400 [dbus-daemon, 4118, @ / tmp / dbus-yxxNr1NkYC] 
nm-applet 4183 stephane 12u unix 0xffff88022e0dfb80 0T0 36221 type = STREAM -> 0xffff88022e0df800 [dbus-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 vedi 0x000000000000000000 sopra invece di 0xffff ..., è perché il kernel.kptr_restrictparametro sysctl è impostato sul tuo sistema che fa sì che i puntatori del kernel siano nascosti da processi non privilegiati, nel qual caso dovrai eseguire lsofcome root per ottenere un risultato significativo).

Questo script non fa alcun tentativo di far fronte ai nomi dei file socket con caratteri di nuova riga, ma non lo fa lsof(né fa lsoffronte a spazi vuoti o due punti).

systemtapqui viene usato per scaricare l'indirizzo e l'indirizzo peer di tutte le unix_sockstrutture unix_socket_tablenell'hash nel kernel.

Testato solo su Linux 3.16 amd64 con systemtap 2.6 e 3.13 con 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: mi sto perdendo qualcosa?
Totor

@Totor, è @varstato aggiunto in systemtap 1.8, 17/06/2012 (l'ultimo è 2.7)
Stéphane Chazelas,

2

4.89 di lsof supporta la visualizzazione delle opzioni degli endpoint.

Citato da 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.

Esempio di output:

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

Dal momento che esiste il kernel 4.2 di Linux CONFIG_UNIX_DIAG, che fornisce ulteriori informazioni sui socket di dominio UNIX, vale a dire le informazioni Virtual File System(VFS), che contiene le informazioni finora mancanti per collegare l'Inodo dal percorso al processo. Può già essere interrogato utilizzando lo ssstrumento da iproute2 a partire dalla versione 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:

Il numero del dispositivo e il percorso Inode da cui è possibile ottenere

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

ss supporta anche il filtraggio:

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

ma tieni presente che questo potrebbe non elencare il socket giusto per te, poiché un processo malvagio potrebbe rinominare il tuo socket originale e sostituirlo con il proprio malefico:

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'sarà tutta la lista il processo originale, non la sostituzione male. Invece usa qualcosa del genere:

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

Oppure scrivi il tuo programma litte basato sul modello contenuto in man 7 sock_diag .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.