🇰🇷 한글 설명
Linux 커널의 IIO(Industrial I/O) 버퍼 기능에서 dma_fence 객체가 적절히 해제되지 않는 메모리 누수 취약점이 발견되었습니다. iio_buffer_enqueue_dmabuf() 함수가 초기 참조 횟수를 해제하지 않아, 버퍼를 인큐할 때마다 kmalloc-128 할당량이 영구적으로 누수됩니다.
💡 쉬운 설명
데이터를 처리하는 과정에서 사용한 메모리 자원을 시스템에 돌려주지 않고 계속 붙잡고 있는 문제입니다. 이 현상이 지속되면 시스템의 메모리가 점차 고갈되어 결국 컴퓨터가 느려지거나 멈출 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
iio: buffer: Fix DMA fence leak in iio_buffer_enqueue_dmabuf()
iio_buffer_enqueue_dmabuf() allocates a struct iio_dma_fence (104 bytes,
kmalloc-128) via kmalloc_obj()+dma_fence_init(), which sets the initial
kref to 1. It then calls dma_resv_add_fence() which takes a second
reference (kref=2), and stores a raw pointer in block->fence.
On the success path the function returns without calling dma_fence_put()
to release the initial reference, so every buffer enqueue permanently
leaks one kmalloc-128 allocation.
The iio_buffer_cleanup() work item only releases the temporary reference
taken during completion signalling by iio_buffer_signal_dmabuf_done();
the initial reference from dma_fence_init() is never released.
With four iio_rwdev instances at 240kHz and 512 samples per buffer,
this produces ~1875 kmalloc-128 allocations per second matching the
observed slab growth exactly. A test with ftrace confirmed that the
dma_fence_destroy event was never triggered.
Fix by calling dma_fence_put() after dma_resv_add_fence(), transferring
ownership of the fence to the DMA reservation object. The DMA fence then
gets properly discarded after being signalled.
📍 영향받는 시스템
Linux kernel (IIO subsystem 사용 환경)
⚔️ 공격 벡터
로컬 공격자가 IIO 장치를 통해 지속적으로 버퍼 인큐 작업을 수행하여 메모리 고갈 유도
🛡️ 대응 방법
커널 패치를 적용하여 dma_resv_add_fence() 호출 후 dma_fence_put()을 호출하도록 수정
🔧 검증 코드
커널 소스 내 해당 함수 존재 여부를 확인하고, slabtop을 통해 kmalloc-128 슬랩 메모리가 지속적으로 증가하는지 모니터링합니다.
grep -r "iio_buffer_enqueue_dmabuf" /lib/modules/$(uname -r)/kernel/drivers/iio/ && slabtop -o | grep kmalloc-128