From patchwork Wed Nov 18 11:49:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 9715 Received: (qmail 28637 invoked by alias); 18 Nov 2015 11:49:25 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 28624 invoked by uid 89); 18 Nov 2015 11:49:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f41.google.com Received: from mail-pa0-f41.google.com (HELO mail-pa0-f41.google.com) (209.85.220.41) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 18 Nov 2015 11:49:23 +0000 Received: by pacdm15 with SMTP id dm15so43043622pac.3 for ; Wed, 18 Nov 2015 03:49:21 -0800 (PST) X-Received: by 10.67.23.229 with SMTP id id5mr1453625pad.64.1447847361108; Wed, 18 Nov 2015 03:49:21 -0800 (PST) Received: from E107787-LIN (gcc1-power7.osuosl.org. [140.211.15.137]) by smtp.gmail.com with ESMTPSA id in6sm3801757pbd.86.2015.11.18.03.49.17 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Wed, 18 Nov 2015 03:49:20 -0800 (PST) From: Yao Qi To: Yao Qi Cc: gdb-patches@sourceware.org Subject: Re: [PATCH] Fix out of boundary access in pass_in_v References: <1447686238-9554-1-git-send-email-yao.qi@linaro.org> Date: Wed, 18 Nov 2015 11:49:13 +0000 In-Reply-To: <1447686238-9554-1-git-send-email-yao.qi@linaro.org> (Yao Qi's message of "Mon, 16 Nov 2015 15:03:58 +0000") Message-ID: <86bnar1q9y.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes Yao Qi writes: > - regcache_cooked_write (regcache, regnum, buf); > + memset (reg, 0, sizeof (reg)); > + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) > + memcpy (reg + V_REGISTER_SIZE - len, buf, len); > + else > + memcpy (reg, buf, len); > + regcache_cooked_write (regcache, regnum, reg); > + After reading AArch64 procedure call standard again, I find that I don't have to worry about the endianess here, because arguments are always allocated at the LSB of SIMD/FP registers. Patch is updated as below, and is pushed in. ================================================================= ==8088==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000cb650 at pc 0x6e195c bp 0x7fff164f9770 sp 0x7fff164f9768 READ of size 16 at 0x6020000cb650 thread T0^ #0 0x6e195b in regcache_raw_write /home/yao/SourceCode/gnu/gdb/git/gdb/regcache.c:912 #1 0x6e1e52 in regcache_cooked_write /home/yao/SourceCode/gnu/gdb/git/gdb/regcache.c:945 #2 0x466d69 in pass_in_v /home/yao/SourceCode/gnu/gdb/git/gdb/aarch64-tdep.c:1101 #3 0x467512 in pass_in_v_or_stack /home/yao/SourceCode/gnu/gdb/git/gdb/aarch64-tdep.c:1196 #4 0x467d7d in aarch64_push_dummy_call /home/yao/SourceCode/gnu/gdb/git/gdb/aarch64-tdep.c:1335 The code in pass_in_v read contents from V registers (128 bit), but the data passed through V registers can be less than 128 bit. In this case, float is passed. So writing V registers contents into contents buff will cause overflow. In this patch, we add an array reg[V_REGISTER_SIZE], which is to hold the contents from V registers, and then copy useful bits to buf. gdb: 2015-11-18 Yao Qi * aarch64-tdep.c (pass_in_v): Add argument len. Add local array reg. Callers updated. diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1f7aed0..a7b44fe 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2015-11-18 Yao Qi + + * aarch64-tdep.c (pass_in_v): Add argument len. Add local array + reg. Callers updated. + 2015-11-17 Yao Qi * infrun.c (resume): Check control.trap_expected only diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index de045e6..de85cb0 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1034,17 +1034,23 @@ static int pass_in_v (struct gdbarch *gdbarch, struct regcache *regcache, struct aarch64_call_info *info, - const bfd_byte *buf) + int len, const bfd_byte *buf) { if (info->nsrn < 8) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int regnum = AARCH64_V0_REGNUM + info->nsrn; + gdb_byte reg[V_REGISTER_SIZE]; info->argnum++; info->nsrn++; - regcache_cooked_write (regcache, regnum, buf); + memset (reg, 0, sizeof (reg)); + /* PCS C.1, the argument is allocated to the least significant + bits of V register. */ + memcpy (reg, buf, len); + regcache_cooked_write (regcache, regnum, reg); + if (aarch64_debug) { debug_printf ("arg %d in %s\n", info->argnum, @@ -1138,7 +1144,8 @@ pass_in_v_or_stack (struct gdbarch *gdbarch, struct type *type, struct value *arg) { - if (!pass_in_v (gdbarch, regcache, info, value_contents (arg))) + if (!pass_in_v (gdbarch, regcache, info, TYPE_LENGTH (type), + value_contents (arg))) pass_on_stack (info, type, arg); } @@ -1263,8 +1270,10 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct type *target_type = check_typedef (TYPE_TARGET_TYPE (arg_type)); - pass_in_v (gdbarch, regcache, &info, buf); pass_in_v (gdbarch, regcache, &info, + TYPE_LENGTH (target_type), buf); + pass_in_v (gdbarch, regcache, &info, + TYPE_LENGTH (target_type), buf + TYPE_LENGTH (target_type)); } else