참고용으로 안드로이드 공식 사이트 Diagnosing Native Crashes 내용 정리함.
1. Abort
SIGABRT Abort message 메시지
crash 원인은 #00 pc 0001cb16 /system/lib/libc.so (abort+57)
로그캣 로그에 "abort message" 메시지가 있을 수 있음.
pid: 4637, tid: 4637, name: crasher >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
r0 00000000 r1 0000121d r2 00000006 r3 00000008
r4 0000121d r5 0000121d r6 ffb44a1c r7 0000010c
r8 00000000 r9 00000000 r10 00000000 r11 00000000
ip ffb44c20 sp ffb44a08 lr eace2b0b pc eace2b16
backtrace:
#00 pc 0001cb16 /system/lib/libc.so (abort+57)
#01 pc 0001cd8f /system/lib/libc.so (__assert2+22)
#02 pc 00001531 /system/bin/crasher (do_action+764)
#03 pc 00002301 /system/bin/crasher (main+68)
#04 pc 0008a809 /system/lib/libc.so (__libc_init+48)
#05 pc 00001097 /system/bin/crasher (_start_main+38)
이전 Android 버전에서는 위와 같이 명확하게 표시되지 않을 수 있음
#04 pc 000168e8 /system/lib/libc.so (abort+4) ~ #00 pc 00042c98 /system/lib/libc.so (tgkill+12)
pid: 1656, tid: 1656, name: crasher >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8
r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c
r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c
ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010
backtrace:
#00 pc 00042c98 /system/lib/libc.so (tgkill+12)
#01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32)
#02 pc 0001bb87 /system/lib/libc.so (raise+10)
#03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34)
#04 pc 000168e8 /system/lib/libc.so (abort+4)
#05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16)
#06 pc 00018d35 /system/lib/libc.so (__assert2+20)
#07 pc 00000f21 /system/xbin/crasher
#08 pc 00016795 /system/lib/libc.so (__libc_init+44)
#09 pc 00000abc /system/xbin/crasher
crasher abort 를 이용하여 강제로 abort 이슈를 재현 할 수 있음.
2. Pure null pointer dereference
NullPoint
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
#00 strlen 에서 null 참조 하였고 가이드 문서는 #01에서 호출자로 작성되어 있지만 #04 __libc_init 메소드에서 원인을 찾으면 될 것으로 보임.
pid: 25326, tid: 25326, name: crasher >>> crasher <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
r0 00000000 r1 00000000 r2 00004c00 r3 00000000
r4 ab088071 r5 fff92b34 r6 00000002 r7 fff92b40
r8 00000000 r9 00000000 sl 00000000 fp fff92b2c
ip ab08cfc4 sp fff92a08 lr ab087a93 pc efb78988 cpsr 600d0030
backtrace:
#00 pc 00019988 /system/lib/libc.so (strlen+71)
#01 pc 00001a8f /system/xbin/crasher (strlen_null+22)
#02 pc 000017cd /system/xbin/crasher (do_action+948)
#03 pc 000020d5 /system/xbin/crasher (main+100)
#04 pc 000177a1 /system/lib/libc.so (__libc_init+48)
#05 pc 000010e4 /system/xbin/crasher (_start+96)
3. Low-address null pointer dereference
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc
#00 pthread_mutex_lock 에서 0xc 액세스 시도하여 발생한 문제이지만 직접적인 원인은 pthread_mutex_t*의 state 요소를 역참조로 발생함. libc 원인을 찾는 것이 중요하며 항상 같인 원인은 아닐 수 있음
pid: 25405, tid: 25405, name: crasher >>> crasher <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc
r0 0000000c r1 00000000 r2 00000000 r3 3d5f0000
r4 00000000 r5 0000000c r6 00000002 r7 ff8618f0
r8 00000000 r9 00000000 sl 00000000 fp ff8618dc
ip edaa6834 sp ff8617a8 lr eda34a1f pc eda618f6 cpsr 600d0030
backtrace:
#00 pc 000478f6 /system/lib/libc.so (pthread_mutex_lock+1)
#01 pc 0001aa1b /system/lib/libc.so (readdir+10)
#02 pc 00001b35 /system/xbin/crasher (readdir_null+20)
#03 pc 00001815 /system/xbin/crasher (do_action+976)
#04 pc 000021e5 /system/xbin/crasher (main+100)
#05 pc 000177a1 /system/lib/libc.so (__libc_init+48)
#06 pc 00001110 /system/xbin/crasher (_start+96)
crasher fprintf-NULL 또는 crasher readdir-NULL을 사용하면 이러한 유형의 충돌 인스턴스를 재현할 수 있음.
4. FORTIFY failure
FORTIFY 실패는 C 라이브러리가 보안 취약점을 일으킬 수 있는 문제를 발견했을 때 발생하는 특수한 중단 케이스.
설정된 버퍼보다 큰 크기를 설정해서 발생
ex) read(fd, buf, 32)
Abort message: 'FORTIFY: read: prevented 32-byte write into 10-byte buffer'
#02 pc 0001e197 /system/lib/libc.so (__fortify_fatal+30)
pid: 25579, tid: 25579, name: crasher >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'FORTIFY: read: prevented 32-byte write into 10-byte buffer'
r0 00000000 r1 000063eb r2 00000006 r3 00000008
r4 ff96f350 r5 000063eb r6 000063eb r7 0000010c
r8 00000000 r9 00000000 sl 00000000 fp ff96f49c
ip 00000000 sp ff96f340 lr ee83ece3 pc ee86ef0c cpsr 000d0010
backtrace:
#00 pc 00049f0c /system/lib/libc.so (tgkill+12)
#01 pc 00019cdf /system/lib/libc.so (abort+50)
#02 pc 0001e197 /system/lib/libc.so (__fortify_fatal+30)
#03 pc 0001baf9 /system/lib/libc.so (__read_chk+48)
#04 pc 0000165b /system/xbin/crasher (do_action+534)
#05 pc 000021e5 /system/xbin/crasher (main+100)
#06 pc 000177a1 /system/lib/libc.so (__libc_init+48)
#07 pc 00001110 /system/xbin/crasher (_start+96)
crasher fortify을 사용하면 이러한 유형의 충돌 인스턴스를 재현 가능.
5. Stack corruption detected by -fstack-protector
스택 손상 감지
컴파일러의 -fstack-protector 옵션은 버퍼 오버런을 방지하기 위해 스택에 버퍼가 있는 함수에 검사를 삽입.
Abort message: 'stack corruption detected'
#03 pc 0004863f /system/lib/libc.so (__stack_chk_fail+6)
pid: 26717, tid: 26717, name: crasher >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'stack corruption detected'
r0 00000000 r1 0000685d r2 00000006 r3 00000008
r4 ffd516d8 r5 0000685d r6 0000685d r7 0000010c
r8 00000000 r9 00000000 sl 00000000 fp ffd518bc
ip 00000000 sp ffd516c8 lr ee63ece3 pc ee66ef0c cpsr 000e0010
backtrace:
#00 pc 00049f0c /system/lib/libc.so (tgkill+12)
#01 pc 00019cdf /system/lib/libc.so (abort+50)
#02 pc 0001e07d /system/lib/libc.so (__libc_fatal+24)
#03 pc 0004863f /system/lib/libc.so (__stack_chk_fail+6)
#04 pc 000013ed /system/xbin/crasher (smash_stack+76)
#05 pc 00001591 /system/xbin/crasher (do_action+280)
#06 pc 00002219 /system/xbin/crasher (main+100)
#07 pc 000177a1 /system/lib/libc.so (__libc_init+48)
#08 pc 00001144 /system/xbin/crasher (_start+96)
crasher smash-stack을 사용하면 이러한 유형의 충돌 인스턴스를 재현 가능.
4. Seccomp SIGSYS from a disallowed system call
허용되지 않은 시스템 호출
signal 31 (SIGSYS), code 1 (SYS_SECCOMP), fault addr --------
Cause: seccomp prevented call to disallowed arm system call 99999
제한된 시스템 호출을 호출하는 스레드 오류
Seccomp 자세한 내용은 공식 블로그에서 확인 (https://android-developers.googleblog.com/2017/07/seccomp-filter-in-android-o.html)
시스템 호출 번호는 아키텍처에 따라 다르므로 헤더에서 시스템 호출 번호를 찾는 것보다는 스택 추적을 사용하여 어떤 시스템 호출이 허용되지 않았는지 확인하는 편이 일반적으로 더 쉬움.
pid: 11046, tid: 11046, name: crasher >>> crasher <<<
signal 31 (SIGSYS), code 1 (SYS_SECCOMP), fault addr --------
Cause: seccomp prevented call to disallowed arm system call 99999
r0 cfda0444 r1 00000014 r2 40000000 r3 00000000
r4 00000000 r5 00000000 r6 00000000 r7 0001869f
r8 00000000 r9 00000000 sl 00000000 fp fffefa58
ip fffef898 sp fffef888 lr 00401997 pc f74f3658 cpsr 600f0010
backtrace:
#00 pc 00019658 /system/lib/libc.so (syscall+32)
#01 pc 00001993 /system/bin/crasher (do_action+1474)
#02 pc 00002699 /system/bin/crasher (main+68)
#03 pc 0007c60d /system/lib/libc.so (__libc_init+48)
#04 pc 000011b0 /system/bin/crasher (_start_main+72)
crasher seccomp를 사용하면 이러한 유형의 충돌 인스턴스를 재현 가능.
5. Execute-only memory violation
Android 10 이상의 arm64의 경우 바이너리 및 라이브러리의 실행 가능 세그먼트는 코드 재사용 공격에 대한 강화 기술로서 메모리 실행 전용(읽기 불가)으로 매핑됨.
해당 가이드는 내용을 이해할 수 없어 추가 이슈 발생 할 경우 재 확인 필요함.
(https://source.android.com/devices/tech/debug/native-crash#xom)
Cause: execute-only (no-read) memory access error; likely due to data in .text.
pid: 2938, tid: 2940, name: crasher64 >>> crasher64 <<<
signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x5f2ced24a8
Cause: execute-only (no-read) memory access error; likely due to data in .text.
x0 0000000000000000 x1 0000005f2cecf21f x2 0000000000000078 x3 0000000000000053
x4 0000000000000074 x5 8000000000000000 x6 ff71646772607162 x7 00000020dcf0d16c
x8 0000005f2ced24a8 x9 000000781251c55e x10 0000000000000000 x11 0000000000000000
x12 0000000000000014 x13 ffffffffffffffff x14 0000000000000002 x15 ffffffffffffffff
x16 0000005f2ced52f0 x17 00000078125c0ed8 x18 0000007810e8e000 x19 00000078119fbd50
x20 00000078125d6020 x21 00000078119fbd50 x22 00000b7a00000b7a x23 00000078119fbdd8
x24 00000078119fbd50 x25 00000078119fbd50 x26 00000078119fc018 x27 00000078128ea020
x28 00000078119fc020 x29 00000078119fbcb0
sp 00000078119fba40 lr 0000005f2ced1b94 pc 0000005f2ced1ba4
backtrace:
#00 pc 0000000000003ba4 /system/bin/crasher64 (do_action+2348)
#01 pc 0000000000003234 /system/bin/crasher64 (thread_callback+44)
#02 pc 00000000000e2044 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36)
#03 pc 0000000000083de0 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64)
crasher xom을 사용하면 이러한 유형의 충돌 인스턴스를 재현 가능.
6. Error detected by fdsan
fdsan (file descriptor sanitizer)로 파일 메모리 할당/해제, 이중 close 등 이슈를 감지 할 수 있도록 설정 후 사용.
fdscan 공식 가이드(https://android.googlesource.com/platform/bionic/+/master/docs/fdsan.md)
Abort message: 'attempted to close file descriptor 3, expected to be unowned, actually owned by FILE* 0x7d8e413018'
pid: 32315, tid: 32315, name: crasher64 >>> crasher64 <<<
signal 35 (), code -1 (SI_QUEUE), fault addr --------
Abort message: 'attempted to close file descriptor 3, expected to be unowned, actually owned by FILE* 0x7d8e413018'
x0 0000000000000000 x1 0000000000007e3b x2 0000000000000023 x3 0000007fe7300bb0
x4 3033313465386437 x5 3033313465386437 x6 3033313465386437 x7 3831303331346538
x8 00000000000000f0 x9 0000000000000000 x10 0000000000000059 x11 0000000000000034
x12 0000007d8ebc3a49 x13 0000007fe730077a x14 0000007fe730077a x15 0000000000000000
x16 0000007d8ec9a7b8 x17 0000007d8ec779f0 x18 0000007d8f29c000 x19 0000000000007e3b
x20 0000000000007e3b x21 0000007d8f023020 x22 0000007d8f3b58dc x23 0000000000000001
x24 0000007fe73009a0 x25 0000007fe73008e0 x26 0000007fe7300ca0 x27 0000000000000000
x28 0000000000000000 x29 0000007fe7300c90
sp 0000007fe7300860 lr 0000007d8ec2f22c pc 0000007d8ec2f250
backtrace:
#00 pc 0000000000088250 /bionic/lib64/libc.so (fdsan_error(char const*, ...)+384)
#01 pc 0000000000088060 /bionic/lib64/libc.so (android_fdsan_close_with_tag+632)
#02 pc 00000000000887e8 /bionic/lib64/libc.so (close+16)
#03 pc 000000000000379c /system/bin/crasher64 (do_action+1316)
#04 pc 00000000000049c8 /system/bin/crasher64 (main+96)
#05 pc 000000000008021c /bionic/lib64/libc.so (_start_main)
crasher fdsan_file 또는 crasher fdsan_dir을 사용하면 이러한 유형의 충돌 인스턴스를 재현 가능.
7. Investigating crash dumps
현재 조사 중인 특정 충돌이 없는 경우 플랫폼 소스에는 crasher라고 하는 debuggerd 테스트 도구가 포함됩니다. system/core/debuggerd/에 mm이 있는 경우 경로에 crasher와 crasher64를 모두 얻게 됩니다. 후자의 경우는 64비트 충돌을 테스트할 수 있습니다. crasher는 개발자가 제공하는 명령줄 인수에 기반하여 여러 가지 흥미로운 방법으로 충돌시킬 수 있습니다. crasher --help를 사용하여 현재 지원되는 선택항목을 확인할 수 있습니다.
샘플 로그
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys'
Revision: '0'
ABI: 'arm'
pid: 1656, tid: 1656, name: crasher >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8
r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c
r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c
ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010
backtrace:
#00 pc 00042c98 /system/lib/libc.so (tgkill+12)
#01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32)
#02 pc 0001bb87 /system/lib/libc.so (raise+10)
#03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34)
#04 pc 000168e8 /system/lib/libc.so (abort+4)
#05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16)
#06 pc 00018d35 /system/lib/libc.so (__assert2+20)
#07 pc 00000f21 /system/xbin/crasher
#08 pc 00016795 /system/lib/libc.so (__libc_init+44)
#09 pc 00000abc /system/xbin/crasher
Tombstone written to: /data/tombstones/tombstone_06
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint, Revision 설정 skip
ABI(Application Binary Interface)
ABI는 arm, arm64, x86 또는 x86-64 중 하나 대부분 단말기에서 사용하는 so 라이브러리는 arm 개발 CPU를 사용하고 있어 arm, amr64 사용하고 있음.
ABI: 'arm'
프로세스에서 충돌이 발생한 특정 스레드 번호
name은 앱의 패키지명 ex) com.json.example
pid: 1656, tid: 1656, name: crasher >>> crasher <<<
모든 충돌에 중단 메시지 행이 있는 것은 아니지만 중단 메시지 행이 있음
중단 메시지는 이 pid/tid와 관련된 치명적인 logcat 출력의 마지막 행으로부터 자동으로 수집되며, 의도적인 중단의 경우에는 프로그램이 자체적으로 중단된 이유를 제공
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
레지스터 덤프는 신호가 수신된 시점에 CPU 레지스터의 내용을 보여줍니다. 이 섹션은 ABI에 따라 매우 다양합니다. 이러한 기능의 유용성은 구체적인 충돌 내용에 따라 다름.
해당 메모리 설명은 정확한 활용 방법을 알지 못함. 개인적으로 해당 메시지는 별도로 참고 하지 않음.
r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8
r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c
r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c
ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010
backtrace는 충돌 시점의 코드 위치를 보여줌.
호출 순서는 #09 -> #00
보통 #00 번 위치에 원인이 되는 코드가 내용이 포함되어 있음.
#00 번 메소드가 라이브러리에서 사용하고 있지 않을 경우 호출 순서 역으로 찾아가야 함.
backtrace:
#00 pc 00042c98 /system/lib/libc.so (tgkill+12)
#01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32)
#02 pc 0001bb87 /system/lib/libc.so (raise+10)
#03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34)
#04 pc 000168e8 /system/lib/libc.so (abort+4)
#05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16)
#06 pc 00018d35 /system/lib/libc.so (__assert2+20)
#07 pc 00000f21 /system/xbin/crasher
#08 pc 00016795 /system/lib/libc.so (__libc_init+44)
#09 pc 00000abc /system/xbin/crasher
tombstones 파일 단말기에 저장된 이슈
파일은 최대 10개가 저장되고 10개 이상이 될 경우 가장 오래된 파일은 삭제됨.(00에서 09 사이의 숫자를 순환)
해당 경로는 /data/이하 접근이 필요하여 사용 단말기(User)버전에서는 접근 할 수 없다.
단말 제조사에서 User Debug 버전 OS에서 접근 가능함.
오래전 Android 에서는 루팅을 통해서 시스템 영역을 접근 할 수 있었지만 현재는 쉽지 않음.
Tombstone written to: /data/tombstones/tombstone_06
출처 (안드로이드 공식 사이트) : https://source.android.com/devices/tech/debug/native-crash
tombstone 디버깅 가이드 1 보기 : https://json8.tistory.com/19
'Android > Debug' 카테고리의 다른 글
[안드로이드] tombstone 디버깅 1 (0) | 2020.05.29 |
---|