Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

99199
1107
135827


[리눅스커널][디버깅] 유저공간 abort 발생 시 커널 패닉 유발하는 패치 3. 커널 디버깅과 코드 학습

개발 도중에 유저 공간에서 abort가 발생합니다. 안드로이드 플렛폼에서는 tombstone이 생성돼 레지스터와 콜스택을 확인할 수 있습니다.
Revision: '0'
ABI: 'arm'
pid: 16458, tid: 16513, name: thermal-engine  >>> /system/vendor/bin/thermal-engine <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
Cause: null pointer dereference
    r0 00000000  r1 a73a48c0  r2 8362dec4  r3 8362deec
    r4 80000000  r5 00000000  r6 83639000  r7 83c35fd8
    r8 00000000  r9 00000000  sl 000084d0  fp a73c2500
    ip 80808000  sp a40885b0  lr 83617861  pc 8362ddae  cpsr 80070030
    d0  5f7a745f736e6520  d1  7269762f7365636d
    d2  6568742f6c617543  d3  6568742f6c616d0a
    
하지만 가끔 유저 공간에서 abort가 발생했을 때 커널 패닉을 유발해 전체 콜스택을 보고 싶을 때가 있습니다.
이번 시간에 이를 위한 설정 방법을 살펴보겠습니다.

코드 수정

먼저 커널 컨피그를 수정합시다.
diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig
index c4e6527..5452f34 100644
--- a/arch/arm/configs/bcm2709_defconfig
+++ b/arch/arm/configs/bcm2709_defconfig
@@ -808,3 +808,4 @@
 # Enable RPI VPN
 CONFIG_RPI_VPN_V34=y
 CONFIG_RPI_USE_DEFAULT_HARD_RESET=y
+CONFIG_DEBUG_USER=y

커널 커맨드에 user_debug=24를 전달하는 코드를 부트 로더에 추가합니다.
diff --git a/target/rpi_common/boot_loader_common.c b/target/rpi_common/boot_loader_common.c
index dc7b483..ff2c2bd 100644
--- a/target/rpi_common/boot_loader_common.c
+++ b/target/rpi_common/boot_loader_common.c
@@ -188,6 +188,7 @@
  bootcmd_add_new_key("gpt");
+ bootcmd_add_pair("user_debug","24");
 }

위 코드는 LK(Little Kernel)에서 커맨드 라인을 추가하는 코드입니다.

user_debug 커널 커맨드를 24로 설정한 이유는 다음 코드에서 UDBG_SEGV와 UDBG_BUS 매크로가 아래와 같이 설정돼 있기 때문입니다.
UDBG_SEGV =  1<<3 (8)
UDBG_BUS = 1<<4(16) 

[https://elixir.bootlin.com/linux/v4.19.30/source/arch/arm/mm/fault.c]
01 static void
02 __do_user_fault(struct task_struct *tsk, unsigned long addr,
03 unsigned int fsr, unsigned int sig, int code,
04 struct pt_regs *regs)
05 {
06 struct siginfo si;
07
08 if (addr > TASK_SIZE)
09 harden_branch_predictor();
10
11 clear_siginfo(&si);
12
13 #ifdef CONFIG_DEBUG_USER
14 if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) ||
15     ((user_debug & UDBG_BUS)  && (sig == SIGBUS))) {
16 printk(KERN_DEBUG "%s: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n",
17        tsk->comm, sig, addr, fsr);
18 show_pte(tsk->mm, addr);
19 show_regs(regs);
20 }
21 #endif

user_debug 전역 변수 기준 조건문인 14~20 번째 줄을 눈여겨봅시다.

위 두 가지 코드를 빌드한 후 타겟 디바이스에 다운로드 합시다.

테스트

다음 명령어로 print-fatal-signals 필드를 1로 설정합시다.
" echo 1 > /proc/sys/kernel/print-fatal-signals" 

"kill -11 4839" 명령어를 입력해 pid가 4839인 errorreporterui 프로세스를 abort 시킵니다.

