GDB (API)
|
00001 /* Linux-specific ptrace manipulation routines. 00002 Copyright (C) 2012-2013 Free Software Foundation, Inc. 00003 00004 This file is part of GDB. 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00018 00019 #ifdef GDBSERVER 00020 #include "server.h" 00021 #else 00022 #include "defs.h" 00023 #include "gdb_string.h" 00024 #endif 00025 00026 #include "linux-ptrace.h" 00027 #include "linux-procfs.h" 00028 #include "nat/linux-waitpid.h" 00029 #include "buffer.h" 00030 #include "gdb_assert.h" 00031 #include "gdb_wait.h" 00032 00033 #include <stdint.h> 00034 00035 /* Stores the currently supported ptrace options. A value of 00036 -1 means we did not check for features yet. A value of 0 means 00037 there are no supported features. */ 00038 static int current_ptrace_options = -1; 00039 00040 /* Find all possible reasons we could fail to attach PID and append these 00041 newline terminated reason strings to initialized BUFFER. '\0' termination 00042 of BUFFER must be done by the caller. */ 00043 00044 void 00045 linux_ptrace_attach_warnings (pid_t pid, struct buffer *buffer) 00046 { 00047 pid_t tracerpid; 00048 00049 tracerpid = linux_proc_get_tracerpid (pid); 00050 if (tracerpid > 0) 00051 buffer_xml_printf (buffer, _("warning: process %d is already traced " 00052 "by process %d\n"), 00053 (int) pid, (int) tracerpid); 00054 00055 if (linux_proc_pid_is_zombie (pid)) 00056 buffer_xml_printf (buffer, _("warning: process %d is a zombie " 00057 "- the process has already terminated\n"), 00058 (int) pid); 00059 } 00060 00061 #if defined __i386__ || defined __x86_64__ 00062 00063 /* Address of the 'ret' instruction in asm code block below. */ 00064 extern void (linux_ptrace_test_ret_to_nx_instr) (void); 00065 00066 #include <sys/reg.h> 00067 #include <sys/mman.h> 00068 #include <signal.h> 00069 00070 #endif /* defined __i386__ || defined __x86_64__ */ 00071 00072 /* Test broken off-trunk Linux kernel patchset for NX support on i386. It was 00073 removed in Fedora kernel 88fa1f0332d188795ed73d7ac2b1564e11a0b4cd. 00074 00075 Test also x86_64 arch for PaX support. */ 00076 00077 static void 00078 linux_ptrace_test_ret_to_nx (void) 00079 { 00080 #if defined __i386__ || defined __x86_64__ 00081 pid_t child, got_pid; 00082 gdb_byte *return_address, *pc; 00083 long l; 00084 int status, kill_status; 00085 00086 return_address = mmap (NULL, 2, PROT_READ | PROT_WRITE, 00087 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 00088 if (return_address == MAP_FAILED) 00089 { 00090 warning (_("linux_ptrace_test_ret_to_nx: Cannot mmap: %s"), 00091 strerror (errno)); 00092 return; 00093 } 00094 00095 /* Put there 'int3'. */ 00096 *return_address = 0xcc; 00097 00098 child = fork (); 00099 switch (child) 00100 { 00101 case -1: 00102 warning (_("linux_ptrace_test_ret_to_nx: Cannot fork: %s"), 00103 strerror (errno)); 00104 return; 00105 00106 case 0: 00107 l = ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) NULL, 00108 (PTRACE_TYPE_ARG4) NULL); 00109 if (l != 0) 00110 warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_TRACEME: %s"), 00111 strerror (errno)); 00112 else 00113 { 00114 #if defined __i386__ 00115 asm volatile ("pushl %0;" 00116 ".globl linux_ptrace_test_ret_to_nx_instr;" 00117 "linux_ptrace_test_ret_to_nx_instr:" 00118 "ret" 00119 : : "r" (return_address) : "%esp", "memory"); 00120 #elif defined __x86_64__ 00121 asm volatile ("pushq %0;" 00122 ".globl linux_ptrace_test_ret_to_nx_instr;" 00123 "linux_ptrace_test_ret_to_nx_instr:" 00124 "ret" 00125 : : "r" ((uint64_t) (uintptr_t) return_address) 00126 : "%rsp", "memory"); 00127 #else 00128 # error "!__i386__ && !__x86_64__" 00129 #endif 00130 gdb_assert_not_reached ("asm block did not terminate"); 00131 } 00132 00133 _exit (1); 00134 } 00135 00136 errno = 0; 00137 got_pid = waitpid (child, &status, 0); 00138 if (got_pid != child) 00139 { 00140 warning (_("linux_ptrace_test_ret_to_nx: waitpid returned %ld: %s"), 00141 (long) got_pid, strerror (errno)); 00142 return; 00143 } 00144 00145 if (WIFSIGNALED (status)) 00146 { 00147 if (WTERMSIG (status) != SIGKILL) 00148 warning (_("linux_ptrace_test_ret_to_nx: WTERMSIG %d is not SIGKILL!"), 00149 (int) WTERMSIG (status)); 00150 else 00151 warning (_("Cannot call inferior functions, Linux kernel PaX " 00152 "protection forbids return to non-executable pages!")); 00153 return; 00154 } 00155 00156 if (!WIFSTOPPED (status)) 00157 { 00158 warning (_("linux_ptrace_test_ret_to_nx: status %d is not WIFSTOPPED!"), 00159 status); 00160 return; 00161 } 00162 00163 /* We may get SIGSEGV due to missing PROT_EXEC of the return_address. */ 00164 if (WSTOPSIG (status) != SIGTRAP && WSTOPSIG (status) != SIGSEGV) 00165 { 00166 warning (_("linux_ptrace_test_ret_to_nx: " 00167 "WSTOPSIG %d is neither SIGTRAP nor SIGSEGV!"), 00168 (int) WSTOPSIG (status)); 00169 return; 00170 } 00171 00172 errno = 0; 00173 #if defined __i386__ 00174 l = ptrace (PTRACE_PEEKUSER, child, (PTRACE_TYPE_ARG3) (uintptr_t) (EIP * 4), 00175 (PTRACE_TYPE_ARG4) NULL); 00176 #elif defined __x86_64__ 00177 l = ptrace (PTRACE_PEEKUSER, child, (PTRACE_TYPE_ARG3) (uintptr_t) (RIP * 8), 00178 (PTRACE_TYPE_ARG4) NULL); 00179 #else 00180 # error "!__i386__ && !__x86_64__" 00181 #endif 00182 if (errno != 0) 00183 { 00184 warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_PEEKUSER: %s"), 00185 strerror (errno)); 00186 return; 00187 } 00188 pc = (void *) (uintptr_t) l; 00189 00190 kill (child, SIGKILL); 00191 ptrace (PTRACE_KILL, child, (PTRACE_TYPE_ARG3) NULL, 00192 (PTRACE_TYPE_ARG4) NULL); 00193 00194 errno = 0; 00195 got_pid = waitpid (child, &kill_status, 0); 00196 if (got_pid != child) 00197 { 00198 warning (_("linux_ptrace_test_ret_to_nx: " 00199 "PTRACE_KILL waitpid returned %ld: %s"), 00200 (long) got_pid, strerror (errno)); 00201 return; 00202 } 00203 if (!WIFSIGNALED (kill_status)) 00204 { 00205 warning (_("linux_ptrace_test_ret_to_nx: " 00206 "PTRACE_KILL status %d is not WIFSIGNALED!"), 00207 status); 00208 return; 00209 } 00210 00211 /* + 1 is there as x86* stops after the 'int3' instruction. */ 00212 if (WSTOPSIG (status) == SIGTRAP && pc == return_address + 1) 00213 { 00214 /* PASS */ 00215 return; 00216 } 00217 00218 /* We may get SIGSEGV due to missing PROT_EXEC of the RETURN_ADDRESS page. */ 00219 if (WSTOPSIG (status) == SIGSEGV && pc == return_address) 00220 { 00221 /* PASS */ 00222 return; 00223 } 00224 00225 if ((void (*) (void)) pc != &linux_ptrace_test_ret_to_nx_instr) 00226 warning (_("linux_ptrace_test_ret_to_nx: PC %p is neither near return " 00227 "address %p nor is the return instruction %p!"), 00228 pc, return_address, &linux_ptrace_test_ret_to_nx_instr); 00229 else 00230 warning (_("Cannot call inferior functions on this system - " 00231 "Linux kernel with broken i386 NX (non-executable pages) " 00232 "support detected!")); 00233 #endif /* defined __i386__ || defined __x86_64__ */ 00234 } 00235 00236 /* Helper function to fork a process and make the child process call 00237 the function FUNCTION, passing CHILD_STACK as parameter. 00238 00239 For MMU-less targets, clone is used instead of fork, and 00240 CHILD_STACK is used as stack space for the cloned child. If NULL, 00241 stack space is allocated via malloc (and subsequently passed to 00242 FUNCTION). For MMU targets, CHILD_STACK is ignored. */ 00243 00244 static int 00245 linux_fork_to_function (gdb_byte *child_stack, void (*function) (gdb_byte *)) 00246 { 00247 int child_pid; 00248 00249 /* Sanity check the function pointer. */ 00250 gdb_assert (function != NULL); 00251 00252 #if defined(__UCLIBC__) && defined(HAS_NOMMU) 00253 #define STACK_SIZE 4096 00254 00255 if (child_stack == NULL) 00256 child_stack = xmalloc (STACK_SIZE * 4); 00257 00258 /* Use CLONE_VM instead of fork, to support uClinux (no MMU). */ 00259 #ifdef __ia64__ 00260 child_pid = __clone2 (function, child_stack, STACK_SIZE, 00261 CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2); 00262 #else /* !__ia64__ */ 00263 child_pid = clone (function, child_stack + STACK_SIZE, 00264 CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2); 00265 #endif /* !__ia64__ */ 00266 #else /* !defined(__UCLIBC) && defined(HAS_NOMMU) */ 00267 child_pid = fork (); 00268 00269 if (child_pid == 0) 00270 function (NULL); 00271 #endif /* defined(__UCLIBC) && defined(HAS_NOMMU) */ 00272 00273 if (child_pid == -1) 00274 perror_with_name (("fork")); 00275 00276 return child_pid; 00277 } 00278 00279 /* A helper function for linux_check_ptrace_features, called after 00280 the child forks a grandchild. */ 00281 00282 static void 00283 linux_grandchild_function (gdb_byte *child_stack) 00284 { 00285 /* Free any allocated stack. */ 00286 xfree (child_stack); 00287 00288 /* This code is only reacheable by the grandchild (child's child) 00289 process. */ 00290 _exit (0); 00291 } 00292 00293 /* A helper function for linux_check_ptrace_features, called after 00294 the parent process forks a child. The child allows itself to 00295 be traced by its parent. */ 00296 00297 static void 00298 linux_child_function (gdb_byte *child_stack) 00299 { 00300 ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0); 00301 kill (getpid (), SIGSTOP); 00302 00303 /* Fork a grandchild. */ 00304 linux_fork_to_function (child_stack, linux_grandchild_function); 00305 00306 /* This code is only reacheable by the child (grandchild's parent) 00307 process. */ 00308 _exit (0); 00309 } 00310 00311 static void linux_test_for_tracesysgood (int child_pid); 00312 static void linux_test_for_tracefork (int child_pid); 00313 00314 /* Determine ptrace features available on this target. */ 00315 00316 static void 00317 linux_check_ptrace_features (void) 00318 { 00319 int child_pid, ret, status; 00320 00321 /* Initialize the options. */ 00322 current_ptrace_options = 0; 00323 00324 /* Fork a child so we can do some testing. The child will call 00325 linux_child_function and will get traced. The child will 00326 eventually fork a grandchild so we can test fork event 00327 reporting. */ 00328 child_pid = linux_fork_to_function (NULL, linux_child_function); 00329 00330 ret = my_waitpid (child_pid, &status, 0); 00331 if (ret == -1) 00332 perror_with_name (("waitpid")); 00333 else if (ret != child_pid) 00334 error (_("linux_check_ptrace_features: waitpid: unexpected result %d."), 00335 ret); 00336 if (! WIFSTOPPED (status)) 00337 error (_("linux_check_ptrace_features: waitpid: unexpected status %d."), 00338 status); 00339 00340 linux_test_for_tracesysgood (child_pid); 00341 00342 linux_test_for_tracefork (child_pid); 00343 00344 /* Clean things up and kill any pending children. */ 00345 do 00346 { 00347 ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0, 00348 (PTRACE_TYPE_ARG4) 0); 00349 if (ret != 0) 00350 warning (_("linux_check_ptrace_features: failed to kill child")); 00351 my_waitpid (child_pid, &status, 0); 00352 } 00353 while (WIFSTOPPED (status)); 00354 } 00355 00356 /* Determine if PTRACE_O_TRACESYSGOOD can be used to catch 00357 syscalls. */ 00358 00359 static void 00360 linux_test_for_tracesysgood (int child_pid) 00361 { 00362 #ifdef GDBSERVER 00363 /* gdbserver does not support PTRACE_O_TRACESYSGOOD. */ 00364 #else 00365 int ret; 00366 00367 ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0, 00368 (PTRACE_TYPE_ARG4) PTRACE_O_TRACESYSGOOD); 00369 if (ret == 0) 00370 current_ptrace_options |= PTRACE_O_TRACESYSGOOD; 00371 #endif 00372 } 00373 00374 /* Determine if PTRACE_O_TRACEFORK can be used to follow fork 00375 events. */ 00376 00377 static void 00378 linux_test_for_tracefork (int child_pid) 00379 { 00380 int ret, status; 00381 long second_pid; 00382 00383 /* First, set the PTRACE_O_TRACEFORK option. If this fails, we 00384 know for sure that it is not supported. */ 00385 ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0, 00386 (PTRACE_TYPE_ARG4) PTRACE_O_TRACEFORK); 00387 00388 if (ret != 0) 00389 return; 00390 00391 #ifdef GDBSERVER 00392 /* gdbserver does not support PTRACE_O_TRACEVFORKDONE yet. */ 00393 #else 00394 /* Check if the target supports PTRACE_O_TRACEVFORKDONE. */ 00395 ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0, 00396 (PTRACE_TYPE_ARG4) (PTRACE_O_TRACEFORK 00397 | PTRACE_O_TRACEVFORKDONE)); 00398 if (ret == 0) 00399 current_ptrace_options |= PTRACE_O_TRACEVFORKDONE; 00400 #endif 00401 00402 /* Setting PTRACE_O_TRACEFORK did not cause an error, however we 00403 don't know for sure that the feature is available; old 00404 versions of PTRACE_SETOPTIONS ignored unknown options. 00405 Therefore, we attach to the child process, use PTRACE_SETOPTIONS 00406 to enable fork tracing, and let it fork. If the process exits, 00407 we assume that we can't use PTRACE_O_TRACEFORK; if we get the 00408 fork notification, and we can extract the new child's PID, then 00409 we assume that we can. 00410 00411 We do not explicitly check for vfork tracing here. It is 00412 assumed that vfork tracing is available whenever fork tracing 00413 is available. */ 00414 ret = ptrace (PTRACE_CONT, child_pid, (PTRACE_TYPE_ARG3) 0, 00415 (PTRACE_TYPE_ARG4) 0); 00416 if (ret != 0) 00417 warning (_("linux_test_for_tracefork: failed to resume child")); 00418 00419 ret = my_waitpid (child_pid, &status, 0); 00420 00421 /* Check if we received a fork event notification. */ 00422 if (ret == child_pid && WIFSTOPPED (status) 00423 && status >> 16 == PTRACE_EVENT_FORK) 00424 { 00425 /* We did receive a fork event notification. Make sure its PID 00426 is reported. */ 00427 second_pid = 0; 00428 ret = ptrace (PTRACE_GETEVENTMSG, child_pid, (PTRACE_TYPE_ARG3) 0, 00429 (PTRACE_TYPE_ARG4) &second_pid); 00430 if (ret == 0 && second_pid != 0) 00431 { 00432 int second_status; 00433 00434 /* We got the PID from the grandchild, which means fork 00435 tracing is supported. */ 00436 #ifdef GDBSERVER 00437 /* Do not enable all the options for now since gdbserver does not 00438 properly support them. This restriction will be lifted when 00439 gdbserver is augmented to support them. */ 00440 current_ptrace_options |= PTRACE_O_TRACECLONE; 00441 #else 00442 current_ptrace_options |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK 00443 | PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC; 00444 00445 /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to 00446 support read-only process state. */ 00447 #endif 00448 00449 /* Do some cleanup and kill the grandchild. */ 00450 my_waitpid (second_pid, &second_status, 0); 00451 ret = ptrace (PTRACE_KILL, second_pid, (PTRACE_TYPE_ARG3) 0, 00452 (PTRACE_TYPE_ARG4) 0); 00453 if (ret != 0) 00454 warning (_("linux_test_for_tracefork: " 00455 "failed to kill second child")); 00456 my_waitpid (second_pid, &status, 0); 00457 } 00458 } 00459 else 00460 warning (_("linux_test_for_tracefork: unexpected result from waitpid " 00461 "(%d, status 0x%x)"), ret, status); 00462 } 00463 00464 /* Enable reporting of all currently supported ptrace events. */ 00465 00466 void 00467 linux_enable_event_reporting (pid_t pid) 00468 { 00469 /* Check if we have initialized the ptrace features for this 00470 target. If not, do it now. */ 00471 if (current_ptrace_options == -1) 00472 linux_check_ptrace_features (); 00473 00474 /* Set the options. */ 00475 ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0, 00476 (PTRACE_TYPE_ARG4) (uintptr_t) current_ptrace_options); 00477 } 00478 00479 /* Returns non-zero if PTRACE_OPTIONS is contained within 00480 CURRENT_PTRACE_OPTIONS, therefore supported. Returns 0 00481 otherwise. */ 00482 00483 static int 00484 ptrace_supports_feature (int ptrace_options) 00485 { 00486 gdb_assert (current_ptrace_options >= 0); 00487 00488 return ((current_ptrace_options & ptrace_options) == ptrace_options); 00489 } 00490 00491 /* Returns non-zero if PTRACE_EVENT_FORK is supported by ptrace, 00492 0 otherwise. Note that if PTRACE_EVENT_FORK is supported so is 00493 PTRACE_EVENT_CLONE, PTRACE_EVENT_EXEC and PTRACE_EVENT_VFORK, 00494 since they were all added to the kernel at the same time. */ 00495 00496 int 00497 linux_supports_tracefork (void) 00498 { 00499 return ptrace_supports_feature (PTRACE_O_TRACEFORK); 00500 } 00501 00502 /* Returns non-zero if PTRACE_EVENT_CLONE is supported by ptrace, 00503 0 otherwise. Note that if PTRACE_EVENT_CLONE is supported so is 00504 PTRACE_EVENT_FORK, PTRACE_EVENT_EXEC and PTRACE_EVENT_VFORK, 00505 since they were all added to the kernel at the same time. */ 00506 00507 int 00508 linux_supports_traceclone (void) 00509 { 00510 return ptrace_supports_feature (PTRACE_O_TRACECLONE); 00511 } 00512 00513 /* Returns non-zero if PTRACE_O_TRACEVFORKDONE is supported by 00514 ptrace, 0 otherwise. */ 00515 00516 int 00517 linux_supports_tracevforkdone (void) 00518 { 00519 return ptrace_supports_feature (PTRACE_O_TRACEVFORKDONE); 00520 } 00521 00522 /* Returns non-zero if PTRACE_O_TRACESYSGOOD is supported by ptrace, 00523 0 otherwise. */ 00524 00525 int 00526 linux_supports_tracesysgood (void) 00527 { 00528 return ptrace_supports_feature (PTRACE_O_TRACESYSGOOD); 00529 } 00530 00531 /* Display possible problems on this system. Display them only once per GDB 00532 execution. */ 00533 00534 void 00535 linux_ptrace_init_warnings (void) 00536 { 00537 static int warned = 0; 00538 00539 if (warned) 00540 return; 00541 warned = 1; 00542 00543 linux_ptrace_test_ret_to_nx (); 00544 }