Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRASH (tests/free) release build linux suite: pointer overflow #1260

Closed
derekbruening opened this issue Nov 28, 2014 · 4 comments
Closed

CRASH (tests/free) release build linux suite: pointer overflow #1260

derekbruening opened this issue Nov 28, 2014 · 4 comments

Comments

@derekbruening
Copy link
Contributor

From [email protected] on June 04, 2013 11:27:21

This happened in my test suite once. I can't reproduce manually, and this is Linux where there's no ldmp:

drmemory-rel-32: 50 tests passed, **** 2 tests failed, of which 1 were flaky: ****
free => Application /work/drmemory/build_suite/build_drmemory-rel-32/tests/free (1336). Unrecoverable Error at PC 0xf754965a. Program aborted. ; (1336). Unrecoverable Error at PC 0xf754965a. Program aborted.

Original issue: http://code.google.com/p/drmemory/issues/detail?id=1260

@derekbruening
Copy link
Contributor Author

From [email protected] on June 04, 2013 09:23:21

Managed to repro after 100 iters:

for ((i=0; i<200; i++)); do echo $i; bin/drmemory.pl -dr_debug -dr_ops "-msgbox_mask 12" -dr /work/dr/git/exports -- tests/free; done

<Application /work/drmemory/build_suite/build_drmemory-rel-32/tests/free (5361). Unrecoverable Error at PC 0xf756d61f. Program aborted.
Received SIGSEGV at pc 0xf756d61f in thread 5361
Base: 0xf7000000
Registers: eax=0x00000000 ebx=0x00000800 ecx=0x000031dc edx=0x48fa7fa0
esi=0x00000000 edi=0x00007800 esp=0x48f0a730 ebp=0x48f401d8
eflags=0x00010202

(gdb) p /x *sc
$2 = {
gs = 0x63,
__gsh = 0x0,
fs = 0x73,
__fsh = 0x0,
es = 0x2b,
__esh = 0x0,
ds = 0x2b,
__dsh = 0x0,
edi = 0x7800,
esi = 0x0,
ebp = 0x48f401d8,
esp = 0x48f0a730,
ebx = 0x800,
edx = 0x48fa7fa0,
ecx = 0x31dc,
eax = 0x0,
trapno = 0xe,
err = 0x6,
eip = 0xf756d61f,
cs = 0x23,
__csh = 0x0,
eflags = 0x10202,
esp_at_signal = 0x48f0a730,
ss = 0x2b,
__ssh = 0x0,
fpstate = 0x48f32c10,
oldmask = 0x0,
cr2 = 0x48fa8000
}
(gdb) x/4i sc->eip
0xf756d61f <__memset_sse2_rep+415>: movdqa %xmm0,0x60(%edx)
(gdb) x/4wx sc->edx + 0x60
0x48fa8000: 0x00000000 0x00000000 0x00000000 0x00000000

in /proc/self/maps:
48f99000-48fa8000 rw-p 00000000 00:00 0
48fa8000-48fd9000 ---p 00000000 00:00 0
48fd9000-48fe2000 rw-p 00000000 00:00 0

release build, so callstack takes some effort:
(gdb) up 4
(gdb) set var $esp = 0x48f0a730
(gdb) set var $ebp = 0x48f401d8
(gdb) set var $eip = 0xf756d61f
(gdb) bt
#0 0xf756d61f in __memset_sse2_rep ()
#1 0x7389344e in umbra_shadow_set_range_arch.part.2 ()
#2 0x73892c60 in umbra_shadow_set_range ()
#3 0x7383fd96 in shadow_set_range ()
#4 0x7381066e in set_initial_structures ()
#5 0x73810b35 in set_initial_layout ()
#6 0x73811cc5 in instru_event_bb_app2app ()
#7 0x7387cbe0 in drmgr_bb_event (drcontext=0x48ec1540, tag=0xf771772a, bb=0x48f0dfec,
for_trace=0 '\000', translating=0 '\000') at /work/dr/git/src/ext/drmgr/drmgr.c:425
#8 0xf726ece8 in instrument_basic_block (dcontext=0x48ec1540, tag=0xf771772a "\270", bb=0x48f0dfec,
for_trace=false, translating=false, emitflags=0x48f0ab88)
at /work/dr/git/src/core/x86/instrument.c:1422
#9 0xf72254e8 in client_process_bb (dcontext=0x48ec1540, bb=0x48f0ae38)
at /work/dr/git/src/core/x86/interp.c:2493
#10 0xf722919f in build_bb_ilist (dcontext=0x48ec1540, bb=0x48f0ae38)
at /work/dr/git/src/core/x86/interp.c:3526
#11 0xf722d305 in build_basic_block_fragment (dcontext=0x48ec1540, start=0xf771772a "\270",
initial_flags=0, link=true, visible=true, for_trace=false, unmangled_ilist=0x0)
at /work/dr/git/src/core/x86/interp.c:4468
#12 0xf70da216 in dispatch (dcontext=0x48ec1540) at /work/dr/git/src/core/dispatch.c:188
(gdb) x/120wx $esp
0x48f0a730: 0x48fa5518 0x738f3ab8 0x7389344e 0x48fa5518
0x48f0a740: 0x00000000 0x00005d64 0xf717b53f 0xf7381940
0x48f0a750: 0x0000000c 0xfffffe00 0xf736f169 0x00000004
0x48f0a760: 0x48f401d8 0x00000200 0x00000000 0x00010000
0x48f0a770: 0x0000ffff 0x00005d64 0xffffb000 0xffff0000
0x48f0a780: 0x00008a70 0xffff8a70 0x00001d64 0x00fa306c
0x48f0a790: 0x48fa306c 0x48f0a7c4 0x738f3ab8 0xffff8a70
0x48f0a7a0: 0x00000000 0x48f0a814 0x73892c60 0x00002590
0x48f0a7b0: 0x48f0a810 0x00000000 0x48f0a810 0x00000000
0x48f0a7c0: 0x00000001 0x48f0a7f4 0xf727271d 0x48ea7e34
0x48f0a7d0: 0x00000100 0x738f3ab8 0x7383fd96 0x48f401d8
0x48f0a7e0: 0xffff8a70 0x00002590 0x48f0a810 0x00000000
0x48f0a7f0: 0x00000001 0x73910800 0x73879157 0x48ea7e34
0x48f0a800: 0x00021000 0xffff8a70 0xffffb000 0x00000001
0x48f0a810: 0x48f403a0 0x00000018 0x00000000 0x00000000
0x48f0a820: 0x48f0a86c 0x48f0a870 0x48f0a834 0xf736f144
0x48f0a830: 0x000014f1 0x00000003 0x738f3ab8 0x73910800
0x48f0a840: 0xffffb000 0xffffc000 0x7381066e 0xffff8a70
0x48f0a850: 0xffffb000 0x00000000 0x00000000 0xf736f144

