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 parentque 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 parentes, pero quiero averiguar quién child1es. ¿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 prognamelsof -c parent -c child1ls -l /proc/$(pidof server)/fdcat /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 elsocketpairmétodo específico del tipo . Para los sockets de Unix, estáunix_socketpairen `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_DIAGcaracterí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 .lsofdesde 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
Xorgen cada extremo en un formato similar a:Si su versión de
lsofes demasiado antigua, hay algunas opciones más.La
ssutilidad (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-popción puede decirle qué proceso (s) tiene ese zócalo abierto. Lo hace haciendo algunosreadlinks 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
lsofpara 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/unixarchivo 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_restrictparámetro sysctl) como ya lo explicó @Totor contiene la dirección del núcleo de unaunix_sockestructura que contiene unpeercampo que apunta al par correspondienteunix_sock. También es lo quelsofgenera laDEVICEcolumna en un socket Unix.Ahora obtener el valor de ese
peercampo significa poder leer la memoria del kernel y conocer el desplazamiento de esepeercampo con respecto a launix_sockdirección.Ya se han dado varias soluciones
gdbbasadas ysystemtapbasadas , pero requierengdb/systemtapy 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
lsofautor.ssno hacer esto? Es un poco por encima de mi cabeza, peross -pxlas 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* 15068y los títulos de las columnas son ...State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Portlsof -c terminology, puedo ver,terminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAMpero 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
Peercolumna una ID (número de inodo) que corresponde a otra ID en laLocalcolumna. Las ID coincidentes son los dos extremos de un zócalo.Nota: La
UNIX_DIAGopció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_sockestructura del núcleo correspondiente , con unpeeratributo que es la dirección del otro extremo del socket (también unaunix_sockinstancia de estructura).Ahora podemos usar
gdbpara encontrar lapeermemoria interna del kernel:Aquí tienes, el otro extremo del zócalo está sujeto
mysql, PID 14815.Su núcleo debe estar compilado
KCORE_ELFpara 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-dbgproporcionará 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
gdbel desplazamiento de memoria para acceder "manualmente" alpeervalor. 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_restrictpará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á ejecutarlsofcomo 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 hacelsoffrente a espacios en blanco o dos puntos).systemtapaquí se usa para volcar la dirección y la dirección de igual de todas lasunix_sockestructuras en elunix_socket_tablehash 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?@varse 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 lassherramienta 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
ssTambié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/socketyss --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