From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12345 invoked by alias); 6 Mar 2013 18:04:48 -0000 Received: (qmail 12245 invoked by uid 22791); 6 Mar 2013 18:04:39 -0000 X-SWARE-Spam-Status: No, hits=-1.3 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_NONE,TW_DW,T_FILL_THIS_FORM_SHORT X-Spam-Check-By: sourceware.org Received: from smarthost.idnet.net (HELO smarthost.idnet.net) (212.69.40.140) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 06 Mar 2013 18:03:58 +0000 Received: from localhost (unknown [127.0.0.1]) by smarthost.idnet.net (Postfix) with ESMTP id 1839E236F57 for ; Wed, 6 Mar 2013 18:10:40 +0000 (UTC) Received: from smarthost.idnet.net ([127.0.0.1]) by localhost (smarthost.idnet.net [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 17vEbyHq7y5v for ; Wed, 6 Mar 2013 18:10:39 +0000 (GMT) Received: from smarthost.idnet.net (localhost.localdomain [127.0.0.1]) by smarthost.idnet.net (Postfix) with ESMTP id BF5F3236F58 for ; Wed, 6 Mar 2013 18:10:39 +0000 (GMT) Received: from m3.idnet.com (unknown [212.69.40.217]) by smarthost.idnet.net (Postfix) with ESMTP id BCE17236F57 for ; Wed, 6 Mar 2013 18:10:39 +0000 (GMT) Received: from mail.idnet.net.uk (mail.idnet.net.uk [212.69.36.63]) by m3.idnet.com (Postfix) with ESMTP id 5AD7922D12 for ; Wed, 6 Mar 2013 18:10:39 +0000 (GMT) Received: from [91.135.5.64] by mail.idnet.net.uk (GMS 17.01.3793/NU3963.00.7ca42f0c) with ESMTP via TLS id hyllwcda for gdb-patches@sourceware.org; Wed, 6 Mar 2013 18:03:57 +0000 Message-ID: <1362593035.2235.57.camel@laria> Subject: [PATCH PR gdb/15236] gdbserver write to linux memory with zero length corrupts stack From: Jeremy Bennett Reply-To: jeremy.bennett@embecosm.com To: gdb-patches@sourceware.org Date: Wed, 06 Mar 2013 18:04:00 -0000 Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Content-Transfer-Encoding: 7bit X-AuthenticatedSender: jeremy.bennett.embecosm.com@idnet.net.uk X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2013-03/txt/msg00223.txt.bz2 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. Demonstrated with the port of GDB 7.5.1 for the Synopsys arc-linux-uclibc- target, currently under development at: https://github.com/foss-for-synopsys-dwc-arc-processors/gdb (to be submitted to the FSF in due course). 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. CHANGELOG ENTRY: 2013-03-06 Jeremy Bennett PR gdb/15236 * linux-low.c (linux_write_memory): Return early success if len is zero. PATCH: I'm working from a git mirror and have produced this using git diff. Advice on how to do this properly appreciated! diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 7b79cd1..450e2db 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,9 @@ +2013-03-06 Jeremy Bennett + + PR gdb/15236 + * linux-low.c (linux_write_memory): Return early success if len is + zero. + 2012-04-29 Yao Qi * server.h: Move some code to ... diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index bbb0693..8e576bd 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -4421,7 +4421,14 @@ 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. + + 6-Mar-13, Jeremy Bennett: [PR gdb/15236] This function can be called with + length 0 (for example with a zero length X packet). If memaddr is aligned + to sizeof (PTRACE_XFER_TYPE), then count will be zero and nothing may be + allocated for buffer (architecture dependent). The function must return + early in this circumstance, to avoid stack corruption when assigning + to buffer[0]. */ static int linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) @@ -4440,6 +4447,10 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) int pid = lwpid_of (get_thread_lwp (current_inferior)); + if (0 == len) { + return 0; /* Zero length write always succeeds. */ + } + if (debug_threads) { /* Dump up to four bytes. */ Best wishes, Jeremy -- Tel: +44 (1590) 610184 Cell: +44 (7970) 676050 SkypeID: jeremybennett Email: jeremy.bennett@embecosm.com Web: www.embecosm.com