So shadow_set_range(0xffff8a70, 0xffffb000, 0x00000000)
calls umbra_shadow_set_range(0x48f401d8, 0xffff8a70, 0x00002590,
0x48f0a810, 0x00000000, 0x00000001)
calls umbra_shadow_set_range_arch()
calls memset(0x48fa5518, 0x00000000, 0x00005d64)

DrMem is setting the shadow value for the initial app stack.

Why is the memset size so large, larger than the app size?

@derekbruening
Copy link
Contributor Author

From [email protected] on June 04, 2013 10:21:20

app_blk_base for 0xffff8a70 = 0xffff0000
app_blk_end then becomes NULL -- no overflow check!

** TODO how fix this in general? not easy!

Xref issue #302 where compiler turned "ptr + val < ptr" into "false". I only
fixed cases where the addition and check were combined, in both DR and DrMem.

For DR this is DRi#704: "properly handle address overflow in stored end
addresses". As a first step there I tackled the API, using size instead of
end address: then the caller has to deal w/ overflow, but at least we're
not passing NULL or whatnot.

From DRi#704:
"for internal to DR have to either avoid (fcache, heap) or store closed-end
or store NULL or store size: any method requires extra checks."
E.g., fcache.c:
/* simpler to just not support taking very last page in address space */
!POINTER_OVERFLOW_ON_ADD(unit->end_pc, commit_size)) {

We have many routines that take in "start, end". Anywhere that computes
or stores an end address can result in a NULL (or technically anything:
undefined result). Here the initial call could overflow:

        set_initial_range(stack_base, stack_base + stack_size);

Back to DR, looking at random spots: dr_query_memory() returns size, but
others return end pc: allmem stores end.

allmem would trigger this add_vm_area() assert:
ASSERT(start < end);
(unlikely to hit issue #302 b/c the add and cmp are separated, and all current
impl will overflow arithmetically when separate)

Summary: CRASH (tests/free) release build linux suite: pointer overflow (was: CRASH (tests/free) release build linux suite)
Owner: [email protected]

@derekbruening
Copy link
Contributor Author

From [email protected] on June 04, 2013 13:28:55

I split the general issue off as issue #1261 .

This issue just covers Umbra.

** TODO add a test

confirmed this catches it pre-fix:

bin/drmemory.pl -dr /work/dr/git/exports -- tests/app_suite_tests --gtest_filter=MmapTests.*
Dr.M Dr. Memory version 1.5.1403
Running main() from gtest_main.cc
Note: Google Test filter = MmapTests.*
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from MmapTests
[ RUN ] MmapTests.PointerOverflow
<Application /work/drmemory/git/build_x86_dbg/tests/app_suite_tests (10703). Client exception at PC 0x7391d8f0. Program aborted.
Received SIGSEGV at client library pc 0x7391d8f0 in thread 10703
Base: 0xf7000000
Registers: eax=0x00000000 ebx=0x739cc684 ecx=0x00004000 edx=0x00006000
esi=0x5043e000 edi=0x4ffa6e34 esp=0x4ffa6b30 ebp=0x4ffa6b34
eflags=0x00010202

post-fix:

bin/drmemory.pl -dr /work/dr/git/exports -- tests/app_suite_tests --gtest_filter=MmapTests.*
Dr.M Dr. Memory version 1.5.1403
Running main() from gtest_main.cc
Note: Google Test filter = MmapTests.*
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from MmapTests
[ RUN ] MmapTests.PointerOverflow
[ OK ] MmapTests.PointerOverflow (19 ms)
[----------] 1 test from MmapTests (47 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (124 ms total)
[ PASSED ] 1 test.

@derekbruening
Copy link
Contributor Author

From [email protected] on June 05, 2013 13:35:11

This issue was closed by revision r1406 .

Status: Fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant