아래 링크의 Android Asan 빌드 방식을 이해하기 위해 이번 테스트를 진행한다.
https://source.android.com/docs/security/test/asan
Windows의 toolchain인 mingw64 package에서는 -fsanitize=address를 지원하지 않는다. ( -lasan lib이 존재하지 않음.)
환경)
WSL 에서 clang++을 이용해서 테스트를 아래의 명령어로 간단하게 진행한다.
목표)
clang으로 빌드할 때, -fsanitize=address 를 포함하는 executable과 shared lib의 결합에 어떤 영향을 주는지 확인.
테스트에 사용될 libfoo.so 및 libfoo_san.so에 사용된 foo_san.cc의 내용은 heap-buffer-overflow를 발생하도록 작성되었다.
SUMMARY: AddressSanitizer: heap-buffer-overflow (libfoo_san.so+0x12a9) in foo()
#foo_san.cc
#include <iostream>
void foo(){
std::cout<<"foo_san"<<std::endl;
char *ptr=(char*) malloc(1);
ptr[2]='a';
}
#main.cc
#include <iostream>
#include "foo.h"
int main(){
char*ptr = (char*)malloc(1);
foo();
ptr[2] ='b';
return 0;
}
#libfoo.so 및 libfoo_san.so 빌드
clang++ -shared -o libfoo.so foo_san.cc
clang++ -shared -fsanitize=address -o libfoo_san.so foo_san.cc
위 두가지 so를 이용하여 main.cc를 두가지 옵션으로 각각 호출 해본다.
test1) 일반 실행 파일 + 일반 shared lib
heap-buffer-overflow에 대한 아무런 오류를 출력해주지 않는다.
$clang++ main.cc libfoo.so -Wl,-rpath,.
jayce@DESKTOP-J8A6E99:/mnt/d/wsl/asan_test/shared_lib$ ./a.out
foo_san
test2) asan 실행 파일 + asan shared lib
아래와 같이 libfoo_san.so의 문제를 예쁘게 출력해 준다.
$clang++ main.cc -fsanitize=address libfoo_san.so -Wl,-rpath,.
jayce@DESKTOP-J8A6E99:/mnt/d/wsl/asan_test/shared_lib$ ./a.out
foo_san
=================================================================
==5530==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000032 at pc 0x7fc4c3f932aa bp 0x7fff5e90be00 sp 0x7fff5e90bdf8
WRITE of size 1 at 0x602000000032 thread T0
#0 0x7fc4c3f932a9 in foo() (libfoo_san.so+0x12a9)
#1 0x4c6b21 in main (/mnt/d/wsl/asan_test/shared_lib/a.out+0x4c6b21)
#2 0x7fc4c3a3a082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
#3 0x41c36d in _start (/mnt/d/wsl/asan_test/shared_lib/a.out+0x41c36d)
0x602000000032 is located 1 bytes to the right of 1-byte region [0x602000000030,0x602000000031)
allocated by thread T0 here:
#0 0x494aad in malloc (/mnt/d/wsl/asan_test/shared_lib/a.out+0x494aad)
#1 0x7fc4c3f93260 in foo() (libfoo_san.so+0x1260)
#2 0x4c6b21 in main (/mnt/d/wsl/asan_test/shared_lib/a.out+0x4c6b21)
#3 0x7fc4c3a3a082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
SUMMARY: AddressSanitizer: heap-buffer-overflow (libfoo_san.so+0x12a9) in foo()
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 01 fa fa fa[01]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
==5530==ABORTING
test3) 일반 실행 파일 + asan shared lib
asan 옵션을 가지고 compile된 so의 경우, 일반 executable과 linking이 불가능하다.
so 생성 시, asan 에 대한 symbol이 추가되기 때문.
따라서 asan 빌드된 library를 device의 일반 library에 replace하여 Asan 기능 활성화는 불가능다.
$clang++ main.cc libfoo_san.so -Wl,-rpath,.
jayce@DESKTOP-J8A6E99:/mnt/d/wsl/asan_test/shared_lib$ clang++ main.cc libfoo_san.so -Wl,-rpath,.
/usr/bin/ld: libfoo_san.so: undefined reference to `__asan_register_globals'
/usr/bin/ld: libfoo_san.so: undefined reference to `__asan_unregister_globals'
/usr/bin/ld: libfoo_san.so: undefined reference to `__asan_init'
/usr/bin/ld: libfoo_san.so: undefined reference to `__asan_report_store1'
/usr/bin/ld: libfoo_san.so: undefined reference to `__asan_after_dynamic_init'
/usr/bin/ld: libfoo_san.so: undefined reference to `__asan_version_mismatch_check_v8'
/usr/bin/ld: libfoo_san.so: undefined reference to `__asan_before_dynamic_init'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
jayce@DESKTOP-J8A6E99:/mnt/d/wsl/asan_test/shared_lib$
jayce@DESKTOP-J8A6E99:/mnt/d/wsl/asan_test/shared_lib$ objdump -t libfoo_san.so | grep asan
00000000000012c0 l F .text 0000000000000021 asan.module_ctor
00000000000012f0 l F .text 0000000000000017 asan.module_dtor
0000000000000000 *UND* 0000000000000000 __asan_register_globals
0000000000000000 *UND* 0000000000000000 __asan_unregister_globals
0000000000000000 *UND* 0000000000000000 __asan_init
0000000000000000 *UND* 0000000000000000 __asan_report_store1
0000000000000000 *UND* 0000000000000000 __asan_after_dynamic_init
0000000000000000 *UND* 0000000000000000 __asan_version_mismatch_check_v8
0000000000000000 *UND* 0000000000000000 __asan_before_dynamic_init
jayce@DESKTOP-J8A6E99:/mnt/d/wsl/asan_test/shared_lib$
test4) 반대로 asan executable의 경우, 일반 lib과 linking에 문제가 없다. 다만 lib에서의 heap-buffer-overflow를 잡아내지 못한다. (executable 자체의 디버깅을 위한 asan 활성화는 target device의 library를 신경쓰지 않고 활성화가 가능함을 의미)
$clang++ main.cc -fsanitize=address libfoo.so -Wl,-rpath,.
jayce@DESKTOP-J8A6E99:/mnt/d/wsl/asan_test/shared_lib$ ./a.out
foo_san
=================================================================
==5538==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000012 at pc 0x0000004c6b67 bp 0x7ffd4a61e960 sp 0x7ffd4a61e958
WRITE of size 1 at 0x602000000012 thread T0
#0 0x4c6b66 in main (/mnt/d/wsl/asan_test/shared_lib/a.out+0x4c6b66)
#1 0x7f6619ee9082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
#2 0x41c36d in _start (/mnt/d/wsl/asan_test/shared_lib/a.out+0x41c36d)
0x602000000012 is located 1 bytes to the right of 1-byte region [0x602000000010,0x602000000011)
allocated by thread T0 here:
#0 0x494aad in malloc (/mnt/d/wsl/asan_test/shared_lib/a.out+0x494aad)
#1 0x4c6b18 in main (/mnt/d/wsl/asan_test/shared_lib/a.out+0x4c6b18)
#2 0x7f6619ee9082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
SUMMARY: AddressSanitizer: heap-buffer-overflow (/mnt/d/wsl/asan_test/shared_lib/a.out+0x4c6b66) in main
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[01]fa fa fa 01 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
==5538==ABORTING
참조:
https://stackoverflow.com/questions/33519085/cannot-specify-multiple-rpath-in-eclipse-cdt
https://stackoverflow.com/questions/25160245/clang-linking-with-a-so-file
'c++' 카테고리의 다른 글
map vs unorderedmap 성능 차이 (0) | 2022.11.02 |
---|---|
undef 활용, log message 출력 (0) | 2019.10.02 |
lambda expression on capture (0) | 2018.06.29 |