#커널 크래시 디버깅 및 TroubleShooting
- Race로 mmc_wait_data_done() 함수에서 커널 패닉
- "cat /d/shrinker" 입력 시 커널 패닉
- 함수 포인터 미지정으로 xfrm_local_error() 커널 패닉
- preempt 조건으로 ___might_sleep() 함수 크래시
- 스택 카나리: __stack_chk_fail() 함수 크래시
- 스택 카나리: tcp_v4_rcv -> __stack_chk_fail 크래시
- 뮤텍스 데드락(Mutex Deadlock)으로 락업(lockup)
- 디바이스 드라이버 Signature 문제로 커널 크래시
- 메모리 불량 커널 크래시 @find_vma_links()
- 메모리 불량 커널 크래시 @ttwu_do_activate()
- Race로 ipv6_ifa_notify() Stuck - watchdog reset
- tty_wakeup() 함수 Data Abort
- irq_affinity_notify() 함수 Data Abort
- cpuacct_charge() 함수 Data Abort
- 워크큐(workqueue) 락업(1)
- 워크큐(workqueue) 락업(2)
- 워크큐(workqueue) 락업(3)
커널 패닉 시 아래 콜 스택이 남아 있습니다.
[39136682.663247] <IRQ> [<ffffffff816351f1>] dump_stack+0x19/0x1b
[39136682.663626] [<ffffffff8162ea6c>] panic+0xd8/0x1e7
[39136682.663988] [<ffffffff8158bd35>] ? tcp_v4_rcv+0x635/0x9f0
[39136682.664361] [<ffffffff8107b00b>] __stack_chk_fail+0x1b/0x20
[39136682.664743] [<ffffffff8158bd35>] tcp_v4_rcv+0x635/0x9f0
[39136682.665131] [<ffffffff8163d0ed>] common_interrupt+0x6d/0x6d
[39136682.665529] <EOI> [<ffffffff81645a2b>] ? sysret_audit+0x17/0x21
위 콜 스택을 보면 여러가지 의문이 생기는데요.
1> tcp_v4_rcv이 인터럽트 핸들러로 호출되는 것 처럼 보이는데, 다른 인터럽트 핸들러도 위와 같은 콜 스택이 확인되나요?
다른 인터럽트 핸들러가 호출될 때와 다른 콜스택이면 스택 Corruption을 의심할 수 있습니다.
2> 커널 패닉이 발생했을 때 RSP 즉 스택 주소(00002aaec5008b98)가 이상합니다.
커널 프로세스의 스택 주소는 struct task_struct->stack -- (struct task_struct->stack)+0x4000 사이이어야 합니다.
crash> bt
PID: 168037 TASK: ffff880494923980 CPU: 26 COMMAND: "app01"
#0 [ffff88046f3a3db8] machine_kexec at ffffffff81051beb
#1 [ffff88046f3a3e18] crash_kexec at ffffffff810f2542
#2 [ffff88046f3a3ee8] panic at ffffffff8162ea73
#3 [ffff88046f3a3f68] __stack_chk_fail at ffffffff8107b00b
#4 [ffff88046f3a3f78] tcp_v4_rcv at ffffffff8158bd35
--- <IRQ stack> ---
#5 [ffff880217dbbf58] ret_from_intr at ffffffff8163d0ed
RIP: 00002aae21629848 RSP: 00002aaec5008b98 RFLAGS: 00000202
RAX: 00002aaf8c0394c0 RBX: ffffffff81645a2b RCX: 0000000000038400
RDX: 0000000000038180 RSI: 00002aaf68157390 RDI: 00002aaf8c0716c0
RBP: 00002aaec5009180 R8: 00002aaf8c0718b0 R9: 0000000000000000
R10: 0000000000000002 R11: 00002aae21657160 R12: 0000000000000000
R13: 00002aaec500a700 R14: 00002aaec500a9c0 R15: 0000000000000000
ORIG_RAX: ffffffffffffffca CS: 0033 SS: 002b
아래 명령어로 스택 주소를 확인해보세요.
struct task_struct.stack ffff880494923980
예)
crash64> struct task_struct.stack ffffffc001580e40
stack = 0xffffffc001574000 <init_thread_union>
3> 만약 2>에서 언급된 것과 같이 스택이 꺠져 있다면, 아래 방법으로 tcp_v4_rcv 함수 내에서 호출되는 함수 전 후로 로그를 확인해도 좋을 것 같습니다.
4> 커널 Makefile을 보면 -fstack-protector 옵션이 켜져 있을 때 스택 카나리 코드가 추가됩니다. 아래 옵션을 한 번 끄고 어떤 동작을 하는 지 점검해도 좋을 것 같습니다.
ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
stackp-flag := -fstack-protector
ifeq ($(call cc-option, $(stackp-flag)),)
$(warning Cannot use CONFIG_CC_STACKPROTECTOR_REGULAR: \
-fstack-protector not supported by compiler)
endif
else
ifdef CONFIG_CC_STACKPROTECTOR_STRONG
stackp-flag := -fstack-protector-strong
ifeq ($(call cc-option, $(stackp-flag)),)
$(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \
-fstack-protector-strong not supported by compiler)
endif
else
# Force off for distro compilers that enable stack protector by default.
stackp-flag := $(call cc-option, -fno-stack-protector)
# Reference: For more information on 'Linux Kernel';
디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1
디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2
'Core BSP 분석 > 커널 트러블슈팅' 카테고리의 다른 글
[Kernel][Crash][0320] 워크큐(workqueue) 락업(1) (0) | 2023.05.07 |
---|---|
[Kernel][Panic] panic@ttwu_do_activate (메모리 불량 보드) (0) | 2023.05.07 |
[Linux][Kernel] data abort@cpuacct_charge - 리눅스 커널 (0) | 2023.05.07 |
[Linux][Kernel] data abort@irq_affinity_notify - 리눅스 커널 (0) | 2023.05.07 |
[Linux][Kernel] data abort @tty_wakeup - 리눅스 커널 (0) | 2023.05.07 |