ptrace(2) System Calls Manual ptrace(2) ptrace - C (libc, -lc) #include long ptrace(enum __ptrace_request op, pid_t pid, void *addr, void *data); ptrace() (<<>>) (<<>>), . , . , . : ( ), . << >> <<() >>, << ( )>>. ptrace ptrace(PTRACE_foo, pid, ) pid -- Linux. , << >> , , clone(2) CLONE_THREAD. fork(2), PTRACE_TRACEME, () execve(2). PTRACE_ATTACH 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 operations 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). PTRACE_O_TRACEEXEC , execve(2) SIGTRAP, , . PTRACE_DETACH. The value of op determines the operation to be performed: PTRACE_TRACEME Indicate that this process is to be traced by its parent. A process probably shouldn't make this operation if its parent isn't expecting to trace it. (pid, addr, and data are ignored.) The PTRACE_TRACEME operation is used only by the tracee; the remaining operations are used only by the tracer. In the following operations, pid specifies the thread ID of the tracee to be acted on. For operations 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 operations are currently equivalent. (data is ignored; but see NOTES.) PTRACE_PEEKUSER addr USER , ( ). ptrace(). , , . ( data ; ). 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 operations are currently equivalent. PTRACE_POKEUSER data addr USER . PTRACE_PEEKUSER, . , , USER . PTRACE_GETREGS PTRACE_GETFPREGS , , data. ( addr ). , SPARC data addr ; data , addr. PTRACE_GETREGS PTRACE_GETFPREGS . PTRACE_GETREGSET ( Linux 2.6.34) . addr , , . NT_PRSTATUS ( 1) . , , , addr NT_foo. data struct iovec, . iov.len, . PTRACE_SETREGS PTRACE_SETFPREGS , , data. c PTRACE_POKEUSER, ( addr ). , SPARC data addr ; data , , addr. PTRACE_SETREGS PTRACE_SETFPREGS . PTRACE_SETREGSET ( Linux 2.6.34) . addr data PTRACE_GETREGSET. PTRACE_GETSIGINFO ( Linux 2.3.99-pre6) , . siginfo_t ( sigaction(2)) data ( addr ). PTRACE_SETSIGINFO ( Linux 2.3.99-pre6) . siginfo_t, data , . , . ptrace() ( addr ). PTRACE_PEEKSIGINFO ( Linux 3.10) siginfo_t . addr ptrace_peeksiginfo_args, , , . siginfo_t , data. ( , ). siginfo si_code (__SI_CHLD, __SI_FAULT . .), - . struct ptrace_peeksiginfo_args { u64 off; /* , */ u32 flags; /* PTRACE_PEEKSIGINFO_SHARED 0 */ s32 nr; /* */ }; , PTRACE_PEEKSIGINFO_SHARED, . , . PTRACE_GETSIGMASK ( Linux 3.11) ( sigprocmask(2)) , data ( sigset_t). addr , data (. . sizeof(sigset_t)). PTRACE_SETSIGMASK ( Linux 3.11) ( sigprocmask(2)) , data ( sigset_t). addr , data (. . sizeof(sigset_t)). PTRACE_SETOPTIONS ( Linux 2.4.6; . ) ptrace data ( addr ). data , : PTRACE_O_EXITKILL ( Linux 3.8) SIGKILL , . ptrace, , - . PTRACE_O_TRACECLONE ( Linux 2.5.46) clone(2) , SIGSTOP PTRACE_EVENT_STOP, PTRACE_SEIZE. waitpid(2) status, status>>8 == (SIGTRAP | (PTRACE_EVENT_CLONE<<8)) PID PTRACE_GETEVENTMSG. clone(2) . clone(2) CLONE_VFORK, PTRACE_EVENT_VFORK, PTRACE_O_TRACEVFORK; , clone(2) SIGCHLD, PTRACE_EVENT_FORK, PTRACE_O_TRACEFORK. PTRACE_O_TRACEEXEC ( Linux 2.5.46) execve(). waitpid(2) status, status>>8 == (SIGTRAP | (PTRACE_EVENT_EXEC<<8)) , . Linux 3.0, PTRACE_GETEVENTMSG. PTRACE_O_TRACEEXIT ( Linux 2.5.60) (exit). waitpid() status, status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8)) PTRACE_GETEVENTMSG. , , ( ). , . PTRACE_O_TRACEFORK ( Linux 2.5.46) fork(2) fork , SIGSTOP PTRACE_EVENT_STOP, PTRACE_SEIZE. waitpid(2) status, status>>8 == (SIGTRAP | (PTRACE_EVENT_FORK<<8)) PID PTRACE_GETEVENTMSG. PTRACE_O_TRACESYSGOOD ( Linux 2.4.6) , 7 (. ., SIGTRAP|0x80). , . PTRACE_O_TRACEVFORK ( Linux 2.5.46) vfork(2) vfork , SIGSTOP PTRACE_EVENT_STOP, PTRACE_SEIZE. waitpid(2) status, status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK<<8)) PID PTRACE_GETEVENTMSG. PTRACE_O_TRACEVFORKDONE ( Linux 2.5.60) vfork(2). waitpid(2) status, status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK_DONE<<8)) PID ( Linux 2.6.18) PTRACE_GETEVENTMSG. PTRACE_O_TRACESECCOMP ( Linux 3.5) seccomp(2) SECCOMP_RET_TRACE. waitpid(2) status, status>>8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP<<8)) PTRACE_EVENT, syscall-enter-stop. PTRACE_EVENT_SECCOMP . seccomp ( SECCOMP_RET_DATA seccomp) PTRACE_GETEVENTMSG. PTRACE_O_SUSPEND_SECCOMP ( Linux 4.3) seccomp . seccomp. , seccomp , , , , . , CAP_SYS_ADMIN, seccomp PTRACE_O_SUSPEND_SECCOMP. PTRACE_GETEVENTMSG ( Linux 2.5.46) ( unsigned long) ptrace, , data . PTRACE_EVENT_EXIT . PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK, PTRACE_EVENT_VFORK_DONE PTRACE_EVENT_CLONE PID . PTRACE_EVENT_SECCOMP SECCOMP_RET_DATA seccomp(2), ( addr ). PTRACE_CONT . data , , ; . , , ( addr ). PTRACE_SYSCALL PTRACE_SINGLESTEP PTRACE_CONT , , / , , ( , , ). , - SIGTRAP. , PTRACE_SYSCALL , , PTRACE_SYSCALL . data PTRACE_CONT ( addr ). PTRACE_SET_SYSCALL ( 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 operation 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 operations are currently supported only on x86. PTRACE_LISTEN ( Linux 3.4) , . , SIGSTOP ( ). <>. PTRACE_LISTEN , PTRACE_SEIZE. PTRACE_KILL SIGKILL ( addr data ). ; ! SIGKILL kill(2) tgkill(2). PTRACE_KILL , , signal-delivery-stop, (. ., , ). , SIGKILL . PTRACE_INTERRUPT ( Linux 3.4) . PTRACE_SYSCALL, syscall-exit-stop ( ). PTRACE_LISTEN, PTRACE_EVENT_STOP WSTOPSIG(status) . ptrace-stop (, ), ptrace-stop. (, ), PTRACE_EVENT_STOP WSTOPSIG(status) == SIGTRAP. PTRACE_INTERRUPT , PTRACE_SEIZE. PTRACE_ATTACH pid, . SIGSTOP, , ; waitpid(2) . << >> ( addr data ). PTRACE_ATTACH ptrace PTRACE_MODE_READ_REALCREDS; . PTRACE_SEIZE ( Linux 3.4) , pid, . PTRACE_ATTACH, PTRACE_SEIZE . group-stops PTRACE_EVENT_STOP WSTOPSIG(status) . PTRACE_EVENT_STOP WSTOPSIG(status) SIGTRAP SIGSTOP. execve(2) SIGTRAP . PTRACE_SEIZE PTRACE_INTERRUPT PTRACE_LISTEN. <<>> (seized) , PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK PTRACE_O_TRACECLONE. addr . data ptrace, . PTRACE_SEIZE ptrace PTRACE_MODE_READ_REALCREDS; . PTRACE_SECCOMP_GET_FILTER ( Linux 4.4) BPF . addr integer . 0. addr , ENOENT. data struct sock_filter BPF, NULL, . -- BPF. data NULL, , struct sock_filter , . EACCES, CAP_SYS_ADMIN, . , addr, BPF, EMEDIUMTYPE. , CONFIG_SECCOMP_FILTER CONFIG_CHECKPOINT_RESTORE. PTRACE_DETACH , PTRACE_CONT, . Linux , ( addr ). PTRACE_GET_THREAD_AREA ( Linux 2.6.0) , get_thread_area(2). TLS GDT, addr, struct user_desc, data ( get_thread_area(2), entry_number struct user_desc ). PTRACE_SET_THREAD_AREA ( Linux 2.6.0) , set_thread_area(2). TLS GDT, addr, , struct user_desc, data ( set_thread_area(2), entry_number struct user_desc ; , ptrace TLS). PTRACE_GET_SYSCALL_INFO ( Linux 5.3) , . , data, struct ptrace_syscall_info. addr , data (. ., sizeof(struct ptrace_syscall_info)). , . addr, . ptrace_syscall_info : struct ptrace_syscall_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? */ } exit; struct { /* op == PTRACE_SYSCALL_INFO_SECCOMP */ __u64 nr; /* System call number */ __u64 args[6]; /* System call arguments */ __u32 ret_data; /* SECCOMP_RET_DATA portion of SECCOMP_RET_TRACE return value */ } seccomp; }; }; op, arch, instruction_pointer stack_pointer ptrace. ; , , op. op ( ), : PTRACE_SYSCALL_INFO_ENTRY entry . PTRACE_SYSCALL_INFO_EXIT exit . PTRACE_SYSCALL_INFO_SECCOMP seccomp PTRACE_EVENT_SECCOMP. PTRACE_SYSCALL_INFO_NONE . In case of system call entry or exit stops, the data returned by PTRACE_GET_SYSCALL_INFO is limited to type PTRACE_SYSCALL_INFO_NONE unless PTRACE_O_TRACESYSGOOD option is set before the corresponding system call stop has occurred. ptrace (, ) (- , SIG_DFL ), (exit). . waitpid(2). , signal-delivery-stop ( ), ( , , ), ( <> ). SIGKILL signal-delivery-stop . SIGKILL (syscall-exit-stop SIGKILL). SIGKILL ( ), . _exit(2), . . - exit_group(2), . PTRACE_O_TRACEEXIT, PTRACE_EVENT_EXIT. exit(2), exit_group(2) - ( SIGKILL, ; ) execve(2). The tracer cannot assume that the ptrace-stopped tracee exists. There are many scenarios when the tracee may die while stopped (such as SIGKILL). Therefore, the tracer must be prepared to handle an ESRCH error on any ptrace operation. Unfortunately, the same error is returned if the tracee exists but is not ptrace-stopped (for commands which require a stopped tracee), or if it is not traced by the process which issued the ptrace call. The tracer needs to keep track of the stopped/running state of the tracee, and interpret ESRCH as "tracee died unexpectedly" only if it knows that the tracee has been observed to enter ptrace-stop. Note that there is no guarantee that waitpid(WNOHANG) will reliably report the tracee's death status if a ptrace operation returned ESRCH. waitpid(WNOHANG) may return 0 instead. In other words, the tracee may be "not yet fully dead", but already refusing ptrace operations. , WIFEXITED(status) WIFSIGNALED(status); , . , -- -- execve(2) ; PID , ptrace PID . : . ptrace, , (, read(2), pause(2) ..), , . PTRACE_LISTEN , , << >>: - ptrace-stop ( ptrace waitpid(2)), <<>>, ( ), group-stop PTRACE_LISTEN, , SIGCONT. , ptrace . . , ptrace , ptrace-stop. , ptrace-stop signal-delivery-stop, group-stop, syscall-stop, PTRACE_EVENT stops . . ptrace-stop, waitpid(2) ( <>). , : pid = waitpid(pid_or_minus_1, &status, __WALL); ptrace-stop pid 0 WIFSTOPPED(status). __WALL WSTOPPED WEXITED, . WCONTINUED waitpid(2) : <> . WNOHANG , waitpid(2) 0 (<< , >>), , . : errno = 0; ptrace(PTRACE_CONT, pid, 0L, 0L); if (errno == ESRCH) { /* */ r = waitpid(tracee, &status, __WALL | WNOHANG); /* r 0 ! */ } ptrace-stop: signal-delivery-stop, group-stop, PTRACE_EVENT, syscall-stop. waitpid(2) WIFSTOPPED(status). , status>>8, , , PTRACE_GETSIGINFO (: WSTOPSIG(status), (status>>8) & 0xff). Signal-delivery-stop When a (possibly multithreaded) process receives any signal except SIGKILL, the kernel selects an arbitrary thread which handles the signal. (If the signal is generated with tgkill(2), the target thread can be explicitly selected by the caller.) If the selected thread is traced, it enters signal-delivery-stop. At this point, the signal is not yet delivered to the process, and can be suppressed by the tracer. If the tracer doesn't suppress the signal, it passes the signal to the tracee in the next ptrace restart operation. This second step of signal delivery is called signal injection in this manual page. Note that if the signal is blocked, signal-delivery-stop doesn't happen until the signal is unblocked, with the usual exception that SIGSTOP can't be blocked. Signal-delivery-stop waitpid(2), WIFSTOPPED(status) , WSTOPSIG(status). SIGTRAP, ptrace-stop; <> <> . WSTOPSIG(status) , group-stop, . signal-delivery-stop, ptrace(PTRACE_restart, pid, 0, sig) where PTRACE_restart is one of the restarting ptrace operations. If sig is 0, then a signal is not delivered. Otherwise, the signal sig is delivered. This operation is called signal injection in this manual page, to distinguish it from signal-delivery-stop. sig WSTOPSIG(status): . , . : PTRACE_SYSCALL, , ( restart_syscall(2) , ). ( poll(2)), , ; , , - EINTR, . ptrace, ptrace-stops, signal-delivery-stop, , sig . ; sig . ptrace << >> -- tgkill(2). The fact that signal injection operations may be ignored when restarting the tracee after ptrace stops that are not signal-delivery-stops is a cause of confusion among ptrace users. One typical scenario is that the tracer observes group-stop, mistakes it for signal-delivery-stop, restarts the tracee with ptrace(PTRACE_restart, pid, 0, stopsig) stopsig, stopsig . SIGCONT -- ( ) , group-stop. signal-delivery-stop. ( , , SIGCONT , ). , group-stop signal-delivery-stop () SIGCONT, SIGCONT. , SIGCONT , . ( ) group-stop. , . Linux 2.4 , SIGSTOP . PTRACE_GETSIGINFO siginfo_t, . PTRACE_SETSIGINFO. PTRACE_SETSIGINFO siginfo_t, si_signo sig , . Group-stop ( ) , . - , group-stop. , signal-delivery-stop ( ) ( , , ), group-stop . , group-stop . Group-stop waitpid(2), WIFSTOPPED(status) WSTOPSIG(status). ptrace-stops, ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo) , SIGSTOP, SIGTSTP, SIGTTIN SIGTTOU; . - , group-stop. , PTRACE_GETSIGINFO. PTRACE_GETSIGINFO EINVAL, group-stop ( , , ESRCH (<< >>), SIGKILL). PTRACE_SEIZE, group-stop PTRACE_EVENT_STOP: status>>16 == PTRACE_EVENT_STOP. group-stop PTRACE_GETSIGINFO. Linux 2.6.38, ptrace-stop , , ( SIGKILL) , waitpid(2). The kernel behavior described in the previous paragraph causes a problem with transparent handling of stopping signals. If the tracer restarts the tracee after group-stop, the stopping signal is effectively ignored--the tracee doesn't remain stopped, it runs. If the tracer doesn't restart the tracee before entering into the next waitpid(2), future SIGCONT signals will not be reported to the tracer; this would cause the SIGCONT signals to have no effect on the tracee. Linux 3.4, : PTRACE_CONT PTRACE_LISTEN, , , waitpid(2) (, SIGCONT). PTRACE_EVENT PTRACE_O_TRACE_*, ptrace-stop-, PTRACE_EVENT. PTRACE_EVENT stops are observed by the tracer as waitpid(2) returning with WIFSTOPPED(status), and WSTOPSIG(status) returns SIGTRAP (or for PTRACE_EVENT_STOP, returns the stopping signal if tracee is in a group-stop). An additional bit is set in the higher byte of the status word: the value status>>8 will be ((PTRACE_EVENT_foo<<8) | SIGTRAP). : PTRACE_EVENT_VFORK vfork(2) clone(2) CLONE_VFORK. , /exec ( , vfork(2)). PTRACE_EVENT_FORK fork(2) clone(2) SIGCHLD. PTRACE_EVENT_CLONE clone(2). PTRACE_EVENT_VFORK_DONE vfork(2) clone(2) CLONE_VFORK, , , exec. , , (. ., ), . ID PTRACE_GETEVENTMSG. PTRACE_EVENT_EXEC execve(2). Linux 3.0, PTRACE_GETEVENTMSG ID . PTRACE_EVENT_EXIT ( exit_group(2)), , execve(2) . PTRACE_GETEVENTMSG . ( , <<>> ). ; PTRACE_CONT PTRACE_DETACH. PTRACE_EVENT_STOP PTRACE_INTERRUPT, group-stop, ptrace-stop ( PTRACE_SEIZE). PTRACE_EVENT_SECCOMP seccomp(2) - syscall , PTRACE_O_TRACESECCOMP . seccomp ( SECCOMP_RET_DATA seccomp) PTRACE_GETEVENTMSG. . PTRACE_GETSIGINFO PTRACE_EVENT SIGTRAP si_signo, si_code (event<<8) | SIGTRAP. Syscall-stop PTRACE_SYSCALL PTRACE_SYSEMU, syscall-enter-stop - ( , - PTRACE_SYSEMU, - ). syscall-entry-stop, PTRACE_SYSCALL, syscall-exit-stop , ( , signal-delivery-stop syscall-enter-stop syscall-exit-stop; syscall-exit-stop). - ( PTRACE_SYSEMU), syscall-exit-stop . , PTRACE_SYSEMU PTRACE_SYSEMU_SINGLESTEP. PTRACE_SYSCALL, , syscall-exit-stop. , PTRACE_EVENT ( seccomp), ( _exit(2) exit_group(2)), SIGKILL, ( , execve(2) , ; ). Syscall-enter-stop syscall-exit-stop waitpid(2), WIFSTOPPED(status) WSTOPSIG(status) SIGTRAP. PTRACE_O_TRACESYSGOOD, WSTOPSIG(status) (SIGTRAP | 0x80). Syscall-stop signal-delivery-stop SIGTRAP, PTRACE_GETSIGINFO : si_code <= 0 SIGTRAP was delivered as a result of a user-space action, for example, a system call (tgkill(2), kill(2), sigqueue(3), etc.), expiration of a POSIX timer, change of state on a POSIX message queue, or completion of an asynchronous I/O operation. si_code == SI_KERNEL (0x80) SIGTRAP . si_code == SIGTRAP si_code == (SIGTRAP|0x80) syscall-stop. , syscall-stop ( ), PTRACE_GETSIGINFO syscall-stop . . , x86, syscall-enter-stop rax == -ENOSYS. SIGTRAP ( ) syscall-exit-stop, rax ENOSYS, SIGTRAP < syscall-enter-stop>>; , << syscall-exit-stop>> . . PTRACE_O_TRACESYSGOOD -- syscall-stop ptrace-stop, . Syscall-enter-stop syscall-exit-stop . ptrace-stop, syscall-enter-stop syscall-exit-stop . , syscall-enter-stop syscall-exit-stop, PTRACE_EVENT ; ptrace-stop . , seccomp ( ) syscall-exit-stop syscall-entry-stop. seccomp, syscall-entry-stop. syscall-enter-stop , PTRACE_SYSCALL, syscall-exit-stop . PTRACE_GETSIGINFO syscall-stop SIGTRAP si_signo, si_code SIGTRAP (SIGTRAP|0x80). PTRACE_EVENT_SECCOMP stops (Linux 3.5 to Linux 4.7) PTRACE_EVENT_SECCOMP ptrace . Linux 4.7 (). . PTRACE_EVENT_SECCOMP - SECCOMP_RET_TRACE. . , seccomp , PTRACE_SYSEMU . . , PTRACE_SYSCALL PTRACE_SYSEMU syscall-entry-stop. , PTRACE_EVENT_SECCOMP , syscall-entry-stop . , PTRACE_EVENT_SECCOMP PTRACE_SYSCALL, syscall-exit-stop, syscall-entry-stop, . PTRACE_EVENT_SECCOMP ( Linux 4.8) Linux 4.8, PTRACE_EVENT_SECCOMP syscall-entry-stop syscall-exit-stop. , seccomp ( PTRACE_EVENT_SECCOMP ), - PTRACE_SYSEMU. , PTRACE_EVENT_SECCOMP syscall-entry-stop (. ., PTRACE_SYSCALL syscall-exit-stop, , ). , , syscall-entry-stop. PTRACE_EVENT_SECCOMP, seccomp SECCOMP_RET_TRACE, SECCOMP_RET_ALLOW. , , PTRACE_EVENT_SECCOMP, . PTRACE_SINGLESTEP [ .] ptrace ptrace (, PTRACE_ATTACH, PTRACE_SEIZE, PTRACE_TRACEME, PTRACE_INTERRUPT PTRACE_KILL) , ptrace-stop, ESRCH. ptrace-stop, . ptrace-stop: ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, pid, addr, 0); ptrace(PTRACE_POKETEXT/POKEDATA/POKEUSER, pid, addr, 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); , . , (siginfo) ptrace-stop, ( 0 errno ); PTRACE_GETEVENTMSG , ptrace-stop - . ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags); . . , , << >> PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK PTRACE_O_TRACECLONE. , ptrace-stop, . : ptrace(cmd, pid, 0, sig); cmd PTRACE_CONT, PTRACE_LISTEN, PTRACE_DETACH, PTRACE_SYSCALL, PTRACE_SINGLESTEP, PTRACE_SYSEMU PTRACE_SYSEMU_SINGLESTEP. signal-delivery-stop, sig , ( ). , sig ( ptrace-stop signal-delivery-stop, sig 0). ptrace(PTRACE_ATTACH, pid, 0, 0); ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_flags); PTRACE_ATTACH SIGSTOP. SIGSTOP, . , , , signal-delivery-stop ! , SIGSTOP, SIGSTOP. , ptrace SIGSTOP SIGSTOP . SIGSTOP , EINTR , << >>. Linux 3.4, PTRACE_ATTACH PTRACE_SEIZE. PTRACE_SEIZE . ( ) -, PTRACE_INTERRUPT. The operation ptrace(PTRACE_TRACEME, 0, 0, 0); . ( ptrace-stop). , PTRACE_TRACEME raise(SIGSTOP); ( ) signal-delivery-stop. PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK PTRACE_O_TRACECLONE, , , , vfork(2) clone(2) CLONE_VFORK, fork(2) clone(2) SIGCHLD, clone(2), , . SIGSTOP , signal-delivery-stop , . : ptrace(PTRACE_DETACH, pid, 0, sig); PTRACE_DETACH , , ptrace-stop. signal-delivery-stop, . sig . If the tracee is running when the tracer wants to detach it, the usual solution is to send SIGSTOP (using tgkill(2), to make sure it goes to the correct thread), wait for the tracee to stop in signal-delivery-stop for SIGSTOP and then detach it (suppressing SIGSTOP injection). A design bug is that this can race with concurrent SIGSTOPs. Another complication is that the tracee may enter other ptrace-stops and needs to be restarted and waited for again, until SIGSTOP is seen. Yet another complication is to be sure that the tracee is not already ptrace-stopped, because no signal delivery happens while it is--not even SIGSTOP. , , group-stop. group-stop , <<>> SIGCONT. signal-delivery-stop, . execve(2) ptrace execve(2), ID ID (ID . , , execve(2), execve(2) , , execve(2)). ID : o PTRACE_EVENT_EXIT, PTRACE_O_TRACEEXIT. , , , _exit(2) 0. o ID, execve(2) (, ptrace <>, waitpid(2) ptrace, ID ). ID ID , ID . o PTRACE_EVENT_EXEC, PTRACE_O_TRACEEXEC. o PTRACE_EVENT_EXIT , , << >> (: WIFEXITED(status) , . ). , , , << , >>. ( ), execve(2) , . - ID . PTRACE_O_TRACEEXEC. -, PTRACE_EVENT_EXEC, execve(2). PTRACE_GETEVENTMSG ID ( Linux 3.0). -, PTRACE_O_TRACEEXEC SIGTRAP execve(2). PTRACE_EVENT_EXEC, , , . On receiving the PTRACE_EVENT_EXEC stop notification, the tracer should clean up all its internal data structures describing the threads of this process, and retain only one data structure--one which describes the single still running tracee, with thread ID == thread group ID == process ID. : execve(2) : *** syscall-enter-stop 1: ** PID1 execve("/bin/foo", "foo" *** PTRACE_SYSCALL 1 ** *** syscall-enter-stop 2: ** PID2 execve("/bin/bar", "bar" *** PTRACE_SYSCALL 2 ** *** PTRACE_EVENT_EXEC for PID0, PTRACE_SYSCALL ** *** syscall-exit-stop PID0: ** PID0 <... execve resumed> ) = 0 PTRACE_O_TRACEEXEC PTRACE_ATTACH, PTRACE_SEIZE, SIGTRAP execve(2). ( , kill -TRAP), - ptrace-stop. PTRACE_GETSIGINFO si_code 0 (SI_USER). () . , (, strace(1)) -execve SIGTRAP , ( SIGTRAP SIG_DFL, ). , SIGTRAP , . PTRACE_O_TRACEEXEC PTRACE_SEIZE SIGTRAP. ptrace UNIX waitpid(2). , waitpid(2), . , Linux 2.6.38 ; . Linux 2.6.38 : o / , , waitpid(2), ( ). -- , . On success, the PTRACE_PEEK* operations return the requested data (but see NOTES), the PTRACE_SECCOMP_GET_FILTER operation returns the number of instructions in the BPF program, the PTRACE_GET_SYSCALL_INFO operation returns the number of bytes available to be written by the kernel, and other operations return zero. On error, all operations return -1, and errno is set to indicate the error. Since the value returned by a successful PTRACE_PEEK* operation may be -1, the caller must clear errno before the call, and then check it afterward to determine whether or not an error occurred. EBUSY ( i386) . EFAULT , , , . , Linux EIO EFAULT, . EINVAL . EIO op is invalid, or an attempt was made to read from or write to an invalid area in the tracer's or the tracee's memory, or there was a word-alignment violation, or an invalid signal was specified during a restart operation. EPERM The specified process cannot be traced. This could be because the tracer has insufficient privileges (the required capability is CAP_SYS_PTRACE); unprivileged processes cannot trace processes that they cannot send signals to or those running set-user-ID/set-group-ID programs, for obvious reasons. Alternatively, the process may already be being traced, or (before Linux 2.6.26) be init(1) (PID 1). ESRCH The specified process does not exist, or is not currently being traced by the caller, or is not stopped (for operations that require a stopped tracee). None. SVr4, 4.3BSD. Before Linux 2.6.26, init(1), the process with PID 1, may not be traced. Although arguments to ptrace() are interpreted according to the prototype given, glibc currently declares ptrace() as a variadic function with only the op argument fixed. It is recommended to always supply four arguments, even if the requested operation does not use them, setting unused/ignored arguments to 0L or (void *) 0. , execve(2). USER . struct user. <<>> (, 32- Linux 32-). ptrace() Linux. UNIX. , ptrace() . ptrace Various parts of the kernel-user-space API (not just ptrace() operations), require so-called "ptrace access mode" checks, whose outcome determines whether an operation is permitted (or, in a few cases, causes a "read" operation to return sanitized data). These checks are performed in cases where one process can inspect sensitive information about, or in some cases modify the state of, another process. The checks are based on factors such as the credentials and capabilities of the two processes, whether or not the "target" process is dumpable, and the results of checks performed by any enabled Linux Security Module (LSM)--for example, SELinux, Yama, or Smack--and by the commoncap LSM (which is always invoked). Linux 2.6.27 . Linux 2.6.27 : PTRACE_MODE_READ For "read" operations or other operations that are less dangerous, such as: get_robust_list(2); kcmp(2); reading /proc/pid/auxv, /proc/pid/environ, or /proc/pid/stat; or readlink(2) of a /proc/pid/ns/* file. PTRACE_MODE_ATTACH <<>> : ptrace (PTRACE_ATTACH) process_vm_writev(2) (PTRACE_MODE_ATTACH Linux 2.6.27). Linux 4.5 () : PTRACE_MODE_FSCREDS UID GID ( credentials(7)) LSM. PTRACE_MODE_REALCREDS UID GID LSM. Linux 4.5. , : PTRACE_MODE_READ_FSCREDS PTRACE_MODE_READ | PTRACE_MODE_FSCREDS. PTRACE_MODE_READ_REALCREDS PTRACE_MODE_READ | PTRACE_MODE_REALCREDS. PTRACE_MODE_ATTACH_FSCREDS PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS. PTRACE_MODE_ATTACH_REALCREDS PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS. : PTRACE_MODE_NOAUDIT ( Linux 3.3) (audit) . ptrace (, /proc/pid/stat), , . , . . , PTRACE_MODE_*, , . ptrace, - (, /proc). . ptrace ( /proc/pid << >> , PID -- << >>). : (1) , . (2) PTRACE_MODE_FSCREDS, UID GID ( credentials(7), UID GID ). PTRACE_MODE_REALCREDS, UID GID ( , UID GID , . PTRACE_MODE_REALCREDS ID ). (3) , : o , ID ID , , ID ID . o CAP_SYS_PTRACE . (4) , << >> 1 (SUID_DUMP_USER; PR_SET_DUMPABLE prctl(2)), CAP_SYS_PTRACE . (5) , ptrace , LSM security_ptrace_access_check(). LSM. commoncap LSM : (5.1) PTRACE_MODE_FSCREDS, ; ( PTRACE_MODE_REALCREDS) . (5.2) , : o , . o CAP_SYS_PTRACE . , commoncap LSM PTRACE_MODE_READ PTRACE_MODE_ATTACH. (6) , . /proc/sys/kernel/yama/ptrace_scope Yama Linux Security Module (LSM) (. ., CONFIG_SECURITY_YAMA) /proc/sys/kernel/yama/ptrace_scope (, Linux 3.4) , ptrace() ( strace(1) gdb(1)). , ptrace (, GPG SSH), , ( ) , , . , Yama LSM : o Any operation that performs a ptrace access mode PTRACE_MODE_ATTACH check--for example, ptrace() PTRACE_ATTACH. (See the "Ptrace access mode checking" discussion above.) o ptrace() PTRACE_TRACEME. , CAP_SYS_PTRACE, /proc/sys/kernel/yama/ptrace_scope : 0 (<< ptrace>>) , PTRACE_MODE_ATTACH ( commoncap LSM). PTRACE_TRACEME . 1 (<< ptrace>>) [ ] , PTRACE_MODE_ATTACH, CAP_SYS_PTRACE . , . prctl(2) PR_SET_PTRACER PID, PTRACE_MODE_ATTACH . Documentation/admin-guide/LSM/Yama.rst ( Documentation/security/Yama.txt Linux 4.13). PTRACE_TRACEME . 2 (<< >>) CAP_SYS_PTRACE PTRACE_MODE_ATTACH , PTRACE_TRACEME. 3 (<< >>) PTRACE_MODE_ATTACH , PTRACE_TRACEME. , . 1 2 , , Yama. - , , UID UID , ( CAP_SYS_PTRACE) ( ). , , , Yama LSM. C At the system call level, the PTRACE_PEEKTEXT, PTRACE_PEEKDATA, and PTRACE_PEEKUSER operations have a different API: they store the result at the address specified by the data parameter, and the return value is the error flag. The glibc wrapper function provides the API given in DESCRIPTION above, with the result being returned via the function return value. On hosts with Linux 2.6 kernel headers, PTRACE_SETOPTIONS is declared with a different value than the one for Linux 2.4. This leads to applications compiled with Linux 2.6 kernel headers failing when run on Linux 2.4. This can be worked around by redefining PTRACE_SETOPTIONS to PTRACE_OLDSETOPTIONS, if that is defined. group-stop , . 2.6.38.6. _exit(2), PTRACE_EVENT_EXIT ( ), WIFEXITED . , execve(2), . , , execve(2). PTRACE_DETACH . 2.6.38.6. SIGKILL PTRACE_EVENT_EXIT . ; SIGKILL ptrace. Linux -- 3.13. EINTR, , ( : , SIGSTOP). Linux 3.2.9, (, ): epoll_wait(2) read(2) inotify(7). : strace -p restart_syscall(<... resuming interrupted call ...>_ select(6, [5], NULL, [5], NULL_ (<<_>> ), . : clock_gettime(CLOCK_MONOTONIC, {15370, 690928118}) = 0 epoll_wait(4,_ , epoll_wait(2) , strace(1) . epoll_wait(2) EINTR. , EINTR epoll_wait(2) (, <<>> EINTR, strace(1) ). , glibc ptrace() errno . 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) () Alexey, Azamat Hackimov , kogamatranslator49 , Darima Kogan , Max Is , Yuri Kozlov ; GNU (GNU General Public License - GPL, 3 ) , - . - , , () () () <>. Linux 6.9.1 2 2024 . ptrace(2)