Je veux déterminer quel processus a l'autre extrémité d'un socket UNIX.
Plus précisément, je pose une question sur celle qui a été créée avec socketpair()
, bien que le problème soit le même pour toutes les sockets UNIX.
J'ai un programme parent
qui crée un socketpair(AF_UNIX, SOCK_STREAM, 0, fds)
, et l' fork()
art. Le processus parent se ferme fds[1]
et continue fds[0]
à communiquer. L'enfant fait le contraire, close(fds[0]); s=fds[1]
. Ensuite, l’enfant exec()
est un autre programme child1
,. Les deux peuvent communiquer en arrière via ce socketpair.
Maintenant, disons que je sais qui parent
est, mais je veux savoir qui child1
est. Comment puis-je faire cela?
Plusieurs outils sont à ma disposition, mais aucun ne peut me dire quel processus se trouve à l’autre bout du socket. J'ai essayé:
lsof -c progname
lsof -c parent -c child1
ls -l /proc/$(pidof server)/fd
cat /proc/net/unix
En gros, je peux voir les deux sockets et tout ce qui les concerne, mais je ne peux pas dire qu'ils sont connectés. J'essaie de déterminer quelle FD dans le parent communique avec quel processus enfant.
la source
socketpair
, et les deux extrémités du socket ne sont pas corrélées, sauf par lasocketpair
méthode spécifique au type . Pour les sockets unix, cela se trouveunix_socketpair
dans `net / unix / af_unix.c . Ce serait bien d'avoir cette information pour les pipes aussi.Linux-3.3 et supérieur.
Sous Linux, à partir de la version 3.3 du noyau (et à condition que la
UNIX_DIAG
fonctionnalité soit intégrée au noyau), l'homologue d'un socket de domaine unix donné (y compris socketpairs) peut être obtenu à l'aide d'une nouvelle API basée sur netlink .lsof
depuis la version 4.89, on peut utiliser cette API:Répertoriera tous les sockets de domaine Unix ayant un processus dont le nom commence par un des
Xorg
deux bouts dans un format semblable à celui-ci:Si votre version de
lsof
est trop ancienne, il existe quelques options supplémentaires.L'
ss
utilitaire (depuisiproute2
) utilise cette même API pour extraire et afficher des informations sur la liste des sockets de domaine Unix sur le système, y compris des informations d'homologue.Les sockets sont identifiés par leur numéro d'inode . Notez que cela n'est pas lié à l'inode du système de fichiers du fichier de socket.
Par exemple dans:
il indique que le socket 3435997 (qui était lié au socket ABSTRACT
/tmp/.X11-unix/X0
) est connecté au socket 3435996. L'-p
option peut vous indiquer le ou les processus pour lesquels cette socket est ouverte. Il le fait en faisant quelquesreadlink
s sur/proc/$pid/fd/*
, il ne peut le faire que sur les processus que vous possédez (sauf si vous êtesroot
). Par exemple ici:Pour savoir quel processus a 3435996, vous pouvez rechercher sa propre entrée dans le résultat de
ss -xp
:Vous pouvez également utiliser ce script comme enveloppe
lsof
pour y afficher facilement les informations pertinentes:Par exemple:
Avant linux-3.3
L'ancienne API Linux permettant de récupérer les informations de socket Unix se fait via le
/proc/net/unix
fichier texte. Il répertorie tous les sockets du domaine Unix (y compris socketpairs). Le premier champ qu'il contient (s'il n'est pas masqué par les non-utilisateurs avec lekernel.kptr_restrict
paramètre sysctl), comme expliqué par @Totor, contient l'adresse du noyau d'uneunix_sock
structure contenant unpeer
champ pointant sur l' homologue correspondantunix_sock
. C'est aussi ce quilsof
sort pour laDEVICE
colonne sur un socket Unix.Désormais, obtenir la valeur de ce
peer
champ signifie pouvoir lire la mémoire du noyau et connaître le décalage de cepeer
champ par rapport à l'unix_sock
adresse.Plusieurs à
gdb
base et àsystemtap
base de solutions ont déjà été données , mais ils ont besoingdb
/systemtap
et les symboles de débogage de Linux pour le noyau en cours d' exécution en cours d' installation qui est généralement pas le cas sur les systèmes de production.Le codage en dur de l'offset n'est pas vraiment une option car cela varie avec la version du noyau.
Maintenant , nous pouvons utiliser une approche heuristique de déterminer l'offset: avoir notre outil créer un mannequin
socketpair
(nous savons l'adresse des deux pairs), et rechercher l'adresse du poste autour de la mémoire à l'autre extrémité pour déterminer le décalage.Voici un script de
perl
validation de principe qui utilise précisément (testé avec succès avec les noyaux 2.4.27 et 2.6.32 sur i386 et 3.13 et 3.16 sur amd64). Comme ci-dessus, cela fonctionne comme un wrapper autour delsof
:Par exemple:
Voici le script:
la source
lsof
auteur.ss
pas ça? C'est un peu au-dessus de ma tête, maisss -px
répertorie un grand nombre de sockets Unix avec des informations sur les pairs du type: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
et les en-têtes de colonne sont ...State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
lsof -c terminology
je peux voirterminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAM
mais si je le faisss -px | grep terminology
je reçois:u_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
Erkki Seppala a en fait un outil qui récupère ces informations du noyau Linux avec gdb .. Il est disponible ici .
la source
Depuis le noyau 3.3
Vous pouvez maintenant obtenir cette information avec
ss
:Vous pouvez maintenant voir dans la
Peer
colonne un identifiant (numéro d'inode) qui correspond à un autre identifiant dans laLocal
colonne. Les ID correspondants sont les deux extrémités d'un socket.Remarque: L'
UNIX_DIAG
option doit être activée dans votre noyau.Avant le noyau 3.3
Linux n'a pas exposé cette information à l'utilisateur.
Cependant, en regardant dans la mémoire du noyau , nous pouvons accéder à ces informations.
Remarque: cette réponse le fait en utilisant
gdb
, cependant, veuillez consulter la réponse de @ StéphaneChazelas qui est plus élaborée à cet égard.Il y a 2 prises différentes, 1 à l'écoute et 1 établie. Le nombre hexa est l'adresse de la
unix_sock
structure de noyau correspondante , l'peer
attribut étant l'adresse de l'autre extrémité du socket (également uneunix_sock
instance de structure).Maintenant, nous pouvons utiliser
gdb
pour trouver lapeer
mémoire dans le noyau:Voilà, l’autre extrémité de la prise est tenue par
mysql
, le PID 14815.Votre noyau doit être compilé avec
KCORE_ELF
pour pouvoir être utilisé/proc/kcore
. De plus, vous avez besoin d’une version de l’image de votre noyau avec des symboles de débogage. Sur Debian 7,apt-get install linux-image-3.2.0-4-amd64-dbg
fournira ce fichier.Pas besoin de l'image du noyau débogable ...
Si vous ne possédez pas (ou ne souhaitez pas conserver) l'image de noyau de débogage sur le système, vous pouvez attribuer à
gdb
l'offset de mémoire un accès "manuel" à lapeer
valeur. Cette valeur de décalage diffère généralement avec la version du noyau ou l'architecture.Sur mon noyau, je sais que le décalage est de 680 octets, soit 85 fois 64 bits. Donc je peux faire:
Voilà, même résultat que ci-dessus.
Si vous avez le même noyau s'exécutant sur plusieurs machines, il est plus facile d'utiliser cette variante car vous n'avez pas besoin de l'image de débogage, seulement de la valeur de décalage.
Pour découvrir (facilement) cette valeur de décalage dans un premier temps, vous avez besoin de l'image de débogage:
Voilà, 680 octets, 85 x 64 bits, ou 170 x 32 bits.
La majeure partie du crédit de cette réponse revient à MvG .
la source
Si vous travaillez sur un système Linux récent avec un systemtap opérationnel (1.8 ou plus récent), vous pouvez utiliser le script ci-dessous pour post-traiter la sortie de
lsof
:Par exemple:
(Si vous voyez 0x0000000000000000 ci-dessus au lieu de 0xffff ..., c'est parce que le
kernel.kptr_restrict
paramètre sysctl est défini sur votre système, ce qui a pour effet de masquer les pointeurs du noyau aux processus non privilégiés. Dans ce cas, vous devrez vous lancer enlsof
tant que root pour obtenir un résultat significatif).Ce script ne tente pas de gérer les noms de fichier de socket avec des caractères de nouvelle ligne, mais ne le fait pas non plus
lsof
(ni leslsof
blancs ni les deux points).systemtap
ici est utilisé pour vider l’adresse et l’adresse de l’homologue de toutes lesunix_sock
structures duunix_socket_table
hachage du noyau.Testé uniquement sur Linux 3.16 amd64 avec systemtap 2.6 et 3.13 avec 2.3.
la source
parse error: unknown statistic operator @var
: est-ce que je manque quelque chose?@var
été ajouté à systemtap 1.8, 2012-06-17 (la dernière est 2.7)4.89 de lsof prend en charge l’affichage des options de points de terminaison.
Cité de lsof.8:
Exemple de sortie:
la source
Depuis le noyau Linux 4.2, il existe
CONFIG_UNIX_DIAG
des informations supplémentaires sur les sockets de domaine UNIX, à savoir les informationsVirtual File System
(VFS), qui contiennent les informations manquantes jusqu'à présent pour relier l'inode du chemin d'accès au processus. Il peut déjà être interrogé à l'aide de l'ss
outil de iproute2 à partir de la version v4.19.0 ~ 55 :Le numéro de périphérique et le chemin Inode que vous pouvez obtenir
ss
prend également en charge le filtrage:mais sachez que ceci pourrait ne pas lister le bon socket pour vous, car un processus pervers pourrait renommer votre socket original et le remplacer par son propre mauvais:
lsof /tmp/socket
,fuser /tmp/socket
etss --processes --unix --all --extended 'sport = /tmp/socket'
tous énuméreront le processus original, pas le remplaçant diabolique. Utilisez plutôt quelque chose comme ceci:Ou écrivez votre propre petit programme basé sur le modèle contenu dans man 7 sock_diag .
la source