본문 바로가기
Android/Debug

[안드로이드] tombstone 디버깅 2

by Jay Son 아기 냥이 해린 짱💖 2020. 7. 5.

참고용으로 안드로이드 공식 사이트 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

 

네이티브 충돌 진단  |  Android 오픈소스 프로젝트  |  Android Open Source Project

 

tombstone 디버깅 가이드 1 보기 : https://json8.tistory.com/19

 

[안드로이드] tombstone 디버깅 1

https://source.android.google.cn/devices/tech/debug?hl=ko 동적으로 연결된 실행 파일이 시작되면 여러 신호 핸들러가 등록되는데, 충돌 시 logcat에 기본 충돌 덤프가 기록되고 보다 자세한 tombstone 파일..

json8.tistory.com

 

반응형

'Android > Debug' 카테고리의 다른 글

[안드로이드] tombstone 디버깅 1  (0) 2020.05.29