Wednesday, February 26, 2014

MALLOC_CHECK_: Detect User space run-time memory errors


MALLOC_CHECK_ overview


MALLOC_CHECK_ 
a glibc tool that can be used to find memory errors in linux user space C/C++ applications.To understand the type of memory errors, I used the same tests I used to explore Valgrind's memcheck. I will also provide details of errors MALLOC_CHECK_ catches in "Usage Example" section below.

MALLOC_CHECK_ Usage
  • Step1: Modify the program with the following code snippet:
         if (mallopt(M_CHECK_ACTION, 7) != 1) {
           fprintf(stderr, "mallopt() failed");
           return(-1);
         }

The number 7 n mallopt argument indicates response level. Different response levels:
0  Ignore error conditions; continue execution (with undefined results).
1  Print a detailed error message and continue execution.                    
2  Abort the program.
3  Print detailed error message, stack trace, and memory mappings, and abort the program.
5  Print a simple error message and continue execution.
7  Print simple error message, stack trace, and memory mappings, and abort the program.

  • Step1: Recompile the program enabling gdb & turning off compiler optimizations:
gcc -g prog.c -o <prog_name>

  • Step2: Run the program in with MALLOC_CHECK_ environment variable set:
MALLOC_CHECK_=<response_level> <prog_name> <prog_args>

From my experiments, I found that the response level provided in source code overrides the response level provided here. Despite this overriding, this environment variable had to be passed at command line for source code change to show the impact. However, when I provided 0 here, this overrode the source code response level. 


MALLOC_CHECK_ Usage Example

I used the code at https://github.com/babuneelam/malloc_check_tests/blob/master/mc_tests.c to explore 10 of the 11 tests:

  1. uninitialized use
  2. Read/Write after free
  3. buffer overrun
  4. Read/Write bad stack location (underrun)
  5. Memory Leak
  6. c++related test (ignore this)
  7. Overlapping memcpy
  8. double free
  9. pass unaddressable memory to system call
  10. Read/Write invalid stack location (overrun)
  11. Read/Write invalid global data location (overrun) 
