Quiero determinar qué proceso tiene el otro extremo de un socket UNIX.
Específicamente, estoy preguntando acerca de uno que fue creado con socketpair()
, aunque el problema es el mismo para cualquier socket UNIX.
Tengo un programa parent
que crea un socketpair(AF_UNIX, SOCK_STREAM, 0, fds)
, y fork()
s. El proceso principal se cierra fds[1]
y se mantiene fds[0]
para comunicarse. El niño hace lo contrario, close(fds[0]); s=fds[1]
. Entonces el niño exec()
es otro programa child1
,. Los dos pueden comunicarse de ida y vuelta a través de este socketpair.
Ahora, digamos que sé quién parent
es, pero quiero averiguar quién child1
es. ¿Cómo hago esto?
Hay varias herramientas a mi disposición, pero ninguna puede decirme qué proceso está en el otro extremo del zócalo. Yo he tratado:
lsof -c progname
lsof -c parent -c child1
ls -l /proc/$(pidof server)/fd
cat /proc/net/unix
Básicamente, puedo ver los dos enchufes, y todo sobre ellos, pero no puedo decir que están conectados. Estoy tratando de determinar qué FD en el padre se está comunicando con qué proceso hijo.
fuente
socketpair
, y los dos extremos del zócalo no están correlacionados, excepto por elsocketpair
método específico del tipo . Para los sockets de Unix, estáunix_socketpair
en `net / unix / af_unix.c . Sería bueno tener esta información también para las tuberías.Linux-3.3 y superior.
En Linux, desde la versión 3.3 del kernel (y siempre que la
UNIX_DIAG
característica esté integrada en el kernel), el par de un socket de dominio unix dado (incluye pares de socket) se puede obtener utilizando una nueva API basada en netlink .lsof
desde la versión 4.89 puede hacer uso de esa API:Enumerará todos los sockets de dominio de Unix que tienen un proceso cuyo nombre comienza
Xorg
en cada extremo en un formato similar a:Si su versión de
lsof
es demasiado antigua, hay algunas opciones más.La
ss
utilidad (fromiproute2
) utiliza esa misma API para recuperar y mostrar información en la lista de sockets de dominio Unix en el sistema, incluida la información de pares.Los enchufes se identifican por su número de inodo . Tenga en cuenta que no está relacionado con el inodo del sistema de archivos del archivo socket.
Por ejemplo en:
dice que el zócalo 3435997 (que estaba vinculado al zócalo ABSTRACT
/tmp/.X11-unix/X0
) está conectado con el zócalo 3435996. La-p
opción puede decirle qué proceso (s) tiene ese zócalo abierto. Lo hace haciendo algunosreadlink
s on/proc/$pid/fd/*
, por lo que solo puede hacerlo en los procesos que posee (a menos que searoot
). Por ejemplo aquí:Para averiguar qué proceso (s) tiene 3435996, puede buscar su propia entrada en la salida de
ss -xp
:También puede usar este script como envoltorio
lsof
para mostrar fácilmente la información relevante allí:Por ejemplo:
Antes de linux-3.3
La antigua API de Linux para recuperar información de socket de Unix es a través del
/proc/net/unix
archivo de texto. Enumera todos los sockets de dominio de Unix (incluidos los pares de sockets). El primer campo allí (si no está oculto para los no superusuarios con elkernel.kptr_restrict
parámetro sysctl) como ya lo explicó @Totor contiene la dirección del núcleo de unaunix_sock
estructura que contiene unpeer
campo que apunta al par correspondienteunix_sock
. También es lo quelsof
genera laDEVICE
columna en un socket Unix.Ahora obtener el valor de ese
peer
campo significa poder leer la memoria del kernel y conocer el desplazamiento de esepeer
campo con respecto a launix_sock
dirección.Ya se han dado varias soluciones
gdb
basadas ysystemtap
basadas , pero requierengdb
/systemtap
y símbolos de depuración del kernel de Linux para la instalación del kernel en ejecución, lo que generalmente no es el caso en los sistemas de producción.Codificar el desplazamiento no es realmente una opción, ya que varía con la versión del kernel.
Ahora podemos usar un enfoque heurístico para determinar el desplazamiento: haga que nuestra herramienta cree un maniquí
socketpair
(entonces conocemos la dirección de ambos pares) y busque la dirección del par alrededor de la memoria en el otro extremo para determinar el desplazamiento.Aquí hay un script de prueba de concepto que hace exactamente eso usando
perl
(probado con éxito con el kernel 2.4.27 y 2.6.32 en i386 y 3.13 y 3.16 en amd64). Al igual que arriba, funciona como un envoltorio alrededor delsof
:Por ejemplo:
Aquí está el guión:
fuente
lsof
autor.ss
no hacer esto? Es un poco por encima de mi cabeza, peross -px
las listas de una gran cantidad de conectores Unix con la información de pares como: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
y los títulos de las columnas son ...State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
lsof -c terminology
, puedo ver,terminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAM
pero si lo hagoss -px | grep terminology
, obtengo:u_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
Erkki Seppala en realidad tiene una herramienta que recupera esta información del kernel de Linux con gdb. Está disponible aquí .
fuente
Desde el kernel 3.3
Usted puede ahora obtener esta información con
ss
:Ahora puede ver en la
Peer
columna una ID (número de inodo) que corresponde a otra ID en laLocal
columna. Las ID coincidentes son los dos extremos de un zócalo.Nota: La
UNIX_DIAG
opción debe estar habilitada en su kernel.Antes del kernel 3.3
Linux no expuso esta información a la tierra de usuarios.
Sin embargo, al examinar la memoria del núcleo , podemos acceder a esta información.
Nota: Esta respuesta lo hace utilizando
gdb
, sin embargo, consulte la respuesta de @ StéphaneChazelas, que es más elaborada a este respecto.Hay 2 enchufes diferentes, 1 escucha y 1 establecido. El número hexa es la dirección de la
unix_sock
estructura del núcleo correspondiente , con unpeer
atributo que es la dirección del otro extremo del socket (también unaunix_sock
instancia de estructura).Ahora podemos usar
gdb
para encontrar lapeer
memoria interna del kernel:Aquí tienes, el otro extremo del zócalo está sujeto
mysql
, PID 14815.Su núcleo debe estar compilado
KCORE_ELF
para poder usarlo/proc/kcore
. Además, necesita una versión de su imagen del núcleo con símbolos de depuración. En Debian 7,apt-get install linux-image-3.2.0-4-amd64-dbg
proporcionará este archivo.No se necesita la imagen del núcleo depurable ...
Si no tiene (o no desea conservar) la imagen del núcleo de depuración en el sistema, puede asignar
gdb
el desplazamiento de memoria para acceder "manualmente" alpeer
valor. Este valor de compensación generalmente difiere con la versión o arquitectura del kernel.En mi kernel, sé que el desplazamiento es de 680 bytes, es decir, 85 veces 64 bits. Entonces puedo hacer:
Voilà, mismo resultado que el anterior.
Si tiene el mismo núcleo ejecutándose en varias máquinas, es más fácil usar esta variante porque no necesita la imagen de depuración, solo el valor de compensación.
Para descubrir (fácilmente) este valor de compensación al principio, necesita la imagen de depuración:
Aquí tienes, 680 bytes, esto es 85 x 64 bits, o 170 x 32 bits.
La mayor parte del crédito por esta respuesta va a MvG .
fuente
Si se encuentra en un sistema Linux reciente con una pestaña de sistema en funcionamiento (1.8 o más reciente), puede usar el siguiente script para procesar la salida de
lsof
:Por ejemplo:
(si ve 0x0000000000000000 arriba en lugar de 0xffff ..., es porque el
kernel.kptr_restrict
parámetro sysctl está configurado en su sistema lo que hace que los punteros del kernel se oculten de los procesos no privilegiados, en cuyo caso deberá ejecutarlsof
como root para obtener un resultado significativo).Este script no intenta hacer frente a los nombres de archivos de socket con caracteres de nueva línea, pero tampoco lo hace
lsof
(ni hacelsof
frente a espacios en blanco o dos puntos).systemtap
aquí se usa para volcar la dirección y la dirección de igual de todas lasunix_sock
estructuras en elunix_socket_table
hash en el kernel.Solo probado en Linux 3.16 amd64 con systemtap 2.6 y 3.13 con 2.3.
fuente
parse error: unknown statistic operator @var
: ¿Me estoy perdiendo de algo?@var
se agregó en systemtap 1.8, 2012-06-17 (la última es 2.7)4.89 de lsof admite la visualización de opciones de punto final.
Citado de lsof.8:
Ejemplo de salida:
fuente
Desde Linux kernel 4.2 existe
CONFIG_UNIX_DIAG
, que proporciona información adicional sobre los sockets de dominio UNIX, es decir, la informaciónVirtual File System
(VFS), que contiene la información que falta hasta ahora para vincular el Inode desde la ruta al proceso. Ya se puede consultar con lass
herramienta de iproute2 a partir de la versión v4.19.0 ~ 55 :El número de dispositivo y la ruta Inode que puede obtener de
ss
También es compatible con el filtrado:pero tenga en cuenta que esto podría no enumerar el zócalo adecuado para usted, ya que un proceso malvado podría cambiar el nombre de su zócalo original y reemplazarlo por el propio malvado:
lsof /tmp/socket
,fuser /tmp/socket
yss --processes --unix --all --extended 'sport = /tmp/socket'
todos enumerarán el proceso original, no el malvado reemplazo. En cambio, use algo como esto:O escriba su propio pequeño programa basado en la plantilla contenida en man 7 sock_diag .
fuente