linux-ptrace.c revision 1.8 1 1.1 christos /* Linux-specific ptrace manipulation routines.
2 1.8 christos Copyright (C) 2012-2023 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of GDB.
5 1.1 christos
6 1.1 christos This program is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3 of the License, or
9 1.1 christos (at your option) any later version.
10 1.1 christos
11 1.1 christos This program is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 1.1 christos
19 1.7 christos #include "gdbsupport/common-defs.h"
20 1.1 christos #include "linux-ptrace.h"
21 1.1 christos #include "linux-procfs.h"
22 1.1 christos #include "linux-waitpid.h"
23 1.7 christos #include "gdbsupport/buffer.h"
24 1.5 christos #ifdef HAVE_SYS_PROCFS_H
25 1.4 christos #include <sys/procfs.h>
26 1.5 christos #endif
27 1.1 christos
28 1.3 christos /* Stores the ptrace options supported by the running kernel.
29 1.3 christos A value of -1 means we did not check for features yet. A value
30 1.3 christos of 0 means there are no supported features. */
31 1.3 christos static int supported_ptrace_options = -1;
32 1.1 christos
33 1.6 christos /* Find all possible reasons we could fail to attach PID and return these
34 1.6 christos as a string. An empty string is returned if we didn't find any reason. */
35 1.1 christos
36 1.6 christos std::string
37 1.6 christos linux_ptrace_attach_fail_reason (pid_t pid)
38 1.1 christos {
39 1.6 christos pid_t tracerpid = linux_proc_get_tracerpid_nowarn (pid);
40 1.6 christos std::string result;
41 1.1 christos
42 1.1 christos if (tracerpid > 0)
43 1.6 christos string_appendf (result,
44 1.6 christos _("process %d is already traced by process %d"),
45 1.6 christos (int) pid, (int) tracerpid);
46 1.1 christos
47 1.1 christos if (linux_proc_pid_is_zombie_nowarn (pid))
48 1.6 christos string_appendf (result,
49 1.6 christos _("process %d is a zombie - the process has already "
50 1.6 christos "terminated"),
51 1.6 christos (int) pid);
52 1.6 christos
53 1.6 christos return result;
54 1.1 christos }
55 1.1 christos
56 1.1 christos /* See linux-ptrace.h. */
57 1.1 christos
58 1.6 christos std::string
59 1.1 christos linux_ptrace_attach_fail_reason_string (ptid_t ptid, int err)
60 1.1 christos {
61 1.6 christos long lwpid = ptid.lwp ();
62 1.6 christos std::string reason = linux_ptrace_attach_fail_reason (lwpid);
63 1.6 christos
64 1.6 christos if (!reason.empty ())
65 1.6 christos return string_printf ("%s (%d), %s", safe_strerror (err), err,
66 1.6 christos reason.c_str ());
67 1.1 christos else
68 1.6 christos return string_printf ("%s (%d)", safe_strerror (err), err);
69 1.1 christos }
70 1.1 christos
71 1.1 christos #if defined __i386__ || defined __x86_64__
72 1.1 christos
73 1.1 christos /* Address of the 'ret' instruction in asm code block below. */
74 1.3 christos EXTERN_C void linux_ptrace_test_ret_to_nx_instr (void);
75 1.1 christos
76 1.1 christos #include <sys/reg.h>
77 1.1 christos #include <sys/mman.h>
78 1.1 christos #include <signal.h>
79 1.1 christos
80 1.1 christos #endif /* defined __i386__ || defined __x86_64__ */
81 1.1 christos
82 1.6 christos /* Kill CHILD. WHO is used to report warnings. */
83 1.6 christos
84 1.6 christos static void
85 1.6 christos kill_child (pid_t child, const char *who)
86 1.6 christos {
87 1.6 christos pid_t got_pid;
88 1.6 christos int kill_status;
89 1.6 christos
90 1.6 christos if (kill (child, SIGKILL) != 0)
91 1.6 christos {
92 1.6 christos warning (_("%s: failed to kill child pid %ld %s"),
93 1.6 christos who, (long) child, safe_strerror (errno));
94 1.6 christos return;
95 1.6 christos }
96 1.6 christos
97 1.6 christos errno = 0;
98 1.6 christos got_pid = my_waitpid (child, &kill_status, 0);
99 1.6 christos if (got_pid != child)
100 1.6 christos {
101 1.6 christos warning (_("%s: "
102 1.6 christos "kill waitpid returned %ld: %s"),
103 1.6 christos who, (long) got_pid, safe_strerror (errno));
104 1.6 christos return;
105 1.6 christos }
106 1.6 christos if (!WIFSIGNALED (kill_status))
107 1.6 christos {
108 1.6 christos warning (_("%s: "
109 1.6 christos "kill status %d is not WIFSIGNALED!"),
110 1.6 christos who, kill_status);
111 1.6 christos return;
112 1.6 christos }
113 1.6 christos }
114 1.6 christos
115 1.1 christos /* Test broken off-trunk Linux kernel patchset for NX support on i386. It was
116 1.1 christos removed in Fedora kernel 88fa1f0332d188795ed73d7ac2b1564e11a0b4cd.
117 1.1 christos
118 1.1 christos Test also x86_64 arch for PaX support. */
119 1.1 christos
120 1.1 christos static void
121 1.1 christos linux_ptrace_test_ret_to_nx (void)
122 1.1 christos {
123 1.1 christos #if defined __i386__ || defined __x86_64__
124 1.1 christos pid_t child, got_pid;
125 1.1 christos gdb_byte *return_address, *pc;
126 1.1 christos long l;
127 1.6 christos int status;
128 1.4 christos elf_gregset_t regs;
129 1.1 christos
130 1.4 christos return_address
131 1.4 christos = (gdb_byte *) mmap (NULL, 2, PROT_READ | PROT_WRITE,
132 1.1 christos MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
133 1.1 christos if (return_address == MAP_FAILED)
134 1.1 christos {
135 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: Cannot mmap: %s"),
136 1.3 christos safe_strerror (errno));
137 1.1 christos return;
138 1.1 christos }
139 1.1 christos
140 1.1 christos /* Put there 'int3'. */
141 1.1 christos *return_address = 0xcc;
142 1.1 christos
143 1.1 christos child = fork ();
144 1.1 christos switch (child)
145 1.1 christos {
146 1.1 christos case -1:
147 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: Cannot fork: %s"),
148 1.3 christos safe_strerror (errno));
149 1.1 christos return;
150 1.1 christos
151 1.1 christos case 0:
152 1.1 christos l = ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) NULL,
153 1.1 christos (PTRACE_TYPE_ARG4) NULL);
154 1.1 christos if (l != 0)
155 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_TRACEME: %s"),
156 1.3 christos safe_strerror (errno));
157 1.1 christos else
158 1.1 christos {
159 1.1 christos #if defined __i386__
160 1.1 christos asm volatile ("pushl %0;"
161 1.1 christos ".globl linux_ptrace_test_ret_to_nx_instr;"
162 1.1 christos "linux_ptrace_test_ret_to_nx_instr:"
163 1.1 christos "ret"
164 1.6 christos : : "r" (return_address) : "memory");
165 1.1 christos #elif defined __x86_64__
166 1.1 christos asm volatile ("pushq %0;"
167 1.1 christos ".globl linux_ptrace_test_ret_to_nx_instr;"
168 1.1 christos "linux_ptrace_test_ret_to_nx_instr:"
169 1.1 christos "ret"
170 1.1 christos : : "r" ((uint64_t) (uintptr_t) return_address)
171 1.6 christos : "memory");
172 1.1 christos #else
173 1.1 christos # error "!__i386__ && !__x86_64__"
174 1.1 christos #endif
175 1.1 christos gdb_assert_not_reached ("asm block did not terminate");
176 1.1 christos }
177 1.1 christos
178 1.1 christos _exit (1);
179 1.1 christos }
180 1.1 christos
181 1.1 christos errno = 0;
182 1.1 christos got_pid = waitpid (child, &status, 0);
183 1.1 christos if (got_pid != child)
184 1.1 christos {
185 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: waitpid returned %ld: %s"),
186 1.3 christos (long) got_pid, safe_strerror (errno));
187 1.1 christos return;
188 1.1 christos }
189 1.1 christos
190 1.1 christos if (WIFSIGNALED (status))
191 1.1 christos {
192 1.1 christos if (WTERMSIG (status) != SIGKILL)
193 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: WTERMSIG %d is not SIGKILL!"),
194 1.1 christos (int) WTERMSIG (status));
195 1.1 christos else
196 1.1 christos warning (_("Cannot call inferior functions, Linux kernel PaX "
197 1.1 christos "protection forbids return to non-executable pages!"));
198 1.1 christos return;
199 1.1 christos }
200 1.1 christos
201 1.1 christos if (!WIFSTOPPED (status))
202 1.1 christos {
203 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: status %d is not WIFSTOPPED!"),
204 1.1 christos status);
205 1.6 christos kill_child (child, "linux_ptrace_test_ret_to_nx");
206 1.1 christos return;
207 1.1 christos }
208 1.1 christos
209 1.1 christos /* We may get SIGSEGV due to missing PROT_EXEC of the return_address. */
210 1.1 christos if (WSTOPSIG (status) != SIGTRAP && WSTOPSIG (status) != SIGSEGV)
211 1.1 christos {
212 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: "
213 1.1 christos "WSTOPSIG %d is neither SIGTRAP nor SIGSEGV!"),
214 1.1 christos (int) WSTOPSIG (status));
215 1.6 christos kill_child (child, "linux_ptrace_test_ret_to_nx");
216 1.1 christos return;
217 1.1 christos }
218 1.1 christos
219 1.4 christos if (ptrace (PTRACE_GETREGS, child, (PTRACE_TYPE_ARG3) 0,
220 1.4 christos (PTRACE_TYPE_ARG4) ®s) < 0)
221 1.4 christos {
222 1.4 christos warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_GETREGS: %s"),
223 1.4 christos safe_strerror (errno));
224 1.4 christos }
225 1.1 christos #if defined __i386__
226 1.4 christos pc = (gdb_byte *) (uintptr_t) regs[EIP];
227 1.1 christos #elif defined __x86_64__
228 1.4 christos pc = (gdb_byte *) (uintptr_t) regs[RIP];
229 1.1 christos #else
230 1.1 christos # error "!__i386__ && !__x86_64__"
231 1.1 christos #endif
232 1.1 christos
233 1.6 christos kill_child (child, "linux_ptrace_test_ret_to_nx");
234 1.1 christos
235 1.1 christos /* + 1 is there as x86* stops after the 'int3' instruction. */
236 1.1 christos if (WSTOPSIG (status) == SIGTRAP && pc == return_address + 1)
237 1.1 christos {
238 1.1 christos /* PASS */
239 1.1 christos return;
240 1.1 christos }
241 1.1 christos
242 1.1 christos /* We may get SIGSEGV due to missing PROT_EXEC of the RETURN_ADDRESS page. */
243 1.1 christos if (WSTOPSIG (status) == SIGSEGV && pc == return_address)
244 1.1 christos {
245 1.1 christos /* PASS */
246 1.1 christos return;
247 1.1 christos }
248 1.1 christos
249 1.1 christos if ((void (*) (void)) pc != &linux_ptrace_test_ret_to_nx_instr)
250 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: PC %p is neither near return "
251 1.1 christos "address %p nor is the return instruction %p!"),
252 1.1 christos pc, return_address, &linux_ptrace_test_ret_to_nx_instr);
253 1.1 christos else
254 1.1 christos warning (_("Cannot call inferior functions on this system - "
255 1.1 christos "Linux kernel with broken i386 NX (non-executable pages) "
256 1.1 christos "support detected!"));
257 1.1 christos #endif /* defined __i386__ || defined __x86_64__ */
258 1.1 christos }
259 1.1 christos
260 1.1 christos /* Helper function to fork a process and make the child process call
261 1.1 christos the function FUNCTION, passing CHILD_STACK as parameter.
262 1.1 christos
263 1.1 christos For MMU-less targets, clone is used instead of fork, and
264 1.1 christos CHILD_STACK is used as stack space for the cloned child. If NULL,
265 1.1 christos stack space is allocated via malloc (and subsequently passed to
266 1.1 christos FUNCTION). For MMU targets, CHILD_STACK is ignored. */
267 1.1 christos
268 1.1 christos static int
269 1.4 christos linux_fork_to_function (gdb_byte *child_stack, int (*function) (void *))
270 1.1 christos {
271 1.1 christos int child_pid;
272 1.1 christos
273 1.1 christos /* Sanity check the function pointer. */
274 1.1 christos gdb_assert (function != NULL);
275 1.1 christos
276 1.1 christos #if defined(__UCLIBC__) && defined(HAS_NOMMU)
277 1.1 christos #define STACK_SIZE 4096
278 1.1 christos
279 1.1 christos if (child_stack == NULL)
280 1.6 christos child_stack = (gdb_byte *) xmalloc (STACK_SIZE * 4);
281 1.1 christos
282 1.1 christos /* Use CLONE_VM instead of fork, to support uClinux (no MMU). */
283 1.1 christos #ifdef __ia64__
284 1.1 christos child_pid = __clone2 (function, child_stack, STACK_SIZE,
285 1.1 christos CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
286 1.1 christos #else /* !__ia64__ */
287 1.1 christos child_pid = clone (function, child_stack + STACK_SIZE,
288 1.1 christos CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
289 1.1 christos #endif /* !__ia64__ */
290 1.1 christos #else /* !defined(__UCLIBC) && defined(HAS_NOMMU) */
291 1.1 christos child_pid = fork ();
292 1.1 christos
293 1.1 christos if (child_pid == 0)
294 1.1 christos function (NULL);
295 1.1 christos #endif /* defined(__UCLIBC) && defined(HAS_NOMMU) */
296 1.1 christos
297 1.1 christos if (child_pid == -1)
298 1.1 christos perror_with_name (("fork"));
299 1.1 christos
300 1.1 christos return child_pid;
301 1.1 christos }
302 1.1 christos
303 1.1 christos /* A helper function for linux_check_ptrace_features, called after
304 1.1 christos the parent process forks a child. The child allows itself to
305 1.1 christos be traced by its parent. */
306 1.1 christos
307 1.4 christos static int
308 1.4 christos linux_child_function (void *child_stack)
309 1.1 christos {
310 1.1 christos ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
311 1.1 christos kill (getpid (), SIGSTOP);
312 1.1 christos
313 1.1 christos /* This code is only reacheable by the child (grandchild's parent)
314 1.1 christos process. */
315 1.1 christos _exit (0);
316 1.1 christos }
317 1.1 christos
318 1.1 christos static void linux_test_for_exitkill (int child_pid);
319 1.1 christos
320 1.1 christos /* Determine ptrace features available on this target. */
321 1.1 christos
322 1.3 christos void
323 1.1 christos linux_check_ptrace_features (void)
324 1.1 christos {
325 1.1 christos int child_pid, ret, status;
326 1.1 christos
327 1.8 christos /* Initialize the options. We consider that these options are always
328 1.8 christos supported. */
329 1.8 christos supported_ptrace_options
330 1.8 christos = (PTRACE_O_TRACESYSGOOD
331 1.8 christos | PTRACE_O_TRACECLONE
332 1.8 christos | PTRACE_O_TRACEFORK
333 1.8 christos | PTRACE_O_TRACEVFORK
334 1.8 christos | PTRACE_O_TRACEVFORKDONE
335 1.8 christos | PTRACE_O_TRACEEXEC);
336 1.1 christos
337 1.1 christos /* Fork a child so we can do some testing. The child will call
338 1.1 christos linux_child_function and will get traced. The child will
339 1.1 christos eventually fork a grandchild so we can test fork event
340 1.1 christos reporting. */
341 1.1 christos child_pid = linux_fork_to_function (NULL, linux_child_function);
342 1.1 christos
343 1.1 christos ret = my_waitpid (child_pid, &status, 0);
344 1.1 christos if (ret == -1)
345 1.1 christos perror_with_name (("waitpid"));
346 1.1 christos else if (ret != child_pid)
347 1.1 christos error (_("linux_check_ptrace_features: waitpid: unexpected result %d."),
348 1.1 christos ret);
349 1.1 christos if (! WIFSTOPPED (status))
350 1.1 christos error (_("linux_check_ptrace_features: waitpid: unexpected status %d."),
351 1.1 christos status);
352 1.1 christos
353 1.1 christos linux_test_for_exitkill (child_pid);
354 1.1 christos
355 1.6 christos /* Kill child_pid. */
356 1.6 christos kill_child (child_pid, "linux_check_ptrace_features");
357 1.1 christos }
358 1.1 christos
359 1.1 christos /* Determine if PTRACE_O_EXITKILL can be used. */
360 1.1 christos
361 1.1 christos static void
362 1.1 christos linux_test_for_exitkill (int child_pid)
363 1.1 christos {
364 1.1 christos int ret;
365 1.1 christos
366 1.1 christos ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
367 1.1 christos (PTRACE_TYPE_ARG4) PTRACE_O_EXITKILL);
368 1.1 christos
369 1.1 christos if (ret == 0)
370 1.3 christos supported_ptrace_options |= PTRACE_O_EXITKILL;
371 1.1 christos }
372 1.1 christos
373 1.1 christos /* Enable reporting of all currently supported ptrace events.
374 1.3 christos OPTIONS is a bit mask of extended features we want enabled,
375 1.3 christos if supported by the kernel. PTRACE_O_TRACECLONE is always
376 1.3 christos enabled, if supported. */
377 1.1 christos
378 1.1 christos void
379 1.3 christos linux_enable_event_reporting (pid_t pid, int options)
380 1.1 christos {
381 1.1 christos /* Check if we have initialized the ptrace features for this
382 1.1 christos target. If not, do it now. */
383 1.3 christos if (supported_ptrace_options == -1)
384 1.1 christos linux_check_ptrace_features ();
385 1.1 christos
386 1.3 christos /* We always want clone events. */
387 1.3 christos options |= PTRACE_O_TRACECLONE;
388 1.3 christos
389 1.3 christos /* Filter out unsupported options. */
390 1.3 christos options &= supported_ptrace_options;
391 1.1 christos
392 1.1 christos /* Set the options. */
393 1.1 christos ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0,
394 1.3 christos (PTRACE_TYPE_ARG4) (uintptr_t) options);
395 1.1 christos }
396 1.1 christos
397 1.1 christos /* Disable reporting of all currently supported ptrace events. */
398 1.1 christos
399 1.1 christos void
400 1.1 christos linux_disable_event_reporting (pid_t pid)
401 1.1 christos {
402 1.1 christos /* Set the options. */
403 1.1 christos ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0, 0);
404 1.1 christos }
405 1.1 christos
406 1.1 christos /* Display possible problems on this system. Display them only once per GDB
407 1.1 christos execution. */
408 1.1 christos
409 1.1 christos void
410 1.1 christos linux_ptrace_init_warnings (void)
411 1.1 christos {
412 1.1 christos static int warned = 0;
413 1.1 christos
414 1.1 christos if (warned)
415 1.1 christos return;
416 1.1 christos warned = 1;
417 1.1 christos
418 1.1 christos linux_ptrace_test_ret_to_nx ();
419 1.1 christos }
420 1.1 christos
421 1.1 christos /* Extract extended ptrace event from wait status. */
422 1.1 christos
423 1.1 christos int
424 1.1 christos linux_ptrace_get_extended_event (int wstat)
425 1.1 christos {
426 1.1 christos return (wstat >> 16);
427 1.1 christos }
428 1.1 christos
429 1.1 christos /* Determine whether wait status denotes an extended event. */
430 1.1 christos
431 1.1 christos int
432 1.1 christos linux_is_extended_waitstatus (int wstat)
433 1.1 christos {
434 1.1 christos return (linux_ptrace_get_extended_event (wstat) != 0);
435 1.1 christos }
436 1.3 christos
437 1.3 christos /* Return true if the event in LP may be caused by breakpoint. */
438 1.3 christos
439 1.3 christos int
440 1.3 christos linux_wstatus_maybe_breakpoint (int wstat)
441 1.3 christos {
442 1.3 christos return (WIFSTOPPED (wstat)
443 1.3 christos && (WSTOPSIG (wstat) == SIGTRAP
444 1.3 christos /* SIGILL and SIGSEGV are also treated as traps in case a
445 1.3 christos breakpoint is inserted at the current PC. */
446 1.3 christos || WSTOPSIG (wstat) == SIGILL
447 1.3 christos || WSTOPSIG (wstat) == SIGSEGV));
448 1.3 christos }
449