diff mbox

resolv: fix unaligned tmp buffer corner-case

Message ID 1426116072-8003-1-git-send-email-abrodkin@synopsys.com
State Accepted
Commit 8ee422cffbfd3e2a16265fe6680a8dde2f5e58fe
Headers show

Commit Message

Alexey Brodkin March 11, 2015, 11:21 p.m. UTC
On execution of "inet/gethost_r-align" test I noticed failure due
to unaligned access (instaed of 4-byte aligned 1-byte aligned
address was attempted to be accessed).

Further investigation confirmed this nice and helpful test failure.
Following commit removed usage of ALIGN_BUFFER_OFFSET on entry to
__read_etc_hosts_r():
http://git.uclibc.org/uClibc/commit/?id=f65e66078b9f4d2d7f0fc336dee36e78fc467c0f

So indeed if target architecture doesn't allow unaligned access
and provided tmp buffer is not word aligned (and we will deal with pointers
which means word-sized data units), then CPU will fail during execution.

In case of ARC we'll see "Unaligned access" exception like this:
 --->8---
 # potentially unexpected fatal signal 7.
 Path: /root/uClibc/test/inet/gethost_r-align
 CPU: 0 PID: 5514 Comm: gethost_r-align Not tainted 3.13.11 #2
 task: 8f42a580 ti: 8f40e000 task.ti: 8f40e000

 [ECR   ]: 0x00230400 => Misaligned r/w from 0x5fdab341
 [EFA   ]: 0x5fdab341
 [BLINK ]: 0x20032a18
 [ERET  ]: 0x20032a3c
     @off 0x12a3c in [/lib/libuClibc-0.9.34-git.so]
     VMA: 0x20020000 to 0x20062000
 [STAT32]: 0x00000086 : U         E2 E1
 BTA: 0x20046014  SP: 0x5fdab260  FP: 0x00000000
 LPS: 0x20046064 LPE: 0x20046068 LPC: 0x00000000
 r00: 0x5fdab341 r01: 0x00000005 r02: 0x00000015
 r03: 0x00000000 r04: 0x5fdab358 r05: 0x00000000
 r06: 0x0a0a0a00 r07: 0x00000000 r08: 0x0000003f
 r09: 0x20067050 r10: 0x00000000 r11: 0x00000014
 r12: 0x00000001 r13: 0x00000000 r14: 0x20060660
 r15: 0x20060661 r16: 0x00000006 r17: 0x5fdab371
 r18: 0x00000018 r19: 0x5fdab2b4 r20: 0x00020000
 r21: 0x00000000 r22: 0x00029068 r23: 0x5fdab371
 r24: 0x00010000 r25: 0x00000000
 --->8---

To fix this problem we'll re-introduce tmp buffer force alignment
before config parser invocation.

Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: Waldemar Brodkorb <wbx@openadk.org>
---
 libc/inet/resolv.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

Comments

