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