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