커널 크래시가 발생합니다.
<6>[  192.145575 / 05-21 22:29:31.815][3] potentially unexpected fatal signal 11.
<6>[  192.145596 / 05-21 22:29:31.815][3] CPU: 3 PID: 4839 Comm: errorreporterui Tainted: G        W      4.19.30-gbbd0bc4-dirty #3
<6>[  192.145609 / 05-21 22:29:31.815][3] task: c244e040 ti: e1348000 task.ti: e1348000
<6>[  192.145620 / 05-21 22:29:31.815][3] PC is at 0xa6671858
<6>[  192.145630 / 05-21 22:29:31.815][3] LR is at 0xa66426dd
<6>[  192.145642 / 05-21 22:29:31.815][3] pc : [<a6671858>]    lr : [<a66426dd>]    psr: 600f0010
<6>[  192.145642 / 05-21 22:29:31.815][3] sp : bef7ddb8  ip : bef7ddc8  fp : 930eeaf0
<6>[  192.145658 / 05-21 22:29:31.815][3] r10: 00000000  r9 : 930eeb3c  r8 : 00000000
<6>[  192.145669 / 05-21 22:29:31.815][3] r7 : 0000015a  r6 : 00000000  r5 : 00000008  r4 : 00000000
<6>[  192.145680 / 05-21 22:29:31.815][3] r3 : ffffffff  r2 : 00000010  r1 : bef7de08  r0 : fffffffc
<6>[  192.145691 / 05-21 22:29:31.815][3] Flags: nZCv  IRQs on  FIQs on  Mode USER_32  ISA ARM  Segment user
<6>[  192.145702 / 05-21 22:29:31.815][3] Control: 10c0383d  Table: a134c06a  DAC: 00000051
<6>[  192.145714 / 05-21 22:29:31.815][3] CPU: 3 PID: 4839 Comm: errorreporterui Tainted: G        W      3.18.66-gbbd0bc4-dirty #3
<6>[  192.145736 / 05-21 22:29:31.815][3] [<c010e400>] (unwind_backtrace) from [<c010b4a8>] (show_stack+0x10/0x14)
<6>[  192.145752 / 05-21 22:29:31.815][3] [<c010b4a8>] (show_stack) from [<c0fd0740>] (dump_stack+0x78/0x98)
<6>[  192.145768 / 05-21 22:29:31.815][3] [<c0fd0740>] (dump_stack) from [<c01338a8>] (get_signal+0x4fc/0x5d0)
<6>[  192.145784 / 05-21 22:29:31.815][3] [<c01338a8>] (get_signal) from [<c010a878>] (do_signal+0x84/0x47c)
<6>[  192.145800 / 05-21 22:29:31.815][3] [<c010a878>] (do_signal) from [<c010ade8>] (do_work_pending+0x54/0xb4)
<6>[  192.145815 / 05-21 22:29:31.815][3] [<c010ade8>] (do_work_pending) from [<c0106bb4>] (work_pending+0xc/0x20)
 
다른 커널 로그입니다.
<7>[   72.248793 / 05-21 22:27:31.925][2] android.ui: unhandled page fault (11) at 0x00000000, code 0x005
<1>[   72.248810 / 05-21 22:27:31.925][2] pgd = da0fc000
<1>[   72.252580 / 05-21 22:27:31.925][2] [00000000] *pgd=00000000
<6>[   72.258764 / 05-21 22:27:31.935][2] CPU: 2 PID: 999 Comm: rpi.ui Tainted: G        W      4.19.30-gbbd0bc4-dirty #3
<6>[   72.258781 / 05-21 22:27:31.935][2] task: d7e0d840 ti: d7f02000 task.ti: d7f02000
<6>[   72.258793 / 05-21 22:27:31.935][2] PC is at 0x73a7c9c0
<6>[   72.258803 / 05-21 22:27:31.935][2] LR is at 0x0
<6>[   72.258814 / 05-21 22:27:31.935][2] pc : [<73a7c9c0>]    lr : [<00000000>]    psr: 00070030
<6>[   72.258814 / 05-21 22:27:31.935][2] sp : 885bc480  ip : 00000000  fp : 131e3218
<6>[   72.258830 / 05-21 22:27:31.935][2] r10: 71488688  r9 : 92778200  r8 : 00000000
<6>[   72.258840 / 05-21 22:27:31.935][2] r7 : 131e2bf0  r6 : 00000000  r5 : 00000001  r4 : 00263c64
<6>[   72.258851 / 05-21 22:27:31.935][2] r3 : 131e3218  r2 : 71488688  r1 : 00000000  r0 : 71488688
<6>[   72.258863 / 05-21 22:27:31.935][2] Flags: nzcv  IRQs on  FIQs on  Mode USER_32  ISA Thumb  Segment user
<6>[   72.258873 / 05-21 22:27:31.935][2] Control: 10c0383d  Table: 9a0fc06a  DAC: 00000051
<6>[   72.258885 / 05-21 22:27:31.935][2] CPU: 2 PID: 999 Comm: rpi.ui Tainted: G        W      3.18.66-gbbd0bc4-dirty #3
<6>[   72.258907 / 05-21 22:27:31.935][2] [<c010e400>] (unwind_backtrace) from [<c010b4a8>] (show_stack+0x10/0x14)
<6>[   72.258924 / 05-21 22:27:31.935][2] [<c010b4a8>] (show_stack) from [<c0fd0740>] (dump_stack+0x78/0x98)
<6>[   72.258940 / 05-21 22:27:31.935][2] [<c0fd0740>] (dump_stack) from [<c0115f8c>] (__do_user_fault+0x108/0x19c)
<6>[   72.258957 / 05-21 22:27:31.935][2] [<c0115f8c>] (__do_user_fault) from [<c0fe05b8>] (do_page_fault+0x33c/0x3e8)
<6>[   72.258972 / 05-21 22:27:31.935][2] [<c0fe05b8>] (do_page_fault) from [<c0100404>] (do_DataAbort+0x34/0x184)
<6>[   72.258986 / 05-21 22:27:31.935][2] [<c0100404>] (do_DataAbort) from [<c0fdec3c>] (__dabt_usr+0x3c/0x40)
<6>[   72.258997 / 05-21 22:27:31.935][2] Exception stack(0xd7f03fb0 to 0xd7f03ff8)
<6>[   72.259009 / 05-21 22:27:31.935][2] 3fa0:                                     71488688 00000000 71488688 131e3218
<6>[   72.259023 / 05-21 22:27:31.935][2] 3fc0: 00263c64 00000001 00000000 131e2bf0 00000000 92778200 71488688 131e3218
<6>[   72.259036 / 05-21 22:27:31.935][2] 3fe0: 00000000 885bc480 00000000 73a7c9c0 00070030 ffffffff 



#커널 크래시 디버깅 및 TroubleShooting

덧글

댓글 입력 영역