Here are the results:
root@babu-VirtualBox:~/tools/malloc_check# gcc -g mc_tests.c -o mc_tests
root@babu-VirtualBox:~/tools/malloc_check# MALLOC_CHECK_=7 ./mc_tests 1
10
*num = 0 
root@babu-VirtualBox:~/tools/malloc_check# MALLOC_CHECK_=7 ./mc_tests 2
root@babu-VirtualBox:~/tools/malloc_check# MALLOC_CHECK_=7 ./mc_tests 3
i[-1] = 49 
free(): invalid pointer
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x767f1)[0xb75b57f1]
/lib/i386-linux-gnu/libc.so.6(cfree+0x9b)[0xb75b914b]
./mc_tests[0x8048676]
./mc_tests[0x8048878]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0xb7558905]
./mc_tests[0x80484e1]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:01 1076878    /home/babu/tools/malloc_check/mc_tests
08049000-0804a000 r--p 00000000 08:01 1076878    /home/babu/tools/malloc_check/mc_tests
0804a000-0804b000 rw-p 00001000 08:01 1076878    /home/babu/tools/malloc_check/mc_tests
09852000-09873000 rw-p 00000000 00:00 0          [heap]
b750a000-b7525000 r-xp 00000000 08:01 262149     /lib/i386-linux-gnu/libgcc_s.so.1
b7525000-b7526000 r--p 0001a000 08:01 262149     /lib/i386-linux-gnu/libgcc_s.so.1
b7526000-b7527000 rw-p 0001b000 08:01 262149     /lib/i386-linux-gnu/libgcc_s.so.1
b753e000-b753f000 rw-p 00000000 00:00 0 
b753f000-b76ed000 r-xp 00000000 08:01 263093     /lib/i386-linux-gnu/libc-2.17.so
b76ed000-b76ef000 r--p 001ae000 08:01 263093     /lib/i386-linux-gnu/libc-2.17.so
b76ef000-b76f0000 rw-p 001b0000 08:01 263093     /lib/i386-linux-gnu/libc-2.17.so
b76f0000-b76f3000 rw-p 00000000 00:00 0 
b7708000-b770c000 rw-p 00000000 00:00 0 
b770c000-b770d000 r-xp 00000000 00:00 0          [vdso]
b770d000-b772d000 r-xp 00000000 08:01 263069     /lib/i386-linux-gnu/ld-2.17.so
b772d000-b772e000 r--p 0001f000 08:01 263069     /lib/i386-linux-gnu/ld-2.17.so
b772e000-b772f000 rw-p 00020000 08:01 263069     /lib/i386-linux-gnu/ld-2.17.so
bfd17000-bfd38000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)
root@babu-VirtualBox:~/tools/malloc_check# MALLOC_CHECK_=7 ./mc_tests 4
root@babu-VirtualBox:~/tools/malloc_check# MALLOC_CHECK_=7 ./mc_tests 5
root@babu-VirtualBox:~/tools/malloc_check# MALLOC_CHECK_=7 ./mc_tests 7
root@babu-VirtualBox:~/tools/malloc_check# MALLOC_CHECK_=7 ./mc_tests 8
Segmentation fault (core dumped)
free(): invalid pointer
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x767f1)[0xb75f47f1]
/lib/i386-linux-gnu/libc.so.6(cfree+0x9b)[0xb75f814b]
./mc_tests[0x8048800]
./mc_tests[0x8048963]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0xb7597905]
./mc_tests[0x8048561]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:01 1076878    /home/babu/tools/malloc_check/mc_tests
08049000-0804a000 r--p 00000000 08:01 1076878    /home/babu/tools/malloc_check/mc_tests
0804a000-0804b000 rw-p 00001000 08:01 1076878    /home/babu/tools/malloc_check/mc_tests
08418000-08439000 rw-p 00000000 00:00 0          [heap]
b7549000-b7564000 r-xp 00000000 08:01 262149     /lib/i386-linux-gnu/libgcc_s.so.1
b7564000-b7565000 r--p 0001a000 08:01 262149     /lib/i386-linux-gnu/libgcc_s.so.1

b7565000-b7566000 rw-p 0001b000 08:01 262149     /lib/i386-linux-gnu/libgcc_s.so.1
b757d000-b757e000 rw-p 00000000 00:00 0
b757e000-b772c000 r-xp 00000000 08:01 263093     /lib/i386-linux-gnu/libc-2.17.so
b772c000-b772e000 r--p 001ae000 08:01 263093     /lib/i386-linux-gnu/libc-2.17.so
b772e000-b772f000 rw-p 001b0000 08:01 263093     /lib/i386-linux-gnu/libc-2.17.so
b772f000-b7732000 rw-p 00000000 00:00 0
b7748000-b774b000 rw-p 00000000 00:00 0
b774b000-b774c000 r-xp 00000000 00:00 0          [vdso]
b774c000-b776c000 r-xp 00000000 08:01 263069     /lib/i386-linux-gnu/ld-2.17.so
b776c000-b776d000 r--p 0001f000 08:01 263069     /lib/i386-linux-gnu/ld-2.17.so
b776d000-b776e000 rw-p 00020000 08:01 263069     /lib/i386-linux-gnu/ld-2.17.so
bfd64000-bfd85000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)
root@babu-VirtualBox:~/tools/malloc_check# MALLOC_CHECK_=7 ./mc_tests 9
Please type a bunch of characters and hit enter.
wer
root@babu-VirtualBox:~/tools/malloc_check#
root@babu-VirtualBox:~/tools/malloc_check# MALLOC_CHECK_=7 ./mc_tests 10
root@babu-VirtualBox:~/tools/malloc_check#
root@babu-VirtualBox:~/tools/malloc_check# MALLOC_CHECK_=7 ./mc_tests 11
root@babu-VirtualBox:~/tools/malloc_check#

As we can see, MALLOC_CHECK_ caught only buffer overrun and double free. 


Reference:

http://man7.org/linux/man-pages/man3/mallopt.3.html


No comments:

UA-48797665-1