130 lines
3.3 KiB
Diff
130 lines
3.3 KiB
Diff
From e3848e3dd64a8d6437531488fe341354bc02eaed Mon Sep 17 00:00:00 2001
|
|
From: Lucian Cojocar <lucian.cojocar@vu.nl>
|
|
Date: Fri, 10 Jun 2016 18:44:44 +0200
|
|
Subject: [PATCH] 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>
|
|
---
|
|
libc/string/arm/memset.S | 20 ++++++++++----------
|
|
1 file changed, 10 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/libc/string/arm/memset.S b/libc/string/arm/memset.S
|
|
index 2be4850..412270f 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)
|
|
--
|
|
2.7.4.GIT
|
|
|