PTRACE(2)

BEZEICHNUNG
ptrace - Prozessverfolgung

ÜBERSICHT
#include <sys/ptrace.h>

long ptrace(enum __ptrace_request abfrage, pid_t pid,
            void *adresse, void *daten);

BESCHREIBUNG
Der Systemaufruf ptrace() stellt ein Mittel bereit, wodurch ein Elternprozess die Ausführung eines anderen Prozesses beobachten und steuern kann und sein Kernel-Abbild sowie die Register untersuchen und ändern kann. Er wird in erster Linie benutzt, um Fehlersuche mittels Haltepunkten zu implementieren und Systemaufrufe zu verfolgen.

Der Elternprozess kann eine Verfolgung mittels fork(2) starten und als Ergebnis einen Kindprozess erhalten, der PTRACE_TRACEME ausführt, was (üblicherweise) von einem exec(3) gefolgt wird. Alternativ kann der Elternprozess die Verfolgung eines existierenden Prozesses mittels PTRACE_ATTACH beginnen.

Während der Kindprozess verfolgt wird, wird er jedesmal stoppen, wenn ein Signal gesandt wird, sogar wenn das Signal ignoriert wird. (Eine Ausnahme ist SIGKILL, das seine normale Wirkung erzielt.) Der Elternprozess wird bei seinem nächsten wait(2) benachrichtigt und könnte den Kindprozess prüfen und verändern, während er gestoppt ist. Der Elternprozess veranlasst den Kindprozess anschließend fortzufahren und wahlweise das versandte Signal zu ignorieren (oder stattdessen sogar ein anderes Signal zu senden).

Wenn der Elternprozess die Verfolgung beendet hat, kann der den Kindprozess mit PTRACE_KILL beenden oder ihn mit PTRACE_DETACH veranlassen in einem normalen, nicht verfolgten Modus fortzufahren.

Der Wert des Arguments abfrage legt die Aktion des Systemaufrufs fest:

PTRACE_TRACEME
    zeigt an, dass der Prozess von seinem Elternprozess verfolgt wird. Jedes Signal (außer SIGKILL), das an diesen Prozess gesandt wird, wird ihn stoppen und seinen Elternprozess mittels wait(2) benachrichtigen. Außerdem werden alle nachrangigen Aufrufe von execve(2) durch diesen Prozess bewirken, dass ihm ein SIGTRAP gesandt wird, das es dem Elternprozess ermöglicht, die Kontrolle darüber zu erlangen, bevor das neue Programm ausgeführt wird. Ein Prozess sollte diese Anfrage wahrscheinlich nicht senden, wenn sein Elternprozess nicht erwartet ihn zu verfolgen. (pid, adresse und daten werden ignoriert.)

Die vorhergehende Anfrage wird nur vom Kindprozess benutzt; die übrigen werden nur vom Elternprozess benutzt. In den folgenden Anfragen gibt pid den Kindprozess an, auf den eingewirkt werden soll. Für andere Anfragen als PTRACE_KILL muss der Kindprozess gestoppt werden.

PTRACE_PEEKTEXT, PTRACE_PEEKDATA
    Liest ein »word« an der Stelle adresse im Speicher des Kindprozesses und gibt das »word« als Ergebnis des ptrace()-Aufrufs zurück. Linux hat keine separaten Adressräume für Text und Daten, daher sind die beiden Abfragen derzeit gleichwertig. (Das Argument daten wird ignoriert.)

PTRACE_PEEKUSER
    Liest ein »word« bei Versatz adresse im BENUTZERbereich des Kindprozesses, der die Register und andere Informationen über den Prozess enthält (siehe <sys/user.h>). Das »word« wird als Ergebnis des ptrace()-Aufrufs zurückgegeben. Typischerweise muss der Versatz am »word« ausgerichtet sein, obwohl dies je nach Architektur variieren kann. Lesen Sie die ANMERKUNGEN. (daten wird ignoriert.)

PTRACE_POKETEXT, PTRACE_POKEDATA
    kopiert das »word« daten an die Stelle adresse im Speicher des Kindprozesses. Wie oberhalb sind die beiden Abfragen derzeit gleichwertig.

