• 【Valgrind】How to check buffer overflow/underflow in 10 mins


    Introduction

    Buffer overflow/underflow frequently happens when we did something wrong with the array index, no matter the array is heap or stack, no matter you are reading the memory or writing the memory.

    1 # To get a precise source code line number by valgrind report, 
    2 # It's better to build debug version, such as '-O0' for GCC. 

    Example 1: heap overflow

     1 // head_overflow.c
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <math.h>
     5 int main(int argc, char** argv)
     6 {
     7   int i;
     8   int *a = malloc(sizeof(int) * 10);
     9   if (!a) return -1; /*malloc failed*/
    10   // init
    11   for (i = 0; i < 11; i++)
    12   {
    13     a[i] = i;
    14   }
    15   // square
    16   for(i=0; i<10; i++)
    17   {
    18     a[i] *= a[i];
    19   }
    20   free(a);
    21   printf("I am finished.
    ");
    22   return 0;
    23 }

    Let's build and run this file:

    $ gcc -O3 -g -o heap_overflow heap_overflow.c
    $ ./heap_overflow
    *** Error in `./heap_overflow': free(): invalid next size (fast): 0x0000000001653010 ***
    Aborted (core dumped)

    Oops, Aborted while invoking free(). What's wrong?? Let's try gdb:

    $ gdb ./heap_overflow
    (gdb) r
    Starting program: /home/jxion/jp4/depot/lechin/users/jxion/test_toys/test_valgrind/heap_overflow
    *** Error in `/home/jxion/jp4/depot/lechin/users/jxion/test_toys/test_valgrind/heap_overflow': free(): invalid next size (fast): 0x0000000000602010 ***
    Program received signal SIGABRT, Aborted.
    0x00007ffff7a4af79 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
    56      ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
    (gdb) 
    (gdb) bt
    #0  0x00007ffff7a4af79 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
    #1  0x00007ffff7a4e388 in __GI_abort () at abort.c:89
    #2  0x00007ffff7a881d4 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7ffff7b96a10 "*** Error in `%s': %s: 0x%s ***
    ") at ../sysdeps/posix/libc_fatal.c:175
    #3  0x00007ffff7a944ae in malloc_printerr (ptr=<optimized out>, str=0x7ffff7b96bb0 "free(): invalid next size (fast)", action=1) at malloc.c:4996
    #4  _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3840
    #5  0x000000000040062c in main (argc=<optimized out>, argv=<optimized out>) at heap_overflow.c:21
    (gdb)

    We still can only get the same err msg that crach in free(), which is line 21. But if we try valgrind:

    $ valgrind ./heap_overflow
    ==31634== Memcheck, a memory error detector
    ==31634== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
    ==31634== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
    ==31634== Command: ./heap_overflow
    ==31634==
    ==31634== Invalid write of size 4
    ==31634==    at 0x40053C: main (heap_overflow.c:14)
    ==31634==  Address 0x51fd068 is 0 bytes after a block of size 40 alloc'd
    ==31634==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==31634==    by 0x4004DD: main (heap_overflow.c:8)
    ==31634==
    I am finished.
    ==31634==
    ==31634== HEAP SUMMARY:
    ==31634==     in use at exit: 0 bytes in 0 blocks
    ==31634==   total heap usage: 1 allocs, 1 frees, 40 bytes allocated
    ==31634==
    ==31634== All heap blocks were freed -- no leaks are possible
    ==31634==
    ==31634== For counts of detected and suppressed errors, rerun with: -v
    ==31634== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

    Valgrind tells exactly where is the problem:

    • Invalid write of size 4 at 0x40053C: main (heap_overflow.c:14)

    Example 2: heap underflow

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <math.h>
     4 int main(int argc, char** argv)
     5 {
     6   int i;
     7   int *a = malloc(sizeof(int) * 10);
     8   if (!a) return -1; /*malloc failed*/
     9   // init
    10   for (i = 0; i < 10; i++)
    11   {
    12     a[i] = i;
    13   }
    14   // sum
    15   for(i=0; i<10; i++)
    16   {
    17     a[i] += a[i-1];
    18   }
    19   free(a);
    20   printf("I am finished.
    ");
    21   return 0;
    22 }

    Also build and run:

    $ gcc -O3 -g -o heap_underflow heap_underflow.c
    $ ./heap_underflow
    I am finished.

    Oh my GOD, it's finished. It means everything seems OK.

    Really?

    Let's try gdb:

    $ gdb ./heap_underflow
    (gdb) r
    Starting program: /home/jxion/jp4/depot/lechin/users/jxion/test_toys/test_valgrind/heap_underflow
    I am finished.
    [Inferior 1 (process 32307) exited normally]
    (gdb) bt
    No stack.
    (gdb)

    Everything seems to be OK. Let's try Valgrind:

    $ valgrind ./heap_underflow
    ==32275== Memcheck, a memory error detector
    ==32275== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
    ==32275== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
    ==32275== Command: ./heap_underflow
    ==32275==
    ==32275== Invalid read of size 4
    ==32275==    at 0x4004E3: main (heap_underflow.c:19)
    ==32275==  Address 0x51fd03c is 4 bytes before a block of size 40 alloc'd
    ==32275==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==32275==    by 0x4004DD: main (heap_underflow.c:8)
    ==32275==
    I am finished.
    ==32275==
    ==32275== HEAP SUMMARY:
    ==32275==     in use at exit: 0 bytes in 0 blocks
    ==32275==   total heap usage: 1 allocs, 1 frees, 40 bytes allocated
    ==32275==
    ==32275== All heap blocks were freed -- no leaks are possible
    ==32275==
    ==32275== For counts of detected and suppressed errors, rerun with: -v
    ==32275== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

    Ooops, we find an error here:

    • Invalid read of size 4 at 0x4004E3: main (heap_underflow.c:19)

    That's because we read data from a[-1] in line 19 !!

    OS and gdb either didn't find this error, while Valgrind check it out.

    Example 3: Stack overflow/underflow, none of OS/GDB/Valgrind realize the issue

    It's weird that no matter OS/GDB/Valgrind, they cannot realize these issues.

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <math.h>
     4 int main(int argc, char** argv)
     5 {
     6   int i;
     7   int a[10];
     8   // init
     9   a[-1] = -1;
    10   a[11] = 11;
    11   printf(" a[-1]= = %d, a[11] = %d
    ", a[-1], a[11]);
    12   printf("I am finished.
    ");
    13   return a[-1];
    14 }

    build and run:

    $ gcc -O0 -g -o stack_overflow stack_overflow.c
    $ ./stack_overflow
     a[-1]= = -1, a[11] = 11
    I am finished.
    
    $ valgrind ./stack_overflow
    ==3705== Memcheck, a memory error detector
    ==3705== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
    ==3705== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
    ==3705== Command: ./stack_overflow
    ==3705==
     a[-1]= = -1, a[11] = 11
    I am finished.
    ==3705==
    ==3705== HEAP SUMMARY:
    ==3705==     in use at exit: 0 bytes in 0 blocks
    ==3705==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
    ==3705==
    ==3705== All heap blocks were freed -- no leaks are possible
    ==3705==
    ==3705== For counts of detected and suppressed errors, rerun with: -v
    ==3705== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    
    $ gdb ./stack_overflow
    (gdb) r
    Starting program: /home/jxion/jp4/depot/lechin/users/jxion/test_toys/test_valgrind/stack_overflow
     a[-1]= = -1, a[11] = 11
    I am finished.
    [Inferior 1 (process 3714) exited with code 0377]
    (gdb) bt
    No stack.
    
    
  • 相关阅读:
    [Golang学习笔记] 06 程序实体3 类型断言和类型转换
    [Golang学习笔记] 05 程序实体2 作用域访问权限和变量重声明
    [Golang学习笔记] 04 程序实体1 变量声明
    [Golang学习笔记] 03 库源码文件
    virgo-tomcat-server的生产环境线上配置与管理
    virgo-tomcat-server最大并发连接数的修改
    linux系统下kvm虚拟机的安装
    关于virgo-tomcat-server-3.6.0.RELEASE配置文件修改说明
    关于在Linux下apache-maven的安装
    H3C系列之三层交换机文件管理
  • 原文地址:https://www.cnblogs.com/xjsxjtu/p/4539028.html
Copyright © 2020-2023  润新知