public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Fix out of boundary access in pass_in_v
@ 2015-11-16 15:04 Yao Qi
  2015-11-18 11:49 ` Yao Qi
  0 siblings, 1 reply; 2+ messages in thread
From: Yao Qi @ 2015-11-16 15:04 UTC (permalink / raw)
  To: gdb-patches

Hi,
I build GDB with -fsanitize=address, and run testsuite.  In
gdb.base/callfuncs.exp, I see the following error,

p t_float_values(0.0,0.0)
=================================================================
==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-16  Yao Qi  <yao.qi@linaro.org>

	* aarch64-tdep.c (pass_in_v): Add argument len.  Add local array
	reg.  Callers updated.
---
 gdb/aarch64-tdep.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index b025eba..4b82553 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -1034,17 +1034,24 @@ 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));
+      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);
+
       if (aarch64_debug)
 	{
 	  debug_printf ("arg %d in %s\n", info->argnum,
@@ -1138,7 +1145,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 +1271,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
-- 
1.9.1

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] Fix out of boundary access in pass_in_v
  2015-11-16 15:04 [PATCH] Fix out of boundary access in pass_in_v Yao Qi
@ 2015-11-18 11:49 ` Yao Qi
  0 siblings, 0 replies; 2+ messages in thread
From: Yao Qi @ 2015-11-18 11:49 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

Yao Qi <qiyaoltc@gmail.com> 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.

-- 
Yao (齐尧)

From: Yao Qi <yao.qi@linaro.org>
Subject: [PATCH] Fix out of boundary access in pass_in_v

Hi,
I build GDB with -fsanitize=address, and run testsuite.  In
gdb.base/callfuncs.exp, I see the following error,

p t_float_values(0.0,0.0)
=================================================================
==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  <yao.qi@linaro.org>

	* 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  <yao.qi@linaro.org>
+
+	* aarch64-tdep.c (pass_in_v): Add argument len.  Add local array
+	reg.  Callers updated.
+
 2015-11-17  Yao Qi  <yao.qi@linaro.org>
 
 	* 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

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-11-18 11:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-16 15:04 [PATCH] Fix out of boundary access in pass_in_v Yao Qi
2015-11-18 11:49 ` Yao Qi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).