PTRACE_POKEUSER
    kopiert das »word« daten an den Versatz adresse im BENUTZERbereich des Kindprozesses. Wie oberhalb muss der Versatz am »word« ausgerichtet sein. Um die Integrität des Kernels aufrecht zu erhalten, sind einige Änderungen in BENUTZERbereich nicht erlaubt.

PTRACE_GETREGS, PTRACE_GETFPREGS
    kopiert die Mehrzweck- beziehungsweise Fließpunktregister des Kindprozesses an die Stelle daten im Elternprozess. Lesen Sie <sys/user.h>, um Informationen über das Format dieser Daten zu erhalten. (adresse wird ignoriert.)

PTRACE_GETSIGINFO (seit Linux 2.3.99-pre6)
    ruft Informationen über das Signal ab, das den Stopp verursachte. Kopiert eine siginfo_t-Struktur (siehe sigaction(2)) vom Kindprozess an die Stelle daten im Elternprozess. (adresse wird ignoriert.)

PTRACE_SETREGS, PTRACE_SETFPREGS
    kopiert die Mehrzweck- beziehungsweise Fließpunktregister des Kindprozessesan die Stelle daten im Elternprozess. Wie für PTRACE_POKEUSER könnten einige Änderungen am Mehrzweckregister verboten sein. (adresse wird ignoriert.)

PTRACE_SETSIGINFO (seit Linux 2.3.99-pre6)
    setzt Signalinformationen. Kopiert eine siginfo_t-Struktur von der Stelle daten vom Eltern- zum Kindprozess. Dies wird nur Signale betreffen, die normalerweise an den Kindprozess zugestellt würden und vom Verfolger abgefangen wurden. Es könnte schwierig werden, diese normalen Signale von künstlichen Signalen zu unterscheiden, die von ptrace() selbst generiert wurden. (adresse wird ignoriert.)

PTRACE_SETOPTIONS (seit Linux 2.4.6; siehe FEHLER für caveats)
    setzt Ptrace-Optionen von daten im Elternprozess. (adresse wird ignoriert.) daten wird als Bit in der Maske der Optionen interpretiert, die durch die folgenden Schalter angegeben wird:

    PTRACE_O_TRACESYSGOOD (seit Linux 2.4.6)
        Wenn Systemaufrufe abgefangen werden, wird Bit 7 in der Signalnummer gesetzt (d.h.(SIGTRAP | 0x80) geschickt). Dies erleichtert es dem Verfolger den Unterschied zwischen normalen abgefangenen Signalen und denen, die durch einen Systemaufruf verursacht wurden, zu erkennen. (PTRACE_O_TRACESYSGOOD funktioniert möglicherweise nicht auf allen Architekturen.)

    PTRACE_O_TRACEFORK (seit Linux 2.5.46)
        stoppt den Kindprozess beim nächsten Aufruf von fork(2) mit SIGTRAP | PTRACE_EVENT_FORK << 8 und startet automatisch die Verfolgung des neuen Prozesszweiges, der mit einem SIGSTOP starten wird. Die PID des neuen Prozesses kann mit PTRACE_GETEVENTMSG abgefragt werden.

    PTRACE_O_TRACEVFORK (seit Linux 2.5.46)
        stoppt den Kindprozess beim nächsten Aufruf von vfork(2) mit SIGTRAP | PTRACE_EVENT_VFORK << 8 und startet automatisch die Verfolgung des neuen »vfork«-Prozesszweiges, der mit einem SIGSTOP starten wird. Die PID des neuen Prozesses kann mit PTRACE_GETEVENTMSG abgefragt werden.

    PTRACE_O_TRACECLONE (seit Linux 2.5.46)
        stoppt den Kindprozess beim nächsten clone(2)-Aufruf mit SIGTRAP | PTRACE_EVENT_CLONE << 8 und startet automatisch die Verfolgung des neuen geklonten Prozesses, der mit einem SIGSTOP starten wird. Die PID des neuen Prozesses kann mit PTRACE_GETEVENTMSG abgefragt werden. Diese Option kann nicht in allen Fällen clone(2)-Aufrufe abfangen. Falls der Kindprozess clone(2) mit dem Schalter CLONE_VFORK aufruft, wird stattdessen PTRACE_EVENT_VFORK geschickt, wenn PTRACE_O_TRACEVFORK gesetzt ist; andernfalls wird PTRACE_EVENT_FORK geschickt, wenn der Kindprozess clone(2) mit dem auf SIGCHLD gesetzten Exit-Signal aufgerufen wird, wenn PTRACE_O_TRACEFORK gesetzt ist.

    PTRACE_O_TRACEEXEC (seit Linux 2.5.46)
        stoppt den Kindprozess beim nächsten execve(2)-Aufruf mit SIGTRAP | PTRACE_EVENT_EXEC << 8.

    PTRACE_O_TRACEVFORKDONE (seit Linux 2.5.60)
        stoppt den Kindprozess beim Abschluss des nächsten vfork(2)-Aufrufs mit SIGTRAP | PTRACE_EVENT_VFORK_DONE << 8.

    PTRACE_O_TRACEEXIT (seit Linux 2.5.60)
        stoppt den Kindprozess beim Beenden mit SIGTRAP | PTRACE_EVENT_EXIT<< 8. Der Exit-Status des Kindprozesses kann mit PTRACE_GETEVENTMSG abgefragt werden. Dieser Stopp findet früh während des Prozesses statt, wenn die Register noch verfügbar sind, was es dem Verfolger ermöglicht zu sehen, wo das Beenden veranlasst wurdu, wohingegen die normale Benachrichtigung über die Beendigung geschickt wird, wenn der Prozess das Beenden abgeschlossen hat. Auch wenn der Kontext verfügbar ist, kann der Verfolger das Beenden an diesem Punkt nicht mehr verhindern.

