🇰🇷 한글 설명
Linux 커널의 BPF 기능에서 NMI 및 tracepoint 프로그램이 LRU 락을 재진입하여 발생하는 데드락 취약점입니다. 이 문제는 동일한 CPU에서 이미 보유 중인 락을 다시 요청함으로써 시스템이 멈추는 현상을 유발합니다. 이를 해결하기 위해 LRU 락을 rqspinlock_t로 전환하고 다양한 실패 복구 경로를 추가했습니다.
💡 쉬운 설명
컴퓨터의 핵심 운영체제인 리눅스에서 특정 프로그램이 실행될 때, 시스템이 서로를 기다리며 멈춰버리는 '교착 상태' 오류가 발생할 수 있습니다. 이 오류가 발생하면 시스템이 응답하지 않거나 완전히 멈출 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
bpf: Fix NMI/tracepoint re-entry deadlock on lru locks
NMI and tracepoint BPF programs can re-enter the per-CPU or global
LRU lock that bpf_lru_pop_free()/push_free() already hold on the
same CPU, AA-deadlocking. Lockdep reports "inconsistent
{INITIAL USE} -> {IN-NMI}" on &l->lock (syzbot c69a0a2c816716f1e0d5)
and "possible recursive locking detected" on &loc_l->lock (syzbot
18b26edb69b2e19f3b33).
Prior trylock and rqspinlock based fixes (see links) were nacked
because compromised on reliability.
This patch converts every LRU lock site to rqspinlock_t and adds a
recovery path for some failure windows to avoid node leaks.
Failure recovery:
- *_pop_free top-level: return NULL; prealloc_lru_pop() already
treats that as no-free-element (-ENOMEM).
- Cross-CPU steal: skip the victim's locked loc_l, try next CPU.
- Post-steal local lock fail: publish stolen node to lockless
per-CPU free_llist; next pop on this CPU picks it up.
- push_free fail: mark node pending_free=1. __local_list_flush(),
__local_list_pop_pending() reclaim the node from pending_list.
__bpf_lru_list_shrink_inactive() reclaims the node from inactive
list. Nodes from active list are reclaimed by __bpf_lru_list_shrink()
or after __bpf_lru_list_rotate_active() demotes it to the inactive.
📍 영향받는 시스템
NMI 및 tracepoint BPF 프로그램을 사용하는 Linux 커널 버전
⚔️ 공격 벡터
특정 BPF 프로그램을 실행하여 커널 내의 LRU 락 재진입을 유도함으로써 시스템 데드락 발생
🛡️ 대응 방법
LRU 락을 rqspinlock_t로 전환하고 복구 로직이 포함된 최신 커널 패치를 적용
🔧 검증 코드
출력된 커널 버전이 해당 취약점이 패치된 최신 버전인지 확인