Rich Felker March 14, 2015, 3:06 p.m. UTC | #1
On Thu, Mar 12, 2015 at 02:21:12AM +0300, Alexey Brodkin wrote:
> On execution of "inet/gethost_r-align" test I noticed failure due
> to unaligned access (instaed of 4-byte aligned 1-byte aligned
> address was attempted to be accessed).
> 
> Further investigation confirmed this nice and helpful test failure.
> Following commit removed usage of ALIGN_BUFFER_OFFSET on entry to
> __read_etc_hosts_r():
> http://git.uclibc.org/uClibc/commit/?id=f65e66078b9f4d2d7f0fc336dee36e78fc467c0f
> 
> So indeed if target architecture doesn't allow unaligned access
> and provided tmp buffer is not word aligned (and we will deal with pointers
> which means word-sized data units), then CPU will fail during execution.
> 
> In case of ARC we'll see "Unaligned access" exception like this:
>  --->8---
>  # potentially unexpected fatal signal 7.
>  Path: /root/uClibc/test/inet/gethost_r-align
>  CPU: 0 PID: 5514 Comm: gethost_r-align Not tainted 3.13.11 #2
>  task: 8f42a580 ti: 8f40e000 task.ti: 8f40e000
> 
>  [ECR   ]: 0x00230400 => Misaligned r/w from 0x5fdab341
>  [EFA   ]: 0x5fdab341
>  [BLINK ]: 0x20032a18
>  [ERET  ]: 0x20032a3c
>      @off 0x12a3c in [/lib/libuClibc-0.9.34-git.so]
>      VMA: 0x20020000 to 0x20062000
>  [STAT32]: 0x00000086 : U         E2 E1
>  BTA: 0x20046014  SP: 0x5fdab260  FP: 0x00000000
>  LPS: 0x20046064 LPE: 0x20046068 LPC: 0x00000000
>  r00: 0x5fdab341 r01: 0x00000005 r02: 0x00000015
>  r03: 0x00000000 r04: 0x5fdab358 r05: 0x00000000
>  r06: 0x0a0a0a00 r07: 0x00000000 r08: 0x0000003f
>  r09: 0x20067050 r10: 0x00000000 r11: 0x00000014
>  r12: 0x00000001 r13: 0x00000000 r14: 0x20060660
>  r15: 0x20060661 r16: 0x00000006 r17: 0x5fdab371
>  r18: 0x00000018 r19: 0x5fdab2b4 r20: 0x00020000
>  r21: 0x00000000 r22: 0x00029068 r23: 0x5fdab371
>  r24: 0x00010000 r25: 0x00000000
>  --->8---
> 
> To fix this problem we'll re-introduce tmp buffer force alignment
> before config parser invocation.
> 
> Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Vineet Gupta <vgupta@synopsys.com>
> Cc: Waldemar Brodkorb <wbx@openadk.org>
> ---
>  libc/inet/resolv.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
> index cfc1eee..7c678ce 100644
> --- a/libc/inet/resolv.c
> +++ b/libc/inet/resolv.c
> @@ -1614,7 +1614,7 @@ int __read_etc_hosts_r(
>  							sizeof(struct in_addr)
>  #endif
>  							;
> -	int ret = HOST_NOT_FOUND;
> +	int i, ret = HOST_NOT_FOUND;
>  
>  	*h_errnop = NETDB_INTERNAL;
>  	if (buflen < aliaslen
> @@ -1626,6 +1626,12 @@ int __read_etc_hosts_r(
>  		*result = NULL;
>  		return errno;
>  	}
> +
> +	/* make sure pointer is aligned */
> +	i = ALIGN_BUFFER_OFFSET(buf);
> +	buf += i;
> +	buflen -= i;

Is this safe against the possibility of buflen<i? Otherwise you're
introducing a serious overflow.

Rich
Bernhard Reutner-Fischer March 14, 2015, 7:47 p.m. UTC | #2
On March 14, 2015 4:06:03 PM GMT+01:00, Rich Felker <dalias@libc.org> wrote:
>On Thu, Mar 12, 2015 at 02:21:12AM +0300, Alexey Brodkin wrote:
>> On execution of "inet/gethost_r-align" test I noticed failure due
>> to unaligned access (instaed of 4-byte aligned 1-byte aligned
>> address was attempted to be accessed).
>> 
>> Further investigation confirmed this nice and helpful test failure.
>> Following commit removed usage of ALIGN_BUFFER_OFFSET on entry to
>> __read_etc_hosts_r():
>>
>http://git.uclibc.org/uClibc/commit/?id=f65e66078b9f4d2d7f0fc336dee36e78fc467c0f
>> 
>> So indeed if target architecture doesn't allow unaligned access
>> and provided tmp buffer is not word aligned (and we will deal with
>pointers
>> which means word-sized data units), then CPU will fail during
>execution.
>> 
>> In case of ARC we'll see "Unaligned access" exception like this:
>>  --->8---
>>  # potentially unexpected fatal signal 7.
>>  Path: /root/uClibc/test/inet/gethost_r-align
>>  CPU: 0 PID: 5514 Comm: gethost_r-align Not tainted 3.13.11 #2
>>  task: 8f42a580 ti: 8f40e000 task.ti: 8f40e000
>> 
>>  [ECR   ]: 0x00230400 => Misaligned r/w from 0x5fdab341
>>  [EFA   ]: 0x5fdab341
>>  [BLINK ]: 0x20032a18
>>  [ERET  ]: 0x20032a3c
>>      @off 0x12a3c in [/lib/libuClibc-0.9.34-git.so]
>>      VMA: 0x20020000 to 0x20062000
>>  [STAT32]: 0x00000086 : U         E2 E1
>>  BTA: 0x20046014  SP: 0x5fdab260  FP: 0x00000000
>>  LPS: 0x20046064 LPE: 0x20046068 LPC: 0x00000000
>>  r00: 0x5fdab341 r01: 0x00000005 r02: 0x00000015
>>  r03: 0x00000000 r04: 0x5fdab358 r05: 0x00000000
>>  r06: 0x0a0a0a00 r07: 0x00000000 r08: 0x0000003f
>>  r09: 0x20067050 r10: 0x00000000 r11: 0x00000014
>>  r12: 0x00000001 r13: 0x00000000 r14: 0x20060660
>>  r15: 0x20060661 r16: 0x00000006 r17: 0x5fdab371
>>  r18: 0x00000018 r19: 0x5fdab2b4 r20: 0x00020000
>>  r21: 0x00000000 r22: 0x00029068 r23: 0x5fdab371
>>  r24: 0x00010000 r25: 0x00000000
>>  --->8---
>> 
>> To fix this problem we'll re-introduce tmp buffer force alignment
>> before config parser invocation.
>> 
>> Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
>> Cc: Vineet Gupta <vgupta@synopsys.com>
>> Cc: Waldemar Brodkorb <wbx@openadk.org>
>> ---
>>  libc/inet/resolv.c | 8 +++++++-
>>  1 file changed, 7 insertions(+), 1 deletion(-)
>> 
>> diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
>> index cfc1eee..7c678ce 100644
>> --- a/libc/inet/resolv.c
>> +++ b/libc/inet/resolv.c
>> @@ -1614,7 +1614,7 @@ int __read_etc_hosts_r(
>>  							sizeof(struct in_addr)
>>  #endif
>>  							;
>> -	int ret = HOST_NOT_FOUND;
>> +	int i, ret = HOST_NOT_FOUND;
>>  
>>  	*h_errnop = NETDB_INTERNAL;
>>  	if (buflen < aliaslen
>> @@ -1626,6 +1626,12 @@ int __read_etc_hosts_r(
>>  		*result = NULL;
>>  		return errno;
>>  	}
>> +
>> +	/* make sure pointer is aligned */
>> +	i = ALIGN_BUFFER_OFFSET(buf);
>> +	buf += i;
>> +	buflen -= i;
>
>Is this safe against the possibility of buflen<i? Otherwise you're
>introducing a serious overflow.

The lines below read:

*h_errnop = NETDB_INTERNAL;
if (buflen < aliaslen 	|| (buflen - aliaslen) < BUFSZ + 1)
  return ERANGE;

So ISTM it should be OK.
diff mbox

Patch

diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index cfc1eee..7c678ce 100644
--- a/libc/inet/resolv.c
+++ b/libc/inet/resolv.c
@@ -1614,7 +1614,7 @@  int __read_etc_hosts_r(
 							sizeof(struct in_addr)
 #endif
 							;
-	int ret = HOST_NOT_FOUND;
+	int i, ret = HOST_NOT_FOUND;
 
 	*h_errnop = NETDB_INTERNAL;
 	if (buflen < aliaslen
@@ -1626,6 +1626,12 @@  int __read_etc_hosts_r(
 		*result = NULL;
 		return errno;
 	}
+
+	/* make sure pointer is aligned */
+	i = ALIGN_BUFFER_OFFSET(buf);
+	buf += i;
+	buflen -= i;
+
 	/* Layout in buf:
 	 * char *alias[MAXTOKENS]  = {address, name, aliases...}
 	 * char **h_addr_list[1]   = {*in[6]_addr, NULL}