🇰🇷 한글 설명
Linux 커널의 mt76 드라이버 내 mt7921 모듈에서 SDIO 헤더를 위한 충분한 헤드룸을 가정하여 발생하는 취약점입니다. 브리지 레이어를 통해 다른 네트워크 장치로부터 전달된 skb를 처리할 때 헤드룸이 부족하면 커널 패닉이 발생할 수 있습니다.
💡 쉬운 설명
네트워크 데이터를 처리할 때 필요한 여유 공간을 확인하지 않고 데이터를 덧붙이다가 시스템이 멈추는 문제입니다. 특정 네트워크 장치들을 서로 연결(브리지)하여 사용할 때 컴퓨터가 갑자기 꺼지거나 재부팅될 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
mt76: mt7921: don't assume adequate headroom for SDIO headers
mt7921_usb_sdio_tx_prepare_skb() calls mt7921_usb_sdio_write_txwi() and
mt7921_skb_add_usb_sdio_hdr(), both of which blindly assume that
adequate headroom will be available in the passed skb. This assumption
typically is satisfied when the skb was allocated in the net core for
transmission via the mt7921 netdev (although even that is only an
optimization and is not strictly guaranteed), but the assumption is
sometimes not satisfied when the skb originated in the receive path of
another netdev and was passed through to the mt7921, such as by the
bridge layer. Blindly prepending bytes to an skb is always wrong.
This commit introduces a call to skb_cow_head() before the call to
mt7921_usb_sdio_write_txwi() in mt7921_usb_sdio_tx_prepare_skb() to
ensure that at least MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE bytes can be
pushed onto the skb.
Without this fix, I can trivially cause kernel panics by bridging an
MT7921AU-based USB 802.11ax interface with an Ethernet interface on an
Intel Atom-based x86 system using its onboard RTL8169 PCI Ethernet
adapter and also on an ARM-based Raspberry Pi 1 using its onboard
SMSC9512 USB Ethernet adapter. Note that the panics do not occur in
every system configuration, as they occur only if the receiving netdev
leaves less headroom in its received skbs than the mt7921 needs for its
SDIO headers.
Here is an example stack trace of this panic on Raspberry Pi OS Lite
2023-02-21 running kernel 6.1.24+ [1]:
skb_panic from skb_push+0x44/0x48
skb_push from mt7921_usb_sdio_tx_prepare_skb+0xd4/0x190 [mt7921_common]
mt7921_usb_sdio_tx_prepare_skb [mt7921_common] from mt76u_tx_queue_skb+0x94/0x1d0 [mt76_usb]
mt76u_tx_queue_skb [mt76_usb] from __mt76_tx_queue_skb+0x4c/0xc8 [mt76]
__mt76_tx_queue_skb [mt76] from mt76_txq_schedule.part.0+0x13c/0x398 [mt76]
mt76_txq_schedule.part.0 [mt76] from mt76_txq_schedule_all+0x24/0x30 [mt76]
mt76_txq_schedule_all [mt76] from mt7921_tx_worker+0x58/0xf4 [mt7921_common]
mt7921_tx_worker [mt7921_common] from __mt76_worker_fn+0x9c/0xec [mt76]
__mt76_worker_fn [mt76] from kthread+0xbc/0xe0
kthread from ret_from_fork+0x14/0x34
After this fix, bridging the mt7921 interface works fine on both of my
previously problematic systems.
[1] https://github.com/raspberrypi/firmware/tree/5c276f55a4b21345cd4d6200a504ee991851ff7a
📍 영향받는 시스템
mt7921 드라이버를 사용하는 Linux 커널 기반 시스템 (특히 Raspberry Pi 및 Intel Atom 기반 시스템)
⚔️ 공격 벡터
MT7921 기반 USB Wi-Fi 인터페이스와 다른 이더넷 인터페이스를 브리지로 연결하여 특정 네트워크 트래픽을 유도함
🛡️ 대응 방법
skb_cow_head() 호출이 포함된 최신 Linux 커널로 업데이트하여 헤드룸 확보 로직을 적용함
🔧 검증 코드
출력된 커널 버전이 해당 취약점이 수정된 패치가 적용된 버전인지 확인합니다.