Denys Vlasenko | dfa0acc | 2011-08-31 15:58:06 +0200 | [diff] [blame] | 1 | This document describes Linux ptrace implementation in Linux kernels |
| 2 | version 3.0.0. (Update this notice if you update the document |
| 3 | to reflect newer kernels). |
| 4 | |
| 5 | |
| 6 | Ptrace userspace API. |
| 7 | |
| 8 | Ptrace API (ab)uses standard Unix parent/child signaling over waitpid. |
| 9 | An unfortunate effect of it is that resulting API is complex and has |
| 10 | subtle quirks. This document aims to describe these quirks. |
| 11 | |
| 12 | Debugged processes (tracees) first need to be attached to the debugging |
| 13 | process (tracer). Attachment and subsequent commands are per-thread: in |
| 14 | multi-threaded process, every thread can be individually attached to a |
| 15 | (potentially different) tracer, or left not attached and thus not |
| 16 | debugged. Therefore, "tracee" always means "(one) thread", never "a |
| 17 | (possibly multi-threaded) process". Ptrace commands are always sent to |
| 18 | a specific tracee using ptrace(PTRACE_foo, pid, ...), where pid is a |
| 19 | TID of the corresponding Linux thread. |
| 20 | |
| 21 | After attachment, each tracee can be in two states: running or stopped. |
| 22 | |
| 23 | There are many kinds of states when tracee is stopped, and in ptrace |
| 24 | discussions they are often conflated. Therefore, it is important to use |
| 25 | precise terms. |
| 26 | |
| 27 | In this document, any stopped state in which tracee is ready to accept |
| 28 | ptrace commands from the tracer is called ptrace-stop. Ptrace-stops can |
| 29 | be further subdivided into signal-delivery-stop, group-stop, |
| 30 | syscall-stop and so on. They are described in detail later. |
| 31 | |
| 32 | |
| 33 | 1.x Death under ptrace. |
| 34 | |
| 35 | When a (possibly multi-threaded) process receives a killing signal (a |
| 36 | signal set to SIG_DFL and whose default action is to kill the process), |
| 37 | all threads exit. Tracees report their death to the tracer(s). This is |
| 38 | not a ptrace-stop (because tracer can't query tracee status such as |
| 39 | register contents, cannot restart tracee etc) but the notification |
| 40 | about this event is delivered through waitpid API similarly to |
| 41 | ptrace-stop. |
| 42 | |
| 43 | Note that killing signal will first cause signal-delivery-stop (on one |
| 44 | tracee only), and only after it is injected by tracer (or after it was |
| 45 | dispatched to a thread which isn't traced), death from signal will |
| 46 | happen on ALL tracees within multi-threaded process. |
| 47 | |
| 48 | SIGKILL operates similarly, with exceptions. No signal-delivery-stop is |
| 49 | generated for SIGKILL and therefore tracer can't suppress it. SIGKILL |
| 50 | kills even within syscalls (syscall-exit-stop is not generated prior to |
| 51 | death by SIGKILL). The net effect is that SIGKILL always kills the |
| 52 | process (all its threads), even if some threads of the process are |
| 53 | ptraced. |
| 54 | |
| 55 | Tracer can kill a tracee with ptrace(PTRACE_KILL, pid, 0, 0). This |
Denys Vlasenko | 0ed9947 | 2012-02-09 19:57:52 +0100 | [diff] [blame] | 56 | operation is deprecated, use kill/tgkill(SIGKILL) instead. |
Denys Vlasenko | dfa0acc | 2011-08-31 15:58:06 +0200 | [diff] [blame] | 57 | |
| 58 | ^^^ Oleg prefers to deprecate it instead of describing (and needing to |
| 59 | support) PTRACE_KILL's quirks. |
| 60 | |
| 61 | When tracee executes exit syscall, it reports its death to its tracer. |
| 62 | Other threads are not affected. |
| 63 | |
| 64 | When any thread executes exit_group syscall, every tracee in its thread |
| 65 | group reports its death to its tracer. |
| 66 | |
| 67 | If PTRACE_O_TRACEEXIT option is on, PTRACE_EVENT_EXIT will happen |
| 68 | before actual death. This applies to exits on exit syscall, group_exit |
| 69 | syscall, signal deaths (except SIGKILL), and when threads are torn down |
| 70 | on execve in multi-threaded process. |
| 71 | |
| 72 | Tracer cannot assume that ptrace-stopped tracee exists. There are many |
| 73 | scenarios when tracee may die while stopped (such as SIGKILL). |
| 74 | Therefore, tracer must always be prepared to handle ESRCH error on any |
| 75 | ptrace operation. Unfortunately, the same error is returned if tracee |
| 76 | exists but is not ptrace-stopped (for commands which require stopped |
| 77 | tracee), or if it is not traced by process which issued ptrace call. |
| 78 | Tracer needs to keep track of stopped/running state, and interpret |
| 79 | ESRCH as "tracee died unexpectedly" only if it knows that tracee has |
| 80 | been observed to enter ptrace-stop. Note that there is no guarantee |
| 81 | that waitpid(WNOHANG) will reliably report tracee's death status if |
| 82 | ptrace operation returned ESRCH. waitpid(WNOHANG) may return 0 instead. |
| 83 | IOW: tracee may be "not yet fully dead" but already refusing ptrace ops. |
| 84 | |
| 85 | Tracer can not assume that tracee ALWAYS ends its life by reporting |
| 86 | WIFEXITED(status) or WIFSIGNALED(status). |
| 87 | |
| 88 | ??? or can it? Do we include such a promise into ptrace API? |
| 89 | |
| 90 | |
| 91 | 1.x Stopped states. |
| 92 | |
| 93 | When running tracee enters ptrace-stop, it notifies its tracer using |
| 94 | waitpid API. Tracer should use waitpid family of syscalls to wait for |
| 95 | tracee to stop. Most of this document assumes that tracer waits with: |
| 96 | |
| 97 | pid = waitpid(pid_or_minus_1, &status, __WALL); |
| 98 | |
| 99 | Ptrace-stopped tracees are reported as returns with pid > 0 and |
| 100 | WIFSTOPPED(status) == true. |
| 101 | |
| 102 | ??? Do we require __WALL usage, or will just using 0 be ok? Are the |
| 103 | rules different if user wants to use waitid? Will waitid require |
| 104 | WEXITED? |
| 105 | |
| 106 | __WALL value does not include WSTOPPED and WEXITED bits, but implies |
| 107 | their functionality. |
| 108 | |
| 109 | Setting of WCONTINUED bit in waitpid flags is not recommended: the |
| 110 | continued state is per-process and consuming it can confuse real parent |
| 111 | of the tracee. |
| 112 | |
| 113 | Use of WNOHANG bit in waitpid flags may cause waitpid return 0 ("no |
| 114 | wait results available yet") even if tracer knows there should be a |
| 115 | notification. Example: kill(tracee, SIGKILL); waitpid(tracee, &status, |
| 116 | __WALL | WNOHANG); |
| 117 | |
| 118 | ??? waitid usage? WNOWAIT? |
| 119 | |
| 120 | ??? describe how wait notifications queue (or not queue) |
| 121 | |
| 122 | The following kinds of ptrace-stops exist: signal-delivery-stops, |
| 123 | group-stop, PTRACE_EVENT stops, syscall-stops [, SINGLESTEP, SYSEMU, |
| 124 | SYSEMU_SINGLESTEP]. They all are reported as waitpid result with |
| 125 | WIFSTOPPED(status) == true. They may be differentiated by checking |
| 126 | (status >> 8) value, and if looking at (status >> 8) value doesn't |
| 127 | resolve ambiguity, by querying PTRACE_GETSIGINFO. (Note: |
| 128 | WSTOPSIG(status) macro returns ((status >> 8) & 0xff) value). |
| 129 | |
| 130 | |
| 131 | 1.x.x Signal-delivery-stop |
| 132 | |
| 133 | When (possibly multi-threaded) process receives any signal except |
| 134 | SIGKILL, kernel selects a thread which handles the signal (if signal is |
| 135 | generated with t[g]kill, thread selection is done by user). If selected |
| 136 | thread is traced, it enters signal-delivery-stop. By this point, signal |
| 137 | is not yet delivered to the process, and can be suppressed by tracer. |
| 138 | If tracer doesn't suppress the signal, it passes signal to tracee in |
| 139 | the next ptrace request. This second step of signal delivery is called |
| 140 | "signal injection" in this document. Note that if signal is blocked, |
| 141 | signal-delivery-stop doesn't happen until signal is unblocked, with the |
| 142 | usual exception that SIGSTOP can't be blocked. |
| 143 | |
| 144 | Signal-delivery-stop is observed by tracer as waitpid returning with |
| 145 | WIFSTOPPED(status) == true, WSTOPSIG(status) == signal. If |
| 146 | WSTOPSIG(status) == SIGTRAP, this may be a different kind of |
| 147 | ptrace-stop - see "Syscall-stops" and "execve" sections below for |
| 148 | details. If WSTOPSIG(status) == stopping signal, this may be a |
| 149 | group-stop - see below. |
| 150 | |
| 151 | |
| 152 | 1.x.x Signal injection and suppression. |
| 153 | |
| 154 | After signal-delivery-stop is observed by tracer, tracer should restart |
| 155 | tracee with |
| 156 | |
| 157 | ptrace(PTRACE_rest, pid, 0, sig) |
| 158 | |
| 159 | call, where PTRACE_rest is one of the restarting ptrace ops. If sig is |
| 160 | 0, then signal is not delivered. Otherwise, signal sig is delivered. |
| 161 | This operation is called "signal injection" in this document, to |
| 162 | distinguish it from signal-delivery-stop. |
| 163 | |
| 164 | Note that sig value may be different from WSTOPSIG(status) value - |
| 165 | tracer can cause a different signal to be injected. |
| 166 | |
| 167 | Note that suppressed signal still causes syscalls to return |
Denys Vlasenko | 0ed9947 | 2012-02-09 19:57:52 +0100 | [diff] [blame] | 168 | prematurely. Kernel should always restart the syscall in this case: |
| 169 | tracer would observe a new syscall-enter-stop for the same syscall, |
| 170 | or, in case of syscalls returning ERESTART_RESTARTBLOCK, |
| 171 | tracer would observe a syscall-enter-stop for restart_syscall(2) |
| 172 | syscall. There may still be bugs in this area which cause some syscalls |
| 173 | to instead return with -EINTR even though no observable signal |
| 174 | was injected to the tracee. |
Denys Vlasenko | dfa0acc | 2011-08-31 15:58:06 +0200 | [diff] [blame] | 175 | |
| 176 | This is a cause of confusion among ptrace users. One typical scenario |
| 177 | is that tracer observes group-stop, mistakes it for |
| 178 | signal-delivery-stop, restarts tracee with ptrace(PTRACE_rest, pid, 0, |
| 179 | stopsig) with the intention of injecting stopsig, but stopsig gets |
| 180 | ignored and tracee continues to run. |
| 181 | |
| 182 | SIGCONT signal has a side effect of waking up (all threads of) |
| 183 | group-stopped process. This side effect happens before |
| 184 | signal-delivery-stop. Tracer can't suppress this side-effect (it can |
| 185 | only suppress signal injection, which only causes SIGCONT handler to |
| 186 | not be executed in the tracee, if such handler is installed). In fact, |
| 187 | waking up from group-stop may be followed by signal-delivery-stop for |
| 188 | signal(s) *other than* SIGCONT, if they were pending when SIGCONT was |
| 189 | delivered. IOW: SIGCONT may be not the first signal observed by the |
| 190 | tracee after it was sent. |
| 191 | |
| 192 | Stopping signals cause (all threads of) process to enter group-stop. |
| 193 | This side effect happens after signal injection, and therefore can be |
| 194 | suppressed by tracer. |
| 195 | |
| 196 | PTRACE_GETSIGINFO can be used to retrieve siginfo_t structure which |
| 197 | corresponds to delivered signal. PTRACE_SETSIGINFO may be used to |
| 198 | modify it. If PTRACE_SETSIGINFO has been used to alter siginfo_t, |
| 199 | si_signo field and sig parameter in restarting command must match, |
| 200 | otherwise the result is undefined. |
| 201 | |
| 202 | |
| 203 | 1.x.x Group-stop |
| 204 | |
| 205 | When a (possibly multi-threaded) process receives a stopping signal, |
| 206 | all threads stop. If some threads are traced, they enter a group-stop. |
| 207 | Note that stopping signal will first cause signal-delivery-stop (on one |
| 208 | tracee only), and only after it is injected by tracer (or after it was |
| 209 | dispatched to a thread which isn't traced), group-stop will be |
| 210 | initiated on ALL tracees within multi-threaded process. As usual, every |
| 211 | tracee reports its group-stop separately to corresponding tracer. |
| 212 | |
| 213 | Group-stop is observed by tracer as waitpid returning with |
| 214 | WIFSTOPPED(status) == true, WSTOPSIG(status) == signal. The same result |
| 215 | is returned by some other classes of ptrace-stops, therefore the |
| 216 | recommended practice is to perform |
| 217 | |
| 218 | ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo) |
| 219 | |
| 220 | call. The call can be avoided if signal number is not SIGSTOP, SIGTSTP, |
| 221 | SIGTTIN or SIGTTOU - only these four signals are stopping signals. If |
| 222 | tracer sees something else, it can't be group-stop. Otherwise, tracer |
| 223 | needs to call PTRACE_GETSIGINFO. If PTRACE_GETSIGINFO fails with |
| 224 | EINVAL, then it is definitely a group-stop. (Other failure codes are |
| 225 | possible, such as ESRCH "no such process" if SIGKILL killed the tracee). |
| 226 | |
| 227 | As of kernel 2.6.38, after tracer sees tracee ptrace-stop and until it |
| 228 | restarts or kills it, tracee will not run, and will not send |
| 229 | notifications (except SIGKILL death) to tracer, even if tracer enters |
| 230 | into another waitpid call. |
| 231 | |
| 232 | Currently, it causes a problem with transparent handling of stopping |
| 233 | signals: if tracer restarts tracee after group-stop, SIGSTOP is |
| 234 | effectively ignored: tracee doesn't remain stopped, it runs. If tracer |
| 235 | doesn't restart tracee before entering into next waitpid, future |
| 236 | SIGCONT will not be reported to the tracer. Which would make SIGCONT to |
| 237 | have no effect. |
| 238 | |
| 239 | |
| 240 | 1.x.x PTRACE_EVENT stops |
| 241 | |
| 242 | If tracer sets TRACE_O_TRACEfoo options, tracee will enter ptrace-stops |
| 243 | called PTRACE_EVENT stops. |
| 244 | |
| 245 | PTRACE_EVENT stops are observed by tracer as waitpid returning with |
| 246 | WIFSTOPPED(status) == true, WSTOPSIG(status) == SIGTRAP. Additional bit |
| 247 | is set in a higher byte of status word: value ((status >> 8) & 0xffff) |
| 248 | will be (SIGTRAP | PTRACE_EVENT_foo << 8). The following events exist: |
| 249 | |
| 250 | PTRACE_EVENT_VFORK - stop before return from vfork/clone+CLONE_VFORK. |
| 251 | When tracee is continued after this, it will wait for child to |
| 252 | exit/exec before continuing its execution (IOW: usual behavior on |
| 253 | vfork). |
| 254 | |
| 255 | PTRACE_EVENT_FORK - stop before return from fork/clone+SIGCHLD |
| 256 | |
| 257 | PTRACE_EVENT_CLONE - stop before return from clone |
| 258 | |
| 259 | PTRACE_EVENT_VFORK_DONE - stop before return from |
| 260 | vfork/clone+CLONE_VFORK, but after vfork child unblocked this tracee by |
| 261 | exiting or exec'ing. |
| 262 | |
| 263 | For all four stops described above: stop occurs in parent, not in newly |
| 264 | created thread. PTRACE_GETEVENTMSG can be used to retrieve new thread's |
| 265 | tid. |
| 266 | |
| 267 | PTRACE_EVENT_EXEC - stop before return from exec. |
| 268 | |
| 269 | PTRACE_EVENT_EXIT - stop before exit (including death from exit_group), |
| 270 | signal death, or exit caused by execve in multi-threaded process. |
| 271 | PTRACE_GETEVENTMSG returns exit status. Registers can be examined |
| 272 | (unlike when "real" exit happens). The tracee is still alive, it needs |
| 273 | to be PTRACE_CONTed or PTRACE_DETACHed to finish exit. |
| 274 | |
| 275 | PTRACE_GETSIGINFO on PTRACE_EVENT stops returns si_signo = SIGTRAP, |
| 276 | si_code = (event << 8) | SIGTRAP. |
| 277 | |
| 278 | |
| 279 | 1.x.x Syscall-stops |
| 280 | |
| 281 | If tracee was restarted by PTRACE_SYSCALL, tracee enters |
| 282 | syscall-enter-stop just prior to entering any syscall. If tracer |
| 283 | restarts it with PTRACE_SYSCALL, tracee enters syscall-exit-stop when |
| 284 | syscall is finished, or if it is interrupted by a signal. (That is, |
| 285 | signal-delivery-stop never happens between syscall-enter-stop and |
| 286 | syscall-exit-stop, it happens *after* syscall-exit-stop). |
| 287 | |
| 288 | Other possibilities are that tracee may stop in a PTRACE_EVENT stop, |
| 289 | exit (if it entered exit or exit_group syscall), be killed by SIGKILL, |
| 290 | or die silently (if execve syscall happened in another thread). |
| 291 | |
| 292 | Syscall-enter-stop and syscall-exit-stop are observed by tracer as |
| 293 | waitpid returning with WIFSTOPPED(status) == true, WSTOPSIG(status) == |
| 294 | SIGTRAP. If PTRACE_O_TRACESYSGOOD option was set by tracer, then |
| 295 | WSTOPSIG(status) == (SIGTRAP | 0x80). |
| 296 | |
| 297 | Syscall-stops can be distinguished from signal-delivery-stop with |
| 298 | SIGTRAP by querying PTRACE_GETSIGINFO: si_code <= 0 if sent by usual |
| 299 | suspects like [tg]kill/sigqueue/etc; or = SI_KERNEL (0x80) if sent by |
| 300 | kernel, whereas syscall-stops have si_code = SIGTRAP or (SIGTRAP | |
| 301 | 0x80). However, syscall-stops happen very often (twice per syscall), |
| 302 | and performing PTRACE_GETSIGINFO for every syscall-stop may be somewhat |
| 303 | expensive. |
| 304 | |
| 305 | Some architectures allow to distinguish them by examining registers. |
| 306 | For example, on x86 rax = -ENOSYS in syscall-enter-stop. Since SIGTRAP |
| 307 | (like any other signal) always happens *after* syscall-exit-stop, and |
| 308 | at this point rax almost never contains -ENOSYS, SIGTRAP looks like |
| 309 | "syscall-stop which is not syscall-enter-stop", IOW: it looks like a |
| 310 | "stray syscall-exit-stop" and can be detected this way. But such |
| 311 | detection is fragile and is best avoided. |
| 312 | |
| 313 | Using PTRACE_O_TRACESYSGOOD option is a recommended method, since it is |
| 314 | reliable and does not incur performance penalty. |
| 315 | |
| 316 | Syscall-enter-stop and syscall-exit-stop are indistinguishable from |
| 317 | each other by tracer. Tracer needs to keep track of the sequence of |
| 318 | ptrace-stops in order to not misinterpret syscall-enter-stop as |
| 319 | syscall-exit-stop or vice versa. The rule is that syscall-enter-stop is |
| 320 | always followed by syscall-exit-stop, PTRACE_EVENT stop or tracee's |
| 321 | death - no other kinds of ptrace-stop can occur in between. |
| 322 | |
| 323 | If after syscall-enter-stop tracer uses restarting command other than |
| 324 | PTRACE_SYSCALL, syscall-exit-stop is not generated. |
| 325 | |
| 326 | PTRACE_GETSIGINFO on syscall-stops returns si_signo = SIGTRAP, si_code |
| 327 | = SIGTRAP or (SIGTRAP | 0x80). |
| 328 | |
| 329 | |
| 330 | 1.x.x SINGLESTEP, SYSEMU, SYSEMU_SINGLESTEP |
| 331 | |
| 332 | ??? document PTRACE_SINGLESTEP, PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP |
| 333 | |
| 334 | |
| 335 | 1.x Informational and restarting ptrace commands. |
| 336 | |
| 337 | Most ptrace commands (all except ATTACH, TRACEME, KILL) require tracee |
| 338 | to be in ptrace-stop, otherwise they fail with ESRCH. |
| 339 | |
| 340 | When tracee is in ptrace-stop, tracer can read and write data to tracee |
| 341 | using informational commands. They leave tracee in ptrace-stopped state: |
| 342 | |
| 343 | longv = ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, pid, addr, 0); |
| 344 | ptrace(PTRACE_POKETEXT/POKEDATA/POKEUSER, pid, addr, long_val); |
| 345 | ptrace(PTRACE_GETREGS/GETFPREGS, pid, 0, &struct); |
| 346 | ptrace(PTRACE_SETREGS/SETFPREGS, pid, 0, &struct); |
| 347 | ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo); |
| 348 | ptrace(PTRACE_SETSIGINFO, pid, 0, &siginfo); |
| 349 | ptrace(PTRACE_GETEVENTMSG, pid, 0, &long_var); |
| 350 | ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags); |
| 351 | |
| 352 | Note that some errors are not reported. For example, setting siginfo |
| 353 | may have no effect in some ptrace-stops, yet the call may succeed |
| 354 | (return 0 and don't set errno). |
| 355 | |
| 356 | ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags) affects one tracee. |
| 357 | Current flags are replaced. Flags are inherited by new tracees created |
| 358 | and "auto-attached" via active PTRACE_O_TRACE[V]FORK or |
| 359 | PTRACE_O_TRACECLONE options. |
| 360 | |
| 361 | Another group of commands makes ptrace-stopped tracee run. They have |
| 362 | the form: |
| 363 | |
| 364 | ptrace(PTRACE_cmd, pid, 0, sig); |
| 365 | |
| 366 | where cmd is CONT, DETACH, SYSCALL, SINGLESTEP, SYSEMU, or |
| 367 | SYSEMU_SINGLESTEP. If tracee is in signal-delivery-stop, sig is the |
| 368 | signal to be injected. Otherwise, sig may be ignored. |
| 369 | |
| 370 | |
| 371 | 1.x Attaching and detaching |
| 372 | |
| 373 | A thread can be attached to tracer using ptrace(PTRACE_ATTACH, pid, 0, |
| 374 | 0) call. This also sends SIGSTOP to this thread. If tracer wants this |
| 375 | SIGSTOP to have no effect, it needs to suppress it. Note that if other |
| 376 | signals are concurrently sent to this thread during attach, tracer may |
| 377 | see tracee enter signal-delivery-stop with other signal(s) first! The |
| 378 | usual practice is to reinject these signals until SIGSTOP is seen, then |
| 379 | suppress SIGSTOP injection. The design bug here is that attach and |
| 380 | concurrent SIGSTOP are racing and SIGSTOP may be lost. |
| 381 | |
| 382 | ??? Describe how to attach to a thread which is already group-stopped. |
| 383 | |
| 384 | Since attaching sends SIGSTOP and tracer usually suppresses it, this |
| 385 | may cause stray EINTR return from the currently executing syscall in |
| 386 | the tracee, as described in "signal injection and suppression" section. |
| 387 | |
| 388 | ptrace(PTRACE_TRACEME, 0, 0, 0) request turns current thread into a |
| 389 | tracee. It continues to run (doesn't enter ptrace-stop). A common |
| 390 | practice is to follow ptrace(PTRACE_TRACEME) with raise(SIGSTOP) and |
| 391 | allow parent (which is our tracer now) to observe our |
| 392 | signal-delivery-stop. |
| 393 | |
| 394 | If PTRACE_O_TRACE[V]FORK or PTRACE_O_TRACECLONE options are in effect, |
| 395 | then children created by (vfork or clone(CLONE_VFORK)), (fork or |
| 396 | clone(SIGCHLD)) and (other kinds of clone) respectively are |
| 397 | automatically attached to the same tracer which traced their parent. |
| 398 | SIGSTOP is delivered to them, causing them to enter |
| 399 | signal-delivery-stop after they exit syscall which created them. |
| 400 | |
| 401 | Detaching of tracee is performed by ptrace(PTRACE_DETACH, pid, 0, sig). |
| 402 | PTRACE_DETACH is a restarting operation, therefore it requires tracee |
| 403 | to be in ptrace-stop. If tracee is in signal-delivery-stop, signal can |
| 404 | be injected. Othervice, sig parameter may be silently ignored. |
| 405 | |
| 406 | If tracee is running when tracer wants to detach it, the usual solution |
| 407 | is to send SIGSTOP (using tgkill, to make sure it goes to the correct |
| 408 | thread), wait for tracee to stop in signal-delivery-stop for SIGSTOP |
| 409 | and then detach it (suppressing SIGSTOP injection). Design bug is that |
| 410 | this can race with concurrent SIGSTOPs. Another complication is that |
| 411 | tracee may enter other ptrace-stops and needs to be restarted and |
| 412 | waited for again, until SIGSTOP is seen. Yet another complication is to |
| 413 | be sure that tracee is not already ptrace-stopped, because no signal |
| 414 | delivery happens while it is - not even SIGSTOP. |
| 415 | |
| 416 | ??? Describe how to detach from a group-stopped tracee so that it |
| 417 | doesn't run, but continues to wait for SIGCONT. |
| 418 | |
| 419 | If tracer dies, all tracees are automatically detached and restarted, |
| 420 | unless they were in group-stop. Handling of restart from group-stop is |
| 421 | currently buggy, but "as planned" behavior is to leave tracee stopped |
| 422 | and waiting for SIGCONT. If tracee is restarted from |
| 423 | signal-delivery-stop, pending signal is injected. |
| 424 | |
| 425 | |
| 426 | 1.x execve under ptrace. |
| 427 | |
| 428 | During execve, kernel destroys all other threads in the process, and |
| 429 | resets execve'ing thread tid to tgid (process id). This looks very |
| 430 | confusing to tracers: |
| 431 | |
| 432 | All other threads stop in PTRACE_EXIT stop, if requested by active |
| 433 | ptrace option. Then all other threads except thread group leader report |
| 434 | death as if they exited via exit syscall with exit code 0. Then |
| 435 | PTRACE_EVENT_EXEC stop happens, if requested by active ptrace option |
| 436 | (on which tracee - leader? execve-ing one?). |
| 437 | |
| 438 | The execve-ing tracee changes its pid while it is in execve syscall. |
| 439 | (Remember, under ptrace 'pid' returned from waitpid, or fed into ptrace |
| 440 | calls, is tracee's tid). That is, pid is reset to process id, which |
| 441 | coincides with thread group leader tid. |
| 442 | |
| 443 | If thread group leader has reported its death by this time, for tracer |
| 444 | this looks like dead thread leader "reappears from nowhere". If thread |
| 445 | group leader was still alive, for tracer this may look as if thread |
| 446 | group leader returns from a different syscall than it entered, or even |
| 447 | "returned from syscall even though it was not in any syscall". If |
| 448 | thread group leader was not traced (or was traced by a different |
| 449 | tracer), during execve it will appear as if it has become a tracee of |
| 450 | the tracer of execve'ing tracee. All these effects are the artifacts of |
| 451 | pid change. |
| 452 | |
| 453 | PTRACE_O_TRACEEXEC option is the recommended tool for dealing with this |
| 454 | case. It enables PTRACE_EVENT_EXEC stop which occurs before execve |
| 455 | syscall return. |
| 456 | |
| 457 | Pid change happens before PTRACE_EVENT_EXEC stop, not after. |
| 458 | |
| 459 | When tracer receives PTRACE_EVENT_EXEC stop notification, it is |
| 460 | guaranteed that except this tracee and thread group leader, no other |
| 461 | threads from the process are alive. |
| 462 | |
| 463 | On receiving this notification, tracer should clean up all its internal |
| 464 | data structures about all threads of this process, and retain only one |
| 465 | data structure, one which describes single still running tracee, with |
| 466 | pid = tgid = process id. |
| 467 | |
| 468 | Currently, there is no way to retrieve former pid of execve-ing tracee. |
| 469 | If tracer doesn't keep track of its tracees' thread group relations, it |
| 470 | may be unable to know which tracee execve-ed and therefore no longer |
| 471 | exists under old pid due to pid change. |
| 472 | |
| 473 | Example: two threads execve at the same time: |
| 474 | |
| 475 | ** we get syscall-entry-stop in thread 1: ** |
| 476 | PID1 execve("/bin/foo", "foo" <unfinished ...> |
| 477 | ** we issue PTRACE_SYSCALL for thread 1 ** |
| 478 | ** we get syscall-entry-stop in thread 2: ** |
| 479 | PID2 execve("/bin/bar", "bar" <unfinished ...> |
| 480 | ** we issue PTRACE_SYSCALL for thread 2 ** |
| 481 | ** we get PTRACE_EVENT_EXEC for PID0, we issue PTRACE_SYSCALL ** |
| 482 | ** we get syscall-exit-stop for PID0: ** |
| 483 | PID0 <... execve resumed> ) = 0 |
| 484 | |
| 485 | In this situation there is no way to know which execve succeeded. |
| 486 | |
| 487 | If PTRACE_O_TRACEEXEC option is NOT in effect for the execve'ing |
| 488 | tracee, kernel delivers an extra SIGTRAP to tracee after execve syscall |
| 489 | returns. This is an ordinary signal (similar to one which can be |
| 490 | generated by "kill -TRAP"), not a special kind of ptrace-stop. |
| 491 | GETSIGINFO on it has si_code = 0 (SI_USER). It can be blocked by signal |
| 492 | mask, and thus can happen (much) later. |
| 493 | |
| 494 | Usually, tracer (for example, strace) would not want to show this extra |
| 495 | post-execve SIGTRAP signal to the user, and would suppress its delivery |
| 496 | to the tracee (if SIGTRAP is set to SIG_DFL, it is a killing signal). |
| 497 | However, determining *which* SIGTRAP to suppress is not easy. Setting |
| 498 | PTRACE_O_TRACEEXEC option and thus suppressing this extra SIGTRAP is |
| 499 | the recommended approach. |
| 500 | |
| 501 | |
| 502 | 1.x Real parent |
| 503 | |
| 504 | Ptrace API (ab)uses standard Unix parent/child signaling over waitpid. |
| 505 | This used to cause real parent of the process to stop receiving several |
| 506 | kinds of waitpid notifications when child process is traced by some |
| 507 | other process. |
| 508 | |
| 509 | Many of these bugs have been fixed, but as of 2.6.38 several still |
| 510 | exist. |
| 511 | |
| 512 | As of 2.6.38, the following is believed to work correctly: |
| 513 | |
| 514 | - exit/death by signal is reported first to tracer, then, when tracer |
| 515 | consumes waitpid result, to real parent (to real parent only when the |
| 516 | whole multi-threaded process exits). If they are the same process, the |
| 517 | report is sent only once. |
| 518 | |
| 519 | |
| 520 | 1.x Known bugs |
| 521 | |
| 522 | Following bugs still exist: |
| 523 | |
| 524 | Group-stop notifications are sent to tracer, but not to real parent. |
| 525 | Last confirmed on 2.6.38.6. |
| 526 | |
| 527 | If thread group leader is traced and exits by calling exit syscall, |
| 528 | PTRACE_EVENT_EXIT stop will happen for it (if requested), but subsequent |
| 529 | WIFEXITED notification will not be delivered until all other threads |
| 530 | exit. As explained above, if one of other threads execve's, thread |
| 531 | group leader death will *never* be reported. If execve-ed thread is not |
| 532 | traced by this tracer, tracer will never know that execve happened. |
| 533 | |
| 534 | ??? need to test this scenario |
| 535 | |
| 536 | One possible workaround is to detach thread group leader instead of |
| 537 | restarting it in this case. Last confirmed on 2.6.38.6. |
| 538 | |
| 539 | SIGKILL signal may still cause PTRACE_EVENT_EXIT stop before actual |
| 540 | signal death. This may be changed in the future - SIGKILL is meant to |
| 541 | always immediately kill tasks even under ptrace. Last confirmed on |
| 542 | 2.6.38.6. |