🇰🇷 한글 설명
Linux 커널의 ARM 아키텍처에서 DEBUG_KMAP_LOCAL 옵션이 활성화된 경우, CPU 개수가 많으면 fixmap 영역이 예약된 범위를 벗어나 가상 DT 매핑 영역과 충돌하는 취약점입니다. 이로 인해 커널이 잘못된 주소를 참조하여 페이지 결함(paging request) 및 시스템 오류(Oops)를 유발할 수 있습니다.
💡 쉬운 설명
시스템의 특정 디버깅 기능이 켜져 있을 때, 컴퓨터의 두뇌(CPU) 개수가 너무 많으면 메모리 관리 영역이 서로 겹쳐서 시스템이 갑자기 멈추거나 오류가 발생할 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
ARM: 9063/1: mm: reduce maximum number of CPUs if DEBUG_KMAP_LOCAL is enabled
The debugging code for kmap_local() doubles the number of per-CPU fixmap
slots allocated for kmap_local(), in order to use half of them as guard
regions. This causes the fixmap region to grow downwards beyond the start
of its reserved window if the supported number of CPUs is large, and collide
with the newly added virtual DT mapping right below it, which is obviously
not good.
One manifestation of this is EFI boot on a kernel built with NR_CPUS=32
and CONFIG_DEBUG_KMAP_LOCAL=y, which may pass the FDT in highmem, resulting
in block entries below the fixmap region that the fixmap code misidentifies
as fixmap table entries, and subsequently tries to dereference using a
phys-to-virt translation that is only valid for lowmem. This results in a
cryptic splat such as the one below.
ftrace: allocating 45548 entries in 89 pages
8<--- cut here ---
Unable to handle kernel paging request at virtual address fc6006f0
pgd = (ptrval)
[fc6006f0] *pgd=80000040207003, *pmd=00000000
Internal error: Oops: a06 [#1] SMP ARM
Modules linked in:
CPU: 0 PID: 0 Comm: swapper Not tainted 5.11.0+ #382
Hardware name: Generic DT based system
PC is at cpu_ca15_set_pte_ext+0x24/0x30
LR is at __set_fixmap+0xe4/0x118
pc : [<c041ac9c>] lr : [<c04189d8>] psr: 400000d3
sp : c1601ed8 ip : 00400000 fp : 00800000
r10: 0000071f r9 : 00421000 r8 : 00c00000
r7 : 00c00000 r6 : 0000071f r5 : ffade000 r4 : 4040171f
r3 : 00c00000 r2 : 4040171f r1 : c041ac78 r0 : fc6006f0
Flags: nZcv IRQs off FIQs off Mode SVC_32 ISA ARM Segment none
Control: 30c5387d Table: 40203000 DAC: 00000001
Process swapper (pid: 0, stack limit = 0x(ptrval))
So let's limit CONFIG_NR_CPUS to 16 when CONFIG_DEBUG_KMAP_LOCAL=y. Also,
fix the BUILD_BUG_ON() check that was supposed to catch this, by checking
whether the region grows below the start address rather than above the end
address.
📍 영향받는 시스템
Linux kernel (ARM architecture) with CONFIG_DEBUG_KMAP_LOCAL=y and high NR_CPUS
⚔️ 공격 벡터
Local (시스템 설정 및 커널 구성에 따른 메모리 충돌 유발)
🛡️ 대응 방법
커널 패치를 적용하여 DEBUG_KMAP_LOCAL 활성화 시 NR_CPUS를 16으로 제한하거나, 메모리 영역 검증 로직을 수정해야 합니다.
🔧 검증 코드
출력 결과에서 CONFIG_DEBUG_KMAP_LOCAL가 y이고 CONFIG_NR_CPUS가 16보다 큰지 확인합니다.
zgrep -E 'CONFIG_DEBUG_KMAP_LOCAL|CONFIG_NR_CPUS' /proc/config.gz 2>/dev/null || grep -E 'CONFIG_DEBUG_KMAP_LOCAL|CONFIG_NR_CPUS' /boot/config-$(uname -r)