Bu unix soket çiftinin diğer ucunda kim var?


54

Hangi işlemin bir UNIX soketinin diğer ucuna sahip olduğunu belirlemek istiyorum.

Özellikle, socketpair()herhangi bir UNIX soketi için aynı olmasına rağmen , yaratılmış olanı soruyorum .

parentBir socketpair(AF_UNIX, SOCK_STREAM, 0, fds)ve fork()s'yi oluşturan bir programım var . Ana süreç kapanır fds[1]ve fds[0]iletişim kurmaya devam eder. Çocuk tersini yapar close(fds[0]); s=fds[1]. O zaman çocuğun exec()başka bir programı var child1. İkisi bu soket çifti üzerinden ileri ve geri iletişim kurabilir.

Şimdi kim parentolduğunu biliyorum diyorum ama kim olduğunu bulmak istiyorum child1. Bunu nasıl yaparım?

Elimde birkaç araç var, ancak hiçbiri soketin diğer ucunda hangi işlem olduğunu söyleyemez. Denedim:

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

Temel olarak, iki soketi ve onlarla ilgili her şeyi görebiliyorum, ancak birbirlerine bağlı olduklarını söyleyemem. Ebeveyn içinde hangi FD'nin hangi çocuk süreci ile iletişim kurduğunu belirlemeye çalışıyorum.

Yanıtlar:


27

Kernel 3.3 olduğundan, kullanmadan mümkündür ssya lsof-4.89bakınız - ya da yukarıda Stéphane Chazelas cevabını .

Eski versiyonlarda, yazara göre lsof, bunu bulmak mümkün değildi: Linux çekirdeği bu bilgiyi açığa çıkarmıyor. Kaynak: comp.unix.admin'deki 2003 konu .

Gösterilen sayı /proc/$pid/fd/$fd, sanal soket dosya sistemindeki soketin inode numarasıdır. Bir boru veya soket çifti oluşturduğunuzda, her bir uç art arda bir inode numarası alır. Sayılar ardışık olarak atfedilir, bu nedenle sayılar 1 ile farklı olma olasılığı yüksektir, ancak bu garanti edilmez (ilk soket N ve N + 1 sarma nedeniyle kullanımda olduğu için veya başka bir iplik olduğu için iki inode ayırması arasında zamanlanmış ve bu iş parçacığı da bazı düğümler oluşturmuş).

2.6.39 numaralı çekirdeğin tanımınısocketpair kontrol ettim ve soketin iki ucu tipe özgü socketpairyöntem dışında korelasyon göstermedi . Unix soketleri için, işte unix_socketpairiçindenet/unix/af_unix.c .


2
@ Gilils teşekkürler. Bir süre önce bunun hakkında bir şeyler okuduğumu hatırlıyorum, ancak bir daha bulamadım. Sadece / proc / net / unix için bir yama yazmam gerekebilir.
Jonathon Reinhart

Ve evet, bu gözlemi artan inode sayılarıyla yaptım ve şu anda üzerinde çalıştığım şey bu. Ancak, belirttiğiniz gibi, garanti edilmez. Baktığım işlem en az 40 açık unix soketine sahip ve N + 1'in gerçek tutmadığı bir örnek gördüm. Aylak.
Jonathon Reinhart

1
@JonathonReinhart Tanımını kontrol ettim vesocketpair soketin iki ucu türe özgü socketpairyöntem dışında ilişkili değil . Unix soketleri için, unix_socketpairnet / unix / af_unix.c dosyasında . Borular için de bu bilgiye sahip olmak güzel olurdu.
Gilles 'SO- kötülük olmayı'

36

Not : Şimdi lsofburada açıklanan her iki yaklaşımı birleştiren ve aynı zamanda https://github.com/stephane-chazelas/misc-scripts/blob/master/lsofc

Linux-3.3 ve üzeri.

Linux'ta, çekirdek sürüm 3.3'ten (ve UNIX_DIAGözellik çekirdeğe yerleştirildiği sürece ), belirli bir unix alan soketinin eşi (soket çiftlerini içerir) yeni bir netlink tabanlı API kullanarak elde edilebilir .

lsof 4.89 sürümünden beri bu API’yı kullanabilir:

lsof +E -aUc Xorg

Adı Xorgiki başından başlayan bir işlem olan tüm Unix alan soketlerine benzer bir formatta listelenir :

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

Sürümünüz lsofçok eskiyse, birkaç seçenek daha vardır.

Yardımcı ssprogram (from iproute2), eş bilgiler de dahil olmak üzere sistemdeki unix alan soketleri listesinde bilgi almak ve görüntülemek için aynı API'yi kullanır.