PTRACE_GETEVENTMSG (seit Linux 2.5.46)
    eine Nachricht (als unsigned long) über das Ptrace-Ereignis abfragen, das einfach so auftrat und es an die Stelle daten im Elternprozess platzieren. Für PTRACE_EVENT_EXIT ist dies der Exit-Status des Kindprozesses. Für PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK und PTRACE_EVENT_CLONE ist dies die PID des neuen Prozesses. Seit Linux 2.6.18 ist auch die PID des neuen Prozesses für PTRACE_EVENT_VFORK_DONE verfügbar. (adresse wird ignoriert.)

PTRACE_CONT
    startet den gestoppten Kindprozess erneut. Falls daten nicht Null und nicht SIGSTOP ist, wird es als Signal interpretiert, das an den Kindprozess geschickt wird, andernfalls wird kein Signal geschickt. Dadurch kann der Elternprozess zum Beispiel steuern, ob ein Signal an den Kindprozess geschickt wird oder nicht. (adresse wird ignoriert.)

PTRACE_SYSCALL, PTRACE_SINGLESTEP
    startet den gestoppten Kindprozess wie für PTRACE_CONT, arrangiert aber, dass der Kindprozess beim nächsten Eintrag oder einem Systemaufruf beziehungsweise nach der Ausführung einer einzelnen Anweisung gestoppt wird. (Der Kindprozess wird auch, wie üblich, über den Empfang des Signals gestoppt.) Aus der Sicht des Elternprozesses scheint es, dass der Kindprozess durch Empfang eines SIGTRAP gestoppt wurde. Daher gibt es zum Beispiel für PTRACE_SYSCALL die Idee, beim ersten Stopp die Argumente des Systemaufrufs zu prüfen, dann einen anderen PTRACE_SYSCALL zu schicken und den Rückgabewert des Systemaufrufs am zweiten Stopp zu prüfen. Das Argument daten wird wie für PTRACE_CONT behandelt. (adresse wird ignoriert.)

PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP (seit Linux 2.6.14)
    für PTRACE_SYSEMU beim nächsten Eintrag für den Systemaufruf, der nicht ausgeführt wird, fortfahren und stoppen. Für PTRACE_SYSEMU_SINGLESTEP das gleiche tun, aber in einem einzigen Schritt, wenn es sich nicht um einen Systemaufruf handelt. Dieser Aufruf wird von Programmen, wie »User Mode Linux« verwandt, die die Systemaufrufe des Kindprozesses emulieren wollen. Das Argument daten wird wie für PTRACE_CONT behandelt. (adresse wird ignoriert; nicht auf allen Architekturen unterstützt.)

PTRACE_KILL
    sendet dem Kindprozess ein SIGKILL, um ihn zu beenden. (adresse und daten werden ignoriert.)

PTRACE_ATTACH
    hängt den in pid angegebenen Prozess an und macht ihn zu einem verfolgten »Kindprozess« des aufrufenden Prozesses. Das Verhalten des Kindprozesses ist wie bei PTRACE_TRACEME. Der aufrufende Prozess bekommt für die meisten Zwecke den Elternprozess des Kindprozesses (z.B. wird er eine Benachrichtigung von Ereignissen des Kindprozesses erhalten und in der Ausgabe von ps(1) als Elternprozess des Kindprozesses erscheinen), aber ein getppid(2) durch den Kindprozess wird immer noch die PID des Original-Elternprozesses zurückgeben. Dem Kindprozess wird ein SIGSTOP geschickt, er wird aber nicht notwendigerweise bei der Komplettierung des Aufrufs gestoppt; benutzen Sie wait(2), um auf das Stoppen des Kindprozesses zu warten. (adresse und daten werden ignoriert.)

PTRACE_DETACH
    startet den gestoppten Kindprozess wie für PTRACE_CONT, löst ihn aber zuerst vom Prozess ab, indem der Übernahme-Effekt von PTRACE_ATTACH und die Effekte von PTRACE_TRACEME rückgängig gemacht werden. Obwohl dies vielleicht nicht beabsichtigt ist, kann unter Linux ein verfolgter Kindprozess auf diese Art abgelöst werden ohne Rücksicht darauf zu nehmen, welche Methode zum Starten der Verfolgung benutzt wurde.(adresse wird ignoriert.)

RÜCKGABEWERT
Bei Erfolg geben PTRACE_PEEK*-Anfragen die angefragten Daten zurück, während andere Anfragen Null zurückgeben. Bei einem Fehler geben alle Anfragen -1 zurück und errno wird entsprechend gesetzt. Da der Wert, der von einer erfolgreichen PTRACE_PEEK*-Anfrage zurückgegeben wurde, -1 sein könnte, muss der Aufrufende nach solchen Anfragen errno prüfen, um zu untersuchen, ob ein Fehler aufgetreten ist oder nicht.

FEHLER

EBUSY
    (nur i386) Es ist beim Reservieren oder der Freigabe eines Debug-Registers ein Fehler aufgetreten.

EFAULT
    Es gab einen Versuch in einem ungültigen Bereich im Speicher des Eltern- oder Kindprozesses zu lesen oder zu schreiben, wahrscheinlich, weil der Bereich nicht abgebildet war oder kein Zugriff möglich war. Unglücklicherweise geben unter Linux mehrere Variationen dieser Störung mehr oder weniger willkürlich EIO oder EFAULT zurück.

EINVAL
    Es wurde versucht, eine ungültige Option zu setzen.

EIO abfrage ist ungültig, es wurde versucht, in einem ungültigen Bereich im Speicher des Eltern- oder Kindprozesses zu lesen oder zu schreiben, es gab eine Verletzung der Ausrichtung an der »word«-Größe oder es wurde während des Neustarts der Abfrage ein ungültiges Signal angegeben.

EPERM
    Der angegebene Prozess kann nicht verfolgt werden. Dies könnte daher rühren, dass der Elternprozess über unzureichende Privilegien verfügt (die Fähigkeit CAP_SYS_PTRACE wird benötigt); unprivilegierte Prozesse können keine Prozesse verfolgen, denen sie keine Signale senden können oder die SUID-/SGID-Programme ausführen, was naheliegend ist. Alternativ könnte der Prozess bereits verfolgt werden oder init(8) (PID 1) sein.

