diff options
author | Lucian Cojocar <lucian.cojocar@vu.nl> | 2016-06-10 18:44:44 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-06-19 23:34:02 +0200 |
commit | e3848e3dd64a8d6437531488fe341354bc02eaed (patch) | |
tree | c72a7d20027421f46721fe067df3acc426943af1 | |
parent | 040632792e9f19ccf49149e4ae3ddac351a98b5a (diff) |
bugfix: ARM: memset.S: use unsigned comparisons
The 'BLT' instruction checks for *signed* values. So if a3, length
parameter of memset, is negative, then value added to the PC will be
large.
memset(buf, 0xaa, 0xffff0000) triggers the bug.
GDB session without the patch:
"""
$ gdb ./main-buggy-memset.elf -q
Reading symbols from ./main-buggy-memset.elf...done.
(gdb) x/i memset
0x8770 <memset>: mov r3, r0
(gdb) r
Starting program: /root/memset/main-buggy-memset.elf
Program received signal SIGSEGV, Segmentation fault.
0x00048808 in ?? ()
"""
The $pc is outside of the memset function because:
"""
(gdb) x/i $pc
=> 0x87e4 <memset+116>: add pc, pc, r2, lsl #2
(gdb) info reg $r2
r2 0x10007 65543
"""
GDB session with the bug fixed (patch applied):
"""
$ gdb ./main-fixed-memset.elf -q
Reading symbols from ./main-fixed-memset.elf...done.
(gdb) x/i memset
0x8770 <memset>: mov r3, r0
(gdb) r
Starting program: /root/memset/main-fixed-memset.elf
Program received signal SIGSEGV, Segmentation fault.
memset () at libc/string/arm/memset.S:92
92 libc/string/arm/memset.S: No such file or directory.
(gdb) x/i $pc
=> 0x87b0 <memset+64>: stmia r3!, {r1, r12}
(gdb) info reg $r3
r3 0x15000 86016
(gdb) info proc mappings
process 5822
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x8000 0xb000 0x3000 0x0
/root/memset/main-fixed-memset.elf
0x12000 0x15000 0x3000 0x2000
/root/memset/main-fixed-memset.elf
0xb6fff000 0xb7000000 0x1000 0x0 [sigpage]
0xbefdf000 0xbf000000 0x21000 0x0
0xffff0000 0xffff1000 0x1000 0x0 [vectors]
(gdb) info reg $sp
sp 0x14d78 0x14d78
"""
GDB crashes inside the memset function, on the store instruction. This
time the crash is (as expected) because of a memory access imediately
after the memory region that contains the stack -- the buffer that's
being memset'd is allocated on the stack.
Signed-off-by: Lucian Cojocar <lucian.cojocar@vu.nl>
-rw-r--r-- | libc/string/arm/memset.S | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/libc/string/arm/memset.S b/libc/string/arm/memset.S index 2be4850e4..412270f50 100644 --- a/libc/string/arm/memset.S +++ b/libc/string/arm/memset.S @@ -67,7 +67,7 @@ memset: memset: mov a4, a1 cmp a3, $8 @ at least 8 bytes to do? - blt 2f + blo 2f orr a2, a2, a2, lsl $8 orr a2, a2, a2, lsl $16 1: @@ -84,27 +84,27 @@ memset: mov ip, a2 1: cmp a3, $8 @ 8 bytes still to do? - blt 2f + blo 2f stmia a4!, {a2, ip} sub a3, a3, $8 cmp a3, $8 @ 8 bytes still to do? - blt 2f + blo 2f stmia a4!, {a2, ip} sub a3, a3, $8 cmp a3, $8 @ 8 bytes still to do? - blt 2f + blo 2f stmia a4!, {a2, ip} sub a3, a3, $8 cmp a3, $8 @ 8 bytes still to do? #if defined(__thumb2__) - itt ge - stmiage a4!, {a2, ip} - subge a3, a3, $8 + itt hs + stmiahs a4!, {a2, ip} + subhs a3, a3, $8 #else - stmgeia a4!, {a2, ip} - subge a3, a3, $8 + stmhsia a4!, {a2, ip} + subhs a3, a3, $8 #endif - bge 1b + bhs 1b 2: movs a3, a3 @ anything left? IT(t, eq) |