¿Por qué la longitud de la ruta del socket está limitada a cien caracteres?

18

En los sistemas Unix, los nombres de ruta generalmente no tienen limitación de longitud (bueno, 4096 caracteres en Linux) ... excepto las rutas de archivos de socket que están limitadas a alrededor de 100 caracteres (107 caracteres en Linux ).

  • Primera pregunta: ¿por qué una limitación tan baja?

He comprobado que parece posible solucionar esta limitación cambiando el directorio de trabajo actual y creando en varios directorios varios archivos de socket, todos con la misma ruta ./myfile.sock: las aplicaciones cliente parecen conectarse correctamente a los procesos esperados del servidor, aunque lsofmuestra todo de ellos escuchando en la misma ruta del archivo socket.

  • ¿Es confiable esta solución o simplemente tuve suerte?
  • ¿Es este comportamiento específico de Linux o esta solución puede aplicarse también a otros Unixes?
WhiteWinterWolf
fuente
El límite es aún más bajo (104) en los sistemas actuales de OpenBSD o Mac OS X 10.11.
2017
Lo importante es que tiene que ser inferior a 108, en aras de la compatibilidad :)
AFAIK son 108 caracteres en Linux. Verifique /usr/include/$arch-linux-gnu/sys/un.h en su máquina.
schaiba
@schaiba: 108 bytes, lo que significa una cadena de 107 caracteres terminada por un terminador nulo.
WhiteWinterWolf

Respuestas:

18

Compatibilidad con otras plataformas, o compatibilidad con cosas más antiguas para evitar desbordamientos al usar snprintf()y strncpy().

Michael Kerrisk explica en su libro en la página 1165 - Capítulo 57, Sockets: dominio Unix:

SUSv3 no especifica el tamaño del campo sun_path. Las primeras implementaciones de BSD usaban 108 y 104 bytes, y una implementación contemporánea (HP-UX 11) usa 92 bytes. Las aplicaciones portátiles deben codificar a este valor inferior y usar snprintf () o strncpy () para evitar desbordamientos del búfer al escribir en este campo.

Los chicos de Docker incluso se burlaron de él, porque algunos sockets tenían 110 caracteres de longitud:

Es por eso que LINUX usa un zócalo de 108 caracteres. ¿Podría esto ser cambiado? Por supuesto. Y esta es la razón por la cual, en primer lugar, esta limitación se creó en sistemas operativos más antiguos:

Citando la respuesta:

Era hacer coincidir el espacio disponible en una práctica estructura de datos del núcleo.

Citando "El diseño e implementación del sistema operativo 4.4BSD" por McKusick et. Alabama. (página 369):

Las instalaciones de administración de memoria giran en torno a una estructura de datos llamada mbuf. Mbufs, o memorias intermedias, tienen 128 bytes de longitud, con 100 o 108 bytes de este espacio reservado para el almacenamiento de datos.

Otros sistemas operativos (sockets de dominio unix):


fuente
1
SUSv3 XNET guardó silencio porque no hubo consenso sobre el tema.
fpmurphy
¿Tienes algún enlace para probar tu punto de vista?
Gracias por esta respuesta ¿Es confiable usar varios archivos de socket con nombres idénticos en relación con diferentes directorios de trabajo (por ejemplo, crear un archivo de socket llamado ./my.socketdirectorio debajo A/y otro archivo de socket también llamado ./my.socketdirectorio debajo B/)? lsofno hace ninguna distinción entre los dos archivos de socket, sin embargo, todavía parece funcionar, pero me pregunto si esto es solo porque tengo suerte. Esta sería una buena solución para crear archivos de socket debajo de una ruta que ya es más larga que el tamaño permitido.
WhiteWinterWolf
La búsqueda de sockets de Unix en mi servidor de correo parece traer el nombre completo de la ruta: lsof -U| grep amavis(nueva línea)amavis-se 2708 zimbra 17u unix 0xffff8806c0a95400 0t0 310330411 /opt/zimbra/data/tmp/amavisd-zmq.sock
Sí, sé que esto es inusual, de ahí mi pregunta aquí;)! Por lo que probé, los nombres relativos funcionan, pero todavía me parece extraño ... pero funciona. Mi aplicación no es de todo el sistema, por lo que los archivos de socket se almacenan con todos los demás datos de la aplicación en una ubicación controlada por el usuario, lo cual es muy preferido pero con una ruta potencialmente demasiado larga, o puedo saturar /tmpcon toneladas de directorios no eliminados con nombres únicos cada uno que contiene un archivo de socket único (completamente feo, pero portátil y seguro).
WhiteWinterWolf
5

En cuanto al por qué, nwildner ya escribió una excelente respuesta .

Aquí solo me enfocaré en el cómo y el uso relativo de la ruta.

Internamente, aunque el archivo de socket también se puede buscar por nombre (supongo), generalmente se buscan por inodo. En Linux, esta búsqueda está garantizada por la función unix_find_socket_byinode()definida en net / unix / af_unix.c .

Esto se puede verificar fácilmente de la siguiente manera:

  • Cree dos directorios A / y B / .
  • Debajo de cada directorio, haga que un proceso escuche en archivos de socket con el mismo nombre. Con socatusted usaría un comando como:
$ socat UNIX-LISTEN:./my.sock -
  • Ahora intercambie los archivos del socket moviendo A / my.sock a B / y viceversa.
  • De ahora en adelante, si la aplicación del cliente se conecta a A / my.sock, se pondrá en contacto con el servidor B , y si se conecta a B / my.sock, se pondrá en contacto con el servidor A (tenga en cuenta que cuando finalice la comunicación, el proceso del servidor puede elimina legítimamente lo que cree que es su propio archivo de socket).

Verifiqué este comportamiento en un puñado de sistemas Unix (Linux Debian, FreeBSD y OpenIndiana para obtener cierta diversidad), por lo que este comportamiento parece ser al menos generalizado, si no estándar.

Las rutas absolutas generalmente se utilizan como una convención entre los procesos del cliente y el servidor, ya que el proceso del cliente no sabe de otra manera cómo establecer la comunicación inicial con el servidor.

Sin embargo, si esta comunicación inicial no es un problema, parece seguro usar rutas relativas para la creación de archivos de socket, lo que permite evitar problemas de longitud de ruta cuando la ubicación del archivo de socket no está directamente controlada por el proceso del servidor.

WhiteWinterWolf
fuente