athos
athos

Reputation: 1281

Memory corruption debug with android ndk

I am getting a segfault in the native part of my android app, in the moment a void function returns to its caller. To visualize better, I put a log statement at the end of the callee function, and one in the caller function, right after the call to the callee (sorry for the pun). In the logcat, the first message is printed, and the second not (the app crashes).

Thinking about a possible memory corruption I decided to activate malloc debug (giving "setprop libc.debug.malloc 10" in adb shell). Then, i get this in the logcat right after the log message from the end of the callee function:

D/MyApp - NativeSide(12778):  I am the callee function and I am about to return!
E/libc    (12778): *** FREE CHECK: buffer 0x82869900 corrupted 16 bytes before allocation
E/libc    (12778): call stack:
E/libc    (12778):  0: 8000e3ea
E/libc    (12778):  1: 8000e49c
E/libc    (12778):  2: 8000e4e2
E/libc    (12778):  3: 8000e540
E/libc    (12778):  4: afd14ccc
E/libc    (12778):  5: 81258188
E/libc    (12778):  6: 81258188
E/libc    (12778):  7: 81258188
E/libc    (12778):  8: 81258188
E/libc    (12778):  9: 81258188
E/libc    (12778): 10: 81258188
E/libc    (12778): 11: 81258188
E/libc    (12778): 12: 81258188
E/libc    (12778): 13: 81258188
E/libc    (12778): 14: 81258188
E/libc    (12778): 15: 81258188
E/libc    (12778): 16: 81258188
E/libc    (12778): 17: 81258188
E/libc    (12778): 18: 81258188
E/libc    (12778): 19: 81258188

I couldn't find any information on how to decipher this output. The numbers shown at each line are changing at every app launch. I hope there's a way to use this information as a clue on where the corruption happens, as I can't find it from the code. I also tried building the native libraries with the "-fstack-check flag, but I couldn't say if I got more informations in the log (it seems not but I might have missed them), or whether I need to do other things to get them.

Also, here's the stack dump, coming after the "FREE CHECK:" message.

I/DEBUG   (12311): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   (12311): Build fingerprint: 'google/soju/crespo:2.3/GRH55/79397:user/release-keys'
I/DEBUG   (12311): pid: 12778, tid: 12907  >>> com.ntrack.tuner <<<
I/DEBUG   (12311): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad
I/DEBUG   (12311):  r0 deadbaad  r1 45ea374c  r2 00000027  r3 00000000
I/DEBUG   (12311):  r4 00000080  r5 45ea374c  r6 8003422e  r7 45ea37b4
I/DEBUG   (12311):  r8 45da4000  r9 a811eca5  10 00100000  fp 00000001
I/DEBUG   (12311):  ip ffffffff  sp 45ea3738  lr 8000f623  pc 8000f650  cpsr 20000030
I/DEBUG   (12311):  d0  3f9664f48406d639  d1  3f8226e3e96e8495
I/DEBUG   (12311):  d2  3faba1ba1bb34201  d3  0000000000000000
I/DEBUG   (12311):  d4  3d7943379e56fd24  d5  3d8f940585cd5f95
I/DEBUG   (12311):  d6  3f2cf2145b888497  d7  3f2cf214636d85f8
I/DEBUG   (12311):  d8  0000000000000000  d9  0000000000000000
I/DEBUG   (12311):  d10 0000000000000000  d11 0000000000000000
I/DEBUG   (12311):  d12 0000000000000000  d13 0000000000000000
I/DEBUG   (12311):  d14 0000000000000000  d15 0000000000000000
I/DEBUG   (12311):  scr 20000010
I/DEBUG   (12311):

Anything, a suggestion on the typical things to check or just the way to make use of the malloc debug informations would be of great help, thanks!

Upvotes: 3

Views: 14480

Answers (2)

P.T.
P.T.

Reputation: 25177

To me, this:

a segfault in the native part of my android app, in the moment a void function returns to its caller.

means stack corruption (more than heap corruption). What state is stored on the stack of this function you're returning from (and from every function it calls ..)?

The call stack output you're seeing should be the address of each function on the stack at the time the corruption was detected. You'll need to know what address your library was loaded at to map those back to a symbol in your .so. (I think this question will help: How to use addr2line in Android)

The fact that 81258188 repeats off the top of the stack dump also suggest that you might've blown out the bottom of the stack (by recursing too many times). If you're not aware of any intentional recursion in your code, then figuring out where your library was loaded and mapping that back to your code could be useful.

Upvotes: 3

user1493941
user1493941

Reputation: 227

The malloc debug property is probably setting some magic numbers before and after the area you allocate. Then, when freeing, it would check those areas to make sure the magic number is still there.

For example, if you allocate 1024 bytes:

char * p = malloc(1024);

The malloc debug code would actually allocate 1024 bytes that you requested, plus some extra around it:

[ 32 bytes ---- | -------- 1024 bytes ------| ---- 32 bytes ]
^ 0xc0000000    ^ 0xc0000020

The library would then write a magic value into those 32 bytes:

[ 32 bytes ---- | -------- 1024 bytes ------| ---- 32 bytes ]
[  0xdeadd00d   |                           | 0xdeadd00d    ]
^ 0xc0000000    ^ 0xc0000020

The library would return 0xc0000020 into p and internally it would save 0xc0000000, the size, etc. Your function then uses the allocated area somehow:

memset(p, 0, 1025);

Notice this line copied more than 1024 bytes. That would write a 0 into the last 32 byte magic area (notice the 0 in the last 32 bytes, which should be 0xdeadd00d):

[ 32 bytes ---- | -------- 1024 bytes ------| ---- 32 bytes ]
[  0xdeadd00d   |  000...             ...00 | 0x0eadd00d    ]
^ 0xc0000000    ^ 0xc0000020  (address)

When your function calls free:

free(p);

The library would then check to make sure the first and last 32 bytes are still 0xdeadd00d. Since your function overwrote the last 32 bytes, it would print an error like you posted.

This is only an example of how a malloc debug checking would work. If you would like to see exactly what the malloc debug checks and how it works, go to the bionic directory of Android source and search for the property you set, libc.debug.malloc.

Check your code for how you use allocated memory in the called function. You are probably writing to an area outside of the area you allocated.

Upvotes: 11

Related Questions