🇰🇷 한글 설명
Linux 커널의 x86 32비트 환경에서 THP(Transparent Huge Pages) 활성화 시, pmd_special/pud_special 지원 누락으로 인해 메모리 관리 오류가 발생합니다. 이로 인해 커널 경고(WARNING) 및 시스템 버그(BUG: Bad rss-counter state)가 발생하여 시스템 안정성이 저해될 수 있습니다.
💡 쉬운 설명
컴퓨터의 메모리를 관리하는 과정에서 특정 설정이 제대로 작동하지 않아 시스템이 혼란을 겪는 문제입니다. 이로 인해 컴퓨터가 갑자기 멈추거나 오류 메시지를 내뱉으며 불안정해질 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
mm: fix __vm_normal_page() to handle missing support for pmd_special()/pud_special()
On x86 32-bit with THP enabled, zap_huge_pmd() is seen to generate a
"WARNING: mm/memory.c:735 at __vm_normal_page+0x6a/0x7d", from the
VM_WARN_ON_ONCE(is_zero_pfn(pfn) || is_huge_zero_pfn(pfn)); followed by
"BUG: Bad rss-counter state"s, then later "BUG: Bad page state"s when
reclaim gets to call shrink_huge_zero_folio_scan().
It's as if the _PAGE_SPECIAL bit never got set in the huge_zero pmd: and
indeed, whereas pte_special() and pte_mkspecial() are subject to a
dedicated CONFIG_ARCH_HAS_PTE_SPECIAL, pmd_special() and pmd_mkspecial()
are subject to CONFIG_ARCH_SUPPORTS_PMD_PFNMAP, which is never enabled on
any 32-bit architecture.
While the problem was exposed through commit d80a9cb1a64a
("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()"), it was an
oversight in commit af38538801c6 ("mm/memory: factor out common code from
vm_normal_page_*()") and would result in other problems:
* huge zero folio accounted in smaps, pagemap (PAGE_IS_FILE) and
numamaps as file-backed THP
* folio_walk_start() returning the folio even without FW_ZEROPAGE set.
Callers seem to tolerate that, though.
... and triggering the VM_WARN_ON_ONE(), although never reported so far.
To fix it, teach vm_normal_page_pmd()/vm_normal_page_pud() to consider
whether pmd_special/pud_special is actually implemented.
📍 영향받는 시스템
THP가 활성화된 x86 32-bit 아키텍처 기반의 Linux 커널
⚔️ 공격 벡터
로컬 시스템에서 메모리 관리 로직의 결함을 유도하여 시스템 불안정성 또는 커널 패닉 유발
🛡️ 대응 방법
커널 패치를 적용하여 vm_normal_page_pmd/pud 함수가 pmd_special/pud_special 구현 여부를 확인하도록 업데이트
🔧 검증 코드
커널 버전과 해당 설정의 활성화 여부를 확인하여 취약한 환경인지 판단합니다.
uname -a && grep -i 'CONFIG_ARCH_SUPPORTS_PMD_PFNMAP' /boot/config-$(uname -r) 2>/dev/null