欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

实战演示:一款用于asan内存检查的工具

最编程 2024-07-20 13:02:48
...

1 ASAN用法

GCC和CLANG都已经集成了功能,编译时加编译选项即可。主要是-fsanitize=address,其他便于调试。

gcc ex1.c -o ex1 -g -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer -fno-common 

注意:ASAN是整合工具,包括了LSAN等其其他工具。

注意:增加编译选项后,执行时就可以检测了,也可以加一些环境变量控制执行时的检测行为。

asan会在运行时检测内存问题,运行时需要添加几个环境变量

ASAN_OPTIONS='detect_leaks=1:halt_on_error=0:alloc_dealloc_mismatch=0:log_path=/tmp/asan_pgsql.log' \
LSAN_OPTIONS='exitcode=0:suppressions=/tmp/asan_supp'
LD_PRELOAD=/usr/local/lib64/libasan.so \
./ex1
  • ASAN_OPTIONS:配置ASAN。
  • LSAN_OPTIONS:配置LSAN,有些LSAN特殊的配置加在这里,比如suppressions忽略一些文件。
  • halt_on_error:出现问题不停止程序运行。
  • alloc_dealloc_mismatch:不允许内存申请不配对的情况,例如malloc / delete。
  • log_path:结果输出到文件中,不打印到标准输出。
  • exitcode:LSAN的配置,遇到问题不退出。
  • suppressions:LSAN支持不检查一些文件。
  • LD_PRELOAD:二进制可以不link libasan.so,加环境变量LD_PRELOAD即可。或者编译时Link libasan.so,可以省略该配置。

ASAN_OPTIONS和编译选项:https://github.com/google/sanitizers/wiki/SanitizerCommonFlags

LSAN_OPTIONS:https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer

实例一:detected memory leaks

ex1.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	void *dst = malloc(8);
	void *src = "1234567";
	memcpy(dst, src, 8);

	printf("%s\n", (char *) dst);
	return 0;
}

编译

gcc ex1.c -o ex1 -g -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer -fno-common

执行

ASAN_OPTIONS='halt_on_error=0:alloc_dealloc_mismatch=0:log_path=/tmp/asan_pgsql.log' \
LD_PRELOAD=/usr/local/lib64/libasan.so \
./ex1

结果

$ cat /tmp/asan_pgsql_01.log.652

=================================================================
==652==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x7f04db292f08 in __interceptor_malloc ../../../../libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x400853 in main /data02/mingjie/pgroot99/pgsrc/test/ex1.c:7
    #2 0x7f04dabdd554 in __libc_start_main (/lib64/libc.so.6+0x22554)

SUMMARY: AddressSanitizer: 8 byte(s) leaked in 1 allocation(s).

实例二:heap-use-after-free

ex1.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	void *dst = malloc(8);
	void *src = "1234567";

	char *p = dst;
	memcpy(dst, src, 8);

	printf("%s\n", (char *) dst);
	free(dst);

	printf("%s\n", p);
	return 0;
}

编译

gcc ex1.c -o ex1 -g -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer -fno-common

执行

ASAN_OPTIONS='halt_on_error=0:alloc_dealloc_mismatch=0:log_path=/tmp/asan_pgsql.log' \
LD_PRELOAD=/usr/local/lib64/libasan.so \
./ex1

结果

$ cat /tmp/asan_pgsql.log.1522
=================================================================
==1522==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000010 at pc 0x7f10079519d4 bp 0x7ffd47fb3d10 sp 0x7ffd47fb34c0
READ of size 2 at 0x602000000010 thread T0
    #0 0x7f10079519d3 in __interceptor_puts ../../../../libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1226
    #1 0x4009b1 in main /data02/mingjie/pgroot99/pgsrc/test/ex1.c:16
    #2 0x7f1007356554 in __libc_start_main (/lib64/libc.so.6+0x22554)
    #3 0x4007d8  (/data02/mingjie/pgroot99/pgsrc/test/ex1+0x4007d8)

0x602000000010 is located 0 bytes inside of 8-byte region [0x602000000010,0x602000000018)
freed by thread T0 here:
    #0 0x7f1007a0bb57 in __interceptor_free ../../../../libsanitizer/asan/asan_malloc_linux.cc:122
    #1 0x4009a5 in main /data02/mingjie/pgroot99/pgsrc/test/ex1.c:14
    #2 0x7f1007356554 in __libc_start_main (/lib64/libc.so.6+0x22554)

previously allocated by thread T0 here:
    #0 0x7f1007a0bf08 in __interceptor_malloc ../../../../libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x400893 in main /data02/mingjie/pgroot99/pgsrc/test/ex1.c:7
    #2 0x7f1007356554 in __libc_start_main (/lib64/libc.so.6+0x22554)

SUMMARY: AddressSanitizer: heap-use-after-free ../../../../libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1226 in __interceptor_puts
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[fd]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc

实例三:heap-buffer-overflow

ex1.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	void *dst = malloc(8);
	void *src = "123456789";

	memcpy(dst, src, 10);

	printf("%s\n", (char *) dst);
	free(dst);
	return 0;
}

编译

gcc ex1.c -o ex1 -g -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer -fno-common

执行

ASAN_OPTIONS='halt_on_error=0:alloc_dealloc_mismatch=0:log_path=/tmp/asan_pgsql.log' \
LD_PRELOAD=/usr/local/lib64/libasan.so \
./ex1

结果

$ cat /tmp/asan_pgsql.log.2239
=================================================================
==2239==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000018 at pc 0x7f8601ff8af0 bp 0x7ffd7ada1200 sp 0x7ffd7ada09b0
WRITE of size 10 at 0x602000000018 thread T0
    #0 0x7f8601ff8aef in __interceptor_memcpy ../../../../libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790
    #1 0x400857 in main /data02/mingjie/pgroot99/pgsrc/test/ex1.c:10
    #2 0x7f86019b3554 in __libc_start_main (/lib64/libc.so.6+0x22554)
    #3 0x400778  (/data02/mingjie/pgroot99/pgsrc/test/ex1+0x400778)

0x602000000018 is located 0 bytes to the right of 8-byte region [0x602000000010,0x602000000018)
allocated by thread T0 here:
    #0 0x7f8602068f08 in __interceptor_malloc ../../../../libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x400833 in main /data02/mingjie/pgroot99/pgsrc/test/ex1.c:7
    #2 0x7f86019b3554 in __libc_start_main (/lib64/libc.so.6+0x22554)

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790 in __interceptor_memcpy
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
=================================================================
==2239==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000018 at pc 0x7f8601fae9d4 bp 0x7ffd7ada1200 sp 0x7ffd7ada09b0
READ of size 10 at 0x602000000018 thread T0
    #0 0x7f8601fae9d3 in __interceptor_puts ../../../../libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1226
    #1 0x400863 in main /data02/mingjie/pgroot99/pgsrc/test/ex1.c:12
    #2 0x7f86019b3554 in __libc_start_main (/lib64/libc.so.6+0x22554)
    #3 0x400778  (/data02/mingjie/pgroot99/pgsrc/test/ex1+0x400778)

0x602000000018 is located 0 bytes to the right of 8-byte region [0x602000000010,0x602000000018)
allocated by thread T0 here:
    #0 0x7f8602068f08 in __interceptor_malloc ../../../../libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x400833 in main /data02/mingjie/pgroot99/pgsrc/test/ex1.c:7
    #2 0x7f86019b3554 in __libc_start_main (/lib64/libc.so.6+0x22554)

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1226 in __interceptor_puts
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc

2 ASAN PostgreSQL

编译选项中增加asan,然后配置环境变量即可。

具体记录在notes中了。

推荐阅读