Very interesting kernel panic occurs with the following callstacks.
crash> bt -I C0ED8B64 -S E853FD20 e5752c00 PID: 1787 TASK: e5752c00 CPU: 4 COMMAND: "python" bt: WARNING: stack address:0xe853fa38, program counter:0xc0ee5b60 #0 [<c0ed8b64>] (panic) from [<c0125038>] #1 [<c0125038>] (__stack_chk_fail) from [<c032b6cc>] #2 [<c032b6cc>] (sock_has_perm) from [<c0327d00>] #3 [<c0327d00>] (security_socket_recvmsg) from [<c0ceb1c8>] #4 [<c0ceb1c8>] (sock_recvmsg) from [<c0cec474>] #5 [<c0cec474>] (___sys_recvmsg) from [<c0ced5b4>] #6 [<c0ced5b4>] (__sys_recvmsg) from [<c0106820>] |
[1]: sock_has_perm() is first called from security_socket_recvmsg().. Stack: 0xE853FDD8
[2]: After a set of registers are pushed into stack area.. Stack: 0xE853FDBC(0xE853FDD8-0x1C)
[3]: The stack is pushed for local variable Stack: 0xE853FD68(0xE853FDBC-0x54)
[4]: R7 is holding 0xC1809948 where __stack_chk_guard is located.
(where: T32) NSP:C032B6D4|C1809948 dcd 0xC1809948 ; __stack_chk_guard (where: binary utility) c032b6d4: c1809948 .word 0xc1809948 crash> p &__stack_chk_guard $3 = (unsigned long *) 0xc1809948 <__stack_chk_guard> |
[5]: R3 is now holding stack canary magic dump 0xdc8cb01f where R3 = 0xdc8cb01f = *0xC1809948
crash> rd 0xC1809948 c1809948: dc8cb01f |
[6]: The stack canary magic dump(0xdc8cb01f: R3) is stored into 0xE853FDB4(=0xE853FD68+0x4c = SP+0x4c)
[7]: To get stack canary magic dump, access 0xE853FDB4 where "ldr r2, [sp, #76] ; 0x4c" instruction is executed.
In this case, R2 is updated as 0xdc8cb01f.
[8]: R3 should have been 0xdc8cb01f instead of 0x0. The weird debug signature is that R7 holds 0xC1800048, which should have been 0xC1809948.
After the following instruction is executed, R7 is never changed within sock_has_perm().
- 0xc032b638 <sock_has_perm+8>: ldr r7, [pc, #148]
[9]: kernel panic occurs
#Code
0xc032b630 <sock_has_perm>: push {r4, r5, r6, r7, r8, r9, lr} //<<--[2] 0xc032b634 <sock_has_perm+0x4>: sub sp, sp, #84 ; 0x54 //<<--[3] 0xc032b638 <sock_has_perm+0x8>: ldr r7, [pc, #148] ; 0xc032b6d4 <sock_has_perm+0xa4> //<<--[4] 0xc032b63c <sock_has_perm+0xc>: add r6, sp, #28 0xc032b640 <sock_has_perm+0x10>: mov r9, r0 0xc032b644 <sock_has_perm+0x14>: ldr r4, [r1, #420] ; 0x1a4 0xc032b648 <sock_has_perm+0x18>: mov r5, r1 0xc032b64c <sock_has_perm+0x1c>: mov r8, r2 0xc032b650 <sock_has_perm+0x20>: ldr r3, [r7] //<<--[5] 0xc032b654 <sock_has_perm+36>: mov r1, #0 0xc032b658 <sock_has_perm+40>: mov r2, #48 ; 0x30 0xc032b65c <sock_has_perm+44>: mov r0, r6 0xc032b660 <sock_has_perm+48>: str r3, [sp, #76] ; 0x4c //<<--[6] // snip 0xc032b6b8 <sock_has_perm+0x88>: ldr r2, [sp, #76] ; 0x4c //<<--[7] 0xc032b6bc <sock_has_perm+0x8c>: ldr r3, [r7] //<<--[8] 0xc032b6c0 <sock_has_perm+0x90>: cmp r2, r3 0xc032b6c4 <sock_has_perm+0x94>: beq 0xc032b6cc <sock_has_perm+156> 0xc032b6c8 <sock_has_perm+0x98>: bl 0xc0125028 <__stack_chk_fail> //<<--[9] |
#Stack dump
NSD:E853FD5C| 00 00 00 00 0x0 NSD:E853FD60| 00 00 00 00 0x0 NSD:E853FD64| CC B6 32 C0 0xC032B6CC \\vmlinux\hooks\sock_has_perm+0x9C NSD:E853FD68| 74 FD 53 E8 0xE853FD74 //<<--[3] NSD:E853FD6C| A0 FD 53 E8 0xE853FDA0 //snip NSD:E853FDAC| 00 00 00 00 0x0 NSD:E853FDB0| 00 00 00 00 0x0 NSD:E853FDB4| 1F B0 8C DC 0xDC8CB01F //<<--[6] location where stack canary magic is saved. NSD:E853FDB8| 00 0A 82 ED 0xED820A00 NSD:E853FDBC| 00 9C C9 C3 0xC3C99C00 //<<--[R4] //<<--[2] New Stack NSD:E853FDC0| 00 00 01 00 0x10000 //<<--[R5] NSD:E853FDC4| 7C FF 53 E8 0xE853FF7C //<<--[R6] NSD:E853FDC8| 00 00 00 00 0x0 NSD:E853FDCC| 00 2C 75 E5 0xE5752C00 NSD:E853FDD0| 00 00 00 00 0x0 //<<--[R9] NSD:E853FDD4| 00 7D 32 C0 0xC0327D00 \\vmlinux\security\security_socket_recvmsg+0x14 //<<--[R14] NSD:E853FDD8| 00 00 00 00 0x0 // <<--[1] |
Please remember that __stack_chk_fail symbol is pushed into the assemble code inside other Kernel APIs for stack corruption sanity-check.
0xc0100974 <do_one_initcall+404>: bl 0xc0125028 <__stack_chk_fail> 0xc0100d8c <name_to_dev_t+828>: bl 0xc0125028 <__stack_chk_fail> 0xc0107854 <__show_regs+700>: bl 0xc0125028 <__stack_chk_fail> 0xc01219c0 <sha384_neon_final+108>: bl 0xc0125028 <__stack_chk_fail> 0xc0133c34 <sys_newuname+352>: bl 0xc0125028 <__stack_chk_fail> 0xc0133d68 <sys_sethostname+276>: bl 0xc0125028 <__stack_chk_fail> |
In case of this coredump, the Linux Kernel is complied with fstack-protector option.
658 ifdef CONFIG_CC_STACKPROTECTOR_REGULAR 659 stackp-flag := -fstack-protector 660 ifeq ($(call cc-option, $(stackp-flag)),) 661 $(warning Cannot use CONFIG_CC_STACKPROTECTOR_REGULAR: \ 662 -fstack-protector not supported by compiler) 663 endif |
'Kernel Crash Case-Studies' 카테고리의 다른 글
[KernelCrash] Abort at 0xecb29f00(defective device) (0) | 2019.03.09 |
---|---|
[KernelCrash] Abort at mmc_wait_data_done() due to race (0) | 2019.03.09 |
[KernelCrash] Abort at rmqueue_bulk() due to page.lru->next corruption (0) | 2019.03.09 |
[리눅스커널][크래시분석] 뮤텍스 데드락(Mutex Deadlock) 락업(lockup) - "simpleperf" 디버깅 (0) | 2019.02.20 |
[리눅스커널][Trace32] T32로 wakelock 디버깅 - container_of 함수 분석 (0) | 2019.02.13 |