Ich möchte einen Dateideskriptor duplizieren, der in einem nicht verwandten Prozess unter Linux ausgeführt wird. Ich weiß übersendmsg(2)und SCM_RIGHTS
(zBhttps://stackoverflow.com/questions/4489433/sending-file-descriptor-over-unix-domain-socket-and-select), aber das funktioniert nur, wenn der andere Prozess kooperiert. Ich brauche eine Lösung, die keine aktive Kooperation des anderen Prozesses erfordert. Ich weiß auch, dass ich zuerst den Dateideskriptor erstellen, eine Kopie aufbewahren und dann den anderen Prozess erstellen könnte, aber ich brauche eine Lösung, bei der der andere Prozess seinen eigenen Dateideskriptor erstellt.
Ich kann den Dateideskriptor sehen:
$ ls -l /proc/13115/fd/3
lrwx------ 1 pts pts 64 2013-05-04 13:15 /proc/13115/fd/3 -> socket:[19445454]
Wird jedoch open("/proc/13115/fd/3", O_RDWR)
in einem anderen Prozess ausgeführt, wird der Fehler zurückgegeben.Kein solches Gerät oder keine solche Adresse. Gibt es etwas anderes, das funktionieren würde? Wahrscheinlich mitptrace?
Antwort1
Dies ist beabsichtigt: Die gemeinsame Nutzung von Dateideskriptoren mit anderen Prozessen ist explizit. Standardmäßig sind Dateideskriptoren so privat wie der eigene Speicher des Prozesses.
Wie üblich, wenn Sie das Recht haben,ptraceSie können mit dem Prozess alles machen, was Sie möchten, einschließlich des Aufrufs sendmsg
. Traditionell ptrace
muss der Aufruf mit derselben Benutzer-ID ausgeführt werden; Sicherheitsbeschränkungen wie SELinux, Fähigkeiten, Jails usw. können ptrace
noch restriktiver sein. Beispielsweise kann ein Nicht-Root-Prozess unter der Standardkonfiguration von Ubuntu nur ptrace
seine eigenen Nachkommen aufrufen (über AppArmor).
Die robuste Verwendung ptrace
ist etwas knifflig: Sie müssen die richtigen Daten einfügen, darauf achten, nichts zu überschreiben, und hinterher aufräumen. Daher empfehle ich, den Code auf Umwegen einzufügen und diesen Code mit einem vorhandenen Tool auszulösen.
Schreiben Sie eine kleine gemeinsame Bibliothek mit dem sendmsg
Code und LD_PRELOAD
übertragen Sie ihn in den anderen Prozess. Hier sind einigeungetestetSkelettcode mit fehlender Fehlerprüfung.
int pts_gift_fd (char *path, int fd) {
int sock;
struct sockaddr_un addr = {0};
struct msghdr msg = {0};
struct iovec iov = {0};
addr.sun_family = AF_UNIX;
strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
/* Populate msg, iov as in the code you've already found */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
connect(sock, (struct sockaddr*)&addr, sizeof(addr));
sendmsg(sock, &msg, 0);
close(sock);
}
Um den Code dann auszulösen, führen Sie ihn gdb -n -pid 13115 -batch -x /dev/stdin
mit aus popen
und geben Sie ihm Eingaben wie diese (wobei %d
das FD ist, das Sie abrufen möchten, und %s
ein Pfad zu einem Unix-Socket ist, den Sie zuvor erstellt haben und auf dem Sie lauschen):
call pts_gift_fd("%s", %d)
detach
quit
Antwort2
Dies ist aus demselben Grund nicht möglich, aus dem Sie nicht auf den Speicher eines nicht verwandten Prozesses zugreifen können, da ein DateideskriptorIstTeil des Speichers eines anderen Prozesses. Der einzige Grund, warum Informationen über solche Dinge vorhanden sind, /proc
ist, dass der Kernel sie dort bereitstellt und sie schreibgeschützt sind (es gibt also Möglichkeiten, sie zu untersuchen).eine Kopiedes Prozessspeichers).
Wenn es sich um eine Datei handelt, können Sie natürlich versuchen, auf die Datei zuzugreifen. Wenn es sich um einen Socket handelt, können Sie ihn mit folgendem Befehl ausspionieren:libpcapoder etwas, das davon abgeleitet ist.
Die Situation ist im Grunde folgende: Ein Dateideskriptor ist (wieder) Teil des Speichers eines Prozesses. Der Deskriptor hat einen zugrunde liegenden Puffer, der im Kernelspeicher vorhanden ist. Wenn der Prozess aus dem Deskriptor liest oder schreibt, schreibt er in diesen Puffer und aus diesem. Für ausgehende Daten leert der Kernel den Puffer (zur Hardware) entsprechend. Für eingehende Daten füllt er den Puffer (von der Hardware) wieder auf, wenn der Prozess ihn leert. Diese Puffer sind meines Wissens nach für andere Prozesse nicht zugänglich, obwohl es einige Möglichkeiten gibt (z. B. libpcap),LektüreDie Daten werden in einer durch die jeweilige Kernelschnittstelle bestimmten Form bereitgestellt, genauso wie die Proc-Schnittstelle einige Daten aus dem Benutzerspeicher des Prozesses bereitstellen kann.