🇰🇷 한글 설명
리눅스 커널의 tracing 기능 중 func_set_flag() 함수에서 NULL 포인터 역참조 취약점이 발견되었습니다. 현재 트레이서가 function 트레이서인지 확인하기 전에 current_trace_flags를 참조하여, 트레이서가 변경된 상태에서 옵션을 수정하려 할 경우 커널 크래시가 발생할 수 있습니다.
💡 쉬운 설명
리눅스 시스템의 기록 기능을 사용하는 과정에서 순서가 잘못되어 컴퓨터가 갑자기 멈추거나 꺼질 수 있는 오류입니다. 특정 설정 파일을 건드릴 때 시스템이 예상치 못한 빈 값을 참조하여 발생합니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
tracing: Fix NULL pointer dereference in func_set_flag()
func_set_flag() dereferences tr->current_trace_flags before verifying
that the current tracer is actually the function tracer. When the active
tracer has been switched away from "function" (e.g., to "wakeup_rt"),
tr->current_trace_flags can be NULL, leading to a NULL pointer
dereference and kernel crash.
The call chain that triggers this is:
trace_options_write()
-> __set_tracer_option()
-> trace->set_flag() /* func_set_flag */
In func_set_flag(), the first operation is:
if (!!set == !!(tr->current_trace_flags->val & bit))
This dereferences tr->current_trace_flags unconditionally. The safety
check that guards against a non-function tracer:
if (tr->current_trace != &function_trace)
return 0;
is placed *after* the dereference, which is too late.
This was observed with the following crash dump:
BUG: unable to handle page fault at 0000000000000000
RIP: func_set_flag+0xd
Call Trace:
__set_tracer_option+0x27
trace_options_write+0x75
vfs_write+0x12a
ksys_write+0x66
do_syscall_64+0x5b
RIP: ffffffff914c973d RSP: ff67ec88b01dfdf0 RFLAGS: 00010202
RAX: 0000000000000000 RBX: ff3a826e80354580 RCX: 0000000000000001
RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffffffff93918080
The disassembly confirms the fault:
func_set_flag+0: mov 0x1f08(%rdi), %rax ; RAX = tr->current_trace_flags = NULL
func_set_flag+13: mov (%rax), %eax ; page fault: dereference NULL
At the time of the crash:
tr->current_trace_flags = 0x0 (NULL)
tr->current_trace = wakeup_rt_tracer (not function_trace)
The scenario is that a process opens a function tracer option file (such
as "func_stack_trace"), then the current tracer is switched to another
tracer (e.g., "wakeup_rt"), which sets current_trace_flags to NULL. When
the process subsequently writes to the option file, func_set_flag() is
invoked and crashes on the NULL dereference.
Fix this by moving the current_trace check before the
current_trace_flags dereference, so that func_set_flag() returns early
when the function tracer is not active.
📍 영향받는 시스템
Linux Kernel (tracing 기능이 활성화된 버전)
⚔️ 공격 벡터
로컬 사용자가 function tracer 관련 옵션 파일에 쓰기 작업을 수행하여 커널 패닉 유도
🛡️ 대응 방법
리눅스 커널을 최신 보안 패치가 적용된 버전으로 업데이트하여 func_set_flag() 내 검증 로직 순서 수정
🔧 검증 코드
출력된 커널 버전을 확인하여 해당 취약점이 해결된 패치 버전인지 확인합니다.