ptrace – process trace
Synopsis
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
void *addr, void *data);
Description
The
ptrace() system call provides a means by which one process (the "tracer") may observe and control the execution of another process (the "tracee"), and examine and change the tracee’s memory and registers. It is primarily used to implement breakpoint debugging and system call tracing.
A tracee first needs to be attached to the tracer. Attachment and subsequent commands are per thread: in a multithreaded process, every thread can be individually attached to a (potentially different) tracer, or left not attached and thus not debugged. Therefore, "tracee" always means "(one) thread", never "a (possibly multithreaded) process". Ptrace commands are always sent to a specific tracee using a call of the form
ptrace(PTRACE_foo, pid, …)
where pid is the thread ID of the corresponding Linux thread.
(Note that in this page, a "multithreaded process" means a thread group consisting of threads created using the clone(2) CLONE_THREAD flag.)
A process can initiate a trace by calling fork(2) and having the resulting child do a PTRACE_TRACEME, followed (typically) by an execve(2). Alternatively, one process may commence tracing another process using PTRACE_ATTACH or PTRACE_SEIZE.
While being traced, the tracee will stop each time a signal is delivered, even if the signal is being ignored. (An exception is SIGKILL, which has its usual effect.) The tracer will be notified at its next call to waitpid(2) (or one of the related "wait" system calls); that call will return a status value containing information that indicates the cause of the stop in the tracee. While the tracee is stopped, the tracer can use various ptrace requests to inspect and modify the tracee. The tracer then causes the tracee to continue, optionally ignoring the delivered signal (or even delivering a different signal instead).
If the PTRACE_O_TRACEEXEC option is not in effect, all successful calls to execve(2) by the traced process will cause it to be sent a SIGTRAP signal, giving the parent a chance to gain control before the new program begins execution.
When the tracer is finished tracing, it can cause the tracee to continue executing in a normal, untraced mode via PTRACE_DETACH.
The value of request determines the action to be performed:
- PTRACE_TRACEME
- Indicate that this process is to be traced by its parent. A process probably shouldn’t make this request if its parent isn’t expecting to trace it. (pid, addr, and data are ignored.)
- The PTRACE_TRACEME request is used only by the tracee; the remaining requests are used only by the tracer. In the following requests, pid specifies the thread ID of the tracee to be acted on. For requests other than PTRACE_ATTACH, PTRACE_SEIZE, PTRACE_INTERRUPT, and PTRACE_KILL, the tracee must be stopped.
- PTRACE_PEEKTEXT, PTRACE_PEEKDATA
- Read a word at the address addr in the tracee’s memory, returning the word as the result of the ptrace() call. Linux does not have separate text and data address spaces, so these two requests are currently equivalent. (data is ignored; but see NOTES.)
- PTRACE_PEEKUSER
- Read a word at offset addr in the tracee’s USER area, which holds the registers and other information about the process (see <sys/user.h>). The word is returned as the result of the ptrace() call. Typically, the offset must be word-aligned, though this might vary by architecture. See NOTES. (data is ignored; but see NOTES.)
- PTRACE_POKETEXT, PTRACE_POKEDATA
- Copy the word data to the address addr in the tracee’s memory. As for PTRACE_PEEKTEXT and PTRACE_PEEKDATA, these two requests are currently equivalent.
- PTRACE_POKEUSER
- Copy the word data to offset addr in the tracee’s USER area. As for PTRACE_PEEKUSER, the offset must typically be word-aligned. In order to maintain the integrity of the kernel, some modifications to the USER area are disallowed.
- PTRACE_GETREGS, PTRACE_GETFPREGS
- Copy the tracee’s general-purpose or floating-point registers, respectively, to the address data in the tracer. See <sys/user.h> for information on the format of this data. (addr is ignored.) Note that SPARC systems have the meaning of data and addr reversed; that is, data is ignored and the registers are copied to the address addr. PTRACE_GETREGS and PTRACE_GETFPREGS are not present on all architectures.
- PTRACE_GETREGSET (since Linux 2.6.34)
- Read the tracee’s registers. addr specifies, in an architecture-dependent way, the type of registers to be read. NT_PRSTATUS (with numerical value 1) usually results in reading of general-purpose registers. If the CPU has, for example, floating-point and/or vector registers, they can be retrieved by setting addr to the corresponding NT_foo constant. data points to a struct iovec, which describes the destination buffer’s location and length. On return, the kernel modifies iov.len to indicate the actual number of bytes returned.
- PTRACE_SETREGS, PTRACE_SETFPREGS
- Modify the tracee’s general-purpose or floating-point registers, respectively, from the address data in the tracer. As for PTRACE_POKEUSER, some general-purpose register modifications may be disallowed. (addr is ignored.) Note that SPARC systems have the meaning of data and addr reversed; that is, data is ignored and the registers are copied from the address addr. PTRACE_SETREGS and PTRACE_SETFPREGS are not present on all architectures.
- PTRACE_SETREGSET (since Linux 2.6.34)
- Modify the tracee’s registers. The meaning of addr and data is analogous to PTRACE_GETREGSET.
- PTRACE_GETSIGINFO (since Linux 2.3.99-pre6)
- Retrieve information about the signal that caused the stop. Copy a siginfo_t structure (see sigaction(2)) from the tracee to the address data in the tracer. (addr is ignored.)
- PTRACE_SETSIGINFO (since Linux 2.3.99-pre6)
- Set signal information: copy a siginfo_t structure from the address data in the tracer to the tracee. This will affect only signals that would normally be delivered to the tracee and were caught by the tracer. It may be difficult to tell these normal signals from synthetic signals generated by ptrace() itself. (addr is ignored.)
- PTRACE_PEEKSIGINFO (since Linux 3.10)
- Retrieve siginfo_t structures without removing signals from a queue. addr points to a ptrace_peeksiginfo_args structure that specifies the ordinal position from which copying of signals should start, and the number of signals to copy. siginfo_t structures are copied into the buffer pointed to by data. The return value contains the number of copied signals (zero indicates that there is no signal corresponding to the specified ordinal position). Within the returned siginfo structures, the si_code field includes information (__SI_CHLD, __SI_FAULT, etc.) that are not otherwise exposed to user space.
struct ptrace_peeksiginfo_args {
u64 off; /* Ordinal position in queue at which
to start copying signals */
u32 flags; /* PTRACE_PEEKSIGINFO_SHARED or 0 */
s32 nr; /* Number of signals to copy */ };
- Currently, there is only one flag, PTRACE_PEEKSIGINFO_SHARED, for dumping signals from the process-wide signal queue. If this flag is not set, signals are read from the per-thread queue of the specified thread.
- PTRACE_GETSIGMASK (since Linux 3.11)
- Place a copy of the mask of blocked signals (see sigprocmask(2)) in the buffer pointed to by data, which should be a pointer to a buffer of type sigset_t. The addr argument contains the size of the buffer pointed to by data (i.e., sizeof(sigset_t)).
- PTRACE_SETSIGMASK (since Linux 3.11)
- Change the mask of blocked signals (see sigprocmask(2)) to the value specified in the buffer pointed to by data, which should be a pointer to a buffer of type sigset_t. The addr argument contains the size of the buffer pointed to by data (i.e., sizeof(sigset_t)).
- PTRACE_SETOPTIONS (since Linux 2.4.6; see BUGS for caveats)
- Set ptrace options from data. (addr is ignored.) data is interpreted as a bit mask of options, which are specified by the following flags:
- PTRACE_O_EXITKILL (since Linux 3.8)
- Send a SIGKILL signal to the tracee if the tracer exits. This option is useful for ptrace jailers that want to ensure that tracees can never escape the tracer’s control.
- PTRACE_O_TRACECLONE (since Linux 2.5.46)
- Stop the tracee at the next clone(2) and automatically start tracing the newly cloned process, which will start with a SIGSTOP, or PTRACE_EVENT_STOP if PTRACE_SEIZE was used. A waitpid(2) by the tracer will return a status value such that
status>>8 == (SIGTRAP | (PTRACE_EVENT_CLONE<<8))
- The PID of the new process can be retrieved with PTRACE_GETEVENTMSG.
- This option may not catch clone(2) calls in all cases. If the tracee calls clone(2) with the CLONE_VFORK flag, PTRACE_EVENT_VFORK will be delivered instead if PTRACE_O_TRACEVFORK is set; otherwise if the tracee calls clone(2) with the exit signal set to SIGCHLD, PTRACE_EVENT_FORK will be delivered if PTRACE_O_TRACEFORK is set.
- PTRACE_O_TRACEEXEC (since Linux 2.5.46)
- Stop the tracee at the next execve(2). A waitpid(2) by the tracer will return a status value such that
status>>8 == (SIGTRAP | (PTRACE_EVENT_EXEC<<8))
- If the execing thread is not a thread group leader, the thread ID is reset to thread group leader’s ID before this stop. Since Linux 3.0, the former thread ID can be retrieved with PTRACE_GETEVENTMSG.
- PTRACE_O_TRACEEXIT (since Linux 2.5.60)
- Stop the tracee at exit. A waitpid(2) by the tracer will return a status value such that
status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8))
- The tracee’s exit status can be retrieved with PTRACE_GETEVENTMSG.
- The tracee is stopped early during process exit, when registers are still available, allowing the tracer to see where the exit occurred, whereas the normal exit notification is done after the process is finished exiting. Even though context is available, the tracer cannot prevent the exit from happening at this point.
- PTRACE_O_TRACEFORK (since Linux 2.5.46)
- Stop the tracee at the next fork(2) and automatically start tracing the newly forked process, which will start with a SIGSTOP, or PTRACE_EVENT_STOP if PTRACE_SEIZE was used. A waitpid(2) by the tracer will return a status value such that
status>>8 == (SIGTRAP | (PTRACE_EVENT_FORK<<8))
- The PID of the new process can be retrieved with PTRACE_GETEVENTMSG.
- PTRACE_O_TRACESYSGOOD (since Linux 2.4.6)
- When delivering system call traps, set bit 7 in the signal number (i.e., deliver SIGTRAP|0x80). This makes it easy for the tracer to distinguish normal traps from those caused by a system call.
- PTRACE_O_TRACEVFORK (since Linux 2.5.46)
- Stop the tracee at the next vfork(2) and automatically start tracing the newly vforked process, which will start with a SIGSTOP, or PTRACE_EVENT_STOP if PTRACE_SEIZE was used. A waitpid(2) by the tracer will return a status value such that
status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK<<8))
- The PID of the new process can be retrieved with PTRACE_GETEVENTMSG.
- PTRACE_O_TRACEVFORKDONE (since Linux 2.5.60)
- Stop the tracee at the completion of the next vfork(2). A waitpid(2) by the tracer will return a status value such that
status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK_DONE<<8))
- The PID of the new process can (since Linux 2.6.18) be retrieved with PTRACE_GETEVENTMSG.
- PTRACE_O_TRACESECCOMP (since Linux 3.5)
- Stop the tracee when a seccomp(2) SECCOMP_RET_TRACE rule is triggered. A waitpid(2) by the tracer will return a status value such that
status>>8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP<<8))
- While this triggers a PTRACE_EVENT stop, it is similar to a syscall-enter-stop. For details, see the note on PTRACE_EVENT_SECCOMP below. The seccomp event message data (from the SECCOMP_RET_DATA portion of the seccomp filter rule) can be retrieved with PTRACE_GETEVENTMSG.
- PTRACE_O_SUSPEND_SECCOMP (since Linux 4.3)
- Suspend the tracee’s seccomp protections. This applies regardless of mode, and can be used when the tracee has not yet installed seccomp filters. That is, a valid use case is to suspend a tracee’s seccomp protections before they are installed by the tracee, let the tracee install the filters, and then clear this flag when the filters should be resumed. Setting this option requires that the tracer have the CAP_SYS_ADMIN capability, not have any seccomp protections installed, and not have PTRACE_O_SUSPEND_SECCOMP set on itself.
- PTRACE_GETEVENTMSG (since Linux 2.5.46)
- Retrieve a message (as an unsigned long) about the ptrace event that just happened, placing it at the address data in the tracer. For PTRACE_EVENT_EXIT, this is the tracee’s exit status. For PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK, PTRACE_EVENT_VFORK_DONE, and PTRACE_EVENT_CLONE, this is the PID of the new process. For PTRACE_EVENT_SECCOMP, this is the seccomp(2) filter’s SECCOMP_RET_DATA associated with the triggered rule. (addr is ignored.)
- PTRACE_CONT
- Restart the stopped tracee process. If data is nonzero, it is interpreted as the number of a signal to be delivered to the tracee; otherwise, no signal is delivered. Thus, for example, the tracer can control whether a signal sent to the tracee is delivered or not. (addr is ignored.)
- PTRACE_SYSCALL, PTRACE_SINGLESTEP
- Restart the stopped tracee as for PTRACE_CONT, but arrange for the tracee to be stopped at the next entry to or exit from a system call, or after execution of a single instruction, respectively. (The tracee will also, as usual, be stopped upon receipt of a signal.) From the tracer’s perspective, the tracee will appear to have been stopped by receipt of a SIGTRAP. So, for PTRACE_SYSCALL, for example, the idea is to inspect the arguments to the system call at the first stop, then do another PTRACE_SYSCALL and inspect the return value of the system call at the second stop. The data argument is treated as for PTRACE_CONT. (addr is ignored.)
- PTRACE_SET_SYSCALL (since Linux 2.6.16)
- When in syscall-enter-stop, change the number of the system call that is about to be executed to the number specified in the data argument. The addr argument is ignored. This request is currently supported only on arm (and arm64, though only for backwards compatibility), but most other architectures have other means of accomplishing this (usually by changing the register that the userland code passed the system call number in).
- PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP (since Linux 2.6.14)
- For PTRACE_SYSEMU, continue and stop on entry to the next system call, which will not be executed. See the documentation on syscall-stops below. For PTRACE_SYSEMU_SINGLESTEP, do the same but also singlestep if not a system call. This call is used by programs like User Mode Linux that want to emulate all the tracee’s system calls. The data argument is treated as for PTRACE_CONT. The addr argument is ignored. These requests are currently supported only on x86.
- PTRACE_LISTEN (since Linux 3.4)
- Restart the stopped tracee, but prevent it from executing. The resulting state of the tracee is similar to a process which has been stopped by a SIGSTOP (or other stopping signal). See the "group-stop" subsection for additional information. PTRACE_LISTEN works only on tracees attached by PTRACE_SEIZE.
- PTRACE_KILL
- Send the tracee a SIGKILL to terminate it. (addr and data are ignored.)
- This operation is deprecated; do not use it! Instead, send a SIGKILL directly using kill(2) or tgkill(2). The problem with PTRACE_KILL is that it requires the tracee to be in signal-delivery-stop, otherwise it may not work (i.e., may complete successfully but won’t kill the tracee). By contrast, sending a SIGKILL directly has no such limitation.
- PTRACE_INTERRUPT (since Linux 3.4)
- Stop a tracee. If the tracee is running or sleeping in kernel space and PTRACE_SYSCALL is in effect, the system call is interrupted and syscall-exit-stop is reported. (The interrupted system call is restarted when the tracee is restarted.) If the tracee was already stopped by a signal and PTRACE_LISTEN was sent to it, the tracee stops with PTRACE_EVENT_STOP and WSTOPSIG(status) returns the stop signal. If any other ptrace-stop is generated at the same time (for example, if a signal is sent to the tracee), this ptrace-stop happens. If none of the above applies (for example, if the tracee is running in user space), it stops with PTRACE_EVENT_STOP with WSTOPSIG(status) == SIGTRAP. PTRACE_INTERRUPT only works on tracees attached by PTRACE_SEIZE.
- PTRACE_ATTACH
- Attach to the process specified in pid, making it a tracee of the calling process. The tracee is sent a SIGSTOP, but will not necessarily have stopped by the completion of this call; use waitpid(2) to wait for the tracee to stop. See the "Attaching and detaching" subsection for additional information. (addr and data are ignored.)
- Permission to perform a PTRACE_ATTACH is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check; see below.
- PTRACE_SEIZE (since Linux 3.4)
- Attach to the process specified in pid, making it a tracee of the calling process. Unlike PTRACE_ATTACH, PTRACE_SEIZE does not stop the process. Group-stops are reported as PTRACE_EVENT_STOP and WSTOPSIG(status) returns the stop signal. Automatically attached children stop with PTRACE_EVENT_STOP and WSTOPSIG(status) returns SIGTRAP instead of having SIGSTOP signal delivered to them. execve(2) does not deliver an extra SIGTRAP. Only a PTRACE_SEIZEd process can accept PTRACE_INTERRUPT and PTRACE_LISTEN commands. The "seized" behavior just described is inherited by children that are automatically attached using PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK, and PTRACE_O_TRACECLONE. addr must be zero. data contains a bit mask of ptrace options to activate immediately.
- Permission to perform a PTRACE_SEIZE is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check; see below.
- PTRACE_SECCOMP_GET_FILTER (since Linux 4.4)
- This operation allows the tracer to dump the tracee’s classic BPF filters.
- addr is an integer specifying the index of the filter to be dumped. The most recently installed filter has the index 0. If addr is greater than the number of installed filters, the operation fails with the error ENOENT.
- data is either a pointer to a struct sock_filter array that is large enough to store the BPF program, or NULL if the program is not to be stored.
- Upon success, the return value is the number of instructions in the BPF program. If data was NULL, then this return value can be used to correctly size the struct sock_filter array passed in a subsequent call.
- This operation fails with the error EACCES if the caller does not have the CAP_SYS_ADMIN capability or if the caller is in strict or filter seccomp mode. If the filter referred to by addr is not a classic BPF filter, the operation fails with the error EMEDIUMTYPE.
- This operation is available if the kernel was configured with both the CONFIG_SECCOMP_FILTER and the CONFIG_CHECKPOINT_RESTORE options.
- PTRACE_DETACH
- Restart the stopped tracee as for PTRACE_CONT, but first detach from it. Under Linux, a tracee can be detached in this way regardless of which method was used to initiate tracing. (addr is ignored.)
- PTRACE_GET_THREAD_AREA (since Linux 2.6.0)
- This operation performs a similar task to get_thread_area(2). It reads the TLS entry in the GDT whose index is given in addr, placing a copy of the entry into the struct user_desc pointed to by data. (By contrast with get_thread_area(2), the entry_number of the struct user_desc is ignored.)
- PTRACE_SET_THREAD_AREA (since Linux 2.6.0)
- This operation performs a similar task to set_thread_area(2). It sets the TLS entry in the GDT whose index is given in addr, assigning it the data supplied in the struct user_desc pointed to by data. (By contrast with set_thread_area(2), the entry_number of the struct user_desc is ignored; in other words, this ptrace operation can’t be used to allocate a free TLS entry.)
- PTRACE_GET_SYSCALL_INFO (since Linux 5.3)
- Retrieve information about the system call that caused the stop. The information is placed into the buffer pointed by the data argument, which should be a pointer to a buffer of type struct ptrace_syscall_info. The addr argument contains the size of the buffer pointed to by the data argument (i.e., sizeof(struct ptrace_syscall_info)). The return value contains the number of bytes available to be written by the kernel. If the size of the data to be written by the kernel exceeds the size specified by the addr argument, the output data is truncated.
- The ptrace_syscall_info structure contains the following fields:
- struct ptrace_syscal_info {
__u8 op; /* Type of system call stop */
__u32 arch; /* AUDIT_ARCH_* value; see seccomp(2) */
__u64 instruction_pointer; /* CPU instruction pointer */
__u64 stack_pointer; /* CPU stack pointer */
union {
struct { /* op == PTRACE_SYSCALL_INFO_ENTRY */
__u64 nr; /* System call number */
__u64 args[6]; /* System call arguments */
} entry;
struct { /* op == PTRACE_SYSCALL_INFO_EXIT */
__s64 rval; /* System call return value */
__u8 is_error; /* System call error flag;
Boolean: does rval contain
an error value (-ERRCODE) or
a nonerror return value? */