KASAN: stack-out-of-bounds Read in sched_show_task (2)

Status: moderation: reported on 2026/09/10 08:38
Subsystems: mm
Labels: prio:high
[Documentation on labels]
Reported-by: syzbot+1802b160d708716c9c98@syzkaller.appspotmail.com
First crash: 66d, last: 66d
✨ AI-generated root cause summary:

In arch/riscv/kernel/stacktrace.c, the macro READ_ONCE_TASK_STACK(task, x) is intended to read frame pointers and return addresses from another task's stack without KASAN instrumentation using READ_ONCE_NOCHECK. However, the macro implementation mistakenly defines an intermediate variable as 'unsigned long addr = x;', which forces an immediate evaluation of the lvalue expression (such as frame->fp) as a normal C load instrumented by KASAN before calling READ_ONCE_NOCHECK(addr) on the local variable. When unwinding another task that is running or preempted, reading frame->fp directly hits stack redzones poisoned by KASAN on the target task's stack, triggering a false-positive KASAN stack-out-of-bounds report.

▶ ▼ ✨ Full AI root cause analysis
Based on kernel commit 77ae27fd98f3:

Root Cause Analysis

1. Relevant Files, Functions, and Data Structures


2. Technical Mechanism

When unwinding the kernel stack of a non-current task (in this report, oom_reaper on CPU 0 unwinding syz.1.97, which is running or preempted), the unwinder needs to safely read frame->fp and frame->ra from the target task's kernel stack. When a task executes kernel code on another CPU, KASAN poisons stack redzones around active local variables on that task's stack (marked with 0xf1 = KASAN_STACK_LEFT, 0xf3, etc.).

To prevent KASAN from generating false-positive warnings while reading another task's stack, READ_ONCE_TASK_STACK is supposed to use READ_ONCE_NOCHECK(x), which dereferences the address using __read_once_word_nocheck(&(x)) (annotated with __no_sanitize_or_inline to suppress KASAN checks).

However, in arch/riscv/kernel/stacktrace.c, READ_ONCE_TASK_STACK is incorrectly defined as follows:

#define READ_ONCE_TASK_STACK(task, x)			\
({							\
	unsigned long val;				\
	unsigned long addr = x;				\
	if ((task) == current)				\
		val = READ_ONCE(addr);			\
	else						\
		val = READ_ONCE_NOCHECK(addr);		\
	val;						\
})

When walk_stackframe() invokes:

fp = READ_ONCE_TASK_STACK(task, frame->fp);

