general protection fault in validate_mm (2)

Status: upstream: reported C repro on 2026/11/01 18:25
Subsystems: mm
Labels: prio:high
[Documentation on labels]
Reported-by: syzbot+10e72ea5747737bcd2ad@syzkaller.appspotmail.com
First crash: 3d14h, last: 20h53m
✨ AI-generated root cause summary:

In validate_mm() (mm/vma.c), struct anon_vma *anon_vma = vma->anon_vma caches the anon_vma pointer at the beginning of the VMA iteration loop. In vms_complete_munmap_vmas(), mm->mmap_lock is downgraded to a read lock before validate_mm() is called, allowing a concurrent page fault on another thread to populate vma->anon_vma via __anon_vma_prepare(). When this race occurs, vma_has_anon_rmap(vma) evaluates to true by re-reading vma->anon_vma, but anon_vma_lock_read(anon_vma) is invoked with the stale NULL local variable, resulting in an unhandled NULL-pointer dereference and kernel crash.

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

Root Cause Analysis

1. Exact Functions, Structs, Fields, and Files Involved


2. Mechanism of the Bug and Violated Invariants

  1. Stale Pointer Caching in validate_mm(): In validate_mm() (mm/vma.c:680-712), the kernel iterates over all VMAs of an mm_struct:

    for_each_vma(vmi, vma) {
    #ifdef CONFIG_DEBUG_VM_RB
        struct anon_vma *anon_vma = vma->anon_vma;
        struct anon_vma_chain *avc;
    #endif
    ...
    #ifdef CONFIG_DEBUG_VM_RB
        if (vma_has_anon_rmap(vma)) {
            anon_vma_lock_read(anon_vma);
            list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
                anon_rmap_tree_verify(avc);
            anon_vma_unlock_read(anon_vma);
        }
    #endif
    

    At the beginning of each loop iteration (line 682), anon_vma is read from vma->anon_vma and stored in a local variable on the stack.

  2. Transition from Unfaulted to Faulted under Read Lock: When an munmap operation completes in vms_complete_munmap_vmas() (mm/vma.c:1412-1437), if vms->unlock is requested, the kernel downgrades mm->mmap_lock from a write lock to a read lock:

    if (vms->unlock)
        mmap_write_downgrade(mm);
    ...
    validate_mm(mm);
    if (vms->unlock)
        mmap_read_unlock(mm);
    

    Because validate_mm(mm) runs with only the mmap_read_lock held, other threads sharing the same mm can concurrently execute page faults. A concurrent page fault on an anonymous VMA that has not yet been faulted will invoke __vmf_anon_prepare() -> __anon_vma_prepare() (mm/rmap.c:211-216), which allocates and publishes vma->anon_vma using smp_store_release(&vma->anon_vma, anon_vma).

  3. Race Condition and NULL Pointer Dereference: If the concurrent thread populates vma->anon_vma after line 682 but before line 706 of validate_mm():

    • Line 682 reads vma->anon_vma == NULL and initializes local variable anon_vma = NULL.
    • The concurrent thread sets vma->anon_vma to a valid pointer.
    • Line 706 calls vma_has_anon_rmap(vma), which checks data_race(vma->anon_vma). Since vma->anon_vma is now non-NULL, the condition evaluates to true.
    • Line 707 calls anon_vma_lock_read(anon_vma) using the stale local variable anon_vma, which remains NULL.
    • anon_vma_lock_read(anon_vma) executes down_read(&anon_vma->root->rwsem). Reading anon_vma->root (at offset 0 of struct anon_vma) with anon_vma == NULL triggers an immediate NULL pointer dereference.
    • In a KASAN-enabled kernel, KASAN checks the shadow address for NULL (0xdffffc0000000000), raising a General Protection Fault (#GP). In a production kernel without KASAN, it faults reading address 0x0, causing an unhandled page fault Oops / panic.

3. Classification and Runtime Impact

  • RootCauseFiles: mm/vma.c contains validate_mm(), where anon_vma was cached prior to calling vma_has_anon_rmap(vma), as well as vms_complete_munmap_vmas(), where validate_mm() is called with mmap_lock downgraded to a read lock.
  • MemoryCorruption (false): The bug is a pure NULL-pointer read dereference (anon_vma->root at offset 0). It does not corrupt memory, execute out-of-bounds writes, or lead to use-after-free.
  • InfoLeak ("none"): No kernel memory contents are exposed or returned to user space.
  • RawDenialOfService (true): A NULL-pointer dereference in kernel mode triggers an Oops or panic, killing the calling process or crashing the system.
  • IsNetCandidate (false): The defect is strictly within core memory management (mm/vma.c / munmap / anon_vma) and has no relationship to networking.
  • IsKVMCandidate (false): The defect has no relationship to virtualization or KVM.
▶ ▼ ✨ AI Jobs (2)
ID Workflow Result Correct Bug Created Started Finished Revision
e40b7d5c repro-c Reproduced: ✅ ❓ general protection fault in validate_mm (2) 2026/11/01 00:05 2026/11/01 00:05 2026/11/01 01:35 25a0ae84
12dc6ba7 assessment-security DenialOfService: ✅ Exploitable: ❌ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ❌ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ✅ UserNamespace: ✅ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ general protection fault in validate_mm (2) 2026/10/29 08:22 2026/10/29 08:22 2026/10/29 09:06 b1d00f76
▶ ▼ Discussions (1)
Title Replies (including bot) Last reply
[syzbot] [mm?] general protection fault in validate_mm (2) 0 (1) 2026/11/01 18:25
▶ ▼ Similar bugs (3)
Kernel Title Rank 🛈 Repro Cause bisect Fix bisect Count Last Reported Patched Status
linux-4.19 general protection fault in validate_mm 2 1 1983d 1983d 0/1 auto-closed as invalid on 2021/09/25 11:25
upstream general protection fault in validate_mm mm 2 1 768d 764d 0/29 auto-obsoleted due to no activity on 2024/12/23 08:47
linux-4.19 general protection fault in validate_mm (2) 2 2 1762d 1817d 0/1 auto-closed as invalid on 2022/05/04 19:51
▶ ▼ Last patch testing requests (1)
Created Duration User Patch Repo Result
2026/11/01 01:37 12m retest repro git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 36aad21d50d1af3f6954bb0c988257a908202477 report job log log

Sample crash report:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
CPU: 0 UID: 0 PID: 6142 Comm: syz-executor263 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:anon_vma_lock_read mm/internal.h:315 [inline]
RIP: 0010:validate_mm+0x3d4/0x780 mm/vma.c:707
Code: d2 e0 98 ff 48 89 df e8 5a 10 f1 ff c6 05 db a8 dd 0f 01 90 0f 0b 90 e9 04 fd ff ff e8 b5 e0 98 ff 48 8b 44 24 08 48 c1 e8 03 <80> 3c 28 00 0f 85 25 03 00 00 48 8b 44 24 08 4c 8d 63 30 48 8b 00
RSP: 0018:ffffc900040d7870 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffff88806b186000 RCX: 0000000000000000
RDX: ffff888000794b00 RSI: ffffffff8274c56b RDI: 0000000000000005
RBP: dffffc0000000000 R08: 0000000000000000 R09: 0000000000000001
R10: ffff88806b186083 R11: 0000000000000001 R12: ffff88806b186010
R13: ffff88806b186040 R14: 0000000000000001 R15: 000000000000003d
FS:  0000000000000000(0000) GS:ffff888095281000(0063) knlGS:000000005727b3c0
CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
CR2: 00000000f7f72000 CR3: 000000004e463000 CR4: 0000000000352ef0
Call Trace:
 <TASK>
 vms_complete_munmap_vmas+0x83b/0xdf0 mm/vma.c:1437
 do_vmi_align_munmap+0x44f/0x5f0 mm/vma.c:1677
 do_vmi_munmap+0x1f8/0x410 mm/vma.c:1725
 __vm_munmap+0x196/0x3c0 mm/vma.c:3562
 __do_sys_munmap mm/mmap.c:1094 [inline]
 __se_sys_munmap mm/mmap.c:1091 [inline]
 __ia32_sys_munmap+0x57/0x80 mm/mmap.c:1091
 do_syscall_32_irqs_on arch/x86/entry/syscall_32.c:79 [inline]
 __do_fast_syscall_32+0x14b/0x8c0 arch/x86/entry/syscall_32.c:282
 do_fast_syscall_32+0x32/0x70 arch/x86/entry/syscall_32.c:307
 entry_SYSENTER_compat_after_hwframe+0x84/0x8e
RIP: 0023:0xf7eaafbc
Code: d2 74 05 c1 e8 0c 89 02 8b 5d fc 31 c0 c9 c3 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 00 51 52 55 89 e5 0f 34 cd 80 <5d> 5a 59 c3 90 2e 8d b4 26 00 00 00 00 8d b4 26 00 00 00 00 58 b8
RSP: 002b:00000000ff8ab10c EFLAGS: 00000296 ORIG_RAX: 000000000000005b
RAX: ffffffffffffffda RBX: 0000000020088000 RCX: 0000000000001000
RDX: 00000000f7f70ff4 RSI: 00000000000000fb RDI: 0000000000000040
RBP: 00000000ff8ab168 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
 </TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:anon_vma_lock_read mm/internal.h:315 [inline]
RIP: 0010:validate_mm+0x3d4/0x780 mm/vma.c:707
Code: d2 e0 98 ff 48 89 df e8 5a 10 f1 ff c6 05 db a8 dd 0f 01 90 0f 0b 90 e9 04 fd ff ff e8 b5 e0 98 ff 48 8b 44 24 08 48 c1 e8 03 <80> 3c 28 00 0f 85 25 03 00 00 48 8b 44 24 08 4c 8d 63 30 48 8b 00
RSP: 0018:ffffc900040d7870 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffff88806b186000 RCX: 0000000000000000
RDX: ffff888000794b00 RSI: ffffffff8274c56b RDI: 0000000000000005
RBP: dffffc0000000000 R08: 0000000000000000 R09: 0000000000000001
R10: ffff88806b186083 R11: 0000000000000001 R12: ffff88806b186010
R13: ffff88806b186040 R14: 0000000000000001 R15: 000000000000003d
FS:  0000000000000000(0000) GS:ffff888095281000(0063) knlGS:000000005727b3c0
CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
CR2: 00000000f7f72000 CR3: 000000004e463000 CR4: 0000000000352ef0
----------------
Code disassembly (best guess), 4 bytes skipped:
   0:	48 89 df             	mov    %rbx,%rdi
   3:	e8 5a 10 f1 ff       	call   0xfff11062
   8:	c6 05 db a8 dd 0f 01 	movb   $0x1,0xfdda8db(%rip)        # 0xfdda8ea
   f:	90                   	nop
  10:	0f 0b                	ud2
  12:	90                   	nop
  13:	e9 04 fd ff ff       	jmp    0xfffffd1c
  18:	e8 b5 e0 98 ff       	call   0xff98e0d2
  1d:	48 8b 44 24 08       	mov    0x8(%rsp),%rax
  22:	48 c1 e8 03          	shr    $0x3,%rax
* 26:	80 3c 28 00          	cmpb   $0x0,(%rax,%rbp,1) <-- trapping instruction
  2a:	0f 85 25 03 00 00    	jne    0x355
  30:	48 8b 44 24 08       	mov    0x8(%rsp),%rax
  35:	4c 8d 63 30          	lea    0x30(%rbx),%r12
  39:	48 8b 00             	mov    (%rax),%rax

Crashes (3):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/11/01 01:50 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 36aad21d50d1 b1d00f76 .config console log report C ci-qemu-upstream-386 general protection fault in validate_mm
2026/10/29 08:22 upstream c339f4010dea b1d00f76 .config console log report info [disk image (non-bootable)] [vmlinux] [kernel image] ci-qemu-upstream-386 general protection fault in validate_mm
2026/10/31 22:30 net cb284914e749 2041d3f8 .config console log report info [disk image] [vmlinux] [kernel image] ci-upstream-net-this-kasan-gce general protection fault in validate_mm
* Struck through repros no longer work on HEAD.