GDB (API)
/home/stan/gdb/src/gdb/common/linux-ptrace.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines