[PATCH 0/2] x86/cacheinfo: Fix slab-out-of-bounds write on hybrid/VM topologies

From: Yunseong Kim

Date: Thu Aug 27 2026 - 20:02:49 EST


__cache_cpumap_setup() and __cache_amd_cpumap_setup() address a sibling
CPU's cacheinfo array using *this* CPU's leaf index, guarded only by a NULL
check on info_list:

sibling_ci = sib_cpu_ci->info_list + index;
cpumask_set_cpu(cpu, &sibling_ci->shared_cpu_map); /* OOB */

Since commit 9677be09e5e4 ("x86/cacheinfo: Delete global num_cache_leaves")
the leaf count is per-CPU, so a sibling can have fewer leaves, and the write
goes past the end of its array. The generic implementation in
drivers/base/cacheinfo.c was already fixed for this exact scenario in commit
198102c9103f ("cacheinfo: Fix shared_cpu_map to handle shared caches at
different levels", CVE-2023-53254); the x86 parallel implementation was
missed.

It is reachable from userspace. populate_cache_leaves() runs in the
CPUHP_AP_BASE_CACHEINFO_ONLINE callback, so a write(2) to
/sys/devices/system/cpu/cpuN/online triggers it. On an affected
configuration it also fires unconditionally at boot during AP bring-up.

Observed on an Intel Core Ultra 7 268V (Lunar Lake) host under crosvm
[1] during my syzkaller work with crosvm [2] The host P-cores enumerate
4 cache leaves and E-cores enumerate 3. crosvm evaluates CPUID leaf
4 per vCPU by executing the instruction inline on whichever host CPU
the vCPU thread is pinned to, so two vCPUs can see different leaf counts
while leaf 0xB/0x1F still presents them as SMT siblings. This creates
the mismatch that the missing bounds check turns into memory corruption.
QEMU does not reproduce it because it computes one CPUID set for all vCPUs.

The bug is also one APIC-ID assignment away from firing on bare metal: a
hybrid part whose different core types land in the same apicid >> index_msb
window reaches this with no VMM involved. On the Lunar Lake host used here,
only the fact that E-core APIC IDs (64+) fall in a different window from
P-core IDs (0-24) prevents it on bare metal.

Patches
=======

1/2: Bounds-check sibling leaf indexing — the minimal containment that
stops the OOB write. Skips siblings whose array is too short.

2/2: Match sibling leaves by level and type, not by index — removes the
index-alignment assumption itself. Mirrors what the generic code
does. Also fixes the subtler problem of cross-linking the wrong
cache when indexes are in range but describe different caches.

Both patches are split for stable backport clarity: 1/2 is the fix with
minimal code change, 2/2 is the correct long-term solution.

Tested with crosvm on the Lunar Lake host, using the deterministic
reproducer [3]:

- Unpatched: crosvm, --cpu-affinity 0=4:1=0 (E-core/P-core), maxcpus=1
echo 1 > /sys/devices/system/cpu/cpu1/online -> KASAN slab-out-of-bounds
write in populate_cache_leaves(), allocated 3264 bytes, write 32 bytes
past the end. Reproduces every run.

- Patched (this series): same configuration, same leaf mismatch confirmed
present, zero KASAN reports.

The cacheinfo-oob-predict tool replays the kernel's sibling test from CPUID
data in userspace and predicts the exact write offset before triggering. The
prediction matched the KASAN report byte-for-byte:

allocated region : predicted 3264, reported 3264 MATCH
bytes to the right: predicted 32, reported 32 MATCH

crosvm's per-vCPU CPUID sampling is a separate bug that should be addressed
by normalising CPUID leaf 4 across vCPUs. That is a crosvm issue and does
not affect the kernel fix.

Links
=====

[1] crosvm: https://github.com/google/crosvm

[2] Developing syzkaller with crosvm instead of QEMU:
https://github.com/google/syzkaller/pull/7747

[3] Reproducer:
https://gist.github.com/yskzalloc/5acfdef88e6354dc047604c9883faa8b

Signed-off-by: Yunseong Kim <yunseong.kim@xxxxxxxx>
---
Yunseong Kim (2):
x86/cacheinfo: Bounds-check sibling leaf indexing
x86/cacheinfo: Match sibling leaves by level and type, not by index

arch/x86/kernel/cpu/cacheinfo.c | 68 ++++++++++++++++++++++++++++++-----------
1 file changed, 51 insertions(+), 17 deletions(-)
---
base-commit: 73e3f0710014fe6d4ed98cfc02292f6121db7558
change-id: 20260828-b4-cacheinfo-7779d15fd837

Best regards,
--
Yunseong Kim <yunseong.kim@xxxxxxxx>