🇰🇷 한글 설명
Linux 커널의 RCU 메커니즘에서 IRQ work 처리 중 rcu_read_unlock()이 데드락을 유발하는 취약점입니다. irq_exit() 과정 중에 rcu_read_unlock_special()이 호출되고 IPI(Inter-Processor Interrupt)가 발생하면 재귀적인 잠금 상태에 빠져 시스템이 멈출 수 있습니다.
💡 쉬운 설명
컴퓨터의 핵심 운영체제인 리눅스에서 특정 작업이 겹칠 때 시스템이 무한 루프에 빠져 멈춰버리는 문제입니다. 특히 특정 프로그램(BPF)을 사용할 때 시스템이 응답하지 않는 현상이 발생할 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
rcu: Fix rcu_read_unlock() deadloop due to IRQ work
During rcu_read_unlock_special(), if this happens during irq_exit(), we
can lockup if an IPI is issued. This is because the IPI itself triggers
the irq_exit() path causing a recursive lock up.
This is precisely what Xiongfeng found when invoking a BPF program on
the trace_tick_stop() tracepoint As shown in the trace below. Fix by
managing the irq_work state correctly.
irq_exit()
__irq_exit_rcu()
/* in_hardirq() returns false after this */
preempt_count_sub(HARDIRQ_OFFSET)
tick_irq_exit()
tick_nohz_irq_exit()
tick_nohz_stop_sched_tick()
trace_tick_stop() /* a bpf prog is hooked on this trace point */
__bpf_trace_tick_stop()
bpf_trace_run2()
rcu_read_unlock_special()
/* will send a IPI to itself */
irq_work_queue_on(&rdp->defer_qs_iw, rdp->cpu);
A simple reproducer can also be obtained by doing the following in
tick_irq_exit(). It will hang on boot without the patch:
static inline void tick_irq_exit(void)
{
+ rcu_read_lock();
+ WRITE_ONCE(current->rcu_read_unlock_special.b.need_qs, true);
+ rcu_read_unlock();
+
[neeraj: Apply Frederic's suggested fix for PREEMPT_RT]
📍 영향받는 시스템
Linux Kernel (RCU 및 IRQ work 관련 모듈 사용 시스템)
⚔️ 공격 벡터
BPF 프로그램을 사용하여 trace_tick_stop() 트레이스포인트에 훅을 걸어 특정 상황을 유도함으로써 시스템 중단 유발
🛡️ 대응 방법
Linux 커널을 최신 보안 패치가 적용된 버전으로 업데이트하여 irq_work 상태 관리 로직을 수정해야 함
🔧 검증 코드
출력된 커널 버전이 해당 취약점이 해결된 패치 버전 이후인지 확인