1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
---
title: 'Fun with ptrace: SIGTRAPs galore'
date: 2022-11-07 13:00 +0100
---
When using `PTRACE_ATTACH` the `ptrace` mechanism reuses SIGTRAP for a number
of things by default.
This makes it unnecessarily hard to distinguish regular traps possibly caused
by breakpoints we might place from other events.
1. After `ptrace(PTRACE_SYSCALL)`, syscall-stops will be reported as SIGTRAPs.
```c
int status;
ptrace(PTRACE_SYSCALL, pid, 0, 0);
waitpid(pid, &status, 0);
if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
/* We don't know if the tracee has just entered/exited a syscall or
* received a regular SIGTRAP (could be caused by a breakpoint we
* placed). */
}
```
This is fixed by using the `PTRACE_O_TRACESYSGOOD` option.
```c
int status;
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD);
ptrace(PTRACE_SYSCALL, pid, 0, 0);
waitpid(pid, &status, 0);
if (WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80)) {
/* We know for sure that the tracee has just entered/exited a
* syscall. */
}
```
2. Every `execve` call will be reported as a SIGTRAP.
```c
int status;
ptrace(PTRACE_CONT, pid, 0, 0);
waitpid(pid, &status, 0);
if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
/* We don't know if the tracee just called execve() or received a
* regular SIGTRAP (could be caused by a breakpoint we placed). */
}
```
This is fixed by using the `PTRACE_O_TRACEEXEC` option.
```c
int status;
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACEEXEC);
ptrace(PTRACE_CONT, pid, 0, 0);
waitpid(pid, &status, 0);
if (WIFSTOPPED(status) && status >> 8 == (SIGTRAP | PTRACE_EVENT_EXEC << 8)) {
/* We know for sure that the tracee has just called execve(). */
}
```
This point doesn't apply to tracees attached using `PTRACE_SEIZE`.
{: .alert .alert-info }
As you can see, you should always use at least the `PTRACE_O_TRACESYSGOOD` and
`PTRACE_O_TRACEEXEC` options to be able to distinguish between SIGTRAPs.
|