Soketler inode numaralarıyla tanımlanır . Bunun soket dosyasının dosya sistemi inode ile ilgili olmadığını unutmayın.

Örneğin:

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

3435997 soketinin (ÖZET soketine /tmp/.X11-unix/X0bağlı) 3435996 soketine bağlı olduğunu söylüyor. -pSeçenek, hangi işlemlerin bu soketin açık olduğunu size söyleyebilir. Bunu, bazılarını readlinkaçık yaparak yapar /proc/$pid/fd/*, böylece yalnızca sahip olduğunuz işlemlerde (siz olmadıkça root) yapabilir. Mesela burada:

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

Hangi işlem (ler) in 3435996 olduğunu bulmak için, aşağıdaki adreste kendi girdisine bakabilirsiniz ss -xp:

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

Bu komut dosyasını lsof, ilgili bilgileri burada kolayca göstermek için etrafındaki bir sarmalayıcı olarak da kullanabilirsiniz :

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

Örneğin:

$ sudo that-lsof-sarıcı -ad3 -p 29215
COMMAND PID KULLANICI FD TİP CİHAZ CİHAZ BOYUTU / KAPALI NODE ADI
xterm 29215 stephane 3u unix 0xffff8800a07da4c0 0t0 3435996 türü = STREAM <-> 3435997 [Xorg, 3080, @ / tmp / .X11-unix / X0]

Linux-3.3'ten önce

Unix soket bilgisini alan eski Linux API'si /proc/net/unixmetin dosyasıdır. Tüm Unix alan soketlerini listeler (soket çiftleri dahil). Buradaki ilk alan ( kernel.kptr_restrictsysctl parametresiyle süper olmayan kullanıcılara gizlenmemişse ) @Totor tarafından açıklandığı gibi , ilgili eşe işaret eden unix_sockbir peeralanı içeren bir yapının çekirdek adresini içerir . Aynı zamanda bir Unix soketindeki sütun için çıktılar . unix_socklsofDEVICE

Şimdi o peeralanın değerini almak, çekirdek belleğini okuyabilmek ve o peeralanın unix_sockadrese göre ofsetini bilmek anlamına gelir .

Çeşitli gdbtabanlı ve systemtapmerkezli çözümler zaten verilmiş ancak gerektirir gdb/ systemtapve çekirdek için Linux çekirdeği ayıklama sembolleri üretim sistemlerinde durum genellikle olmadığı yüklenen.

Ofsetin kodlanması gerçekten, çekirdek sürümüne göre değişen bir seçenek değildir.

Şimdi ofsetin belirlenmesinde sezgisel bir yaklaşım kullanabiliriz: aracımızın bir kukla oluşturmasını sağlayın socketpair(daha sonra her iki eşin adresini de biliyoruz) ve ofseti belirlemek için diğer uçtaki eşin adresini aranır.

İşte sadece bunu kullanan bir kavram kanıtı betiği perl(i386 ve 3.13 ve 3.16 amd64'te çekirdek 2.4.27 ve 2.6.32 ile başarıyla test edilmiştir). Yukarıdaki gibi, etrafında bir sarmalayıcı olarak çalışır lsof:

Örneğin:

$ that-lsof-sarıcı -AUc nm-applet
COMMAND PID KULLANICI FD TİP CİHAZ CİHAZ BOYUTU / KAPALI NODE ADI
mil-uygulama 4183 stephane 4u unix 0xffff8800a055eb40 0T0 36.888 türü = STREAM -> 0xffff8800a055e7c0 [dbus-cini 4190, @ / tmp / dbus-AiBCXOnuP6] 
nm uygulama 4183 stephane 7U unix 0xffff8800a055e440 0T0 36890 türü = STREAM -> 0xffff8800a055e0c0 [Xorg, 3080, @ / tmp / .X11-unix / X0] 
nm uygulama 4183 stephane 8U unix 0xffff8800a05c1040 0T0 36201 türü = STREAM -> 0xffff8800a05c13c0 [dbus-cini 4118 @ / tmp / dbus-yxxNr1NkYC] 
nm uygulama 4183 stephane 11u unix 0xffff8800a055d080 0T0 36.219 türü = STREAM -> 0xffff8800a055d400 [dbus-cini 4118 @ / tmp / dbus-yxxNr1NkYC] 
nm uygulama 4183 unix 0xffff88022e0dfb80 0T0 36221 türü = STREAM 12U stephane -> 0xffff88022e0df800 [dbus-cini 2268 / var / çalıştırmak / dbus / system_bus_socket]
nm-applet 4183 stephane 13u unix 0xffff88022e0f80c0 0t0 37025 türü = STREAM -> 0xffff88022e29ec00 [dbus-daemon, 2268, / var / run / dbus / system_bus_socket]

İşte senaryo:

#! /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, bu konuda bir takip var o yorumun . Unix soketlerinin diğer ucunu bulamamak, beni her zaman sinirlendiren bir şeydir (genellikle X müşterilerini bulmaya çalışırken ve bununla ilgili son bir soru vardı ). Benzer bir yaklaşımın sözde terminaller için kullanılıp kullanılmayacağını görmeye çalışacağım ve bunları lsofyazara önereceğim .
Stéphane Chazelas 17:15

1
Bunun çekirdeğin kendisi tarafından sağlanmadığına hala inanamıyorum! Gerçekten bir yama göndermeliyim, eğer başka bir şey olmasa bile neden olmadığını bilmeliyim.
Jonathon Reinhart

1
bunu yapmaz ssmı? ss -pxusers: ("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* 15068State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
Başımın

1
Ayrıca, ben yaparsam lsof -c terminologygörebildiğim terminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAMama bunu yaparsam ss -px | grep terminologyben alıyorum:u_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
mikeserv

1
@mikeserv, gerçekten öyle görünüyor! Görünüşe göre son zamanlarda çok zaman harcıyorum ...
Stéphane Chazelas


8

Çekirdek 3.3'ten beri

Sen olabilir şimdi bu bilgileri almak ss:

# ss -xp

Şimdi Peersütunda , sütundaki başka bir kimliğe karşılık gelen bir kimliği (inode numarası) görebilirsiniz Local. Eşleşen kimlikler bir soketin iki ucudur.

Not: UNIX_DIAGSeçenek, çekirdeğinizde etkinleştirilmiş olmalıdır.

Çekirdek öncesi 3.3

Linux bu bilgiyi kullanıcıya vermedi.

Ancak, çekirdek belleğe bakarak bu bilgilere erişebiliriz.

Not: Bu cevap bunu kullanarak gdb, ancak, bu konuda daha ayrıntılı olan @ StéphaneChazelas'ın cevabına bakınız .

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

2 farklı soket var, 1 dinliyor ve 1 kurulmuş. Hexa numarası, soketin diğer ucunun adresi (aynı zamanda bir yapı örneği) olan bir özniteliğe sahip , karşılık gelen çekirdek unix_sockyapısınınpeer adresidir .unix_sock

Şimdi çekirdek içindeki belleği gdbbulmak için kullanabiliriz 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

İşte, soketin diğer ucu mysqlPID 14815 tarafından tutulur.

Sizin çekirdek derlenmesi gerekir KCORE_ELFkullanmak /proc/kcore. Ayrıca, çekirdek görüntüsünüzün hata ayıklama sembolleriyle birlikte bir sürümüne ihtiyacınız var. Debian 7'de apt-get install linux-image-3.2.0-4-amd64-dbgbu dosyayı sağlayacaktır.

Hata ayıklanabilir çekirdek görüntüsüne gerek yok ...

Sistemde hata ayıklama çekirdeği görüntüsüne sahip değilseniz (veya saklamak istemiyorsanız) gdb, peerdeğere "elle" erişmesi için bellek ofsetini verebilirsiniz . Bu ofset değeri genellikle çekirdek sürüm veya mimariye göre değişir.

Çekirdeğimde ofsetin 680 byte olduğunu biliyorum, bu 85 kat 64 bit. Böylece yapabilirim:

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

Voilà, yukarıdaki ile aynı sonuç.

Birkaç çekirdekte aynı çekirdeğe sahipseniz, bu değişkeni kullanmak daha kolaydır, çünkü hata ayıklama görüntüsüne, sadece ofset değerine ihtiyacınız yoktur.

Bu ofset değerini ilk başta (kolayca) keşfetmek için, hata ayıklama görüntüsüne ihtiyacınız vardır:

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

İşte, 680 bayt, bu 85 x 64 bit veya 170 x 32 bit.

Bu cevap için kredinin çoğu MvG'ye gidiyor .


2
Ofseti geri almak için başka bir yaklaşım, bir soket çifti oluşturmak, / proc / net / unix içindeki / / proc / net / unix içindeki karşılık gelen girişleri tanımlamak ve / proc / pif / fd / * üzerindeki okuma bağlantılarından gelen inode numaralarına dayanarak giriş yapmak için bir soketin adresinin etrafındaki belleği taramak olabilir. diğerinin adresi. Bu, kendisi tarafından uygulanabilecek oldukça taşınabilir (Linux sürümleri ve mimarileri karşısında) yapabilir. PoC ile gelmeye çalışacağım.
Stéphane Chazelas

2
Şimdi test ettik sistemlerde iyi çalışıyor gibi bir PoC ekledik .
Stéphane Chazelas

5

Son zamanlarda bir-yeterince SystemTap'ı varsa, şansını kullanabilirsiniz nerede bir son-yeterli çekirdek gerekecek çünkü bu çözüm, çalışma olsa da, sınırlı ilgi olduğunu ssbazlı yaklaşımlar eski bir çekirdeğinizdeipfwadm iseniz ve, diğer çözüm , daha hacky çalışması daha olasıdır ve ek yazılım gerektirmez.

systemtapBu tür bir görev için nasıl kullanılacağının bir kanıtı olarak hala faydalıdır .

Çalışan bir systemtap (1.8 veya daha yenisi) olan yeni bir Linux sisteminde, aşağıdakilerin çıktısını işlemek için aşağıdaki betiği kullanabilirsiniz lsof:

Örneğin:

$ lsof -aUc nm-uygulaması | sudo that-script
COMMAND PID KULLANICI FD TİP CİHAZ CİHAZ BOYUTU / KAPALI NODE ADI
mil-uygulama 4183 stephane 4u unix 0xffff8800a055eb40 0T0 36.888 türü = STREAM -> 0xffff8800a055e7c0 [dbus-cini 4190, @ / tmp / dbus-AiBCXOnuP6] 
nm uygulama 4183 stephane 7U unix 0xffff8800a055e440 0T0 36890 türü = STREAM -> 0xffff8800a055e0c0 [Xorg, 3080, @ / tmp / .X11-unix / X0] 
nm uygulama 4183 stephane 8U unix 0xffff8800a05c1040 0T0 36201 türü = STREAM -> 0xffff8800a05c13c0 [dbus-cini 4118 @ / tmp / dbus-yxxNr1NkYC] 
nm uygulama 4183 stephane 11u unix 0xffff8800a055d080 0T0 36.219 türü = STREAM -> 0xffff8800a055d400 [dbus-cini 4118 @ / tmp / dbus-yxxNr1NkYC] 
nm uygulama 4183 unix 0xffff88022e0dfb80 0T0 36221 türü = STREAM 12U stephane -> 0xffff88022e0df800 [dbus-cini 2268 / var / çalıştırmak / dbus / system_bus_socket]
nm-applet 4183 stephane 13u unix 0xffff88022e0f80c0 0t0 37025 türü = STREAM -> 0xffff88022e29ec00 [dbus-daemon, 2268, / var / run / dbus / system_bus_socket]

yerine 0xffff yukarıdaki 0x0000000000000000 görürseniz çünkü (..., bu kadar kernel.kptr_restrictsysctl parametresi çalıştırmak gerekir bu durumda olmayan ayrıcalıklı süreçlerden gizlenmesine çekirdek işaretçileri neden sisteminizde hemen üzerinde bulunur lsofbir olsun root olarak anlamlı sonuç).

Bu betik, yeni satır karakterleriyle soket dosya adlarıyla baş etmek için herhangi bir girişimde lsofbulunmaz lsof;

systemtapBurada, karma içindeki tüm unix_sockyapıların adreslerini ve akran adreslerini unix_socket_tableçekirdeğe dökmek için kullanılır .

Yalnızca Linux 3.16 amd64'te systemtap 2.6 ile ve 3.13'te 2.3 ile test edilmiştir.

#! /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: bir şey mi eksik?
Totor

@Totor, @varsystemtap 1.8, 2012-06-17'de eklendi (en son 2.7)
Stéphane Chazelas

2

4,89 of lsof uç nokta seçeneklerini göstermeyi destekler.

Lsof.8'den alıntı:

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

Çıktı örneği:

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 çekirdeği 4.2'den beri CONFIG_UNIX_DIAG, UNIX etki alanı soketleri hakkında ek bilgi sağlayan, yani Virtual File SystemInode'yi işlemden süreçle ilişkilendiren şu ana kadar eksik olan bilgileri içeren (VFS) bilgileri vardır. V4.19.0 ~ 55 sürümünden ssitibaren iproute2 aracını kullanarak zaten sorgulanabilir :

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

Aldığınız cihaz numarası ve yol Inode

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

ss ayrıca filtrelemeyi de destekler:

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

Ancak, bunun sizin için doğru soketi listeleyemeyebileceğini lütfen unutmayın, çünkü kötü bir işlem orijinal soketinizi yeniden adlandırabilir ve onunla kötü bir şeyle değiştirebilir:

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

lsof /tmp/socket, fuser /tmp/socketVe ss --processes --unix --all --extended 'sport = /tmp/socket'tüm orijinal süreci, listeler değil kötülük değiştirme. Bunun yerine şunun gibi bir şey kullanın:

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

Veya man 7 sock_diag içindeki şablona göre kendi litte programınızı yazınız .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.