ESRCH
    Der angegebene Prozess exisitiert nicht, wird derzeit nicht vom Aufrufenden verfolgt oder ist nicht gestoppt (bei Anfragen, die dies erfordern).

KONFORM ZU
SVr4, 4.3BSD

ANMERKUNGEN
Obwohl Argumente für ptrace() gemäß dem angegebenen Prototypen interpretiert werden, deklariert Glibc derzeit ptrace() als eine variable Funktion mit nur dem festen anfrage-Argument. Dies bedeutet, dass nicht gewollte anhängende Argumente weggelassen werden könnten, obwohl dies Gebrauch vom nicht dokumentierten gcc(1)-Verhalten macht.

init(8), der Prozess mit der Prozessnummer 1, kann nicht verfolgt werden.

Das Layout des Speicherinhalts und des BENUTZERbereichs sind ziemlich von Betriebsystem und Architektur abhängig. Der mitgelieferte Versatz und die zurückgegebenen Daten könnten nicht ganz zu der Definition von struct user passen.

Die Größe eines »word« wird durch die Betriebsystemvariante festgelegt (z.B. ist es für ein 32-Bit-Linux 32 Bit, etc.).

Verfolgung bewirkt ein paar feine Unterschiede in der Semantik des verfolgenden Prozesses. Wenn ein Prozess zum Beispiel mit PTRACE_ATTACH angehängt ist, kann dessen Original-Elternprozess nicht länger Benachrichtigungen mittels wait(2) empfangen, wenn er stoppt und es gibt effektiv keine Möglichkeit für den neuen Elternprozess diese Benachrichtigung zu simulieren.

Wenn der Elternprozess ein Ergeignis mit gesetztem PTRACE_EVENT_* empfängt, liegt der Kindprozess nicht im normalen Signal-Lieferungspfad. Dies bedeutet, dass der Elternprozess nicht ptrace(PTRACE_CONT) mit einem Signal oder ptrace(PTRACE_KILL) ausführen kann. Stattdessen kann kill(2) mit einem SIGKILL-Signal benutzt werden, um den Kindprozess nach dem Empfang einer dieser Nachrichten zu beenden.

Diese Seite dokumentiert die Möglichkeit, wie der ptrace()-Aufruf derzeit in Linux arbeitet. Sein Verhalten unterscheidet sich auf anderen UNIX-Geschmacksrichtungen deutlich. Auf jeden Fall ist die Benutzung von ptrace() in hohem Grad abhängig vom Betriebssystem und der Architektur.

Die SunOS-Handbuchseite beschreibt ptrace() als »einzigartig und geheimnisvoll«, was es auch ist. Die proc-basierte Schnittstelle zur Fehlersuche in Solaris 2 implementiert eine Obermenge von ptrace()-Funktionalität in einer kräftigeren und einheitlicheren Art.

FEHLER
Auf Rechnern mit 2.6 Kernel-Headern ist PTRACE_SETOPTIONS mit einem anderen Wert deklariert, als auf einem für 2.4. Dies führt dazu, dass Anwendungen, die mit solchen Headern kompiliert wurden, bei der Ausführung auf 2.4er Kerneln scheitern. Dies kann durch Neudefinieren von PTRACE_SETOPTIONS zu PTRACE_OLDSETOPTIONS umgangen werden, wenn dies definiert ist.

SIEHE AUCH
gdb(1), strace(1), execve(2), fork(2), signal(2), wait(2), exec(3), capabilities(7)

KOLOPHON
Diese Seite ist Teil der Veröffentlichung 3.27 des Projekts Linux-man-pages. Eine Beschreibung des Projekts und Informationen, wie Fehler gemeldet werden können, finden sich unter http://www.kernel.org/doc/man-pages/.

ÜBERSETZUNG
Die deutsche Übersetzung dieser Handbuchseite wurde von Patrick Rother <krd@gulu.net> und Chris Leick <c.leick@vollbio.de> erstellt. Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen. Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an <debian-l10n-german@lists.debian.org>.