Wie wird readlink () von "/ proc / self / exe" gehandhabt, wenn die ausführbare Datei während der Ausführung ersetzt wird?

8

In meiner C ++ - Anwendung führt meine Anwendung einen execv() in einem fork() ed untergeordneten Prozess aus, um die gleiche ausführbare Datei zu verwenden, um einige Arbeiten in einem neuen untergeordneten Prozess mit verschiedenen Argumenten zu verarbeiten, die mit Pipes zum übergeordneten Prozess kommunizieren. Um den Pfadnamen zu self zu bekommen, führe ich den folgenden Code auf dem Linux-Port aus (ich habe auf Macintosh einen anderen Code):

%Vor%

Wenn jedoch während der Ausführung der ausführbaren Datei die ausführbare Datei durch eine aktualisierte Version der binären Version auf der Festplatte ersetzt wird, lautet das readlink() -Zeichenfolgenergebnis wie folgt: "/usr/local/bin/myExecutable (deleted)"

Ich verstehe, dass meine ausführbare Datei durch eine neuere aktualisierte Version ersetzt wurde und das Original für /proc/self/exe jetzt ersetzt wird. Wenn ich jedoch zu execv() gehe, schlägt es jetzt mit der errno 2 - No such file or directory. fälschlicherweise fehl zu dem zusätzlichen abschließenden " (deleted)" im Ergebnis.

Ich möchte, dass execv() entweder die alte ausführbare Datei für self oder die aktualisierte verwendet. Ich konnte nur die Zeichenfolge erkennen, die mit " (deleted)" endet, und sie so modifizieren, dass sie wegfällt und in die aktualisierte ausführbare Datei aufgelöst wird, aber das erscheint mir plump.

Wie kann ich execv() die aktuelle ausführbare Datei (oder, wenn es einfacher ist, ersetzen) mit einem neuen Satz von Argumenten ersetzen, wenn die ursprüngliche ausführbare Datei während der Ausführung durch eine aktualisierte ersetzt wurde?

    
WilliamKF 09.03.2015, 23:00
quelle

3 Antworten

4

Anstatt readlink zu verwenden, um den Pfad zu Ihrer eigenen ausführbaren Datei zu ermitteln, können Sie direkt open für /proc/self/exe aufrufen. Da der Kernel bereits offene fd für Prozesse hat, die gerade ausgeführt werden, erhalten Sie eine fd, unabhängig davon, ob der Pfad durch eine neue ausführbare Datei ersetzt wurde oder nicht.

Als nächstes können Sie fexecve anstelle von execv verwenden, was einen fd -Parameter anstelle eines filename -Parameters für die ausführbare Datei akzeptiert.

%Vor%

Der obige Code lässt die Fehlerbehandlung aus Platzgründen aus.

    
andrewrk 17.08.2016, 15:52
quelle
2

Eine Lösung ist beim ausführbaren Start (z. B. nahe dem Anfang von main() ), um den Wert des Links /proc/self/exe einmal zu lesen und ihn für die zukünftige Verwendung statisch zu speichern:

%Vor%

Auf diese Weise ist es sehr unwahrscheinlich, dass die ursprüngliche ausführbare Datei innerhalb der Mikrosekunden von main () ersetzt wird, die den Pfad zu ihrer Binärdatei zwischenspeichert. So könnte eine lange laufende Anwendung (z. B. Stunden oder Tage) auf der Festplatte ersetzt werden, aber nach der ursprünglichen Frage könnte es fork() und execv() zu der aktualisierten Binärdatei, die möglicherweise einen Bugfix hat. Dies hat den zusätzlichen Vorteil, plattformübergreifend zu arbeiten, und somit könnte auch der abweichende Macintosh-Code zum Lesen des Binärpfades ebenfalls geschützt werden Binäraustausch nach dem Start.

WARNUNG Editoren beachten: readlink beendet die Zeichenfolge nicht null, daher kann das obige Programm möglicherweise nicht versehentlich funktionieren oder nicht, wenn der Puffer vor dem Aufruf von readlink

    
WilliamKF 12.03.2015 02:36
quelle
1

Der Grund dafür, dass Sie das (deleted) -Teil in den symbolischen Link eingefügt haben, ist, dass Sie die Datei mit dem richtigen Programmbinärtext durch eine andere Datei ersetzt haben und der symbolische Link zur ausführbaren Datei nie wieder gültig ist. Angenommen, Sie verwenden diese symbolische Verknüpfung, um die Symboltabelle dieses Programms zu erhalten oder um einige eingebettete Daten zu laden, und Sie ändern das Programm ... die Tabelle wäre falsch und Sie könnten sogar Ihr Programm zum Absturz bringen. Die ausführbare Datei für das Programm, das Sie ausgeführt haben, ist nicht mehr verfügbar (Sie haben es gelöscht) und das Programm, das Sie an seiner Stelle eingefügt haben, entspricht nicht der Binärdatei, die Sie ausführen.

Wenn Sie aufheben (2) ein Programm ausführen, markiert der Kernel diesen Symlink in /proc , so dass das Programm

kann
  • erkennt, dass die Binärdatei gelöscht wurde und nicht mehr zugänglich ist.
  • Mit
  • können Sie noch einige Informationen des letzten Namens sammeln (anstatt den Symlink aus dem /proc Baum zu löschen)

Sie können nicht in eine Datei schreiben, die vom Kernel ausgeführt wird, aber niemand verhindert, dass Sie diese Datei löschen. Die Datei wird weiterhin im Dateisystem vorhanden sein, solange Sie sie ausführen, aber kein Name zeigt darauf (ihr Speicherplatz wird freigegeben, sobald der Prozess exit (2) ) Der Kernel löscht nicht sein Inhalt, bis die Inode-Zahl im Kernelspeicher auf Null geht, was passiert, wenn alle Verwendungen (Referenzen) zu dieser Datei fällig sind.

    
Luis Colorado 11.03.2015 14:02
quelle

Tags und Links