ptrace(2) System Calls Manual ptrace(2) BEZEICHNUNG ptrace - Prozessverfolgung BIBLIOTHEK Standard-C-Bibliothek (libc, -lc) UBERSICHT #include long ptrace(enum __ptrace_request Akt, pid_t pid, void *Adresse, void *Daten); BESCHREIBUNG Der Systemaufruf ptrace() stellt ein Mittel bereit, wodurch ein Prozess (der >>Verfolger<<) die Ausfuhrung eines anderen Prozesses (des >>verfolgten Prozesses<<) beobachten und steuern kann und seinen Speicher sowie die Register untersuchen und andern kann. Er wird in erster Linie benutzt, um Fehlersuche mittels Haltepunkten zu implementieren und Systemaufrufe zu verfolgen. Ein verfolgter Prozess muss zuerst an den Verfolger angehangt werden. Anhangen und nachfolgende Befehle bestehen pro Thread: In einem Prozess mit mehreren Threads kann jeder Thread individuell an einen (moglicherweise unterschiedlichen) Verfolger angehangt werden oder nicht angehangt und folglich nicht auf Fehler untersucht werden. Daher bedeutet >>verfolgter Prozess<< immer >>(ein) Thread<<, niemals >>ein Prozess (mit moglicherweise mehreren Threads)<<. Ptrace-Befehle werden immer an einen bestimmten verfolgten Prozess gesandt. Der Aufruf hat folgende Form: ptrace(PTRACE_foo, PID, ) wobei PID die Thread-Kennung des zugehorigen Linux-Threads ist. (Beachten Sie, dass auf dieser Seite ein >>Prozess aus mehreren Threads<< eine Thread-Gruppe bezeichnet, die aus Threads besteht, die mittels des clone(2)-Schalters CLONE_THREAD erzeugt wurde.) Ein Prozess kann eine Verfolgung mittels fork(2) starten und als Ergebnis einen Kindprozess erhalten, der PTRACE_TRACEME ausfuhrt, was (ublicherweise) von einem execve(2) gefolgt wird. Alternativ kann ein Prozess die Verfolgung eines anderen Prozesses mittels PTRACE_ATTACH oder PTRACE_SEIZE beginnen. Wahrend der Prozess 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 Verfolger wird bei seinem nachsten Aufruf von waitpid(2) (oder den zugehorigen >>wait<<-Systemaufrufen) benachrichtigt; dies wird einen Statuswert zuruckgeben, der Informationen enthalt, die den Grund angeben, weshalb der verfolgte Prozess stoppte. Wahrend der verfolgte Prozess angehalten ist, kann der Verfolger verschiedene Ptrace-Aktionen verwenden, um den verfolgten Prozess zu untersuchen und zu verandern. Dann veranlasst der Verfolger den verfolgten Prozess fortzufahren und wahlweise das versandte Signal zu ignorieren (oder stattdessen sogar ein anderes Signal zu senden). Falls die Option PTRACE_O_TRACEEXEC nicht in Kraft ist, werden alle erfolgreichen Aufrufe von execve(2) durch den verfolgten Prozess zum Senden eines SIGTRAP-Signals veranlassen, um dem Elternprozess die Moglichkeit zu geben, die Kontrolle zu erlangen, bevor die Ausfuhrung des neuen Programms beginnt. Wenn der Verfolger die Verfolgung beendet hat, kann er veranlassen, das der verfolgte Prozess mit PTRACE_DETACH in einem normal Modus ohne Verfolgung fortfahrt. Der Wert von Akt legt die durchzufuhrende Aktion fest: PTRACE_TRACEME zeigt an, dass dieser Prozess durch seinen Elternprozess verfolgt wird. Ein Prozess sollte diese Aktion wahrscheinlich nicht durchfuhren, falls sein Elternprozess nicht erwartet, ihn zu verfolgen.(PID, Adresse und Daten werden ignoriert.) Die Aktion PTRACE_TRACEME wird nur vom verfolgten Prozess benutzt; die verbleibenden Aktionen werden nur vom verfolgenden Prozess benutzt. In den folgenden Aktionen gibt PID die Thread-Kennung des verfolgten Prozesses an, der beeinflusst werden soll. Fur andere Aktionen als PTRACE_ATTACH, PTRACE_SEIZE, PTRACE_INTERRUPT und PTRACE_KILL muss der verfolgte Prozess gestoppt werden. PTRACE_PEEKTEXT PTRACE_PEEKDATA liest ein >>word<< an der Stelle Adresse im Speicher des verfolgten Prozesses und gibt das >>word<< als Ergebnis des ptrace()-Aufrufs zuruck. Linux hat keine separaten Adressraume fur Text und Daten, daher sind diese beiden Aktionen derzeit gleichwertig. (Das Argument Daten wird ignoriert, lesen Sie aber auch ANMERKUNGEN.) PTRACE_PEEKUSER Liest ein >>word<< bei Versatz Adresse im BENUTZERbereich des verfolgten Prozesses, der die Register und andere Informationen uber den Prozess enthalt (siehe ). Das >>word<< wird als Ergebnis des ptrace()-Aufrufs zuruckgegeben. Typischerweise muss der Versatz am >>word<< ausgerichtet sein, obwohl dies je nach Architektur variieren kann. Lesen Sie die ANMERKUNGEN. (Daten wird ignoriert, lesen Sie aber auch ANMERKUNGEN.) PTRACE_POKETEXT PTRACE_POKEDATA kopiert das >>word<< Daten an die Stelle Adresse im Speicher des verfolgenden Prozesses. Wie bei PTRACE_PEEKTEXT und PTRACE_PEEKDATA sind die beiden Aktionen derzeit gleichwertig. PTRACE_POKEUSER kopiert das >>word<< Daten an den Versatz Adresse im BENUTZERbereich des verfolgten Prozesses. Wie fur PTRACE_PEEKUSER muss der Versatz am >>word<< ausgerichtet sein. Um die Integritat des Kernels aufrecht zu erhalten, sind einige Anderungen in BENUTZERbereich nicht erlaubt. PTRACE_GETREGS PTRACE_GETFPREGS kopiert die Mehrzweck- beziehungsweise Fliesspunktregister des verfolgten Prozesses an die Stelle Daten im Verfolger. Lesen Sie , um Informationen uber das Format dieser Daten zu erhalten. (Adresse wird ignoriert.) Beachten Sie, dass auf SPARC-Systemen die Bedeutung von Daten und Adresse umgekehrt ist; daher wird Daten ignoriert und die Register werden an die Adresse Adresse kopiert. PTRACE_GETREGS und PTRACE_GETFPREGS sind nicht auf allen Architekturen verfugbar. PTRACE_GETREGSET (seit Linux 2.6.34) liest die Register des verfolgten Prozesses. Adresse gibt auf eine von der Architektur unabhangige Weise den Typ des Registers an, das gelesen werden soll. NT_PRSTATUS (mit numerischem Wert 1) fuhrt normalerweise dazu, dass Allzweckregister gelesen werden. Falls die CPU zum Beispiel Fliesskomma- und/oder Vektorregister hat, konnen sie durch Setzen von Adresse auf die entsprechende Konstante NT_foo ermittelt werden. Daten zeigt auf einen struct iovec, der den Speicherort und die Lange des Zielpuffers beschreibt. Bei der Ruckkehr andert der Kernel iov.len, um die tatsachliche Anzahl zuruckgegebener Byte anzuzeigen. PTRACE_SETREGS PTRACE_SETFPREGS verandert die Mehrzweck- beziehungsweise Fliesspunktregister des verfolgten Prozesses von der Adresse Daten im Verfolger. Wie fur PTRACE_POKEUSER konnen einige Anderungen am Mehrzweckregister verboten sein. (Adresse wird ignoriert.) Beachten Sie, dass auf SPARC-Systemen die Bedeutung von Daten und Adresse umgekehrt ist; daher wird Daten ignoriert und die Register werden von der Adresse Adresse kopiert. PTRACE_SETREGS und PTRACE_SETFPREGS sind nicht auf allen Architekturen verfugbar. PTRACE_SETREGSET (seit Linux 2.6.34) verandert die Register des verfolgten Prozesses. Die Bedeutung von Adresse und Daten ist analog zu PTRACE_GETREGSET. PTRACE_GETSIGINFO (seit Linux 2.3.99-pre6) ruft Informationen uber das Signal ab, das den Stopp verursachte. Kopiert eine siginfo_t-Struktur (siehe sigaction(2)) vom verfolgten Prozess an die Stelle Daten im Verfolger. (Adresse wird ignoriert.) PTRACE_SETSIGINFO (seit Linux 2.3.99-pre6) setzt Signalinformationen: kopiert eine siginfo_t-Struktur von der Adresse Daten vom verfolgenden zum verfolgten Prozess. Dies wird nur Signale betreffen, die normalerweise an den verfolgten Prozess zugestellt wurden und vom Verfolger abgefangen wurden. Es konnte schwierig werden, diese normalen Signale von kunstlichen Signalen zu unterscheiden, die von ptrace() selbst generiert wurden. (Adresse wird ignoriert.) PTRACE_PEEKSIGINFO (seit Linux 3.10) fragt siginfo_t-Strukturen ab, ohne Signale aus einer Warteschlange zu entfernen. Adresse zeigt auf eine ptrace_peeksiginfo_args-Struktur, die die Ordnungsposition angibt, von der das Kopieren der Signale starten soll sowie die Anzahl zu kopierender Signale. siginfo_t-Strukturen werden in den Puffer kopiert, auf den Daten verweist. Der Ruckgabewert enthalt die Anzahl der kopierten Signale (null zeigt an, dass es an der angegebenen Ordnungsposition kein entsprechendes Signal gibt). Innerhalb der zuruckgegebenen siginfo-Strukturen enthalt das Feld si_code Informationen (__SI_CHLD, __SI_FAULT, etc.), die ansonsten nicht an den Anwendungsraum offengelegt werden. struct ptrace_peeksiginfo_args { u64 off; /* Ordnungsposition in der Warteschlange, an der mit dem Kopieren der Signale begonnen wird */ u32 flags; /* PTRACE_PEEKSIGINFO_SHARED oder 0 */ s32 nr; /* Anzahl zu kopierender Signale */ }; Derzeit gibt es nur einen Schalter, PTRACE_PEEKSIGINFO_SHARED, um Signale aus der prozessweiten Signalwarteschlange auszugeben. Falls dieser Schalter nicht gesetzt ist, werden Signale von der Thread-eigenen Warteschlange des angegebenen Threads gelesen. PTRACE_GETSIGMASK (seit Linux 3.11) Platzieren Sie eine Kopie der Maske blockierter Signale (siehe sigprocmask(2)) in den Puffer, auf den Daten zeigt. Dies sollte ein Zeiger auf einen Puffer des Typs sigset_t sein. Das Argument Adresse enthalt die Grosse des Puffers, auf den Daten zeigt (d.h. sizeof(sigset_t)). PTRACE_SETSIGMASK (seit Linux 3.11) andert die Maske blockierter Signale (siehe sigprocmask(2)) auf den Wert, der im Puffer angegeben wird, auf den Daten zeigt. Dies sollte ein Zeiger auf einen Puffer des Typs sigset_t sein. Das Argument Adresse enthalt die Grosse des Puffers, auf den Daten zeigt (d.h. sizeof(sigset_t)). PTRACE_SETOPTIONS (seit Linux 2.4.6; siehe FEHLER fur Vorsichtsmassnahmen) setzt Ptrace-Optionen von Daten. (Adresse wird ignoriert.) Daten wird als Bit in der Maske der Optionen interpretiert, die durch die folgenden Schalter angegeben wird: PTRACE_O_EXITKILL (seit Linux 3.8) schickt an den verfolgten Prozess ein SIGKILL-Signal, falls der verfolgende Prozess beendet wird. Diese Option ist fur diejenigen nutzlich, die Ptrace einsperren und sicherstellen wollen, dass der verfolgte Prozess nie der Steuerung des verfolgenden Prozesses entkommt. PTRACE_O_TRACECLONE (seit Linux 2.5.46) stoppt den verfolgten Prozess beim nachsten Aufruf von clone(2) und startet automatisch die Verfolgung des neu geklonten Prozesses, der mit einem SIGSTOP oder, falls PTRACE_SEIZE benutzt wurde, mit PTRACE_EVENT_STOP starten wird. Ein waitpid(2) durch den Verfolger wird einen Statuswert wie diesen zuruckgeben: status>>8 == (SIGTRAP | (PTRACE_EVENT_CLONE<<8)) Die PID des neuen Prozesses kann mit PTRACE_GETEVENTMSG abgefragt werden. Diese Option kann nicht in allen Fallen clone(2)-Aufrufe abfangen. Falls der verfolgte Prozess 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 verfolgte Prozess clone(2) mit dem auf SIGCHLD gesetzten Beendigungssignal aufgerufen wird, falls PTRACE_O_TRACEFORK gesetzt ist. PTRACE_O_TRACEEXEC (seit Linux 2.5.46) stoppt den verfolgten Prozess beim nachsten execve(2). Ein waitpid(2) durch den Verfolger wird einen Statuswert wie diesen zuruckgeben: status>>8 == (SIGTRAP | (PTRACE_EVENT_EXEC<<8)) Falls der ausfuhrende Thread kein fuhrender Thread der Gruppe ist, wird die Thread-Kennung vor dem Stopp auf die Kennung des fuhrenden Threads der Gruppe zuruckgesetzt. Seit Linux 3.0 kann die vorherige Thread-Kennung mit PTRACE_GETEVENTMSG abgefragt werden. PTRACE_O_TRACEEXIT (seit Linux 2.5.60) stoppt den verfolgten Prozess beim Beenden. Ein waitpid(2) durch den Verfolger wird einen Statuswert wie diesen zuruckgeben: status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8)) Der Exit-Status des verfolgten Prozesses kann mit PTRACE_GETEVENTMSG abgefragt werden. Der verfolgte Prozess wird fruhzeitig wahrend des Beendens gestoppt, wenn die Register noch verfugbar sind, was es dem Verfolger ermoglicht, zu sehen, wo das Beenden veranlasst wurde, wohingegen die normale Benachrichtigung uber die Beendigung geschickt wird, wenn der Prozess das Beenden abgeschlossen hat. Auch wenn der Kontext verfugbar ist, kann der Verfolger das Beenden an diesem Punkt nicht mehr verhindern. PTRACE_O_TRACEFORK (seit Linux 2.5.46) stoppt den verfolgten Prozess beim nachsten Aufruf von fork(2) und startet die Verfolgung des neuen Prozesszweiges, der mit einem SIGSTOP oder, falls PTRACE_SEIZE benutzt wurde, mit PTRACE_EVENT_STOP starten wird. Ein waitpid(2) durch den Verfolger wird einen Statuswert wie diesen zuruckgeben: status>>8 == (SIGTRAP | (PTRACE_EVENT_FORK<<8)) Die PID des neuen Prozesses kann mit PTRACE_GETEVENTMSG abgefragt werden. 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, mitzuteilen. PTRACE_O_TRACEVFORK (seit Linux 2.5.46) stoppt den verfolgten Prozess beim nachsten Aufruf von vfork(2) und startet automatisch die Verfolgung des neuen >>vfork<<-Prozesszweiges, der mit einem SIGSTOP oder, falls PTRACE_SEIZE benutzt wurde, mit PTRACE_EVENT_STOP starten wird. Ein waitpid(2) durch den Verfolger wird einen Statuswert wie diesen zuruckgeben: status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK<<8)) Die PID des neuen Prozesses kann mit PTRACE_GETEVENTMSG abgefragt werden. PTRACE_O_TRACEVFORKDONE (seit Linux 2.5.60) stoppt den verfolgten Prozess bei Vollendung des nachsten vfork(2). Ein waitpid(2) durch den Verfolger wird einen Statuswert wie diesen zuruckgeben: status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK_DONE<<8)) Die PID des neuen Prozesses kann (seit Linux 2.6.18) abgefragt werden mit PTRACE_O_TRACESECCOMP (seit Linux 3.5) stoppt den verfolgten Prozess, wenn eine seccomp(2) SECCOMP_RET_TRACE-Regel ausgelost wird. Ein waitpid(2) durch den Verfolger wird einen Statuswert wie diesen zuruckgeben: status>>8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP<<8)) Wahrend dies ein PTRACE_EVENT-Stopp auslost, ist es einem Systemaufrufeintrittsstopp ahnlich. Fur Details lesen Sie die Bemerkungen uber PTRACE_EVENT_SECCOMP weiter unten. Die Seccomp-Ereignisnachrichtendaten (aus dem Abschnitt SECCOMP_RET_DATA der Seccomp-Filterregel) konnen uber PTRACE_GETEVENTMSG ermittelt werden. PTRACE_O_SUSPEND_SECCOMP (seit Linux 4.3) setzt den Seccomp-Schutz des verfolgten Prozesses aus. Dies gilt unabhangig vom Modus und kann verwandt werden, wenn der verfolgte Prozess noch keine Seccomp-Filter installiert hat. Das bedeutet, dass ein gultiger Anwendungsfall darin besteht, den Seccomp-Schutz auszusetzen, bevor er von dem verfolgten Prozess installiert wird, dann den verfolgten Prozess die Filter installieren zu lassen und danach diesen Schalter wieder zuruckzusetzen, wenn die Filter wiederaufgenommen werden sollen. Um diese Option zu setzen, muss der verfolgende Prozess uber die Capability CAP_SYS_ADMIN verfugen, er darf selber keinen Seccomp-Schutz installiert haben und darf nicht PTRACE_O_SUSPEND_SECCOMP auf sich selbst setzen. PTRACE_GETEVENTMSG (seit Linux 2.5.46) fragt eine Nachricht (als unsigned long) uber das Ptrace-Ereignis, das einfach so auftrat, ab und platziert es an die Adresse Daten im Verfolger. Fur PTRACE_EVENT_EXIT ist dies der Exit-Status des verfolgten Prozesses. Fur PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK und PTRACE_EVENT_CLONE ist dies die PID des neuen Prozesses. Fur PTRACE_EVENT_SECCOMP ist das SECCOMP_RET_DATA von seccomp(2)s Filter, das der ausgelosten Regel zugeordnet ist. (Adresse wird ignoriert.) PTRACE_CONT startet den gestoppten, verfolgten Prozess erneut. Falls Daten nicht null ist, wird es als Nummer des Signals interpretiert, das an den verfolgten Prozess geschickt wird; andernfalls wird kein Signal geschickt. Dadurch kann der Verfolger zum Beispiel steuern, ob ein Signal an den verfolgten Prozess geschickt wird oder nicht. (Adresse wird ignoriert.) PTRACE_SYSCALL PTRACE_SINGLESTEP startet den gestoppten, verfolgten Prozess wie fur PTRACE_CONT, arrangiert aber, dass der verfolgte Prozess beim nachsten Eintritt oder einem Systemaufruf beziehungsweise nach der Ausfuhrung einer einzelnen Anweisung gestoppt wird. (Der verfolgte Prozess wird auch, wie ublich, uber den Empfang des Signals gestoppt.) Aus der Sicht des Verfolgers scheint es, als ob der verfolgte Prozess durch Empfang eines SIGTRAP gestoppt wurde. Daher gibt es zum Beispiel fur PTRACE_SYSCALL die Idee, beim ersten Stopp die Argumente des Systemaufrufs zu prufen, dann einen anderen PTRACE_SYSCALL zu schicken und den Ruckgabewert des Systemaufrufs am zweiten Stopp zu prufen. Das Argument Daten wird wie fur PTRACE_CONT behandelt. (Adresse wird ignoriert.) PTRACE_SET_SYSCALL (seit Linux 2.6.16) Wenn im Systemaufrufeintrittsstopp, wird die Nummer des auszufuhrenden Systemaufrufs auf die im Argument data angegebene Nummer geandert. Das Argument addr wird ignoriert. Diese Aktion wird derzeit nur auf Arm (und Arm64, allerdings nur fur die Ruckwartskompatibilitat) unterstutzt, aber die meisten anderen Architekturen haben andere Mittel, um dies zu erreichen (normalerweise durch Anderung des Registers, in dem der Code aus der Anwendungsebene die Nummer des Systemaufrufs ubergab). PTRACE_SYSEMU PTRACE_SYSEMU_SINGLESTEP (seit Linux 2.6.14) fur PTRACE_SYSEMU beim nachsten Eintritt fur den Systemaufruf, der nicht ausgefuhrt wird, fortfahren und stoppen. Siehe die Dokumentation zu Systemaufrufstopps weiter unten. Fur 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 verfolgten Prozesses emulieren wollen. Das Argument Daten wird wie fur PTRACE_CONT behandelt. Das Argument Adresse wird ignoriert. Diese Aktionen werden derzeit nur unter x86 unterstutzt. PTRACE_LISTEN (seit Linux 3.4) startet den gestoppten verfolgten Prozess erneut, verhindert jedoch seine Ausfuhrung. Der resultierende Status ist dem eines Prozesses ahnlich, der durch ein SIGSTOP (oder ein anderes Stoppsignal) angehalten wurde. Zusatzliche Informationen finden Sie im Unterabschnitt >>Gruppenstopp<<. PTRACE_LISTEN funktioniert nur bei verfolgten Prozessen, die durch PTRACE_SEIZE angehangt wurden. PTRACE_KILL sendet dem verfolgten Prozess ein SIGKILL, um ihn zu beenden. (Adresse und Daten werden ignoriert.) Diese Aktion ist uberholt; benutzen Sie sie nicht! Senden Sie stattdessen ein SIGKILL direkt mittels kill(2) oder tgkill(2). Das Problem bei PTRACE_KILL ist, dass es verlangt, dass sich der verfolgte Prozess in einem Signallieferstopp befindet, andernfalls funktioniert es moglicherweise nicht (d.h. es konnte komplett erfolgreich sein, wurde aber den verfolgten Prozess killen). Im Gegensatz dazu hat das direkte Senden von einem SIGKILL keine derartige Beschrankung. PTRACE_INTERRUPT (seit Linux 3.4) stoppt einen verfolgten Prozess. Falls der verfolgte Prozess im Kernel-Space lauft oder schlaft und PTRACE_SYSCALL in Kraft ist, wird der Systemaufruf unterbrochen und Systemaufrufbeendigungsstopp gemeldet. (Der unterbrochene Systemaufruf wird beim Neustart des verfolgten Prozesses ebenfalls neu gestartet.) Falls der verfolgte Prozess bereits durch ein Signal gestoppt und PTRACE_LISTEN an ihn gesendet wurde, stoppt der verfolgte Prozess mit PTRACE_EVENT_STOP und WSTOPSIG(Status) gibt das Stoppsignal zuruck. Falls zur selben Zeit irgendein anderes >>ptrace-stop<< erzeugt wird (zum Beispiel, weil ein Signal an den verfolgten Prozess gesendet wird), tritt dieses >>ptrace-stop<< auf. Falls nichts von obigem zutrifft (zum Beispiel, weil der verfolgte Prozess im Anwendungsraum lauft), stoppt er mit PTRACE_EVENT_STOP mit WSTOPSIG(status) == SIGTRAP. PTRACE_INTERRUPT funktioniert nur bei verfolgten Prozessen, die durch PTRACE_SEIZE angehangt wurden. PTRACE_ATTACH hangt an den Prozess, der durch PID angegeben wird, an und lasst ihn zum verfolgten Prozess des aufrufenden Prozesses werden. Dem verfolgten Prozess wird ein SIGSTOP gesandt, er wird aber nicht notwendigerweise durch die Vollendung dieses Aufrufs gestoppt; benutzen Sie waitpid(2), um auf das Stoppen des verfolgten Prozesses zu warten. Lesen Sie den Unterabschnitt >>Anhangen und Loslosen<<, um zusatzliche Informationen zu erhalten. (Adresse und Daten werden ignoriert.) Berechtigungen, ein PTRACE_ATTACH durchzufuhren, werden durch eine Ptrace-Zugriffsmodus-PTRACE_MODE_ATTACH_REALCREDS-Uberprufung geregelt; siehe unten. PTRACE_SEIZE (seit Linux 3.4) hangt an den zu dem in PID angegebenen Prozess an, wodurch er ein verfolgter Prozess des aufrufenden Prozesses wird. Anders als PTRACE_ATTACH beendet PTRACE_SEIZE den Prozess nicht. Gruppenstopps werden als PTRACE_EVENT_STOP berichtet und WSTOPSIG(status) liefert das Stopp-Signal zuruck. Automatisch angehangte Kinder stoppen mit PTRACE_EVENT_STOP und WSTOPSIG(status) liefert SIGTRAP zuruck, statt ein SIGSTOP Signal geliefert zu bekommen. execve(2) liefert kein zusatzliches SIGTRAP aus. Nur ein Prozess, der PTRACE_SEIZE ist, kann die Befehle PTRACE_INTERRUPT und PTRACE_LISTEN akzeptieren. Das gerade beschriebene >>beschlagnahmte<< (engl. >>seized<<) Verhalten wird von Kindern geerbt, die automatisch mittels PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK und PTRACE_O_TRACECLONE angehangt sind. Adresse muss Null sein. Daten enthalt eine Bitmaske, die die sofort zu aktivierenden Optionen enthalt. Berechtigungen, ein PTRACE_SEIZE durchzufuhren, werden durch eine Ptrace-Zugriffsmodus-PTRACE_MODE_ATTACH_REALCREDS-Uberprufung geregelt; siehe unten. PTRACE_SECCOMP_GET_FILTER (seit Linux 4.4) Diese Aktion erlaubt es dem verfolgenden Prozess, die klassischen BPF-Filter des verfolgten Prozesses auszugeben. Adresse ist eine Ganzzahl, die den Index des Filters, der ausgegeben werden soll, angibt. Der neuste installierte Filter hat den Index 0. Falls Adresse grosser als die Anzahl der installierten Filter ist, schlagt die Aktion mit dem Fehler ENOENT fehl. Daten ist entweder ein Zeiger auf ein Feld struct sock_filter, das gross genug ist, ein BPF-Programm zu speichern, oder NULL, falls das Programm nicht gespeichert werden soll. Im Erfolgsfall ist der Ruckgabewert die Anzahl der Befehle in dem BPF-Programm. Falls Daten NULL war, dann kann dieser Ruckgabewert benutzt werden, um in einem folgenden Aufruf die korrekte Grosse des Feldes struct sock_filter zu ubergeben. Diese Aktion schlagt mit dem Fehler EACCES fehl, falls der Aufrufende nicht die Capability CAP_SYS_ADMIN hat oder falls der Aufrufende in einem strikten oder Filter-Seccomp-Modus ist. Falls der durch Adresse referenzierte Filter kein klassischer BPF-Filter ist, schlagt die Aktion mit dem Fehler EMEDIUMTYPE fehl. Diese Aktion ist verfugbar, falls der Kernel mit den Optionen CONFIG_SECCOMP_FILTER und CONFIG_CHECKPOINT_RESTORE konfiguriert wurde. PTRACE_DETACH startet den gestoppten, verfolgten Prozess wie fur PTRACE_CONT, lost ihn aber zuerst vom Prozess ab. Unter Linux kann ein verfolgter Prozess auf diese Art abgelost werden, ohne Rucksicht darauf zu nehmen, welche Methode zum Starten der Verfolgung benutzt wurde. (Adresse wird ignoriert.) PTRACE_GET_THREAD_AREA (seit Linux 2.6.0) Diese Aktion fuhrt eine ahnliche Aufgabe wie get_thread_area(2) durch. Sie liest den TLS-Eintrag in dem GDT, dessen Index in addr gegeben ist und legt eine Kopie des Eintrags in das durch Daten verwiesende struct user_desc. (Im Gegensatz wird mit get_thread_area(2) die entry_number des struct user_desc ignoriert.) PTRACE_SET_THREAD_AREA (seit Linux 2.6.0) Diese Aktion fuhrt eine ahnliche Aufgabe wie set_thread_area(2) durch. Sie setzt den TLS-Eintrag in dem GDT, dessen Index in Adresse gegeben ist, und weist ihm die in dem durch Daten verwiesenen struct user_desc zu. (Im Gegensatz zu set_thread_area(2) wird die entry_number des struct user_desc ignoriert; mit anderen Worten, diese Ptrace-Aktion kann nicht zur Bereitstellung eines freien TLS-Eintrags verwandt werden.) PTRACE_GET_SYSCALL_INFO (seit Linux 5.3) Ermittelt Informationen uber den Systemaufruf, der den Stopp ausgelost hat. Die Information wird in den Puffer gelegt, auf den das Argument data zeigt, das ein Zeiger auf einen Puffer vom Typ struct ptrace_syscall_info sein sollte. Das Argument addr enthalt die Grosse des Puffers, auf den das Argument data zeigt (d.h. sizeof(struct ptrace_syscall_info)). Der Ruckgabewert enthalt die Anzahl von Bytes, die zum Schreiben durch den Kernel verfugbar sind. Falls die Grosse der durch den Kernel zu schreibenden Bytes die durch das Argument addr angegebene Grosse uberschreiten sollte, wird die Ausgabe abgeschnitten. Die Struktur ptrace_syscall_info enthalt die folgenden Felder: struct ptrace_syscall_info { __u8 op; /* Typ des Systemaufruf-Stopps */ __u32 arch; /* AUDIT_ARCH_*-Wert; siehe seccomp(2) */ __u64 instruction_pointer; /* CPU-Anweisungszeiger */ __u64 stack_pointer; /* CPU-Stack-Zeiger */ union { struct { /* op == PTRACE_SYSCALL_INFO_ENTRY */ __u64 nr; /* Systemaufrufnummer */ __u64 args[6]; /* Systemaufrufargumente */ } entry; struct { /* op == PTRACE_SYSCALL_INFO_EXIT */ __s64 rval; /* Systemaufruf-Ruckgabewert */ __u8 is_error; /* Systemaufruf-Fehlerschalter; logisch: enthalt rval einen Fehlerwert (-ERRCODE) oder einen nichtfehler-Ruckgabewert? */ } exit; struct { /* op == PTRACE_SYSCALL_INFO_SECCOMP */ __u64 nr; /* Systemaufrufnummer */ __u64 args[6]; /* Systemaufrufargumente */ __u32 ret_data; /* SECCOMP_RET_DATA-Anteil vom SECCOMP_RET_TRACE- Ruckgabewert */ } seccomp; }; }; Die Felder op, arch, instruction_pointer und stack_pointer sind fur alle Arten von Ptrace-Systemaufrufstopps definiert. Der Rest der Struktur ist eine Union; Sie sollten nur solche Felder lesen, die fur Ihre Art von Systemaufrufstopp durch das Feld op definiert sind. Das Feld op enthalt einen der folgenden Werte (definiert in ), der anzeigt, welcher Stopp-Typ aufgetreten und welcher Teil der Union gefullt ist: PTRACE_SYSCALL_INFO_ENTRY Die Komponente entry der Union enthalt Informationen mit Bezug zu einem Systemaufruf-Eintrags-Stopp. PTRACE_SYSCALL_INFO_EXIT Die Komponente exit der Union enthalt Informationen mit Bezug zu einem Systemaufruf-Exit-Stopp. PTRACE_SYSCALL_INFO_SECCOMP Die Komponente seccomp der Union enthalt Informationen mit Bezug zu einem PTRACE_EVENT_SECCOMP-Stopp PTRACE_SYSCALL_INFO_NONE Keine Komponente der Union enthalt relevante Informationen. Falls der Systemaufrufeintritt oder -ausstieg beendet wird, werden die von PTRACE_GET_SYSCALL_INFO zuruckgelieferten Daten auf den Typ PTRACE_SYSCALL_INFO_NONE eingeschrankt, ausser die Option PTRACE_O_TRACESYSGOOD wurde gesetzt, bevor die Beendigung des Systemaufrufs aufgetreten ist. Tod unter Ptrace Wenn ein Prozess (der moglicherweise aus mehreren Threads besteht) ein totendes Signal erhalt (eines, dessen Zuordnung auf SIG_DFL gesetzt ist und dessen Standardaktion das Toten des Prozesses ist) werden alle Threads beendet. Verfolgte Prozesse melden ihren Tod an ihre(n) Verfolger. Die Benachrichtigung uber dieses Ereignis wird uber waitpid(2) zugestellt. Beachten Sie, dass das killende Signal zuerst einen Signallieferstopp (auf nur einen verfolgten Prozess) verursachen wird und nur nachdem es durch den Verfolger eingespeist wurde (oder nachdem es an einen nicht verfolgten Thread versandt wurde), wird der Tod von dem Signal auf alle verfolgten Prozesse innerhalb eines Prozesses mit mehreren Threads ausgehen. (Der Begriff >>Signallieferstopp<< wird nachfolgend erklart.) SIGKILL erzeugt keinen >>Signallieferstopp<<. Daher kann der Verfolger es nicht unterdrucken. SIGKILL killt sogar innerhalb von Systemaufrufen (der Systemaufrufbeendigungsstopp wird nicht vorrangig vor dem Tod durch SIGKILL erzeugt). Der reine Effekt besteht darin, dass SIGKILL den Prozess (all seine Threads) immer killt, sogar dann, wenn einige Threads des Prozesses verfolgt werden. Wenn der verfolgte Prozess _exit(2) aufruft, meldet er seinem Verfolger seinen Tod. Andere Threads werden nicht beeinflusst. Wenn irgendein Thread exit_group(2) ausfuhrt, meldet jeder verfolgte Prozess in dessen Gruppe seinen Tod an den Verfolger. Falls die Option PTRACE_O_TRACEEXIT aktiv ist, wird PTRACE_EVENT_EXIT vor dem tatsachlichen Tod auftreten. Dies wird angewandt, um mittels exit(2), exit_group(2) und Todessignalen (ausgenommen SIGKILL, abhangig von der Kernel-Version, siehe FEHLER unten) zu beenden und wenn Threads bei execve(2) in einem Prozess mit mehreren Threads zerrissen werden. Der Verfolger kann nicht abschatzen, ob der von Ptrace gestoppte Prozess existiert. Es gibt mehrere Szenarien, in denen der verfolgte Prozess sterben kann, wahrend er gestoppt ist (wie SIGKILL). Daher muss der Verfolger vorbereitet werden, bei allen Ptrace-Aktionen einen ESRCH-Fehler zu handhaben. Leider wird der gleiche Fehler zuruckgegeben, falls der verfolgte Prozess existiert, aber nicht von Ptrace gestoppt wurde (fur Befehle, die einen gestoppten, verfolgten Prozess erfordern) oder falls er nicht durch den Prozess verfolgt wird, der den Ptrace-Aufruf abschickte. Der Verfolger muss den Uberblick uber den >>laufend<<-/>>gestoppt<<-Status des verfolgten Prozesses behalten und ESRCH nur dann als >>verfolgter Prozess starb unerwartet<< interpretieren, falls er weiss, dass der verfolgte Prozess beobachtet wurde, um in einen Ptrace-Stopp einzutreten. Beachten Sie, dass es keine Garantie gibt, dass waitpid(WNOHANG) zuverlassig den Todesstatus des verfolgten Prozesses meldet, falls eine Ptrace-Aktion ESRCH zuruckgibt. waitpid(WNOHANG) konnte stattdessen 0 zuruckgeben. In anderen Worten kann es sein, dass der verfolgte Prozess >>noch nicht vollstandig tot<< ist, aber bereits Ptrace-Aktionen ablehnt. Der Verfolger kann nicht abschatzen, ob der verfolgte Prozess immer sein Leben durch Melden von WIFEXITED(status) oder WIFSIGNALED(status) aushaucht. Es gibt Falle, in denen dies nicht geschieht. Falls ein Thread, der nicht fuhrender Thread der Thread-Gruppe ist, zum Beispiel ein execve(2) ausfuhrt, verschwindet er; seine PID wird nie wieder gesehen und alle nachfolgenden Ptrace-Stopps werden unter der PID des fuhrenden Threads der Thread-Gruppe gemeldet. Gestoppt-Status Ein verfolgter Prozess kann zwei Status haben: laufend oder gestoppt. Fur die Zwecke von Ptrace wird ein durch einen Systemaufruf (wie read(2), pause(2), etc.) blockierter verfolgter Prozess dennoch als laufend betrachtet, sogar, wenn der verfolgte Prozess fur lange Zeit blockiert ist. Der Status des verfolgten Prozesses nach PTRACE_LISTEN ist eine Grauzone: Er ist nicht in einem Ptrace-Stopp (Ptrace-Befehle funktionieren nicht bei ihm und er wird waitpid(2)-Benachrichtigungen ubermitteln), aber er kann auch als >>gestoppt<< angesehen werden, da er keine Anweisungen ausfuhrt (ist nicht eingeplant) und falls er vor PTRACE_LISTEN in einem Gruppenstopp war, wird er nicht auf Signale antworten, bis er SIGCONT empfangt. Es gibt viele Arten von Status, wenn ein verfolgter Prozess gestoppt wurde und in Ptrace-Diskussionen werden sie oft durcheinandergebracht. Daher ist es wichtig, prazise Begriffe zu verwenden. In dieser Handbuchseite wird jeder Gestoppt-Status, in dem der verfolgte Prozess bereit ist, Ptrace-Befehle vom Verfolger zu akzeptieren, Ptrace-Stopp genannt. Ptrace-Stopps konnen weiter in Signallieferstopp, Gruppenstopp, PTRACE_EVENT stops und so fort unterteilt werden. Diese gestoppten Status werden nachfolgend im Detail beschrieben. Wenn der laufende, verfolgte Prozess in Ptrace-Stopp eintritt, benachrichtigt er seinen Verfolger mittels waitpid(2) (oder einem anderen der >>wait<<-Systemaufrufe). Meistens geht diese Handbuchseite davon aus, dass der Verfolger wartet mit: PID = waitpid(PID_ODER_Minus1, &status, __WALL); Mit Ptrace-Stopp angehaltene, verfolgte Prozesse werden als Ruckgaben mit PID grosser als 0 und >>WIFSTOPPED(status) true<< gemeldet. Der Schalter __WALL enthalt nicht die Schalter WSTOPPED und WEXITED, impliziert aber ihre Funktionalitat. Es wird nicht empfohlen, den Schalter WCONTINUED zu setzen, wenn waitpid(2) aufgerufen wird: Der Status >>continued<< gilt pro Prozess und ihn zu verbrauchen, kann den echten Elternprozess des verfolgten Prozesses verwirren. Die Benutzung des Schalters WNOHANG konnte waitpid(2) veranlassen, 0 zuruckzugeben (>>noch keine Warteergebnisse verfugbar<<), sogar dann, wenn der Verfolger weiss, dass dort eine Benachrichtigung sein soll. Beispiel: errno = 0; ptrace(PTRACE_CONT, pid, 0L, 0L); if (errno == ESRCH) { /* verfolgter Prozess ist tot */ r = waitpid(tracee, &status, __WALL | WNOHANG); /* r kann hier immer noch 0 sein! */ } Die folgenden Arten von Ptrace-Stopps existieren: Signallieferstopps, Gruppenstopps, PTRACE_EVENT-Stopps und Systemaufrufstopps. Sie alle werden von waitpid(2) mit >>WIFSTOPPED(status) true<< gemeldet. Sie konnten durch Untersuchen des Wertes status>>8 unterschieden werden und, falls es eine Unklarheit im Wert gibt, durch Abfragen von PTRACE_GETSIGINFO. (Hinweis: Das Makro WSTOPSIG(status) kann nicht fur diese Untersuchung verwandt werden, da es den Wert (status>>8) & 0xff zuruckgibt.) Signallieferstopp Wenn ein Prozess (moglicherweise mit mehreren Threads) ein Signal ausser SIGKILL empfangt, wahlt der Kernel einen beliebigen Thread aus, der das Signal handhabt. (Falls das Signal mit tgkill(2) erzeugt wurde, kann der Ziel-Thread explizit durch den Aufrufenden ausgewahlt werden.) Falls der ausgewahlte Thread verfolgt wird, tritt er in einen Signallieferstopp ein. An diesem Punkt wird das Signal noch nicht an den Prozess zugestellt und kann durch den Verfolger unterdruckt werden. Falls der Verfolger das Signal nicht unterdruckt, ubergibt er das Signal bei der nachsten Ptrace-Neustartaktion an den verfolgten Prozess. Dieser zweite Schritt der Signalzustellung wird in dieser Handbuchseite Signaleinspeisung genannt. Beachten Sie, dass, falls das Signal blockiert ist, der Signallieferstopp nicht auftritt, bis die Blockade des Signals aufgehoben wurde, mit der ublichen Ausnahme, dass SIGSTOP nicht blockiert werden kann. Der Signallieferstopp wird vom Verfolger als waitpid(2) beobachtet und kehrt mit >>WIFSTOPPED(status) true<< mit dem Signal zuruck, das von WSTOPSIG(status) zuruckgegeben wurde. Falls das Signal SIGTRAP ist, konnte dies eine andere Art eines Ptrace-Stopps sein; Einzelheiten finden Sie in den Abschnitten >>Systemaufrufstopps<< und >>execve<< unterhalb. Falls WSTOPSIG(status) ein stoppendes Signal zuruckgibt, konnte dies ein Gruppenstopp sein; siehe unten. Signaleinspeisung und -unterdruckung Nachdem der Signallieferstopp durch den Verfolger beobachtet wurde, sollte der Verfolger den verfolgten Prozess mit dem Aufruf ptrace(PTRACE_restart, PID, 0, Signal) neu starten, wobei PTRACE_restart einer der neu startenden Ptrace-Aktion ist. Falls Signal 0 ist, wird das Signal nicht zugestellt. Andernfalls wird das Signal Signal zugestellt. Diese Aktion wird in dieser Handbuchseite Signaleinspeisung genannt, um sie vom Signallieferstopp zu unterscheiden. Der Signalwert kann sich vom Wert WSTOPSIG(status) unterschieden: Der Verfolger kann veranlassen, dass ein anderes Signal eingespeist wird. Beachten Sie, dass ein unterdrucktes Signal immer noch Systemaufrufe verursacht, um vorzeitig zuruckzukehren. In diesem Fall werden Systemaufrufe neu gestartet: Der Verfolger wird den verfolgten Prozess beobachten, um den unterbrochenen Systemaufruf neu auszufuhren (oder den Systemaufruf restart_syscall(2) fur wenige Systemaufrufe, die unterschiedliche Mechanismen zum erneuten Starten verwenden), falls der Verfolger PTRACE_SYSCALL benutzt. Sogar Systemaufrufe (wie poll(2)), die nach einem Signal nicht mehr neu startbar sind, werden nach dem Unterdrucken des Signals neu gestartet werden. Es existieren jedoch einige Kernelfehler, die zum Fehlschlagen einiger Systemaufrufe mit EINTR fuhren, sogar, wenn kein beobachtbares Signal in den verfolgten Prozess eingespeist wurde. Es wird nicht garantiert, dass beim Neustarten von Ptrace-Befehlen, die in anderen Ptrace-Stopps als Signallieferstopps angestossen wurden,ein Signal eingespeist wird, nicht einmal, wenn Signal nicht Null ist. Es wird kein Fehler gemeldet; ein Signal ungleich Null konnte einfach ignoriert werden. Ptrace-Benutzer sollten nicht versuchen, auf diese Art >>ein neues Signal zu erzeugen<<: Benutzen Sie stattdessen tgkill(2). Die Tatsache, dass Signaleinspeisungsaktionen beim erneuten Starten des verfolgten Prozesses nach Ptrace-Stopps, die keine Signallieferstopps sind, ignoriert werden konnen, ist ein Grund fur Verwirrung bei Ptrace-Benutzern. Ein typisches Szenario ist, dass der Verfolger Gruppenstopps beobachtet, sie falschlicherweise fur Signallieferstopps halt und den verfolgen Prozess mit ptrace(PTRACE_restart, PID, 0, Stoppsignal) neu startet mit der Absicht Stoppsignal einzuspeisen, Stoppsignal aber ignoriert wird und der verfolgte Prozess weiter lauft. Das Signal SIGCONT hat einen Seiteneffekt, dass es einen Prozess im Gruppenstopp (alle Threads davon) aufweckt. Dieser Seiteneffekt tritt vor dem Signallieferstopp auf. Der Verfolger kann diesen Seiteneffekt nicht unterdrucken (er kann nur Signaleinspeisung unterdrucken, was nur dazu fuhrt, dass die SIGCONT-Handhabung nicht im verfolgten Prozess ausgefuhrt wird, falls eine solche Handhabung installiert ist). Tatsachlich konnte dem Aufwecken aus den Gruppenstopp ein Signallieferstopp fur andere Signale als SIGCONT folgen, falls sie ausstehen, wenn SIGCONT gesandt wurde. In anderen Worten konnte es sein, dass SIGCONT nicht das erste durch den Verfolger beobachtete Signal ist, nachdem es gesandt wurde. Stoppen von Signalen fuhrt dazu, das ein Prozess (alle Threads davon) in einen Gruppenstopp eintritt. Dieser Seiteneffekt tritt nach der Signaleinspeisung auf und kann daher durch den Verfolger unterdruckt werden. In Linux 2.4 und alter kann das Signal SIGSTOP nicht eingespeist werden. PTRACE_GETSIGINFO kann benutzt werden, um eine siginfo_t-Struktur zu erhalten, die dem gesandten Signal entspricht. PTRACE_SETSIGINFO kann benutzt werden, um es zu verandern. Falls PTRACE_SETSIGINFO benutzt wurde, um siginfo_t zu verandern, mussen das Feld si_signo und der Parameter Signal im Befehl zum Neustart ubereinstimmen, andernfalls ist das Ergebnis undefiniert. Gruppenstopp Wenn ein Prozess (der moglicherweise aus mehreren Threads besteht) ein Stoppsignal empfangt, werden alle Threads gestoppt. Falls einige Threads verfolgt werden, treten sie in eine Thread-Gruppe ein. Beachten Sie, dass das Stoppsignal zuerst einen Signallieferstopp verursachen wird (nur auf den verfolgten Prozess) und nur, nachdem es durch den Verfolger eingespeist wurde (oder nachdem es an einen Thread geschickt wurde, der nicht verfolgt wird), wird der Gruppenstopp auf alle verfolgten Prozesse innerhalb eines Prozesses aus mehreren Threads eingeleitet. Wie ublich meldet jeder verfolgte Prozess seinen Gruppenstopp separat an den entsprechenden Verfolger. Der Gruppenstopp wird vom Verfolger als waitpid(2) beobachtet und kehrt mit >>WIFSTOPPED(status) true<< mit dem Stoppsignal zuruck, das uber WSTOPSIG(status) verfugbar ist. Dasselbe Ergebnis wird von einigen anderen Klassen von Ptrace-Stopps zuruckgegeben, daher ist die empfohlene Vorgehensweise, folgenden Aufruf zu tatigen: ptrace(PTRACE_GETSIGINFO, PID, 0, &siginfo) Der Aufruf kann vermieden werden, falls das Signal nicht SIGSTOP, SIGTSTP, SIGTTIN oder SIGTTOU ist. Nur diese vier Signale sind Stoppsignale. Falls der Verfolger etwas anderes sieht, kann es kein Gruppenstopp sein. Andernfalls benotigt der Verfolger den Aufruf PTRACE_GETSIGINFO. Falls PTRACE_GETSIGINFO mit EINVAL fehlschlagt, ist es definitiv ein Gruppenstopp. (Andere Fehlerkodes wie ESRCH (>>kein derartiger Prozess<<) sind moglich, falls ein SIGKILL den verfolgten Prozess gekillt hat. Falls ein verfolgter Prozess mittels PTRACE_SEIZE angehangt wurde, wird ein Gruppenstopp durch PTRACE_EVENT_STOP angezeigt: Status>>16 == PTRACE_EVENT_STOP. Dies ermoglicht, einen Gruppenstopp festzustellen, ohne dass ein zusatzlicher PTRACE_GETSIGINFO-Aufruf erforderlich ist. Ab Linux 2.6.38 wird der verfolgte Prozess, nachdem der Verfolger den Ptrace-Stopp des verfolgten Prozesses sieht und bis er neu startet oder ihn killt, nicht laufen und keine Benachrichtigungen an den Verfolger senden (ausser dem Tod durch SIGKILL), nicht einmal, wenn der Verfolger in einen anderen waitpid(2)-Aufruf gelangt. Das im vorhergehenden Absatz beschriebene Verhalten verursacht ein Problem bei transparenter Behandlung von Stoppsignalen. Falls der Verfolger den verfolgten Prozess nach einem Gruppenstopp neu startet, wird das Stoppsignal effektiv ignoriert - der verfolgte Prozess bleibt nicht gestoppt, er lauft. Falls der Verfolger den verfolgten Prozess neu startet, bevor er in das nachste waitpid(2) eintritt, werden zukunftige SIGCONT-Signale nicht an den Verfolger gemeldet. Dies wurde dazu fuhren, dass die SIGCONT-Signale keine Auswirkungen auf den verfolgten Prozess haben. Seit Linux 3.4 gibt es eine Methode, die dieses Problem bewaltigt: Statt PTRACE_CONT kann ein PTRACE_LISTEN-Befehl zum Neustart eines verfolgten Prozesses auf eine Weise benutzt werden, die ihn nicht ausfuhrt, aber auf ein neues Ereignis wartet, das er uber waitpid(2) melden kann, wenn er zum Beispiel mit SIGCONT neu gestartet wird. PTRACE_EVENT-Stopps Falls der Verfolger PTRACE_O_TRACE_*-Optionen setzt, wird der verfolgte Prozess in PTRACE_EVENT-Stopps genannte Stopps gelangen. PTRACE_EVENT-Stopps werden durch den Verfolger als waitpid(2) beobachtet, kehren mit WIFSTOPPED(status) zuruck und WSTOPSIG(status) gibt SIGTRAP zuruck (oder fur PTRACE_EVENT_STOP: gibt das Stopp-Signal zuruck, falls der verfolgte Prozess in einem Gruppen-Stopp ist). Es wird ein zusatzliches Bit in das hohere Bit des Status (Datentyp Word) gesetzt: Der Wert status>>8 wird wie folgt sein: ((PTRACE_EVENT_foo<<8) | SIGTRAP). Es gibt die folgenden Ereignisse: PTRACE_EVENT_VFORK stoppt vor dem Zuruckkehren von vfork(2) oder clone(2) mit dem Schalter CLONE_VFORK. Wenn der verfolgte Prozess nach diesem Stopp fortgefuhrt wird, wird er auf das Beenden/Ausfuhren des Kindprozesses warten, bevor er mit seiner Ausfuhrung fortfahrt (in anderen Worten, das ubliche Verhalten auf vfork(2)). PTRACE_EVENT_FORK stoppt vor dem Zuruckkehren von fork(2) oder clone(2) mit dem auf SIGCHLD gesetzten Beendigungssignal. PTRACE_EVENT_CLONE stoppt vor dem Zuruckkehren von clone(2). PTRACE_EVENT_VFORK_DONE stoppt vor dem Zuruckkehren von vfork(2) oder clone(2) mit dem Schalter CLONE_VFORK, aber nachdem die Blockade dieses verfolgten Prozesses durch Beenden oder Ausfuhrung aufgehoben wurde. Fur alle vier oben beschriebenen Stopps tritt der Stopp im Elternprozess auf (d.h. im verfolgenden Prozess), nicht im neu erstellten Thread. PTRACE_GETEVENTMSG kann benutzt werden, um die Kennung des neuen Threads zu erhalten. PTRACE_EVENT_EXEC stoppt vor dem Zuruckkehren von execve(2). Ab Linux 3.0, gibt PTRACE_GETEVENTMSG die vorherige Thread-Kennung zuruck. PTRACE_EVENT_EXIT stoppt vor dem Beenden (einschliesslich des Todes aus exit_group(2)), dem Signaltod oder endet, verursacht durch execve(2), in einem Prozess aus mehreren Threads. PTRACE_GETEVENTMSG gibt den Exit-Status zuruck. Register konnen untersucht werden (solange nicht >>wirklich<< beendet wird). Der verfolgte Prozess ist immer noch lebendig; er benotigt zum Fertigstellen des Beendens PTRACE_CONT oder PTRACE_DETACH. PTRACE_EVENT_STOP Stopp, der durch einen PTRACE_INTERRUPT-Befehl, einen Gruppenstopp oder ein >>ptrace-stop<< zu Beginn veranlasst wurde, wenn ein neuer Kindprozess angehangt wird (nur beim Anhangen mittels PTRACE_SEIZE). PTRACE_EVENT_SECCOMP Stopp, der durch eine seccomp(2)-Regel durch den Eintritt des verfolgten Prozesses in einen Systemaufruf ausgelost wird, wenn PTRACE_O_TRACESECCOMP vom Verfolger gesetzt wird. Die Seccomp-Ereignisdaten (von dem Anteil SECCOMP_RET_DATA der Filterregel) konnen durch PTRACE_GETEVENTMSG ermittelt werden. Die Semantik dieses Stopps werden in einem separaten Abschnitt weiter unten beschrieben. PTRACE_GETSIGINFO auf PTRACE_EVENT-Stopps gibt SIGTRAP in si_signo zuruck, wobei si_code auf (event<<8) | SIGTRAP gesetzt ist. Systemaufrufstopps Falls der verfolgte Prozess durch PTRACE_SYSCALL oder PTRACE_SYSEMU neu gestartet wurde, gerat der verfolgte Prozess in einen Systemaufrufeintrittsstopp kurz vor dem Eintritt in irgendeinen Systemaufruf (der nicht ausgefuhrt wird, falls der Neustart PTRACE_SYSEMU verwandte, unabhangig von allen Anderungen, die zu diesem Zeitpunkt an den Registern vorgenommen wurden oder wie der verfolgte Prozess nach diesem Stopp neu gestartet wird). Unabhangig davon, welche Methode den Systemaufrufeintrittsstopp verursachte, falls der Verfolger den verfolgten Prozess mit PTRACE_SYSCALL neu startet, gerat der verfolgte Prozess in einen Systemaufrufbeendigungsstopp, wenn der Systemaufruf beendet ist oder falls er durch ein Signal unterbrochen wurde. (Sprich, der Signallieferstopp tritt nie zwischen Systemaufrufeintrittsstopp und Systemaufrufbeendigungsstopp auf; er findet nach dem Systemaufrufbeendigungsstopp statt.) Falls der verfolgte Prozess mittels irgendeiner anderen Methode fortgesetzt wird (einschliesslich PTRACE_SYSEMU), erfolgt kein Systemaufrufbeendigungsstop. Beachten Sie, dass alle Erwahnungen von PTRACE_SYSEMU genauso auf PTRACE_SYSEMU_SINGLESTEP zutreffen. Selbst falls der verfolgte Prozess mittels PTRACE_SYSCALL fortgesetzt wird, wird nicht garantiert, dass der nachste Stopp ein Systemaufrufbeendigungsstopp sein wird. Andere Moglichkeiten sind, dass der verfolgte Prozess in einem PTRACE_EVENT-Stopp (einschliesslich Seccomp-Stopp) stoppen konnte, endet (falls er in _exit(2) oder exit_group(2) eintritt), durch SIGKILL gekillt wird oder leise stirbt (falls er die Thread-Gruppe anfuhrt, kommt das execve(2) in einem anderen Thread vor und der Thread wird nicht vom selben Verfolger verfolgt; diese Situation wird spater besprochen). Systemaufrufeintrittsstopp und Systemaufrufbeendigungsstopp werden vom Verfolger als waitpid(2) beobachtet, kehren mit >>WIFSTOPPED(status) true<< zuruck und WSTOPSIG(status) gibt SIGTRAP zuruck. Falls die Option PTRACE_O_TRACESYSGOOD durch den Verfolger gesetzt wurde, wird WSTOPSIG(status) den Wert (SIGTRAP | 0x80) zuruckgeben. Systemaufrufstopps konnen von Signallieferstopps mit SIGTRAP durch Abfrage von PTRACE_GETSIGINFO fur die folgenden Falle unterschieden werden: si_code <= 0 SIGTRAP wurde mit einem Ergebnis einer Anwendungsraumaktion, zum Beispiel einem Systemaufruf ((tgkill(2), kill(2), sigqueue(3), etc.), Ablauf eines POSIX-Timers, Statusanderung einer POSIX-Nachrichtenwarteschlange oder Vervollstandigung einer asynchronen E/A-Aktion geliefert. si_code == SI_KERNEL (0x80) SIGTRAP wurde vom Kernel gesandt. si_code == SIGTRAP or si_code == (SIGTRAP|0x80) Dies ist ein Systemaufrufstopp. Systemaufrufstopps kommen jedoch sehr oft vor (zweimal pro Systemaufruf) und das Ausfuhren von PTRACE_GETSIGINFO fur jeden Systemaufrufstopp konnte etwas aufwendig sein. Einige Architekturen erlauben, die Falle durch Untersuchen der Register zu unterscheiden. Zum Beispiel auf x86, rax == -ENOSYS im Systemaufrufeintrittsstopp. Da SIGTRAP (wie jedes andere Signal) immer nach dem Systemaufrufbeendigungsstopp auftritt und rax an diesem Punkt fast nie ENOSYS enthalt, sieht das SIGTRAP aus wie ein >>Systemaufrufstopp, der kein Systemaufrufeintrittsstopp ist<<; in anderen Worten, er sieht aus wie ein >>herrenloser Systemaufrufbeendigungsstopp<< und kann auf diese Art erkannt werden. Aber eine solche Erkennung ist fragil und wird am besten vermieden. Die Benutzung der Option PTRACE_O_TRACESYSGOOD ist die empfohlene Methode, um Systemaufrufstopps von anderen Arten der Ptrace-Stopps zu unterscheiden, da sie zuverlassig ist und sich keine Leistungseinbusse zuzieht. Systemaufrufeintrittsstopp und Systemaufrufbeendigungsstopp sind fur den Verfolger nicht voneinander zu unterscheiden. Der Verfolger muss den Uberblick uber die Abfolge der Ptrace-Stopps behalten, um nicht den Systemaufrufeintrittsstopp falschlicherweise als Systemaufrufbeendigungsstopp oder umgekehrt zu interpretieren. Im Allgemeinen folgt diesem Systemaufrufeintrittsstopp immer ein Systemaufrufbeendigungsstopp, PTRACE_EVENT-Stopp oder der Tod des verfolgten Prozesses; dazwischen konnen keine anderen Arten von Ptrace-Stopps auftreten. Beachten Sie allerdings, dass Seccomp-Stopps (siehe unten) Systemaufrufbeendigungsstopps ohne vorhergehende Systemaufrufeintrittsstopps hervorrufen konnen. Falls Seccomp verwandt wird, muss Sorgfalt eingesetzt werden, um solche Stopps nicht als Systemaufrufeintrittsstopps misszuinterpretieren. Falls der Verfolger nach dem Systemaufrufeintrittsstopp einen anderen Befehl zum Neustarten als PTRACE_SYSCALL verwendet, wird der Systemaufrufbeendigungsstopp nicht erzeugt. PTRACE_GETSIGINFO auf Systemaufrufstopps gibt SIGTRAP in si_signo zuruck, wobei si_code auf SIGTRAP oder (SIGTRAP|0x80) gesetzt ist. PTRACE_EVENT_SECCOMP-Stopps (Linux 3.5 bis 4.7) Das Verhalten des PTRACE_EVENT_SECCOMP-Stopps und seiner Wechselwirkung mit anderen Arten von Ptrace-Stopps hat sich zwischen Kernel-Versionen geandert. Hier wird das Verhalten von seiner Einfuhrung bis Linux 4.7 (einschliesslich) beschrieben. Das Verhalten in neueren Kernelversionen wird im nachsten Abschnitt beschrieben. Ein PTRACE_EVENT_SECCOMP-Stopp erfolgt, wann immer eine SECCOMP_RET_TRACE-Regel ausgelost wird. Dies ist von der Methode, die zum Neustart des Systemaufrufes verwandt wurde, unabhangig. Insbesondere lauft Seccomp immer noch, selbst falls der verfolgte Prozess mittels PTRACE_SYSEMU neu gestartet wurde und dieser Systemaufruf wird bedingungslos ubersprungen. Neustarts aus diesem Stopp verhalten sich so, als ob der Stopp direkt vor dem in Frage stehenden Systemaufruf stattgefunden hatte. Insbesondere werden sowohl PTRACE_SYSCALL als auch PTRACE_SYSEMU normalerweise einen folgenden Systemaufrufeintrittsstopp auslosen. Falls allerdings nach dem PTRACE_EVENT_SECCOMP die Systemaufrufnummer negativ ist, werden sowohl der Systemaufrufeintrittsstopp als auch der Systemaufruf selbst ubersprungen. Das bedeutet, dass falls die Systemaufrufnummer nach dem PTRACE_EVENT_SECCOMP negativ ist und der verfolgte Prozess mittels PTRACE_SYSCALL neu gestartet wird, der nachste beobachtete Stopp ein Systemaufrufbeendigungsstopp statt des vielleicht erwarteten Systemaufrufeintrittsstopps sein wird. PTRACE_EVENT_SECCOMP-Stopps (seit Linux 4.8) Beginnend mit Linux 4.8 wurde der Stopp PTRACE_EVENT_SECCOMP neu geordnet, so dass er zwischen Systemaufrufeintrittsstopp und Systemaufrufbeendigungsstopp auftritt. Beachten Sie, dass Seccomp nicht langer ausgefuhrt wird (und kein PTRACE_EVENT_SECCOMP berichtet wird) falls der Systemaufruf aufgrund PTRACE_SYSEMU ubersprungen wird. Funktional arbeitet ein PTRACE_EVENT_SECCOMP-Stopp vergleichbar mit einem Systemaufrufeintrittsstopp (d.h. Fortsetzungen mittels PTRACE_SYSCALL werden einen Systemaufrufbeendigungsstopp auslosen, die Systemaufrufnummer konnte sich andern und alle anderen veranderten Register sind im gleich auszufuhrenden Systemaufruf ebenfalls sichtbar). Beachten Sie, dass es einen vorhergehenden Systemaufrufeintrittsstopp gegeben haben kann, aber nicht muss. Nach einem Stopp PTRACE_EVENT_SECCOMP wird Seccomp mit einer Regel SECCOMP_RET_TRACE, die identisch zu einer SECCOMP_RET_ALLOW funktioniert, erneut ausgefuhrt. Insbesondere bedeutet dies, dass falls Register nicht wahrend des Stopps PTRACE_EVENT_SECCOMP verandert wurden, der Systemaufruf dann erlaubt wird. PTRACE_SINGLESTEP-Stopps [Einzelheiten dieser Arten von Stopps sind noch nicht dokumentiert.] Benachrichtigende und neustartende Ptrace-Befehle Die meisten Ptrace-Befehle (alle ausser PTRACE_ATTACH, PTRACE_SEIZE, PTRACE_TRACEME, PTRACE_INTERRUPT und PTRACE_KILL) erfordern, dass der verfolgte Prozess in einem Ptrace-Stopp ist, andernfalls scheitern sie mit ESRCH. Wenn der verfolgte Prozess im Ptrace-Stopp ist, kann der Verfolger Daten des verfolgten Prozesses mittels benachrichtigenden Befehlen lesen und schreiben. Diese Befehle belassen den verfolgten Prozess im Status Ptrace-gestoppt: ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, PID, Adresse, 0); ptrace(PTRACE_POKETEXT/POKEDATA/POKEUSER, PID, Adresse, long_val); ptrace(PTRACE_GETREGS/GETFPREGS, PID, 0, &struct); ptrace(PTRACE_SETREGS/SETFPREGS, PID, 0, &struct); ptrace(PTRACE_GETREGSET, PID, NT_foo, &iov); ptrace(PTRACE_SETREGSET, PID, NT_foo, &iov); ptrace(PTRACE_GETSIGINFO, PID, 0, &siginfo); ptrace(PTRACE_SETSIGINFO, PID, 0, &siginfo); ptrace(PTRACE_GETEVENTMSG, PID, 0, &long_var); ptrace(PTRACE_SETOPTIONS, PID, 0, PTRACE_O_flags); Beachten Sie, dass einige Fehler nicht gemeldet wurden. Das Setzen des Informationssignals (siginfo) hat zum Beispiel in einigen Ptrace-Stopps moglicherweise keine Auswirkungen, der Aufruf kann jedoch erfolgreich sein (0 zuruckgeben und errno nicht setzen); Abfragen von PTRACE_GETEVENTMSG konnte erfolgreich sein und einen zufalligen Wert zuruckgeben, falls der aktuelle Ptrace-Stopp nicht dokumentiert ist, um eine aussagekraftige Ereignisnachricht zuruckzugeben. Der Aufruf ptrace(PTRACE_SETOPTIONS, PID, 0, PTRACE_O_flags); beeinflusst einen verfolgten Prozess. Die aktuellen Schalter des verfolgten Prozesses werden ersetzt. Schalter werden geerbt durch neu erzeugte Prozesse und >>automatisch angehangt<< uber aktive PTRACE_O_TRACEFORK-, PTRACE_O_TRACEVFORK- oder PTRACE_O_TRACECLONE-Optionen. Eine weitere Gruppe von Befehlen lasst die per Ptrace gestoppten, verfolgten Prozesse laufen. Sie haben die Form: ptrace(Befehl, PID, 0, Signal); wobei Befehl PTRACE_CONT, PTRACE_LISTEN, PTRACE_DETACH, PTRACE_SYSCALL, PTRACE_SINGLESTEP, PTRACE_SYSEMU oder PTRACE_SYSEMU_SINGLESTEP ist. Falls der verfolgte Prozess sich im Signallieferstopp befindet, ist Signal das Signal, das eingespeist wird (falls es ungleich Null ist). Andernfalls kann Signal ignoriert werden. (Wenn ein verfolgter Prozess von einem anderen Ptrace-Stopp als dem Signallieferstopp neu gestartet wird, ist die empfohlene Vorgehensweise, 0 in Signal zu ubergeben.) Anhangen und Loslosen Ein Thread kann an den Verfolger angehangt werden mit dem Aufruf ptrace(PTRACE_ATTACH, PID, 0, 0); oder ptrace(PTRACE_SEIZE, PID, 0, PTRACE_O_flags); PTRACE_ATTACH sendet ausserdem SIGSTOP an diesen Thread. Falls der Verfolger mochte, dass dieser SIGSTOP keine Auswirkungen hat, muss er ihn unterdrucken. Beachten Sie, dass der Verfolger, falls wahrend des Anhangens gleichzeitig weitere Signale an diesen Thread gesandt werden, den Eintritt in den Signallieferstopp mit anderen Signalen zuerst sieht! Die ubliche Vorgehensweise ist, diese Signale neu einzuspeisen, bis SIGSTOP gesehen wird und dann die Einspeisung von SIGSTOP zu unterdrucken. Der Entwurfsfehler ist hierbei, dass sich ein Ptrace-Anhangen und ein gleichzeitig gesandtes SIGSTOP einen Wettlauf liefern und das gleichzeitige SIGSTOP verloren gegangen sein kann. Da Anhangen SIGSTOP sendet und der Verfolger es ublicherweise unterdruckt, konnte dies zu einer herrenlosen EINTR-Ruckgabe vom aktuell ausgefuhrten Systemaufruf in diesem verfolgten Prozess fuhren, wie er im Abschnitt >>Signaleinspeisung und -unterdruckung<< beschrieben wird. Seit Linux 3.4 kann PTRACE_SEIZE anstelle von PTRACE_ATTACH benutzt werden. PTRACE_SEIZE stoppt nicht den angehangten Prozess. Falls Sie ihn nach dem Anhangen (oder zu einem anderen Zeitpunkt) stoppen wollen ohne irgendwelche Signale zu senden, verwenden Sie den Befehl PTRACE_INTERRUPT. Die Aktion ptrace(PTRACE_TRACEME, 0, 0, 0); verwandelt den aufrufenden Thread in einen verfolgten Prozess. Der Thread fahrt mit der Ausfuhrung fort (gerat nicht in den Ptrace-Stopp). Eine ubliche Vorgehensweise besteht darin, PTRACE_TRACEME mit raise(SIGSTOP); zu folgen und dem Elternprozess (der nun der Verfolger ist) zu ermoglichen, den Signallieferstopp zu beobachten. Falls die Optionen PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK oder PTRACE_O_TRACECLONE in Kraft sind, werden Kindprozesse mit vfork(2), beziehungsweise clone(2) mit dem Schalter CLONE_VFORK, fork(2) oder clone(2) mit auf SIGCHLD gesetztem Beendigungssignal und anderen Arten von clone(2) automatisch an den gleichen Verfolger angehangt, der ihren Elternprozess verfolgte. SIGSTOP wird an die Kindprozesse gesandt, was sie veranlasst, in einen Signallieferstopp zu gelangen, nachdem sie den Systemaufruf beenden, der sie erzeugt hat. Loslosen des verfolgten Prozesses wird erreicht durch: ptrace(PTRACE_DETACH, PID, 0, Signal); PTRACE_DETACH ist eine Neustartaktion; daher erfordert sie, dass der verfolgte Prozess in einem Ptrace-Stopp ist. Falls der verfolgte Prozess in einem Signallieferstopp ist, kann ein Signal eingespeist werden. Andernfalls wird der Parameter Signal stillschweigend ignoriert. Falls der verfolgte Prozess lauft, wenn der Verfolger ihn loslosen mochte, besteht die ubliche Losung darin, SIGSTOP zu senden (mittels tgkill(2), um sicherzustellen, dass es an den korrekten Thread geht), darauf zu warten, dass der verfolgte Prozess in einen Signallieferstopp fur SIGSTOP stoppt und ihn dann loszulosen (SIGSTOP-Einspeisung wird unterdruckt). Ein Entwurfsfehler besteht darin, dass sich dies mit gleichzeitigen SIGSTOPs Ressourcenwettlaufe liefern kann. Eine weitere Komplikation besteht darin, dass der verfolgte Prozess in andere Ptrace-Stopps geraten kann und neu gestartet werden muss und nochmals gewartet werden muss, bis SIGSTOP gesehen wird. Noch eine weitere Komplikation besteht darin, dass nicht sicher ist, ob der verfolgte Prozess nicht bereits mit Ptrace gestoppt wurde, da keine Signallieferung stattfindet, obwohl es noch nicht einmal SIGSTOP ist. Falls der Verfolger stirbt, werden alle verfolgten Prozesse automatisch losgelost und neu gestartet, es sei denn, sie sind im Gruppenstopp. Die Handhabung des Neustarts aus dem Gruppenstopp ist derzeit fehlerhaft, aber das >>wie-geplant<<-Verhalten ist, den verfolgten Prozess gestoppt zu lassen und auf SIGCONT zu warten. Falls der verfolgte Prozess neu vom Signallieferstopp gestartet wurde, wird das ausstehende Signal einspeist. execve(2) unter Ptrace Wenn ein Thread in einem Prozess mit mehreren Threads execve(2) aufruft, zerstort der Kernel alle anderen Threads im Prozess und setzt die Thread-Kennung des ausfuhrenden Threads auf die Gruppenkennung (Prozesskennung) zuruck. (Oder anders ausgedruckt, wenn ein Prozess mit mehreren Threads ein execve(2) bei Vervollstandigung des Aufrufs ausfuhrt, scheint es durch das execve(2) im fuhrenden Thread der Prozessgruppe aufzutreten, unabhangig davon, welcher Thread das execve(2) aufrief.) Dieses Zurucksetzen der Thread-Kennung sieht fur Verfolger sehr verwirrend aus: o Alle anderen Threads stoppen im PTRACE_EVENT_EXIT-Stopp, falls die Option PTRACE_O_TRACEEXIT eingeschaltet wurde. Dann melden alle anderen Threads ausser dem fuhrenden Thread der Gruppe den Tod, als ob sie uber _exit(2) mit dem Exit-Code 0 beendet worden waren. o Der ausfuhrende, verfolgte Prozess andert seine Thread-Kennung, wahrend er in dem execve(2) ist. (Denken Sie daran, unter Ptrace ist die von waitpid(2) zuruckgegebene oder in Ptrace-Aufrufe gespeiste >>PID<<, die Thread-Kennung des verfolgten Prozesses.) Sprich, die Thread-Kennung des verfolgten Prozesses wird zuruckgesetzt, so dass sie ihrer Prozesskennung entspricht, die dieselbe ist, wie die Thread-Kennung des fuhrenden Threads der Thread-Gruppe. o Dann kommt es zu einem PTRACE_EVENT_EXEC-Stopp, falls die Option PTRACE_O_TRACEEXEC eingeschaltet wurde. o Falls der fuhrende Thread der Gruppe seinen PTRACE_EVENT_EXEC-Stopp mittlerweile gemeldet hat, scheint es fur den Verfolger, als ob der tote fuhrende Thread >>aus dem Nichts wieder auftaucht<<. (Hinweis: Der fuhrende Thread der Gruppe meldet den Tod nicht uber WIFEXITED(status) bis es mindestens einen lebenden anderen Thread gibt. Dies eliminiert die Moglichkeit, dass der Verfolger ihn sterben und dann erneut erscheinen sieht.) Falls der fuhrende Thread der Gruppe immer noch lebt, konnte dies fur den Verfolger so aussehen, als ob der fuhrende Thread der Gruppe von einem anderen Systemaufruf als dem beigetretenen zuruckkehrt oder sogar >>von einem Systemaufruf zuruckkehrt, obwohl er in keinem Systemaufruf war<<. Falls der fuhrende Thread der Gruppe nicht verfolgt wurde (oder von einem anderen Verfolger verfolgt wurde), dann wird es wahrend execve(2) so aussehen, als ob er ein verfolgter Prozess des Verfolgers des ausfuhrenden verfolgten Prozesses geworden ware. All die Auswirkungen oberhalb sind Artefakte des Thread-Kennungswechsels im verfolgten Prozess. Die Option PTRACE_O_TRACEEXEC ist das empfohlene Werkzeug fur den Umgang mit dieser Situation. Zuerst aktiviert es PTRACE_EVENT_EXEC-Stopp, der vor der Ruckkehr von execve(2) auftritt. In diesem Stopp kann der Verfolger PTRACE_GETEVENTMSG verwenden, um die vorherige Thread-Kennung des verfolgten Prozesses zu erhalten. (Diese Funktion wurde in Lunux 3.0 eingefuhrt.) Als zweites deaktiviert die Option PTRACE_O_TRACEEXEC die alte SIGTRAP-Erzeugung auf execve(2). Wenn der Verfolger die PTRACE_EVENT_EXEC-Stoppbenachrichtigung empfangt, ist garantiert, dass ausser diesem verfolgten Prozess und dem fuhrenden Thread der Gruppe keine anderen Threads des Prozesses lebendig sind. Beim Empfang der PTRACE_EVENT_EXEC-Stoppbenachrichtigung sollte der Verfolger all seine internen Datenstrukturen aufraumen, die Threads dieses Prozesses beschreiben und nur eine Datenstruktur behalten, - eine, die den einzelnen, laufenden, verfolgten Prozess beschreibt mit Thread-Kennung == Thread-Gruppenkennung == Prozesskennung. Beispiel: Zwei Threads rufen zur gleichen Zeit execve(2) auf: *** wir bekommen einen Systemaufrufeintrittsstopp in Thread 1: ** PID1 execve("/bin/foo", "foo" > *** wir liefern PTRACE_SYSCALL fur Thread 1 ** *** wir bekommen einen Systemaufrufeintrittsstopp in Thread 2: ** PID2 execve("/bin/bar", "bar" > *** wir liefern PTRACE_SYSCALL fur Thread 2 ** *** wir bekommen PTRACE_EVENT_EXEC fur PID0, wir liefern PTRACE_SYSCALL ** *** wir bekommen Systemaufrufbeendigungsstopp fur PID0: ** PID0 < execve wieder aufgenommen> ) = 0 Falls die Option PTRACE_O_TRACEEXEC fur den ausfuhrenden, verfolgten Prozess nicht in Kraft ist und falls der verfolgte Prozess PTRACE_ATTACHed statt PTRACE_SEIZEd war, sendet der Kernel ein zusatzliches SIGTRAP an den verfolgten Prozess, nachdem execve(2) zuruckgekehrt ist. Dies ist ein gewohnliches Signal (ahnlich einem, das durch kill -TRAP erzeugt werden kann), keine Spezialart eines Ptrace-Stopps. Unter Einsatz von PTRACE_GETSIGINFO fur dieses Signal gibt si_code auf 0 gesetzt (SI_USER) zuruck. Dieses Signal kann durch die Signalmaske blockiert sein und konnte daher (viel) spater gesandt werden. Ublicherweise wurde der Verfolger dem Anwender dieses zusatzliche SIGTRAP-Signal nach Execve nicht zeigen wollen und seinen Versand an den verfolgten Prozess unterdrucken (falls SIGTRAP auf SIGTRAP gesetzt ist, killt es das Signal). Es ist jedoch nicht einfach zu bestimmen, welches SIGTRAP zu unterdrucken ist. Die empfohlene Herangehensweise ist, die Option PTRACE_O_TRACEEXEC zu setzen oder PTRACE_SEIZE zu verwenden und damit dieses zusatzliche SIGTRAP zu unterdrucken. Echter Elternprozess Die Ptrace-Programmierschnittstelle (miss)braucht die Standard-UNIX-Eltern-/Kindprozess-Signalgebung uber waitpid(2). Diese wird benutzt, um den echten Elternprozess zum Stopp des Empfangs mehrerer Arten von waitpid(2)-Benachrichtigungen zu veranlassen, wenn der Kindprozess durch einen anderen Prozess verfolgt wird. Viele dieser Fehler wurden behoben, aber ab Linux 2.6.38 existieren etliche immer noch; siehe FEHLER oberhalb. Ab Linux 2.6.38 wird davon ausgegangen, dass folgendes korrekt funktioniert: o Beenden/Sterben durch Signal wird zuerst an den Verfolger gemeldet, dann, wenn der Verfolger das waitpid(2)-Ergebnis verbraucht, an den echten Elternprozess (an den echten Elternprozess nur, wenn der ganze Prozess aus mehreren Threads existiert). Falls der Verfolger und der echte Elternprozess derselbe Prozess sind, wird der Bericht nur einmal gesandt. RUCKGABEWERT Bei Erfolg geben die PTRACE_PEEK*-Aktionen die angeforderten Daten zuruck (aber siehe die ANMERKUNGEN), die Aktion PTRACE_SECCOMP_GET_FILTER liefert die Anzahl der Anweisungen in dem BPF-Programm zuruck, die Aktion PTRACE_GET_SYSCALL_INFO liefert die Anzahl der Byte zuruck, die zum Schreiben durch den Kernel verfugbar sind und andere Aktionen geben Null zuruck. Bei einem Fehler geben alle Aktionen -1 zuruck und errno wird gesetzt, um den Fehler anzuzeigen. Da der Wert, der von einer erfolgreichen Aktion PTRACE_PEEK* zuruckgegeben wurde, -1 sein konnte, muss der Aufrufende vor dem Aufruf errno leeren und es dann hinterher untersuchen, um festzustellen, 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 ungultigen Bereich im Speicher des Verfolgers oder des verfolgten Prozesses zu lesen oder zu schreiben, wahrscheinlich, weil der Bereich nicht abgebildet war oder kein Zugriff moglich war. Unglucklicherweise geben unter Linux mehrere Variationen dieser Ausnahmebehandlung mehr oder weniger willkurlich EIO oder EFAULT zuruck. EINVAL Es wurde versucht, eine ungultige Option zu setzen. EIO Akt ist ungultig, es wurde versucht, in einem ungultigen Bereich im Speicher des Verfolgers oder des verfolgten Prozesses zu lesen oder zu schreiben, es gab eine Verletzung der Ausrichtung an der >>word<<-Grosse oder es wurde wahrend der Neustart-Aktion ein ungultiges Signal angegeben. EPERM Der angegebene Prozess kann nicht verfolgt werden. Dies konnte daher ruhren, dass der Verfolger uber unzureichende Privilegien verfugt (die Capability CAP_SYS_PTRACE wird benotigt); unprivilegierte Prozesse konnen keine Prozesse verfolgen, denen sie keine Signale senden konnen oder die SUID-/SGID-Programme ausfuhren, was naheliegend ist. Alternativ konnte der Prozess bereits verfolgt werden oder (Linux vor 2.6.26) init(1) (PID 1) sein. ESRCH Der angegebene Prozess existiert nicht, wird derzeit nicht vom Aufrufenden verfolgt oder ist nicht gestoppt (bei Aktionen, die einen gestoppten verfolgten Prozess erfordern). STANDARDS Keine. GESCHICHTE SVr4, 4.3BSD. In Linux-Versionen vor 2.6.26 kann init(1) den Prozess mit der Prozessnummer 1 nicht verfolgen. ANMERKUNGEN Obwohl Argumente fur ptrace() gemass dem angegebenen Prototypen interpretiert werden, deklariert Glibc derzeit ptrace() als eine variable Funktion mit nur dem festen Argument Akt. Es wird empfohlen, immer vier Argumente anzugeben, sogar dann, wenn die angeforderte Aktion sie nicht verwendet. Setzen Sie unbenutzte/ignorierte Argumente auf 0L oder (void *) 0. Der Elternprozess des verfolgten Prozesses wird weiterhin der Verfolger sein, selbst wenn der Verfolger execve(2) aufruft. Das Layout des Speicherinhalts und des BENUTZERbereichs sind ziemlich betriebsystem- und architekturspezifisch. Der mitgelieferte Versatz und die zuruckgegebenen Daten passen moglicherweise nicht ganz zu der Definition von struct user. Die Grosse eines >>word<< wird durch die Betriebsystemvariante festgelegt (z.B. ist es fur ein 32-Bit-Linux 32 Bit). Diese Seite dokumentiert die Moglichkeit, wie der ptrace()-Aufruf derzeit in Linux arbeitet. Sein Verhalten unterscheidet sich auf anderen unixoiden Betriebssystemen deutlich. Auf jeden Fall ist die Benutzung von ptrace() in hohem Grad abhangig vom Betriebssystem und der Architektur. Ptrace-Zugriffsmodusuberprufung Verschiedene Teile des Kernel-Benutzerraum-APIs (nicht nur ptrace()-Aktionen) benotigen sogenannte >>Ptrace-Zugriffsmodusuberprufungen<<, deren Ergebnis bestimmt, ob eine Aktion erlaubt (oder, in wenigen Fallen, einer >>Lese<<-Aktion bereinigte Daten zuruckliefern) wird. Diese Uberprufungen werden in Fallen durchgefuhrt, in denen ein Prozess vertrauliche Informationen uber einen anderen Prozess einsehen konnte oder in einigen Fallen den Zustand eines anderen Prozesse verandern konnte. Die Uberprufungen basieren auf Faktoren wie den Berechtigungsnachweisen und den Capabilitys der zwei Prozesse, ob der Speicherinhalt des >>Zielprozesses<< ausgegeben werden kann und dem Ergebnis der Uberprufungen, die durch jedes aktivierte Linux-Sicherheitsmodul (LSM) - zum Beispiel SELinux, Yama oder Smack - und durch das Commoncap-LSM (das immer ausgefuhrt wird), ausgefuhrt wird. Vor Linux 2.6.27 waren alle Zugriffsprufungen von einem einzigen Typ. Seit Linux 2.6.27 werden zwei Zugriffsmodi unterschieden: PTRACE_MODE_READ Fur >>Lese<<-Aktionen oder andere Aktionen, die weniger gefahrlich sind, wie get_robust_list(2); kcmp(2); Lesen aus /proc/PID/auxv, /proc/PID/environ oder /proc/PID/stat; oder readlink(2) einer /proc/PID/ns/*-Datei. PTRACE_MODE_ATTACH Fur >>Schreibe<<-Aktionen oder andere Aktionen, die gefahrlicher sind, wie Ptrace-Anhangungen (PTRACE_ATTACH) an einen anderen Prozess oder Aufrufe von process_vm_writev(2). (PTRACE_MODE_ATTACH war tatsachlich die Vorgabe vor Linux 2.6.27.) Seit Linux 4.5 sind die obigen Zugriffsmodusprufungen mittels ODER mit einem der folgenden Modifikatoren verknupft: PTRACE_MODE_FSCREDS Die Dateisystem-UID und -GID (siehe credentials(7)) oder die effektiven Capabilitys fur LSM-Prufungen des Aufrufenden verwenden. PTRACE_MODE_REALCREDS Die reale UID und GID oder die erlaubten Capabilitys fur LSM-Prufungen des Aufrufenden verwenden. Dies war vor Linux 4.5 die Vorgabe. Da die Kombination eines der Berechtigungsnachweise-Modifikatoren mit einem der vorgenannten Zugriffsmodi typisch ist, sind ein paar Makros in den Kernelquellen fur die Kombinationen definiert. PTRACE_MODE_READ_FSCREDS Definiert als PTRACE_MODE_READ | PTRACE_MODE_FSCREDS. PTRACE_MODE_READ_REALCREDS Definiert als PTRACE_MODE_READ | PTRACE_MODE_REALCREDS. PTRACE_MODE_ATTACH_FSCREDS Definiert als PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS. PTRACE_MODE_ATTACH_REALCREDS Definiert als PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS. Ein weiterer Modifikator kann mit den Zugriffsmodus mittels ODER verknupft werden: PTRACE_MODE_NOAUDIT (seit Linux 3.3) Diese Zugriffsmodusprufung nicht auditieren. Dieser Modifikator wird fur Ptrace-Zugriffsmodusprufungen eingesetzt (wie z.B. Prufungen beim Lesen von /proc/PID/stat), die lediglich die Ausgabe filtern oder bereinigen, statt dem Aufrufenden einen Fehler zuruckzuliefern. In diesen Fallen ist der Zugriff auf die Datei keine Sicherheitsverletzung und es gibt keinen Grund, einen Sicherheitsauditdatensatz zu erstellen. Dieser Modifikator unterdruckt die Erstellung eines solchen Auditdatensatzes fur diese Zugriffsprufung. Beachten Sie, dass alle in diesem Unterabschnitt beschriebenen Konstanten PTRACE_MODE_* kernelintern und nicht im Anwendungsraum sichtbar sind. Die Konstantennamen werden hier benannt, um den verschiedenen Arten von Ptrace-Zugriffsmodusprufungen, die fur verschiedene Systemaufrufe und Zugriff auf verschiedene Pseudodateien (z.B. unter /proc) durchgefuhrt werden, einen Namen zu geben. Diese Namen werden in anderen Handbuchseiten benutzt, um eine einfache Abkurzung fur die Benennung der verschiedenen Kernelprufungen bereitzustellen. Der fur Ptrace-Zugriffsmodusprufungen eingesetzte Algorithmus bestimmt, ob dem aufrufenden Prozess erlaubt wird, die entsprechende Aktion auf dem Zielprozess durchzufuhren. (Im Falle des Offnens von /proc/[PID]-Dateien ist der >>aufrufende Prozess<< derjenige, der die Datei offnet, und der Prozess mit der entsprechenden PID der >>Zielprozess<<). Der Algorithmus geht wie folgt: (1) Falls der aufrufende Thread und der Ziel-Thread in der gleichen Thread-Gruppe sind, wird der Zugriff immer erlaubt. (2) Falls der Zugriffsmodus PTRACE_MODE_FSCREDS festlegt, dann wird fur die Prufung im nachsten Schritt die Dateisystem-UID und -GID des Aufrufenden verwandt. (Wie in credentials(7) vermerkt, haben die Dateisystem-UID und -GID fast immer die gleichen Werte wie die entsprechenden effektiven Kennungen.) Andernfalls legt der Zugriffsmodus PTRACE_MODE_REALCREDS fest, so dass die reale UID und GID fur die Prufungen im nachsten Schritt verwandt werden. (Die meisten APIs, die die UIDs und GIDs des Aufrufenden prufen, verwenden effektive Kennungen. Aus historischen Grunden verwendet die Prufung PTRACE_MODE_REALCREDS stattdessen die realen Kennungen.) (3) Zugriff verweigern, falls keines der Folgenden wahr ist: o Die reale, effektive und saved-set-Benutzerkennungen des Zieles passen auf die der Benutzerkennung des Aufrufenden und die reale, effektive und saved-set-Gruppenkennung des Zieles passen auf die der Gruppenkennung des Aufrufenden. o Der Aufrufende verfugt uber die Capability CAP_SYS_PTRACE in dem Benutzernamensraum des Ziels. (4) Verweigert den Zugriff, falls das Attribut >>dumpable<< einen anderen Wert als 1 (SUID_DUMP_USER, siehe die Diskussion von PR_SET_DUMPABLE in prctl(2)) hat und der Aufrufende nicht uber die Capability CAP_SYS_PTRACE in dem Benutzernamensraum des Zielprozesses verfugt. (5) Die Schnittstelle security_ptrace_access_check() wird aufgerufen, um zu erkennen, ob Ptrace-Zugriff erlaubt ist. Das Ergebnis hangt von dem/den LSM(en) ab. Die Implementierung dieser Schnittstelle im LSM Commoncap fuhrt die folgenden Schritte durch: (5.1) Falls der Zugriffsmodus PTRACE_MODE_FSCREDS enthalt, dann wird die effektive Capability-Menge des Aufrufenden in der nachfolgenden Prufung verwandt, andernfalls (der Zugriffsmodus legt PTRACE_MODE_REALCREDS fest) wird die erlaubte Capability-Menge des Aufrufenden verwandt. (5.2) Zugriff verweigern, falls keines der Folgenden wahr ist: o Der aufrufende und der Zielprozess sind im gleichen Benutzernamensraum und die Capabilitys des Aufrufenden sind eine Obermenge der erlaubten Capabilitys des Zielprozesses. o Der Aufrufende verfugt uber die Capability CAP_SYS_PTRACE in dem Benutzernamensraum des Zielprozesses. Beachten Sie, dass das LSM Commoncap nicht zwischen PTRACE_MODE_READ und PTRACE_MODE_ATTACH unterscheidet. (6) Falls der Zugriff in den vorhergehenden Schritten nicht verweigert wurde, dann wird er erlaubt. /proc/sys/kernel/yama/ptrace_scope Auf Systemen, auf denen das Yama Linux Security Module (LSM) installiert (d.h. der Kernel mit CONFIG_SECURITY_YAMA konfiguriert worden) ist, kann die Datei /proc/sys/kernel/yama/ptrace_scope (verfugbar seit Linux 3.4) zum Einschranken der Nachverfolgung von Prozessen mit ptrace() verwandt werden (und damit auch die Moglichkeit, Werkzeuge wie strace(1) und gdb(1) zu verwenden). Das Ziel einer solchen Einschrankung besteht darin, Angriffseskalationen zu vermeiden, bei denen ein kompromittierter Prozess sich mittels Ptrace-attach an andere sensitive Prozesse (z.B. einem GPG-Agenten oder einer SSH-Sitzung), die dem Benutzer gehoren, anhangen konnte, um zusatzliche Berechtigungsnachweise zu erlangen, die im Speicher existieren, und damit den Umfang des Angriffs zu erhohen. Genauer gesagt begrenzt die Yama LSM zwei Arten von Aktionen: o Jede Aktion, die eine Ptrace-Zugriffsmodusprufung PTRACE_MODE_ATTACH durchfuhrt - beispielsweise ptrace() PTRACE_ATTACH. (Siehe die obige Diskussion >>Ptrace-Zugriffsmodusuberprufung<<). o ptrace() PTRACE_TRACEME. Ein Prozess, der uber die Capability CAP_SYS_PTRACE verfugt, kann die Datei /proc/sys/kernel/yama/ptrace_scope mit einem der folgenden Werte aktualisieren: 0 (>>klassische Ptrace-Berechtigungen<<) Keine zusatzlichen Beschrankungen bei Aktionen, die PTRACE_MODE_ATTACH-Uberprufungen durchfuhren (die uber die von Commoncap und anderen LSMs hinausgehen). PTRACE_TRACEME wird unverandert verwandt. 1 (>>eingeschrankter Ptrace<<) [Vorgabewert] Wenn eine Aktion durchgefuhrt wird, die eine PTRACE_MODE_ATTACH-Uberprufung benotigt, muss der aufrufende Prozess entweder uber die Capability CAP_SYS_PTRACE in dem Benutzernamensraum des Zielprozesses verfugen oder er muss eine vorbestimmte Beziehung zum Zielprozess haben. Standardmassig ist die vorbestimmte Beziehung, dass der Zielprozess ein Nachkomme des Aufrufenden sein muss. Ein Zielprozess kann die prctl(2)-Aktion PR_SET_PTRACER einsetzen, um eine zusatzliche PID zu erklaren, der es erlaubt ist, PTRACE_MODE_ATTACH-Aktionen auf dem Ziel durchzufuhren. Siehe die Kernelquelldatei Documentation/admin-guide/LSM/Yama.rst (oder Documentation/security/Yama.txt vor Linux 4.13) fur weitere Details. PTRACE_TRACEME wird unverandert verwandt. 2 (>>nur Admin-Anhangung<<) Nur Prozesse mit der Capability CAP_SYS_PTRACE im Benutzernamensraum des Zielprozesses durfen PTRACE_MODE_ATTACH-Aktionen durchfuhren oder Kinder, die PTRACE_TRACEME einsetzen, verfolgen. 3 (>>keine Anhangung<<) Kein Prozess darf PTRACE_MODE_ATTACH-Aktionen durchfuhren oder Kindprozesse verfolgen, die PTRACE_TRACEME einsetzen. Sobald dieser Wert in die Datei geschrieben wurde, kann er nicht mehr geandert werden. Beachten Sie im Hinblick auf die Werte 1 und 2, dass die Erstellung eines neuen Benutzernamensraums effektiv den durch Yama bereitgestellten Schutz entfernt. Dies ruhrt daher, dass der Prozess in dem Elternbenutzerraum, dessen effektive UID auf die UID des Erstellers des Kindnamensraums passt, uber alle Capabilitys (einschliesslich CAP_SYS_PTRACE) verfugt, wenn er Aktionen innerhalb des Kindnamensraums (und weiter entfernter Nachkommen dieses Namensraums) durchfuhrt. Wenn ein Prozess versucht, einen Benutzernamensraum zu verwenden, um sich in eine Sandbox zu bringen, wird er konsequenterweise den durch das Yama LSM bereitgestellten Schutz schwachen. Unterschiede C-Bibliothek/Kernel Auf der Systemaufrufebene haben die Aktionen PTRACE_PEEKTEXT, PTRACE_PEEKDATA und PTRACE_PEEKUSER eine unterschiedliche Programmierschnittstelle: Sie speichern das Ergebnis an der durch den Parameter Daten angegebenen Adresse und der Ruckgabewert ist ein Fehlercode. Die Glibc-Wrapper-Funktion stellt die oben in BESCHREIBUNG angegebene Programmierschnittstelle bereit. Ihr Ergebnis wird uber den Ruckgabewert der Funktion zuruckgegeben. FEHLER Auf Rechnern mit 2.6 Linux-Headern ist PTRACE_SETOPTIONS mit einem anderen Wert deklariert, als auf einem fur 2.4. Dies fuhrt dazu, dass Anwendungen, die mit 2.6-Linux-Headern kompiliert wurden, bei der Ausfuhrung auf 2.4er Kerneln scheitern. Dies kann durch Neudefinieren von PTRACE_SETOPTIONS zu PTRACE_OLDSETOPTIONS umgangen werden, wenn dies definiert ist. Gruppenstoppbenachrichtigungen werden an der Verfolger gesandt, aber nicht an den echten Elternprozess. Zuletzt auf 2.6.38.6 bestatigt. Falls ein fuhrender Thread einer Gruppe verfolgt und durch den Aufruf von _exit(2) beendet wird, wird es fur ihn zu einem PTRACE_EVENT_EXIT-Stopp kommen (falls angefordert), aber die nachfolgende WIFEXITED-Benachrichtigung wird nicht gesandt, bis alle anderen Threads beendet sind. Wie oben erklart, wird der Tod des fuhrenden Prozesses der Gruppe gemeldet, falls einer der anderen Threads execve(2) aufruft. Falls der ausgefuhrte Thread nicht durch den Verfolger verfolgt wird, wird der Verfolger niemals erfahren, dass execve(2) auftrat. Eine mogliche Notlosung ist ein PTRACE_DETACH fur den fuhrenden Thread der Gruppe, anstatt ihn in diesem Fall neu zu starten. Zuletzt auf 2.6.38.6 bestatigt. Ein SIGKILL-Signal kann immer noch einen PTRACE_EVENT_EXIT-Stopp vor dem tatsachlichen Signaltod verursachen. Dies konnte in Zukunft geandert werden; SIGKILL ist dazu gedacht, Aufgaben immer sofort zu killen, sogar unter Ptrace. Zuletzt auf Linux 3.13 bestatigt. Einige Systemaufrufe kehren mit EINTR zuruck, falls ein Signal an den verfolgten Prozess gesandt, die Auslieferung aber durch den Verfolger unterdruckt wurde. (Dies ist eine ganz typische Aktion: Sie wird normalerweise von Fehlersuchprogrammen bei jedem Anhangen durchgefuhrt, um kein fingiertes SIGSTOP einzuleiten.) Ab Linux 3.2.9 werden die folgenden Systemaufrufe beeinflusst (diese Liste ist wahrscheinlich nicht vollstandig): epoll_wait(2) und read(2) von einem inotify(7)-Dateideskriptor. Das ubliche Anzeichen fur diesen Fehler ist, falls Sie einen ruhenden Prozess mit dem Befehl strace -p anhangen, dass Sie statt der erwarteten einzeiligen Ausgabe, wie restart_syscall(< resuming interrupted call >_ oder select(6, [5], NULL, [5], NULL_ ('_' kennzeichnet die Cursor-Position) mehr als eine Zeile beobachten konnen, zum Beispiel: clock_gettime(CLOCK_MONOTONIC, {15370, 690928118}) = 0 epoll_wait(4,_ Was hier nicht sichtbar ist, ist, dass der Prozess in epoll_wait(2) blockiert wurde, bevor strace(1) an ihn angehangt hat. Das Anhangen verursachte ein epoll_wait(2), um zum Anwendungsraum mit dem Fehler EINTR zuruckzukehren. In diesem besonderen Fall reagiert das Programm auf EINTR, indem die aktuelle Zeit gepruft und dann epoll_wait(2) erneut ausgefuhrt wird. (Programme, die keine derartigen >>verirrten<< EINTR-Fehler erwarten, konnen sich bei einem strace(1)-Anhangen in unbeabsichtigter Weise verhalten.) Entgegen den normalen Regeln kann der Glibc-Wrapper fur ptrace() errno auf Null setzen. SIEHE AUCH gdb(1), ltrace(1), strace(1), clone(2), execve(2), fork(2), gettid(2), prctl(2), seccomp(2), sigaction(2), tgkill(2), vfork(2), waitpid(2), exec(3), capabilities(7), signal(7) UBERSETZUNG Die deutsche Ubersetzung dieser Handbuchseite wurde von Patrick Rother , Chris Leick , Mario Blattermann und Helge Kreutzmann erstellt. Diese Ubersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezuglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG ubernommen. Wenn Sie Fehler in der Ubersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Ubersetzer . Linux man-pages 6.8 2. Mai 2024 ptrace(2)