Warum ist die Socket-Pfadlänge auf 100 Zeichen begrenzt?

18

Auf Unix-Systemen gibt es für Pfadnamen in der Regel praktisch keine Längenbeschränkung (also 4096 Zeichen unter Linux) ... außer für Socket-Dateipfade, die auf ungefähr 100 Zeichen begrenzt sind (107 Zeichen unter Linux ).

  • Erste Frage: Warum so eine geringe Einschränkung?

Ich habe überprüft, ob es möglich zu sein scheint, diese Einschränkung zu umgehen, indem ich das aktuelle Arbeitsverzeichnis ändere und in verschiedenen Verzeichnissen mehrere Socket-Dateien mit demselben Pfad erstelle ./myfile.sock: Die Client-Anwendungen scheinen sich korrekt mit den erwarteten Server-Prozessen zu verbinden, obwohl lsofalle angezeigt werden von ihnen hören auf dem gleichen Socket-Dateipfad.

  • Ist diese Problemumgehung zuverlässig oder hatte ich nur Glück?
  • Ist dieses Verhalten für Linux spezifisch oder kann diese Problemumgehung auch für andere Unixe angewendet werden?
WhiteWinterWolf
quelle
Das Limit ist auf aktuellen OpenBSD-Systemen oder Mac OS X 10.11 sogar noch niedriger (104).
thrig
Das Wichtigste ist, dass es aus Kompatibilitätsgründen niedriger als 108 sein muss :)
AFAIK unter Linux sind es 108 Zeichen. Bitte überprüfen Sie /usr/include/$arch-linux-gnu/sys/un.h auf Ihrem Computer.
Schaiba
@schaiba: 108 Byte, dh eine Zeichenfolge mit 107 Zeichen, die mit einem Nullterminator abgeschlossen wird.
WhiteWinterWolf

Antworten:

18

Kompatibilität mit anderen Plattformen oder Kompatibilität mit älteren Produkten, um Überläufe bei der Verwendung von snprintf()und zu vermeiden strncpy().

Michael Kerrisk erklärt in seinem Buch auf der Seite 1165 - Kapitel 57, Sockets: Unix-Domain:

SUSv3 gibt die Größe des sun_path-Felds nicht an. Frühe BSD-Implementierungen verwendeten 108 und 104 Bytes, und eine aktuelle Implementierung (HP-UX 11) verwendet 92 Bytes. Tragbare Anwendungen sollten auf diesen niedrigeren Wert codieren und snprintf () oder strncpy () verwenden, um Pufferüberläufe beim Schreiben in dieses Feld zu vermeiden.

Die Jungs von Docker haben sich sogar darüber lustig gemacht, weil einige Sockets 110 Zeichen lang waren:

Aus diesem Grund verwendet LINUX eine 108-Zeichen-Buchse. Könnte dies geändert werden? Na sicher. Und das ist der Grund, warum in erster Linie diese Einschränkung auf älteren Betriebssystemen erstellt wurde:

Zitiere die Antwort:

Es sollte dem verfügbaren Speicherplatz in einer praktischen Kernel-Datenstruktur entsprechen.

Zitat "Das Design und die Implementierung des 4.4BSD-Betriebssystems" von McKusick et. al. (Seite 369):

Die Speicherverwaltungseinrichtungen drehen sich um eine Datenstruktur, die als mbuf bezeichnet wird. Mbufs oder Speicherpuffer sind 128 Byte lang, wobei 100 oder 108 Byte dieses Speicherplatzes für die Datenspeicherung reserviert sind.

Andere Betriebssysteme (Unix-Domain-Sockets):


