Ich möchte feststellen, welcher Prozess das andere Ende eines UNIX-Sockets hat.
Insbesondere frage ich nach einem, der mit erstellt wurde socketpair()
, obwohl das Problem für alle UNIX-Sockets gleich ist.
Ich habe ein Programm parent
, das a socketpair(AF_UNIX, SOCK_STREAM, 0, fds)
und fork()
s erstellt. Der übergeordnete Prozess wird geschlossen fds[1]
und die fds[0]
Kommunikation wird fortgesetzt. Das Kind tut das Gegenteil close(fds[0]); s=fds[1]
. Dann ist das Kind ein exec()
anderes Programm child1
,. Über dieses Socketpaar können die beiden miteinander kommunizieren.
Angenommen, ich weiß, wer parent
ist, aber ich möchte herausfinden, wer child1
ist. Wie mache ich das?
Es stehen mehrere Tools zur Verfügung, aber keiner kann mir sagen, welcher Prozess sich am anderen Ende des Sockets befindet. Ich habe versucht:
lsof -c progname
lsof -c parent -c child1
ls -l /proc/$(pidof server)/fd
cat /proc/net/unix
Grundsätzlich kann ich die beiden Steckdosen und alles daran sehen, aber nicht sagen, dass sie verbunden sind. Ich versuche festzustellen, welcher FD im Elternteil mit welchem Kindprozeß kommuniziert.
quelle
socketpair
überprüft , und die beiden Enden des Sockels sind nur durch die typspezifischesocketpair
Methode korreliert . Für Unix-Sockets ist dasunix_socketpair
in net / unix / af_unix.c . Es wäre schön, diese Informationen auch für Pfeifen zu haben.Linux-3.3 und höher.
Unter Linux kann seit Kernel-Version 3.3 (und vorausgesetzt, die
UNIX_DIAG
Funktion ist im Kernel integriert) der Peer eines bestimmten Unix-Domain-Sockets (einschließlich Socket-Paaren) mithilfe einer neuen netlink- basierten API abgerufen werden .lsof
Seit Version 4.89 kann diese API verwendet werden:Listet alle Unix-Domain-Sockets mit einem Prozess auf, dessen Name
Xorg
an beiden Enden in einem Format beginnt, das etwa wie folgt lautet :Wenn Ihre Version von
lsof
zu alt ist, gibt es einige weitere Optionen.Das
ss
Dienstprogramm (fromiproute2
) verwendet dieselbe API zum Abrufen und Anzeigen von Informationen in der Liste der Unix-Domain-Sockets auf dem System, einschließlich Peer-Informationen.Die Sockets werden anhand ihrer Inode-Nummer identifiziert . Beachten Sie, dass es nicht mit dem Dateisystem-Inode der Socket-Datei zusammenhängt.
Zum Beispiel in:
Es heißt, dass der Socket 3435997 (der an den ABSTRACT-Socket gebunden war
/tmp/.X11-unix/X0
) mit dem Socket 3435996 verbunden ist. Die-p
Option gibt an, bei welchen Prozessen dieser Socket geöffnet ist. Dies geschieht durch einigereadlink
s on/proc/$pid/fd/*
, so dass dies nur bei Prozessen möglich ist, die Sie besitzen (es sei denn, Sie sindroot
). Zum Beispiel hier:Um herauszufinden, welche Prozesse 3435996 haben, können Sie einen eigenen Eintrag in der Ausgabe von
ss -xp
:Sie können dieses Skript auch als Wrapper verwenden, um
lsof
die relevanten Informationen dort einfach anzuzeigen:Zum Beispiel:
Vor Linux-3.3
Die alte Linux-API zum Abrufen von Unix-Socket-Informationen erfolgt über die
/proc/net/unix
Textdatei. Es listet alle Unix-Domain-Sockets (einschließlich Socket-Paare) auf. Das erste Feld dort (falls nicht für Nicht-Superuser mit demkernel.kptr_restrict
Parameter sysctl ausgeblendet ), wie bereits von @Totor erläutert, enthält die Kernel-Adresse einerunix_sock
Struktur, die einpeer
Feld enthält , das auf den entsprechenden Peer verweistunix_sock
. Dies ist auch dielsof
Ausgabe für dieDEVICE
Spalte in einem Unix-Socket.Wenn Sie nun den Wert dieses
peer
Felds ermitteln, können Sie den Kernel-Speicher lesen und den Versatz diesespeer
Felds in Bezug auf dieunix_sock
Adresse ermitteln.Es wurden bereits mehrere
gdb
-basierte undsystemtap
-basierte Lösungen angegeben, für die jedochgdb
/systemtap
und Linux-Kernel-Debugsymbole für den ausgeführten Kernel erforderlich sind, was auf Produktionssystemen im Allgemeinen nicht der Fall ist.Das Hardcodieren des Offsets ist nicht wirklich eine Option, da dies mit der Kernelversion variiert.
Jetzt können wir den Versatz mit einem heuristischen Ansatz bestimmen: Lassen Sie unser Tool einen Dummy erstellen
socketpair
(dann kennen wir die Adresse beider Peers) und suchen Sie nach der Adresse des Peers im Arbeitsspeicher am anderen Ende, um den Versatz zu bestimmen.Hier ist ein Proof-of-Concept-Skript, das genau das tut
perl
(erfolgreich getestet mit Kernel 2.4.27 und 2.6.32 auf i386 und 3.13 und 3.16 auf amd64). Wie oben funktioniert es als Wrapper umlsof
:Zum Beispiel:
Hier ist das Skript:
quelle
lsof
Autor vorschlagen .ss
nicht? Es geht mir irgendwie über den Kopf,ss -px
listet aber viele Unix-Sockets mit Peer-Informationen wie: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
und die Spaltenüberschriften sind ...State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
lsof -c terminology
kann ich sehen,terminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAM
aber wenn ich es tue,ss -px | grep terminology
bekomme ich:u_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
Erkki Seppala hat tatsächlich ein Tool , das diese Informationen mit gdb aus dem Linux-Kernel abruft. Es ist hier verfügbar .
quelle
Seit dem Kernel 3.3
Sie können diese Informationen jetzt abrufen mit
ss
:Jetzt können Sie in der
Peer
Spalte eine ID (Inode-Nummer) sehen, die einer anderen ID in derLocal
Spalte entspricht. Passende IDs sind die beiden Enden eines Sockets.Hinweis: Die
UNIX_DIAG
Option muss in Ihrem Kernel aktiviert sein.Vor dem Kernel 3.3
Linux hat diese Informationen nicht dem Userland zugänglich gemacht.
Indem jedoch in den Kernelspeicher suchen , können wir auf diese Informationen zugreifen.
Hinweis: Diese Antwort ist so unter Verwendung
gdb
jedoch finden Sie @ StéphaneChazelas' Antwort , die mehr in dieser Hinsicht ausgearbeitet wird.Es gibt 2 verschiedene Steckdosen, 1 hörend und 1 hergestellt. Die Hexa-Zahl ist die Adresse der entsprechenden Kernel-
unix_sock
Struktur , wobei einpeer
Attribut die Adresse des anderen Endes des Sockets ist (auch eineunix_sock
Strukturinstanz).Jetzt können wir
gdb
denpeer
internen Kernel-Speicher finden:Das andere Ende der Buchse wird von
mysql
PID 14815 gehalten.Ihr Kernel muss
KCORE_ELF
zur Verwendung mit kompiliert werden/proc/kcore
. Außerdem benötigen Sie eine Version Ihres Kernel-Images mit Debugging-Symbolen. Unter Debian 7apt-get install linux-image-3.2.0-4-amd64-dbg
wird diese Datei bereitgestellt.Keine Notwendigkeit für das debuggbare Kernel-Image ...
Wenn Sie das Debug-Kernel-Image auf dem System nicht haben (oder nicht behalten möchten), können Sie
gdb
den Speicher-Offset so einstellen, dass "manuell" auf denpeer
Wert zugegriffen wird. Dieser Offsetwert unterscheidet sich normalerweise mit der Kernelversion oder -architektur.Auf meinem Kernel weiß ich, dass der Versatz 680 Bytes beträgt, also 85 mal 64 Bits. Also kann ich tun:
Voilà, gleiches Ergebnis wie oben.
Wenn Sie den gleichen Kernel auf mehreren Computern ausführen, ist es einfacher, diese Variante zu verwenden, da Sie nicht das Debug-Image, sondern nur den Offset-Wert benötigen.
Um diesen Offsetwert (einfach) zu ermitteln, benötigen Sie das Debug-Image:
Hier, 680 Bytes, das sind 85 x 64 Bits oder 170 x 32 Bits.
Der größte Teil des Verdienstes für diese Antwort geht an MvG .
quelle
Wenn Sie ein aktuelles Linux-System mit einem funktionierenden Systemtap (1.8 oder neuer) verwenden, können Sie das folgende Skript verwenden, um die Ausgabe von
lsof
:Zum Beispiel:
(Wenn Sie oben 0x0000000000000000 anstelle von 0xffff sehen ... ist dies darauf zurückzuführen, dass der
kernel.kptr_restrict
Parameter sysctl auf Ihrem System festgelegt ist, wodurch Kernel-Zeiger vor nicht privilegierten Prozessen verborgen werden. In diesem Fall müssen Sielsof
als root ausgeführt werden, um a zu erhalten aussagekräftiges Ergebnis).Dieses Skript unternimmt keinen Versuch, mit Socket-Dateinamen mit Zeilenumbrüchen umzugehen, aber auch nicht
lsof
(und auch nichtlsof
mit Leerzeichen oder Doppelpunkten).systemtap
Hier werden die Adresse und die Peer-Adresse allerunix_sock
Strukturen imunix_socket_table
Hash im Kernel gesichert.Nur unter Linux 3.16 amd64 mit Systemtap 2.6 und 3.13 mit 2.3 getestet.
quelle
parse error: unknown statistic operator @var
: vermisse ich etwas?@var
wurde am 17.06.2012 (letzter Stand ist 2.7) in systemtap 1.8 eingetragen4.89 von lsof unterstützt die Anzeige von Endpunktoptionen.
Zitiert aus lsof.8:
Ausgabebeispiel:
quelle
Seit Linux-Kernel 4.2 gibt es dort
CONFIG_UNIX_DIAG
zusätzliche Informationen zu UNIX-Domain-Sockets, nämlich dieVirtual File System
(VFS-) Informationen, die die bisher fehlenden Informationen enthalten, um den Inode vom Pfad zum Prozess zu verlinken. Es kann bereits mit demss
Tool von iproute2 ab Version 4.19.0 ~ 55 abgefragt werden :Die Gerätenummer und der Pfad-Inode, die Sie erhalten können
ss
unterstützt auch die Filterung:Beachten Sie jedoch, dass dies möglicherweise nicht den richtigen Socket für Sie auflistet, da ein böser Prozess Ihren ursprünglichen Socket möglicherweise umbenennen und durch einen eigenen bösen Socket ersetzen kann:
lsof /tmp/socket
,fuser /tmp/socket
Undss --processes --unix --all --extended 'sport = /tmp/socket'
wird alle ursprünglichen Prozesslisten, nicht den Bösen Ersatzes. Verwenden Sie stattdessen Folgendes:Oder schreiben Sie Ihr eigenes kleines Programm basierend auf der Vorlage in man 7 sock_diag .
quelle