Unix-Domänen-Sockets für Nicht-Root-Benutzer

Unix-Domänen-Sockets für Nicht-Root-Benutzer

Ich arbeite an einer Anwendung, die Unix Domain Socket für IPC verwendet. Die übliche Methode besteht meines Wissens darin, die Socket-Datei in zu platzieren /var/run. Ich arbeite mit Ubuntu 18.04 und sehe, dass dies var/runein symbolischer Link für ist /run. Leider ist der Ordner nur für folgendes zugänglich root:

  ls -Al /
  drwxr-xr-x  27 root root        800 Apr 12 17:39 run

Daher hat nur Root Schreibzugriff auf diesen Ordner, was die Verwendung von Unix-Domain-Sockets für normale Benutzer unmöglich macht.

Zunächst einmal verstehe ich nicht, warum. Und wie verwendet man Unix-Domain-Sockets für Nicht-Root-Benutzer? Ich kann natürlich den Home-Ordner verwenden, aber ich bevorzuge eine korrekte und gängige Methode.

Antwort1

Es ist nichts falsch daran, den Socket in einer Dotfile oder einem Dotdir im Home-Verzeichnis des Benutzers zu erstellen, sofern es sich bei dem Benutzer nicht um einen speziellen Systembenutzer handelt. Das einzige Problem wäre, wenn das Home-Verzeichnis von mehreren Rechnern über NFS gemeinsam genutzt würde, aber das ließe sich leicht umgehen, indem man den Hostnamen in den Namen des Sockets einbezieht.


Unter Linux/Ubuntu können Sie auch"abstrakt"Unix-Domain-Sockets, die keinen Pfad oder Inode im Dateisystem verwenden. Abstrakte Unix-Sockets sind solche, deren Adresse/Pfad mit einem NUL-Byte beginnt:

abstrakt: Eine abstrakte Socket-Adresse wird (von einem Pfadnamen-Socket) dadurch unterschieden, dass es sun_path[0]sich um ein Null-Byte ( \0) handelt.

Die Adresse des Sockets in diesem Namespace ergibt sich aus den zusätzlichen Bytes in , sun_pathdie durch die angegebene Länge der Adressstruktur abgedeckt werden. (Nullbytes im Namen haben keine besondere Bedeutung.) Der Name hat keinen Bezug zu Dateisystempfadnamen. Wenn die Adresse eines abstrakten Sockets zurückgegeben wird, addrlen ist der zurückgegebene Wert größer als sizeof(sa_family_t)(d. h. größer als 2) und der Name des Sockets ist in den ersten (addrlen - sizeof(sa_family_t))Bytes von enthalten sun_path.

Bei der Anzeige für den Benutzer oder bei der Eingabe durch den Benutzer werden die NUL-Bytes in einer abstrakten Unix-Socket-Adresse normalerweise durch @s ersetzt. Viele Programme machen das schrecklich falsch, da sie reguläre s in keiner Weise umgehen @und/oder davon ausgehen, dass nur das erste Byte NUL sein kann.

Im Gegensatz zu regulären Unix-Socket-Pfaden haben abstrakte Unix-Socket-Namen eine andere Semantik, da sich jeder an sie binden kann (sofern der Name nicht bereits vergeben ist) und jeder eine Verbindung zu ihnen herstellen kann.

Anstatt sich darauf zu verlassen, dass die Datei-/Verzeichnisberechtigung einschränkt, wer eine Verbindung zu Ihrem Socket herstellen kann, und anzunehmen, dass z. B. nur Root Sockets in einem Verzeichnis erstellen kann, sollten Sie die Anmeldeinformationen des Peers prüfen getsockopt(SO_PEERCRED)(um die UID/PID desjenigen zu erhalten, der die Verbindung zum Peer hergestellt oder ihn gebunden hat) oder die SCM_CREDENTIALSZusatznachricht (um die UID/PID desjenigen zu erhalten, der eine Nachricht über den Socket gesendet hat).

Dies (das Ersetzen der üblichen Dateiberechtigungsprüfungen) ist meiner Meinung nach auch die einzig sinnvolle Verwendung von SO_PEERCRED/ SCM_CREDENTIALS.

Antwort2

Ihr Unix-Domain-Socket sollte nicht direkt in gehen /run, Sie müssen darin einen Ordner erstellen /run, beispielsweise /run/my-ipcmit den entsprechenden Rechten für Ihren Benutzer, und dann in diesen Ordner schreiben.

Der Ordner muss beim Booten neu erstellt werden. Die akzeptierte Antwort fürdiese Frageerklärt einige Alternativen.

verwandte Informationen