[BUG] KASAN: stack-out-of-bounds Write in cpu_init_exception_handling

From: Jaeyoung Chung

Date: Thu Aug 20 2026 - 05:46:58 EST


Hello,

We found a "KASAN: stack-out-of-bounds Write in cpu_init_exception_handling" on
Linux v7.2. The issue was found by our own race fuzzer. We have not analyzed the
root cause, so we do not have a proposed fix to offer.

To reproduce the race reliably, we applied the delay patch below to the
kernel and ran the C reproducer as root inside an x86_64 QEMU guest. The
crash log we observed, the delay patch and the reproducer are all included
below.

We used the syzbot kernel config, disabled the two options below, and built
it with clang-20:

https://syzkaller.appspot.com/text?tag=KernelConfig&x=1941312e3e971b07

./scripts/config --file .config --disable MODVERSIONS --disable GENDWARFKSYMS
make LLVM=1 olddefconfig

We could not reproduce this on a different config, so the report may depend on
the exact stack layout the syzbot config produces.

We hope this report is useful. Please let us know if any further
information would help.

Reported-by: Eulgyu Kim <eulgyukim@xxxxxxxxx>
Reported-by: Jaeyoung Chung <jjy600901@xxxxxxxxx>

Kernel delay patch:
==================================================================
diff --git a/kernel/cpu.c b/kernel/cpu.c
index b3c8553d7bd6..9eaea7b14027 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -17,6 +17,7 @@
#include <linux/oom.h>
#include <linux/rcupdate.h>
#include <linux/delay.h>
+#include <linux/sched.h>
#include <linux/export.h>
#include <linux/bug.h>
#include <linux/kthread.h>
@@ -833,6 +834,9 @@ static int cpuhp_bringup_ap(unsigned int cpu)
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
int ret;

