🇰🇷 한글 설명
Linux 커널의 qbman 드라이버에서 qman_destroy_fq() 함수의 race condition 취약점으로, QMAN_FQ_FLAG_DYNAMIC_FQID 설정 시 멀티스레딩 환경에서 fqid가 동시에 해제 및 재할당될 수 있습니다. 이는 fq_table 상태 불일치를 초래하며, 메모리 배리어(smp_wmb)를 통한 접근 순서 제어로 수정됩니다.
💡 쉬운 설명
Linux 운영체제의 큐 관리 시스템에서 여러 프로세스가 동시에 같은 자원을 사용할 때 발생하는 동시성 문제입니다. 메모리 접근 순서를 명확히 제어하여 한 프로세스가 완전히 해제한 후에만 다른 프로세스가 재할당하도록 보장합니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
soc: fsl: qbman: fix race condition in qman_destroy_fq
When QMAN_FQ_FLAG_DYNAMIC_FQID is set, there's a race condition between
fq_table[fq->idx] state and freeing/allocating from the pool and
WARN_ON(fq_table[fq->idx]) in qman_create_fq() gets triggered.
Indeed, we can have:
Thread A Thread B
qman_destroy_fq() qman_create_fq()
qman_release_fqid()
qman_shutdown_fq()
gen_pool_free()
-- At this point, the fqid is available again --
qman_alloc_fqid()
-- so, we can get the just-freed fqid in thread B --
fq->fqid = fqid;
fq->idx = fqid * 2;
WARN_ON(fq_table[fq->idx]);
fq_table[fq->idx] = fq;
fq_table[fq->idx] = NULL;
And adding some logs between qman_release_fqid() and
fq_table[fq->idx] = NULL makes the WARN_ON() trigger a lot more.
To prevent that, ensure that fq_table[fq->idx] is set to NULL before
gen_pool_free() is called by using smp_wmb().
📍 영향받는 시스템
Linux kernel with Freescale QorIQ SOC QMAN driver (qbman) enabled with QMAN_FQ_FLAG_DYNAMIC_FQID support
⚔️ 공격 벡터
Local privilege escalation or DoS through malicious parallel queue create/destroy operations exploiting race condition in fq_table management
🛡️ 대응 방법
Update to patched Linux kernel version with smp_wmb() memory barrier added before fq_table[fq->idx] = NULL in qman_destroy_fq()
🔧 검증 코드
커널 설정이나 바이너리에 smp_wmb 메모리 배리어가 포함되어 있으면 패치가 적용된 것입니다. 명령어가 결과를 반환하지 않으면 취약한 커널입니다.
grep -n 'smp_wmb' /boot/config-$(uname -r) 2>/dev/null || strings /boot/vmlinuz-$(uname -r) | grep -q smp_wmb && echo 'Barrier present'