🇰🇷 한글 설명
Linux 커널의 ks8851 네트워크 드라이버에서 IRQ 스레드 처리 중 소프트인터럽트(softirq)가 발생하여 시스템이 멈추는(hang) 취약점입니다. ks8851_irq() 함수가 스핀락을 보유한 상태에서 netif_rx()를 호출하고, 이 과정에서 다시 동일한 스핀락을 요청하게 되어 데드락이 발생합니다.
💡 쉬운 설명
네트워크 카드가 데이터를 처리하는 과정에서 시스템이 스스로를 잠가버려 컴퓨터가 멈추는 현상입니다. 특정 네트워크 장치를 사용할 때 데이터가 들어오면 시스템이 응답하지 않을 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
net: ks8851: Handle softirqs at the end of IRQ thread to fix hang
The ks8851_irq() thread may call ks8851_rx_pkts() in case there are
any packets in the MAC FIFO, which calls netif_rx(). This netif_rx()
implementation is guarded by local_bh_disable() and local_bh_enable().
The local_bh_enable() may call do_softirq() to run softirqs in case
any are pending. One of the softirqs is net_rx_action, which ultimately
reaches the driver .start_xmit callback. If that happens, the system
hangs. The entire call chain is below:
ks8851_start_xmit_par from netdev_start_xmit
netdev_start_xmit from dev_hard_start_xmit
dev_hard_start_xmit from sch_direct_xmit
sch_direct_xmit from __dev_queue_xmit
__dev_queue_xmit from __neigh_update
__neigh_update from neigh_update
neigh_update from arp_process.constprop.0
arp_process.constprop.0 from __netif_receive_skb_one_core
__netif_receive_skb_one_core from process_backlog
process_backlog from __napi_poll.constprop.0
__napi_poll.constprop.0 from net_rx_action
net_rx_action from __do_softirq
__do_softirq from call_with_stack
call_with_stack from do_softirq
do_softirq from __local_bh_enable_ip
__local_bh_enable_ip from netif_rx
netif_rx from ks8851_irq
ks8851_irq from irq_thread_fn
irq_thread_fn from irq_thread
irq_thread from kthread
kthread from ret_from_fork
The hang happens because ks8851_irq() first locks a spinlock in
ks8851_par.c ks8851_lock_par() spin_lock_irqsave(&ksp->lock, ...)
and with that spinlock locked, calls netif_rx(). Once the execution
reaches ks8851_start_xmit_par(), it calls ks8851_lock_par() again
which attempts to claim the already locked spinlock again, and the
hang happens.
Move the do_softirq() call outside of the spinlock protected section
of ks8851_irq() by disabling BHs around the entire spinlock protected
section of ks8851_irq() handler. Place local_bh_enable() outside of
the spinlock protected section, so that it can trigger do_softirq()
without the ks8851_par.c ks8851_lock_par() spinlock being held, and
safely call ks8851_start_xmit_par() without attempting to lock the
already locked spinlock.
Since ks8851_irq() is protected by local_bh_disable()/local_bh_enable()
now, replace netif_rx() with __netif_rx() which is not duplicating the
local_bh_disable()/local_bh_enable() calls.
📍 영향받는 시스템
ks8851 네트워크 드라이버를 사용하는 Linux 커널 시스템
⚔️ 공격 벡터
네트워크 패킷 유입을 통한 데드락 유도 (로컬/원격 패킷 유입)
🛡️ 대응 방법
ks8851_irq() 핸들러 내의 스핀락 보호 구간 외부로 softirq 호출을 이동시키고, netif_rx()를 __netif_rx()로 교체하는 커널 패치 적용
🔧 검증 코드
현재 실행 중인 커널 버전을 확인하여 해당 취약점이 해결된 최신 보안 패치 버전인지 확인합니다.