+ if (!strncmp(current->comm, "syzrepro0", 9)) {
+ mdelay(80);
+ }
/*
* Some architectures have to walk the irq descriptors to
* setup the vector space for the cpu which comes online.
@@ -1385,6 +1389,9 @@ static int cpuhp_down_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,

ret = cpuhp_invoke_callback_range(false, cpu, st, target);
if (ret) {
+ if (!strncmp(current->comm, "syzrepro", 8)) {
+ mdelay(20);
+ }
pr_debug("CPU DOWN failed (%d) CPU %u state %s (%d)\n",
ret, cpu, cpuhp_get_step(st->state)->name,
st->state);

==================================================================

C reproducer:
==================================================================
#define _GNU_SOURCE
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>

#define SYSCHK(x) ({ long __r = (long)(x); if (__r == -1L) { perror(#x); exit(1); } __r; })

#define ONLINE "/sys/devices/system/cpu/cpu1/online"
#define STATE "/sys/devices/system/cpu/cpu1/hotplug/state"
#define FAIL "/sys/devices/system/cpu/cpu1/hotplug/fail"
#define STATES "/sys/devices/system/cpu/hotplug/states"

static int bringup;
static char failval[16];
static volatile int window, stop;

static int rd(const char *path, char *buf, size_t len)
{
int fd = SYSCHK(open(path, O_RDONLY));
int n = SYSCHK(read(fd, buf, len - 1));

close(fd);
buf[n] = 0;
return n;
}

static void wr(const char *path, const char *val)
{
int fd = SYSCHK(open(path, O_WRONLY));

write(fd, val, strlen(val));
close(fd);
}

static int state_id(const char *name)
{
char buf[8192], *line, *save, *c;
int id = -1;

rd(STATES, buf, sizeof(buf));
for (line = strtok_r(buf, "\n", &save); line;
line = strtok_r(NULL, "\n", &save)) {
c = strchr(line, ':');
if (c && !strcmp(c + 2, name))
id = atoi(line);
}
return id;
}

static void *arm_thread(void *arg)
{
char buf[64];

prctl(PR_SET_NAME, "syzrepro1", 0, 0, 0);
while (!stop) {
if (!window) {
usleep(300);
continue;
}
rd(STATE, buf, sizeof(buf));
if (atoi(buf) == bringup)
wr(FAIL, failval);
usleep(200);
}
return NULL;
}

int main(void)
{
pthread_t t1;
int i, fail_state;

prctl(PR_SET_NAME, "syzrepro0", 0, 0, 0);

bringup = state_id("cpu:bringup");
fail_state = state_id("timers:prepare");
if (bringup < 0 || fail_state < 0 || fail_state >= bringup) {
fprintf(stderr, "state lookup failed: bringup=%d fail=%d\n",
bringup, fail_state);
return 1;
}
snprintf(failval, sizeof(failval), "%d", fail_state);

wr(FAIL, "-1");
pthread_create(&t1, NULL, arm_thread, NULL);

for (i = 0; i < 200; i++) {
wr(ONLINE, "0");
window = 1;
wr(ONLINE, "1");
window = 0;
usleep(2000);
}

stop = 1;
pthread_join(t1, NULL);
return 0;
}
==================================================================

Crash log:
==================================================================
BUG: KASAN: stack-out-of-bounds in __set_tss_desc arch/x86/include/asm/desc.h:183 [inline]
BUG: KASAN: stack-out-of-bounds in cpu_init_exception_handling+0x301/0x950 arch/x86/kernel/cpu/common.c:2418
Write of size 16 at addr ffffc90000177ea0 by task swapper/1/0

CPU: 1 UID: 0 PID: 0 Comm: swapper/1 Not tainted 7.2.0-dirty #10 PREEMPT(full)
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
print_address_description+0x55/0x1e0 mm/kasan/report.c:378
print_report+0x64/0x70 mm/kasan/report.c:482
kasan_report+0x118/0x150 mm/kasan/report.c:595
check_region_inline mm/kasan/generic.c:-1 [inline]
kasan_check_range+0x2b0/0x2c0 mm/kasan/generic.c:200
__asan_memset+0x22/0x50 mm/kasan/shadow.c:84
__set_tss_desc arch/x86/include/asm/desc.h:183 [inline]
cpu_init_exception_handling+0x301/0x950 arch/x86/kernel/cpu/common.c:2418
start_secondary+0x17/0x110 arch/x86/kernel/smpboot.c:248
common_startup_64+0x13e/0x157
</TASK>

The buggy address belongs to stack of task swapper/1/0
and is located at offset 128 in frame:
cpu_init_exception_handling+0x0/0x950 arch/x86/include/asm/msr.h:-1

This frame has 5 objects:
[32, 42) 'gdt_descr.i8.i'
[64, 74) 'gdt_descr.i.i'
[96, 106) 'gdt.i'
[128, 144) 'tss.i'
[160, 168) 'd.i'

The buggy address belongs to a 8-page vmalloc region starting at 0xffffc90000170000 allocated at copy_process+0x7d9/0x3dc0 kernel/fork.c:2115
The buggy address belongs to the physical page:
page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x100697
flags: 0x57ff00000000000(node=1|zone=2|lastcpupid=0x7ff)
raw: 057ff00000000000 ffffea000401a5c8 ffffea000401a5c8 0000000000000000
raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 0, migratetype Unmovable, gfp_mask 0x29c2(GFP_NOWAIT|__GFP_HIGHMEM|__GFP_IO|__GFP_FS|__GFP_ZERO), pid 1, tgid 1 (swapper/0), ts 1601422137, free_ts 0
set_page_owner include/linux/page_owner.h:32 [inline]
post_alloc_hook+0x205/0x260 mm/page_alloc.c:1859
prep_new_page mm/page_alloc.c:1867 [inline]
get_page_from_freelist+0x2366/0x23f0 mm/page_alloc.c:3946
__alloc_frozen_pages_noprof+0x181/0x370 mm/page_alloc.c:5304
__alloc_pages_noprof+0x10/0x100 mm/page_alloc.c:5338
__alloc_pages_node_noprof include/linux/gfp.h:291 [inline]
alloc_pages_node_noprof include/linux/gfp.h:318 [inline]
vm_area_alloc_pages mm/vmalloc.c:3691 [inline]
__vmalloc_area_node mm/vmalloc.c:3914 [inline]
__vmalloc_node_range_noprof+0x7c7/0x1750 mm/vmalloc.c:4104
__vmalloc_node_noprof+0xc2/0x110 mm/vmalloc.c:4165
alloc_thread_stack_node kernel/fork.c:359 [inline]
dup_task_struct+0x2aa/0x910 kernel/fork.c:929
copy_process+0x7d9/0x3dc0 kernel/fork.c:2115
fork_idle+0xb3/0x240 kernel/fork.c:2658
idle_init kernel/smpboot.c:53 [inline]
idle_threads_init+0xd0/0x150 kernel/smpboot.c:72
smp_init+0x16/0x110 kernel/smp.c:1029
kernel_init_freeable+0x289/0x3e0 init/main.c:1650
kernel_init+0x1d/0x1d0 init/main.c:1548
ret_from_fork+0x509/0xb70 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
page_owner free stack trace missing

Memory state around the buggy address:
ffffc90000177d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffffc90000177e00: 00 00 00 00 f1 f1 f1 f1 00 02 f2 f2 00 02 f2 f2
>ffffc90000177e80: 00 02 f2 f2 00 f3 f2 f2 00 f3 f3 f3 00 00 00 00
^
ffffc90000177f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffffc90000177f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
==================================================================