web-dev-qa-db-fra.com

Qui a eu l'autre extrémité de ce SocketPair Unix?

Je veux déterminer quel processus a l'autre extrémité d'une prise UNIX.

Plus précisément, je pose une question à propos de celui créé avec socketpair(), bien que le problème soit le même pour toute prise UNIX.

J'ai un programme parent qui crée une socketpair(AF_UNIX, SOCK_STREAM, 0, fds) et fork() s. Le processus parent ferme fds[1] Et conserve fds[0] Pour communiquer. L'enfant fait le contraire, close(fds[0]); s=fds[1]. Ensuite, l'enfant exec() s 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?

Il y a plusieurs outils à ma disposition, mais aucun ne peut me dire quel processus est à l'autre extrémité de la prise. J'ai essayé:

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

Fondamentalement, je peux voir les deux prises et tout ce qui leur concerne, mais ne peut pas dire qu'ils sont connectés. J'essaie de déterminer quelle fd dans le parent communique avec quel processus enfant.

58
Jonathon Reinhart

Depuis le noyau 3.3

Vous CANmaintenant Obtenez ces informations avec ss :

# ss -xp

Maintenant, vous pouvez voir dans la colonne Peer Colonne (numéro d'inode) qui correspond à un autre ID dans la colonne Local. Les identifiants correspondants sont les deux extrémités d'une prise.

Noter la UNIX_DIAG L'option doit être activée dans votre noyau.

Avant le noyau 3.3

Linux n'a pas exposé ces informations à Userland.

Cependant, par à la recherche de la mémoire du noyau , nous pouvons accéder à ces informations.

Remarque: cette réponse le fait en utilisant gdb, cependant, s'il vous plaît voir @ Stéphanechatzelas 'réponse qui est plus élaboré à cet égard.

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

Il y a 2 sockets différentes, 1 écoute et 1 établi. Le numéro hexa est l'adresse au noyau correspondant unix_sock structure , ayant un attribut peer étant l'adresse L'autre extrémité de la prise (Aussi un unix_sock instance de structure).

Maintenant, nous pouvons utiliser gdb pour trouver le peer dans la mémoire du noyau:

# 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

Vous y allez, l'autre extrémité de la prise est détenue par mysql, PID 14815.

Votre noyau doit être compilé avec KCORE_ELF utiliser /proc/kcore. De plus, vous avez besoin d'une version de votre image de 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 debuggable ...

Si vous n'avez pas (ou ne voulez pas garder) l'image du noyau de débogage sur le système, vous pouvez donner gdb le décalage de la mémoire sur "manuellement" accéder à la valeur peer. Cette valeur de compensation 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:

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

Voilà, même résultat que ci-dessus.

Si vous avez le même noyau exécuté sur plusieurs machines, il est plus facile d'utiliser cette variante car vous n'avez pas besoin de l'image de débogage, seule la valeur de décalage.

Pour (facilement) découvrir cette valeur de compensation au début, vous avez besoin de l'image de débogage:

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

Vous y allez, 680 octets, il s'agit de 85 x 64 bits, ou 170 x 32 bits.

La majeure partie du crédit pour cette réponse va à MVG .

9
Totor

Erkki Seppala a en fait un outil qui récupère ces informations du noyau Linux avec GDB. C'est disponible ici .

Depuis le noyau Linux 4.2, il existe CONFIG_UNIX_DIAG, qui fournit des informations supplémentaires sur les prises de domaine UNIX, à savoir le Virtual File System (VFS) Informations, qui contient les informations manquantes jusqu'à présent pour relier l'inode à partir du chemin du processus. Il peut déjà être interrogé à l'aide de l'outil ss de iproute2 commençant par la version 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:

Le numéro de périphérique et le chemin d'accès Vous pouvez obtenir de

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

ss prend également en charge le filtrage:

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

mais sachez que cela pourrait ne pas énumérer la bonne prise pour vous, en tant que Evil Processus Pourriez renommer votre prise d'origine et remplacez-la avec son propre Evil One:

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

lsof /tmp/socket, fuser /tmp/socket et ss --processes --unix --all --extended 'sport = /tmp/socket' répertoriera tous le processus d'origine non le remplacement diabolique. Utilisez plutôt quelque chose comme ça:

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

Ou écrivez votre propre programme LITTE basé sur le modèle contenu dans Man 7 sock_diag .

3
pmhahn

4.89 de LSOF Prises en charge Affichage des options de terminaison.

Cité de 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.

Exemple de sortie:

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
Masatake YAMATO