🇰🇷 한글 설명
Linux 커널의 qcom_geni 시리얼 드라이버에서 DMA 완료 인터럽트가 전달되기 전에 버퍼를 비울 경우 kfifo 언더플로우가 발생하는 취약점입니다. 이 레이스 컨디션으로 인해 kfifo의 인덱스가 꼬이게 되어, 다음 DMA 전송 시 오래된 버퍼 데이터가 전송될 수 있습니다.
💡 쉬운 설명
데이터를 전송하는 도중에 갑자기 전송 취소 명령이 내려지면, 시스템 내부의 데이터 기록 위치가 엉뚱한 곳을 가리키게 되는 문제입니다. 이로 인해 이전에 보냈어야 할 잘못된 데이터가 다시 전송되는 오류가 발생할 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
serial: qcom_geni: fix kfifo underflow when flush precedes DMA completion IRQ
When uart_flush_buffer() runs before the DMA completion IRQ is delivered,
the following race can occur (all steps serialized by uart_port_lock):
1. DMA starts: tx_remaining = N, kfifo contains N bytes
2. DMA completes in hardware; IRQ is pending but not yet delivered
3. uart_flush_buffer() acquires the port lock and calls kfifo_reset(),
making kfifo_len() = 0 while tx_remaining remains N
4. uart_flush_buffer() releases the port lock
5. DMA IRQ fires; handle_tx_dma() acquires the port lock and calls
uart_xmit_advance(uport, tx_remaining) on an empty kfifo
uart_xmit_advance() increments kfifo->out by tx_remaining. Since
kfifo_reset() already set both in and out to 0, out wraps past in,
causing kfifo_len() to return UART_XMIT_SIZE - tx_remaining. The next
start_tx_dma() call then submits a DMA transfer of stale buffer data.
Fix this by snapshotting kfifo_len() at the start of handle_tx_dma()
and skipping uart_xmit_advance() when fifo_len < tx_remaining, which
indicates the kfifo was reset by a preceding flush.
📍 영향받는 시스템
Qualcomm GENI 기반 시리얼 드라이버를 사용하는 Linux 커널 시스템
⚔️ 공격 벡터
특정 타이밍에 DMA 완료 전 버퍼를 비우는(flush) 동작을 유도하여 레이스 컨디션 발생
🛡️ 대응 방법
해당 취약점이 수정된 최신 Linux 커널 버전으로 업데이트
🔧 검증 코드
출력된 커널 버전이 해당 취약점이 패치된 버전인지 배포판 보안 공지를 통해 확인