quelle
1
SUSv3 XNET schwieg, weil es zu diesem Thema keinen Konsens gab.
fpmurphy
Haben Sie einen Link, der Ihre Sichtweise bestätigt?
Danke für diese Antwort. Ist es zuverlässig mehr Socket - Dateien tragen identische Namen in Bezug auf unterschiedliche Arbeitsverzeichnisse zu verwenden (zum Beispiel eine Datei mit dem Namen Sockets erstellen ./my.socketunter Verzeichnis A/, und eine andere Socket - Datei auch genannt ./my.socketunten Verzeichnis B/)? lsofmacht keinen Unterschied zwischen den beiden Socket-Dateien, aber es scheint immer noch zu funktionieren, aber ich frage mich, ob das nur so ist, weil ich Glück habe. Dies ist eine gute Lösung, um Socket-Dateien unter einem Pfad zu erstellen, der bereits länger als die zulässige Größe ist.
WhiteWinterWolf
Die Suche nach Unix-Sockets auf meinem Mailserver scheint den vollständigen Pfadnamen zu lsof -U| grep amavisliefern : (newline)amavis-se 2708 zimbra 17u unix 0xffff8806c0a95400 0t0 310330411 /opt/zimbra/data/tmp/amavisd-zmq.sock
Ja, ich weiß, dass dies ungewöhnlich ist, daher meine Frage hier;)! Für das, was ich getestet habe, funktionieren relative Namen, aber es scheint mir immer noch seltsam ... aber es funktioniert. Meine Anwendung ist nicht systemweit, daher werden Socket-Dateien entweder mit allen anderen Anwendungsdaten an einem benutzergesteuerten Ort gespeichert, der stark bevorzugt wird, aber möglicherweise einen zu langen Pfad aufweist, oder ich kann /tmpmit Tonnen von eindeutig benannten, nicht gelöschten Verzeichnissen überhäufen mit einer einzigen Socket-Datei (absolut hässlich, aber portabel und sicher).
WhiteWinterWolf
5

In Bezug auf das Warum hat nwildner bereits eine hervorragende Antwort geschrieben .

Hier werde ich mich nur auf das Wie und die relative Pfadnutzung konzentrieren.

Intern kann die Socket-Datei zwar auch nach Namen gesucht werden (glaube ich), sie wird jedoch normalerweise nach Inode gesucht. Unter Linux wird diese Suche durch die unix_find_socket_byinode()in net / unix / af_unix.c definierte Funktion sichergestellt .

Dies kann leicht wie folgt überprüft werden:

  • Erstellen Sie zwei Verzeichnisse A / und B / .
  • Lassen Sie unter jedem Verzeichnis einen Prozess Socket-Dateien mit demselben Namen abhören. Mit socatwürden Sie einen Befehl verwenden wie:
$ socat UNIX-LISTEN:./my.sock -
  • Tauschen Sie nun die Socket-Dateien aus, indem Sie A / my.sock nach B / verschieben und umgekehrt.
  • Von nun an, wenn die Client - Anwendung eine Verbindung herstellt zu A / my.sock wird es den Server kontaktieren Sie B , und wenn es eine Verbindung herstellt B / my.sock wird es den Server kontaktieren A (Hinweis aber , dass , wenn die Kommunikation endet, wird der Server - Prozess kann legitimerweise löschen (was es für eine eigene Socket-Datei hält).

Ich habe dieses Verhalten auf einer Handvoll von Unix-Systemen (Linux Debian, FreeBSD und OpenIndiana, um eine gewisse Diversität zu erzielen) überprüft, so dass dieses Verhalten zumindest weit verbreitet zu sein scheint, wenn nicht sogar Standard.

Absolute Pfade werden normalerweise als Konvention zwischen den Client- und Serverprozessen verwendet, da der Clientprozess sonst möglicherweise nicht weiß, wie die anfängliche Kommunikation mit dem Server hergestellt wird.

Wenn diese anfängliche Kommunikation jedoch kein Problem darstellt, ist es anscheinend sicher, relative Pfade für die Erstellung von Socket-Dateien zu verwenden, um Probleme mit der Pfadlänge zu vermeiden, wenn der Speicherort der Socket-Datei nicht direkt vom Serverprozess gesteuert wird.

WhiteWinterWolf
quelle