У кого інший кінець цієї unix-розвідки?


54

Я хочу визначити, який процес має інший кінець сокета UNIX.

Зокрема, я запитую про те, що було створено socketpair(), хоча проблема однакова для будь-якого сокета UNIX.

У мене є програма, parentяка створює a socketpair(AF_UNIX, SOCK_STREAM, 0, fds)і fork()s. Батьківський процес закривається fds[1]і продовжує fds[0]спілкуватися. Дитина робить протилежне, close(fds[0]); s=fds[1]. Тоді дитина exec()ще одна програма, child1. Ці двоє можуть спілкуватися вперед і назад за допомогою цієї розетки.

Тепер, скажімо, я знаю, хто parentє, але я хочу з’ясувати, хто child1це. Як це зробити?

У мене є кілька інструментів, але жоден не може мені сказати, який процес знаходиться на іншому кінці розетки. Я намагався:

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

В основному я бачу два розетки і все про них, але не можу сказати, що вони підключені. Я намагаюся визначити, який ФД у батька спілкується з яким дочірнім процесом.

Відповіді:


27

Так як ядро 3.3, можна з допомогою ssабо lsof-4.89чи вище - см відповідь Stéphane Chazelas в .

У старих версіях, за словами автора lsof, з'ясувати це було неможливо: ядро ​​Linux не розкриває цю інформацію. Джерело: Нитка 2003 року на comp.unix.admin .

Число, вказане в, /proc/$pid/fd/$fd- це номер індексу сокета у віртуальній файловій системі сокета. Коли ви створюєте пару труб або розеток, кожен кінець послідовно отримує номер inode. Цифри присвоюються послідовно, тому існує велика ймовірність того, що числа відрізняються на 1, але це не гарантується (або тому, що перший сокет був N і N +1 вже використовувався через обгортання, або тому, що якась інша нитка була заплановано між двома виділеннями inode, і цей потік також створив деякі inode).

Я перевірив визначення socketpairв ядрі 2.6.39 , і два кінці сокета не співвідносяться, за винятком типового socketpairметоду . Для unix-розеток, це unix_socketpairвnet/unix/af_unix.c .


2
Дякую @Gillles. Я пам’ятаю, що читав щось про це назад, але не зміг його знайти знову. Можливо, мені просто доведеться писати патч для / proc / net / unix.
Джонатан Райнхарт

І так, я зробив це спостереження зі збільшенням кількості inode, і в даний час це те, з чим я працюю. Однак, як ви зазначили, це не гарантується. У процесі, який я переглядаю, є щонайменше 40 відкритих unix-сокетів, і я побачив один екземпляр, де N + 1 не відповідає дійсності. Бампер.
Джонатан Райнхарт

