PR gdb/15236: gdbserver write to linux memory with zero length corrupts stack
authorPedro Alves <palves@redhat.com>
Thu, 7 Mar 2013 09:47:57 +0000 (09:47 +0000)
committerPedro Alves <palves@redhat.com>
Thu, 7 Mar 2013 09:47:57 +0000 (09:47 +0000)
PROBLEM:

The function linux_write_memory () in linux-low.c allocates a buffer
on the stack to hold a copy of the data to be written.

  register PTRACE_XFER_TYPE *buffer = (PTRACE_XFER_TYPE *)
    alloca (count * sizeof (PTRACE_XFER_TYPE));

"count" is the number of bytes to be written, rounded up to the
nearest multiple of sizeof (PTRACE_XFER_TYPE) and allowing for not
being an aligned address. The function later uses

  buffer[0] = ptrace (PTRACE_PEEKTEXT, pid,
                      (PTRACE_ARG3_TYPE) (uintptr_t) addr, 0);

The problem is that this function can be called to write zero bytes on
an aligned address, for example when receiving an X packet of length 0
(used to test if 8-bit write is supported). Under these circumstances,
count can be zero.

Since in this case, buffer[0] may never have been allocated, the stack
is corrupted and gdbserver may crash.

SOLUTION:

Writing zero bytes should always succeed. The patch below returns
successfully early if the length is zero, so avoiding the stack
corruption.

Verified on the ARC GDB 7.5.1 port.

2013-03-07  Jeremy Bennett  <jeremy.bennett@embecosm.com>

PR server/15236

* linux-low.c (linux_write_memory): Return early success if LEN is
zero.

gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-low.c

index a8cf78c022a9dfc2570ad4538c5de714683ccf47..67bc149c0d4975259bfe21692652503a0939b7e1 100644 (file)
@@ -1,3 +1,9 @@
+2013-03-07  Jeremy Bennett  <jeremy.bennett@embecosm.com>
+
+       PR server/15236
+       * linux-low.c (linux_write_memory): Return early success if LEN is
+       zero.
+
 2013-03-05  Corinna Vinschen  <vinschen@redhat.de>
 
        * configure.srv: Add x86_64-*-cygwin* as target.
index c52cd2e165a39a989de21e21e6648dea517aa019..5f036284a92719f9dcfda3556036ce5af3ab4e3a 100644 (file)
@@ -4481,7 +4481,7 @@ linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
 
 /* Copy LEN bytes of data from debugger memory at MYADDR to inferior's
    memory at MEMADDR.  On failure (cannot write to the inferior)
-   returns the value of errno.  */
+   returns the value of errno.  Always succeeds if LEN is zero.  */
 
 static int
 linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
@@ -4500,6 +4500,12 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
 
   int pid = lwpid_of (get_thread_lwp (current_inferior));
 
+  if (len == 0)
+    {
+      /* Zero length write always succeeds.  */
+      return 0;
+    }
+
   if (debug_threads)
     {
       /* Dump up to four bytes.  */