🇰🇷 한글 설명
리눅스 커널의 mm/memory-failure 구성 요소에서 hugetlb_lock과 관련된 AA 데드락 취약점이 발견되었습니다. 두 개의 madvise(MADV_HWPOISON) 호출이 동시에 발생하고 unmap 작업이 경합할 경우, 재귀적 스핀락 획득 시도로 인해 시스템이 멈출 수 있습니다.
💡 쉬운 설명
컴퓨터의 메모리를 관리하는 과정에서 두 가지 작업이 동시에 충돌하여 시스템이 무한 대기 상태에 빠지는 문제입니다. 이로 인해 시스템이 응답하지 않거나 멈추는 현상이 발생할 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison
Two concurrent madvise(MADV_HWPOISON) calls on the same hugetlb page can
trigger a recursive spinlock self-deadlock (AA deadlock) on hugetlb_lock
when racing with a concurrent unmap:
thread#0 thread#1
-------- --------
madvise(folio, MADV_HWPOISON)
-> poisons the folio successfully
madvise(folio, MADV_HWPOISON) unmap(folio)
try_memory_failure_hugetlb
get_huge_page_for_hwpoison
spin_lock_irq(&hugetlb_lock) <- held
__get_huge_page_for_hwpoison
hugetlb_update_hwpoison()
-> MF_HUGETLB_FOLIO_PRE_POISONED
goto out:
folio_put()
refcount: 1 -> 0
free_huge_folio()
spin_lock_irqsave(&hugetlb_lock)
-> AA DEADLOCK!
The out: path in __get_huge_page_for_hwpoison() calls folio_put() to drop
the GUP reference while the hugetlb_lock is still held by the hugetlb.c
wrapper get_huge_page_for_hwpoison(). If concurrent unmap has released
the page table mapping reference, folio_put() drops the folio refcount to
zero, triggering free_huge_folio() which attempts to re-acquire the
non-recursive hugetlb_lock.
Fix this by moving hugetlb_lock acquisition from the hugetlb.c wrapper
into get_huge_page_for_hwpoison(). Place spin_unlock_irq() before the
folio_put() at the out: label so the folio is always released outside the
lock.
[
[email protected]: fix race, rename label per Miaohe]
📍 영향받는 시스템
Linux Kernel (hugetlb 관련 메모리 관리 모듈 사용 시스템)
⚔️ 공격 벡터
동시에 madvise(MADV_HWPOISON) 호출과 unmap 작업을 수행하는 로컬 프로세스 경합
🛡️ 대응 방법
리눅스 커널을 최신 보안 패치가 적용된 버전으로 업데이트하여 hugetlb_lock 획득 시점을 수정해야 합니다.
🔧 검증 코드
출력된 커널 버전을 확인하여 해당 취약점이 해결된 패치 버전인지 확인합니다.