the macro expands with x being the lvalue frame->fp:

  1. The statement unsigned long addr = x; expands to unsigned long addr = frame->fp;. This performs a direct memory dereference of frame->fp via a standard compiler-generated load.
  2. Because walk_stackframe() is compiled with KASAN instrumentation enabled, this load is checked against KASAN shadow memory.
  3. If the frame pointer or return address falls in a KASAN-poisoned region (such as a stack redzone 0xf1 belonging to a function frame of the target task), KASAN immediately reports a stack-out-of-bounds violation at line 88.
  4. Furthermore, val = READ_ONCE_NOCHECK(addr); erroneously passes addr (which is a local variable on the calling task's stack) to READ_ONCE_NOCHECK(), reading the already-evaluated local variable without KASAN checks while leaving the actual remote stack dereference fully instrumented.

3. Invariant Violation and Fix

The macro violates the invariant that unwinding another task's stack must not perform KASAN-instrumented memory accesses on that task's stack frames.

To fix this defect, READ_ONCE_TASK_STACK must pass the lvalue expression (x) directly to READ_ONCE or READ_ONCE_NOCHECK without evaluating it into an intermediate variable first (matching the implementation in arch/x86/include/asm/unwind.h):

#define READ_ONCE_TASK_STACK(task, x)			\
({							\
	unsigned long val;				\
	if ((task) == current)				\
		val = READ_ONCE(x);			\
	else						\
		val = READ_ONCE_NOCHECK(x);		\
	val;						\
})
▶ ▼ ✨ AI Jobs (7)
ID Workflow Result Correct Bug Created Started Finished Revision
1fc98db1 assessment-security DenialOfService: ❌ Exploitable: ❌ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ❌ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ✅ UserNamespace: ✅ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ KASAN: stack-out-of-bounds Read in sched_show_task (2) 2026/11/05 16:32 2026/11/05 16:32 2026/11/05 17:21 5cecaf1f
4263434a assessment-security 💥 KASAN: stack-out-of-bounds Read in sched_show_task (2) 2026/09/26 08:17 2026/09/26 08:17 2026/09/26 08:17 a3c7249d
b42c672f assessment-security 💥 KASAN: stack-out-of-bounds Read in sched_show_task (2) 2026/09/17 02:30 2026/09/17 02:30 2026/09/17 02:30 95928915
8c684e25 assessment-security 💥 KASAN: stack-out-of-bounds Read in sched_show_task (2) 2026/09/12 00:54 2026/09/12 00:54 2026/09/12 00:54 6816f32e
568072d6 repro-c 💥 KASAN: stack-out-of-bounds Read in sched_show_task (2) 2026/09/10 12:25 2026/09/10 12:25 2026/09/10 14:10 1fe56c0a
55fe8fdc assessment-security 💥 KASAN: stack-out-of-bounds Read in sched_show_task (2) 2026/09/09 01:14 2026/09/09 01:14 2026/09/09 01:14 243b72f1
1d2a9a63 assessment-security 💥 KASAN: stack-out-of-bounds Read in sched_show_task (2) 2026/09/08 01:10 2026/09/08 01:10 2026/09/08 01:10 680aa3e1
▶ ▼ Similar bugs (1)
Kernel Title Rank 🛈 Repro Cause bisect Fix bisect Count Last Reported Patched Status
upstream KASAN: stack-out-of-bounds Read in sched_show_task prio:high input usb serial 17 syz, C 166 308d 1148d 0/29 closed as invalid on 2026/07/31 14:07

Sample crash report:
task:syz.1.97        state:R  running task     stack:0     pid:5329  tgid:5329  ppid:3215   task_flags:0x400840 flags:0x0000000a
Call Trace:
[<ffffffff865a0e70>] context_switch kernel/sched/core.c:5520 [inline]
[<ffffffff865a0e70>] __schedule+0x1de4/0x4ff0 kernel/sched/core.c:7270
==================================================================
BUG: KASAN: stack-out-of-bounds in walk_stackframe+0x512/0x56a arch/riscv/kernel/stacktrace.c:88
Read of size 8 at addr ffff8f8002006950 by task oom_reaper/33

CPU: 0 UID: 0 PID: 33 Comm: oom_reaper Tainted: G             L      syzkaller #0 PREEMPT 
Tainted: [L]=SOFTLOCKUP
Hardware name: riscv-virtio,qemu (DT)
Call Trace:
[<ffffffff8007e614>] dump_backtrace+0x2e/0x3c arch/riscv/kernel/stacktrace.c:149
[<ffffffff80003112>] show_stack+0x30/0x3c arch/riscv/kernel/stacktrace.c:155
[<ffffffff800630cc>] __dump_stack lib/dump_stack.c:94 [inline]
[<ffffffff800630cc>] dump_stack_lvl+0x114/0x1aa lib/dump_stack.c:120
[<ffffffff8000e264>] print_address_description mm/kasan/report.c:378 [inline]
[<ffffffff8000e264>] print_report+0x27a/0x592 mm/kasan/report.c:482
[<ffffffff80bf8576>] kasan_report+0xf0/0x26c mm/kasan/report.c:595
[<ffffffff80bfa226>] __asan_report_load8_noabort+0x12/0x1a mm/kasan/report_generic.c:381
[<ffffffff8007e0d0>] walk_stackframe+0x512/0x56a arch/riscv/kernel/stacktrace.c:88
[<ffffffff8007e614>] dump_backtrace+0x2e/0x3c arch/riscv/kernel/stacktrace.c:149
[<ffffffff80003112>] show_stack+0x30/0x3c arch/riscv/kernel/stacktrace.c:155
[<ffffffff802239b8>] sched_show_task kernel/sched/core.c:8220 [inline]
[<ffffffff802239b8>] sched_show_task+0x414/0x5ea kernel/sched/core.c:8195
[<ffffffff809204e6>] oom_reap_task mm/oom_kill.c:618 [inline]
[<ffffffff809204e6>] oom_reaper+0xd12/0x105e mm/oom_kill.c:650
[<ffffffff801f6df4>] kthread+0x312/0x438 kernel/kthread.c:436
[<ffffffff8006c352>] ret_from_fork_kernel+0x94/0xe74 arch/riscv/kernel/process.c:230
[<ffffffff865c0e42>] ret_from_fork_kernel_asm+0x16/0x18 arch/riscv/kernel/entry.S:368

The buggy address belongs to a 8-page vmalloc region starting at 0xffff8f8002000000 allocated at kernel_clone+0x198/0xf7c kernel/fork.c:2772
The buggy address belongs to the physical page:
page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0xb1aa6
memcg:ffffaf80202e7c02
flags: 0x0(node=0|zone=0)
raw: 0000000000000000 0000000000000000 ffff8d8002c6a988 0000000000000000
raw: 0000000000000000 0000000000000000 00000001ffffffff ffffaf80202e7c02
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 3215, tgid 3215 (syz-executor), ts 3137427627400, free_ts 3137215226500
 __set_page_owner+0x92/0x4b0 mm/page_owner.c:341
 set_page_owner include/linux/page_owner.h:32 [inline]
 post_alloc_hook+0xe4/0x1a0 mm/page_alloc.c:1859
 prep_new_page mm/page_alloc.c:1867 [inline]
 get_page_from_freelist+0x914/0x3950 mm/page_alloc.c:3946
 __alloc_frozen_pages_noprof+0x224/0x2e58 mm/page_alloc.c:5304
 alloc_pages_mpol+0x1f0/0x59c mm/mempolicy.c:2490
 alloc_frozen_pages_noprof+0x156/0x2ce mm/mempolicy.c:2561
 alloc_pages_noprof+0x20/0x140 mm/mempolicy.c:2581
 vm_area_alloc_pages mm/vmalloc.c:3689 [inline]
 __vmalloc_area_node mm/vmalloc.c:3914 [inline]
 __vmalloc_node_range_noprof+0x103e/0x1b34 mm/vmalloc.c:4104
 __vmalloc_node_noprof+0xfc/0x132 mm/vmalloc.c:4165
 alloc_thread_stack_node kernel/fork.c:359 [inline]
 dup_task_struct kernel/fork.c:930 [inline]
 copy_process+0x762/0x81b6 kernel/fork.c:2139
 kernel_clone+0x198/0xf7c kernel/fork.c:2772
 __do_sys_clone+0xfe/0x13e kernel/fork.c:2914
 __se_sys_clone kernel/fork.c:2882 [inline]
 __riscv_sys_clone+0xa0/0x10e kernel/fork.c:2882
 syscall_handler+0x92/0x114 arch/riscv/include/asm/syscall.h:112
 do_trap_ecall_u+0x4ca/0x658 arch/riscv/kernel/traps.c:341
 handle_exception+0x168/0x174 arch/riscv/kernel/entry.S:237
page last free pid 3215 tgid 3215 stack trace:
 __reset_page_owner+0x76/0x1bc mm/page_owner.c:320
 reset_page_owner include/linux/page_owner.h:25 [inline]
 __free_pages_prepare mm/page_alloc.c:1406 [inline]
 __free_frozen_pages+0x6b2/0x136e mm/page_alloc.c:2950
 free_frozen_pages+0xe/0x16 mm/page_alloc.c:2988
 __free_slab+0xda/0x250 mm/slub.c:3441
 free_slab+0x28/0x16c mm/slub.c:3475
 discard_slab mm/slub.c:3481 [inline]
 __slab_free+0x23c/0x2f8 mm/slub.c:5741
 ___cache_free+0x94/0xac mm/slub.c:6449
 qlink_free mm/kasan/quarantine.c:163 [inline]
 qlist_free_all+0x64/0x134 mm/kasan/quarantine.c:179
 kasan_quarantine_reduce+0x152/0x1b4 mm/kasan/quarantine.c:286
 __kasan_slab_alloc+0x5c/0x82 mm/kasan/common.c:350
 kasan_slab_alloc include/linux/kasan.h:253 [inline]
 slab_post_alloc_hook mm/slub.c:4584 [inline]
 slab_alloc_node mm/slub.c:4917 [inline]
 __do_kmalloc_node mm/slub.c:5333 [inline]
 __kvmalloc_node_noprof+0x274/0x9a4 mm/slub.c:6905
 xt_alloc_table_info+0x5a/0xbc net/netfilter/x_tables.c:1286
 do_replace+0x1c4/0x478 net/ipv4/netfilter/ip_tables.c:1124
 do_ip6t_set_ctl+0x410/0x9b6 net/ipv6/netfilter/ip6_tables.c:1643
 nf_setsockopt+0x78/0xda net/netfilter/nf_sockopt.c:101
 ipv6_setsockopt+0x126/0x158 net/ipv6/ipv6_sockglue.c:970

Memory state around the buggy address:
 ffff8f8002006800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ffff8f8002006880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff8f8002006900: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3
                                                 ^
 ffff8f8002006980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ffff8f8002006a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
==================================================================

Crashes (1):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/09/06 08:36 git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git for-next 77ae27fd98f3 4f7b22a0 .config console log report info [disk image (non-bootable)] [vmlinux] [kernel image] ci-qemu2-riscv64 KASAN: stack-out-of-bounds Read in sched_show_task
* Struck through repros no longer work on HEAD.