1
@JonathonReinhart Я перевірив визначенняsocketpair , і два кінці сокета не співвідносяться, окрім socketpairметоду, що залежить від типу . Для unix-сокетів, це unix_socketpairв `net / unix / af_unix.c . Було б непогано мати цю інформацію і для труб.
Жил 'ТАК - перестань бути злим'

36

Примітка . Зараз я підтримую lsofобгортку, що поєднує в собі обидва описані тут підходи, а також додає інформацію для однорангових зворотних TCP-з'єднань за адресою https://github.com/stephane-chazelas/misc-scripts/blob/master/lsofc

Linux-3.3 та вище.

У Linux, так як ядра версії 3.3 (і при умови , що UNIX_DIAGфункція вбудована в ядро), рівноправний даного домену Сокет (включає в себе socketpairs) можуть бути отримані з використанням нового NETLINK API на основі.

lsof оскільки версія 4.89 може використовувати цей API:

lsof +E -aUc Xorg

Буде перераховано всі сокети домену Unix, які мають процес, ім'я якого починається з Xorgобох кінців у форматі, подібному до:

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

Якщо ваша версія lsofзанадто стара, є ще кілька варіантів.

ssУтиліта (від iproute2) використовує той же API для отримання і відображення інформації про список доменних сокетів UNIX на системі , включаючи інформацію експертною.

Розетки ідентифікуються за їх номером inode . Зауважте, що це не пов’язано з inode файлової системи файлу socket.

Наприклад у:

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

в ньому йдеться про те, що сокет 3435997 (який був прив’язаний до гнізда ABSTRACT /tmp/.X11-unix/X0) пов'язаний з сокетом 3435996. -pОпція може вказати, для яких процесів відкритий цей сокет. Він робить це, роблячи деякі readlinkS на /proc/$pid/fd/*, так що це може зробити тільки те , що на процеси , які ви володієте (якщо ви не root). Наприклад, тут:

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

Щоб дізнатися, який процес (и) має 3435996, ви можете знайти власний запис у висновку ss -xp:

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

Ви також можете використовувати цей скрипт як обгортку, lsofщоб легко показати відповідну інформацію там:

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

Наприклад:

$ sudo that-lsof-обгортка -ad3 -p 29215
ВИМОГА ПІДПРИЄМНИКА ПІДПРИЄМЦЯ FD ТИП ПРИЛАДУ ВИДАЛЕННЯ / ВИКЛ
xterm 29215 stephane 3u unix 0xffff8800a07da4c0 0t0 3435996 тип = STREAM <-> 3435997 [Xorg, 3080, @ / tmp / .X11-unix / X0]

До linux-3.3

Старий Linux API для отримання інформації про сокет Unix здійснюється через /proc/net/unixтекстовий файл. У ньому перераховані всі розетки домену Unix (включаючи socketpairs). Перше поле там (якщо воно не приховане для неперевірених користувачів з kernel.kptr_restrictпараметром sysctl), як уже пояснило @Totor, містить адресу ядра unix_sockструктури структури, яка містить peerполе, що вказує на відповідного однорангового unix_sock . Це також lsofвихідні дані для DEVICEстовпця на сокет Unix.

Тепер отримати значення цього peerполя означає вміти читати пам'ять ядра та знати зміщення цього peerполя стосовно unix_sockадреси.

Уже дано декілька рішень на gdbбазі та на systemtapбазі, але вони вимагають gdb/ systemtapта Linux-символів налагодження ядра для встановленого запущеного ядра, що, як правило, не відбувається у виробничих системах.

Жорстке кодування зміщення насправді не є варіантом, оскільки це залежить від версії ядра.

Тепер ми можемо використовувати евристичний підхід при визначенні зміщення: запропонуйте нашому інструменту створити манекен socketpair(тоді ми знаємо адресу обох однолітків), а також шукати адресу однорангової пам’яті на іншому кінці для визначення зміщення.

Ось сценарій із підтвердженням концепції, який робить саме це за допомогою perl(успішно протестований з ядром 2.4.27 та 2.6.32 на i386 та 3.13 та 3.16 на amd64). Як і вище, він працює як обгортка навколо lsof:

Наприклад:

$ that-lsof-wrapper -aUc nm-аплет
ВИМОГА ПІДПРИЄМНИКА ПІДПРИЄМЦЯ FD ТИП ПРИЛАДУ ВИДАЛЕННЯ / ВИКЛ
нм-аплет 4183 Stephane 4u UNIX 0xffff8800a055eb40 0t0 36888 Тип = ПОТІК -> 0xffff8800a055e7c0 [DBus-демон, 4190, @ / TMP / DBus-AiBCXOnuP6] 
нм-аплет 4183 Stephane 7u UNIX 0xffff8800a055e440 0t0 36890 Тип = ПОТІК -> 0xffff8800a055e0c0 [Xorg, 3080, @ / tmp / .X11-unix / X0] 
nm-applet 4183 stephane 8u unix 0xffff8800a05c1040 0t0 36201 type = STREAM -> 0xffff8800a05c13c0 [dbus-daemon, 4118, @ / tmp / dbus-yxxNr1NhaYu 
11pnm 11p) UNIX 0xffff8800a055d080 0t0 36219 Тип = ПОТІК -> 0xffff8800a055d400 [DBus-демон, 4118, @ / TMP / DBus-yxxNr1NkYC] 
нм-аплет 4183 Stephane 12u Unix 0xffff88022e0dfb80 0t0 36221 типу = STREAM -> 0xffff88022e0df800 [DBus-демон, 2268, / вар / run / dbus / system_bus_socket]
nm-applet 4183 stephane 13u unix 0xffff88022e0f80c0 0t0 37025 тип = STREAM -> 0xffff88022e29ec00 [dbus-daemon, 2268, / var / run / dbus / system_bus_socket]

Ось сценарій:

#! /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, це продовження цього коментаря . Неможливо знайти інший кінець сокетів Unix - це те, що мене завжди дратувало (часто, коли намагалися знайти клієнтів X, і останнім питанням з цього приводу виникало ). Я спробую перевірити, чи може подібний підхід застосовуватись для псевдотерміналів, і запропоную їх lsofавторові.
Стефан Шазелас

1
Я досі не можу повірити, що це не передбачено самим ядром! Я дійсно повинен надіслати виправлення, якщо не що інше, як виявити, чому він ще не існує.
Джонатан Райнхарт

1
це ssне робить цього? Це щось над моєю головою, але ss -pxперераховує багато unix-сокетів з інформацією про однолітків, як-от: 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а заголовки стовпців - ...State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
mikeserv

1
Крім того, якщо я це lsof -c terminologyможу, я бачу, terminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAMале якщо я ss -px | grep terminologyu_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
дістаю

1
@mikeserv, схоже, це справді! Здається, останнім часом витрачаю багато часу ...
Стефан Шазелас

9

Erkki Seppala насправді має інструмент, який отримує цю інформацію з ядра Linux за допомогою gdb. Доступний тут .


2
Дуже корисна інформація! Навіть якщо інструмент для мене не вийшов (він спричинив ядро ​​Oops), ідея допомогла мені визначити інший кінець. Я описав своє рішення на Stack Overflow.
MvG

8

Оскільки ядро ​​3.3

Ви можете прямо зараз отримати цю інформацію ss:

# ss -xp

Тепер ви можете бачити в Peerстовпці ідентифікатор (номер inode), який відповідає іншому ідентифікатору в Localстовпці. Відповідні ідентифікатори - це два кінці розетки.

Примітка. UNIX_DIAGПараметр повинен бути включений у вашому ядрі.

Перед ядром 3.3

Linux не розкривав цю інформацію для користувачів.

Однак, заглянувши в пам'ять ядра , ми можемо отримати доступ до цієї інформації.

Примітка. Ця відповідь робить це, використовуючи gdb, однак, дивіться відповідь @ StéphaneChazelas, яка в цьому плані більш детально розроблена.

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

Є 2 різні розетки, 1 прослуховування та 1 встановлений. Шістнадцятковий номер - це адреса до відповідної unix_sockструктури ядра , peerатрибут - адреса іншого кінця сокета (також unix_sockекземпляр структури).

Тепер ми можемо використовувати gdbдля пошуку peerпам'яті ядра:

# 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

Ось вам, інший кінець розетки утримується mysql, PID 14815.

Ваше ядро ​​повинно бути складено KCORE_ELFдля використання /proc/kcore. Також вам потрібна версія зображення вашого ядра із символами налагодження. На Debian 7 apt-get install linux-image-3.2.0-4-amd64-dbgнадасть цей файл.

Немає необхідності у зображенні ядра, що налагоджується ...

Якщо у вас немає (або не хочете зберігати) зображення ядра налагодження в системі, ви можете надати gdbзсув пам'яті для "вручну" доступу до peerзначення. Це значення зміщення зазвичай відрізняється від версії ядра або архітектури.

У моєму ядрі я знаю, що зміщення становить 680 байт, тобто 85 разів 64 біта. Тож я можу зробити:

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

Voilà, такий же результат, як і вище.

Якщо у вас є одне ядро, яке працює на декількох машинах, простіше використовувати цей варіант, оскільки вам не потрібно зображення налагодження, лише значення зміщення.

Щоб (легко) виявити це значення зміщення спочатку, вам потрібне зображення налагодження:

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

Ось ви, 680 байт, це 85 х 64 біт або 170 х 32 біт.

Більшість заслуг за цю відповідь належить MvG .


2
Іншим підходом до отримання зсуву може бути створення socketpair, ідентифікація відповідних записів у / proc / net / unix на основі номерів inode із посилань read / on / pif / fd / * та сканування пам'яті навколо адреси одного сокета для адреса іншого. Це може створити досить портативний (через версії та архітектури Linux), який може бути реалізований самим lsof. Я спробую придумати PoC.
Стефан Шазелас

2
Зараз я додав такий PoC, який, здається, працює добре на тестованих системах.
Стефан Шазелас

5

Це рішення, хоч і працює, представляє обмежений інтерес, оскільки, якщо у вас є досить недавній системний вклад, швидше за все, у вас буде достатньо недавнього ядра, де ви можете використовувати підходи , що ssбазуються , і якщо ви використовуєте більш старе ядро, це інше рішення , хоча більше хакі , швидше за все, і не потребує додаткового програмного забезпечення.

Все ще корисно як демонстрація того, як використовувати systemtapдля такого роду завдань.

Якщо в останній системі Linux з робочою системною вкладкою (1.8 або новішої версії), ви можете використовувати скрипт нижче, щоб обробити вихід lsof:

Наприклад:

$ lsof -aUc nm-аплет | судо-що-скрипт
ВИМОГА ПІДПРИЄМНИКА ПІДПРИЄМЦЯ FD ТИП ПРИЛАДУ ВИДАЛЕННЯ / ВИКЛ
нм-аплет 4183 Stephane 4u UNIX 0xffff8800a055eb40 0t0 36888 Тип = ПОТІК -> 0xffff8800a055e7c0 [DBus-демон, 4190, @ / TMP / DBus-AiBCXOnuP6] 
нм-аплет 4183 Stephane 7u UNIX 0xffff8800a055e440 0t0 36890 Тип = ПОТІК -> 0xffff8800a055e0c0 [Xorg, 3080, @ / tmp / .X11-unix / X0] 
nm-applet 4183 stephane 8u unix 0xffff8800a05c1040 0t0 36201 type = STREAM -> 0xffff8800a05c13c0 [dbus-daemon, 4118, @ / tmp / dbus-yxxNr1NhaYu 
11pnm 11p) UNIX 0xffff8800a055d080 0t0 36219 Тип = ПОТІК -> 0xffff8800a055d400 [DBus-демон, 4118, @ / TMP / DBus-yxxNr1NkYC] 
нм-аплет 4183 Stephane 12u Unix 0xffff88022e0dfb80 0t0 36221 типу = STREAM -> 0xffff88022e0df800 [DBus-демон, 2268, / вар / run / dbus / system_bus_socket]
nm-applet 4183 stephane 13u unix 0xffff88022e0f80c0 0t0 37025 тип = STREAM -> 0xffff88022e29ec00 [dbus-daemon, 2268, / var / run / dbus / system_bus_socket]

(якщо ви бачите 0x0000000000000000 вище замість 0xffff ..., це тому, що kernel.kptr_restrictпараметр sysctl встановлений у вашій системі, що призводить до того, що вказівники ядра приховуються від непривілейованих процесів, і в цьому випадку вам потрібно запустити lsofяк root, щоб отримати змістовний результат).

Цей скрипт не робить жодних спроб впоратися з іменами файлів сокет з символами нового рядка, але також не робить lsof(також не lsofсправляється з пробілами або двокрапками).

systemtapтут використовується для скидання адреси та однорангової адреси всіх unix_sockструктур у unix_socket_tableхеші в ядрі.

Тестується лише на Linux 3.16 amd64 з systemtap 2.6 та 3.13 з 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: я щось пропускаю?
Тотор

@Totor, @varдодано в systemtap 1.8, 2012-06-17 (остання версія 2.7)
Stéphane Chazelas

2

4,89 lsof підтримує показ параметрів кінцевої точки.

Цитується з 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.

Приклад виходу:

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

Оскільки Linux ядро ​​4.2 існує CONFIG_UNIX_DIAG, яке надає додаткову інформацію про сокети домену UNIX, а саме інформацію Virtual File System(VFS), яка містить поки що відсутню інформацію для зв’язку Inode з шляху до процесу. Його вже можна запитувати за допомогою ssінструменту з iproute2, починаючи з версії 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:

Номер пристрою та шлях Inode, з якого ви можете отримати

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

ss також підтримує фільтрацію:

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

але врахуйте, що це може не вказати правильний сокет для вас, оскільки злий процес може перейменувати ваш початковий сокет і замінити його на власний злий:

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

lsof /tmp/socket, fuser /tmp/socketі ss --processes --unix --all --extended 'sport = /tmp/socket'всі будуть перелічувати оригінальний процес, а не заміну. Замість цього використовуйте щось подібне:

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

Або напишіть власну програму litte на основі шаблону, що міститься у man 7 sock_diag .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.