ptrace(2) System Calls Manual ptrace(2) ptrace - LIBRARY Standard C library (libc, -lc) #include long ptrace(enum __ptrace_request request, 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. , ( SIGKILL, ). waitpid(2) ( <<>> ); status, , . , ptrace . , ( ). PTRACE_O_TRACEEXEC , execve(2) SIGTRAP, , . PTRACE_DETACH. request : PTRACE_TRACEME , . , , ( pid, addr data ). PTRACE_TRACEME ; . , , pid , . ( PTRACE_ATTACH, PTRACE_SEIZE, PTRACE_INTERRUPT PTRACE_KILL) . PTRACE_PEEKTEXT PTRACE_PEEKDATA addr, , ptrace() Linux , ( data ; ). PTRACE_PEEKUSER addr USER , ( ). ptrace(). , , . ( data ; ). PTRACE_POKETEXT PTRACE_POKEDATA data addr. , PTRACE_PEEKTEXT PTRACE_PEEKDATA, . 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 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) PTRACE_SYSEMU , . syscall-stop . PTRACE_SYSEMU_SINGLESTEP , , . , User Mode Linux, . data PTRACE_CONT. addr . 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). , , ptrace, . , (, SIGKILL). , ESRCH ptrace. , , , ptrace ( , ), , ptrace. / ESRCH << >> , , ptrace-stop. , , waitpid(WNOHANG) , ptrace ESRCH. waitpid(WNOHANG) 0. , << >>, ptrace. , 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 (, ) - SIGKILL, ( tgkill(2), ). , signal-delivery-stop. . , ptrace. . , , signal-delivery-stop (, , SIGSTOP, ). 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) PTRACE_restart -- ptrace. sig 0, . , sig. , 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). , ptrace signal-delivery-stops, ptrace. : group-stop, signal-delivery-stop, 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 , , (tgkill(2), kill(2), sigqueue(3) . .), POSIX, POSIX /. 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. 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* requests return the requested data (but see NOTES), the PTRACE_SECCOMP_GET_FILTER request returns the number of instructions in the BPF program, the PTRACE_GET_SYSCALL_INFO request returns the number of bytes available to be written by the kernel, and other requests return zero. On error, all requests return -1, and errno is set to indicate the error. Since the value returned by a successful PTRACE_PEEK* request 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 request, ; , . 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 , , ( , ). None. SVr4, 4.3BSD. Before Linux 2.6.26, init(1), the process with PID 1, may not be traced. ptrace() , glibc ptrace() , request. , ( 0L (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 PTRACE_PEEKTEXT, PTRACE_PEEKDATA PTRACE_PEEKUSER : , data, . glibc , , . 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 , Kogan, Max Is , Yuri Kozlov ; GNU 3 , . . , , . Linux man-pages 6.06 31 2023 . ptrace(2)