BUG: unable to handle kernel paging request in wg_socket_reinit

Status: moderation: reported on 2026/11/13 03:34
Subsystems: wireguard
Labels: prio:high
[Documentation on labels]
Reported-by: syzbot+f9737c77df0b77893c53@syzkaller.appspotmail.com
First crash: 4d00h, last: 4d00h
✨ AI-generated root cause summary:

During network namespace exit, wg_netns_exit_rtnl() invokes wg_socket_reinit(wg, NULL, NULL) to tear down WireGuard's endpoint sockets. However, wg->sock6 contained a dangling reference to an already-freed struct sock whose memory had been reallocated and zero-initialized. When wg_socket_reinit() calls sock_free(old6) -> sk_clear_memalloc(old6), sk_mem_reclaim() attempts to read sk->sk_prot->memory_allocated, which crashes with a NULL pointer dereference because sk->sk_prot is NULL (0x0).

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

Technical Analysis of Root Cause

1. Manifestation Site & Crash Anatomy

The kernel oops occurs in network namespace cleanup (cleanup_net workqueue) when ops_exit_rtnl_list() calls WireGuard's pernet exit handler wg_netns_exit_rtnl():

sk_has_account include/net/sock.h:1578 [inline]
sk_mem_reclaim include/net/sock.h:1626 [inline]
sk_clear_memalloc+0x9c/0x254 net/core/sock.c:325
sock_free drivers/net/wireguard/socket.c:337 [inline]
wg_socket_reinit+0x190/0x2bc drivers/net/wireguard/socket.c:435
wg_netns_exit_rtnl+0xd8/0x1e0 drivers/net/wireguard/device.c:425
ops_exit_rtnl_list net/core/net_namespace.c:181 [inline]
ops_undo_list+0x2bc/0x81c net/core/net_namespace.c:249
cleanup_net+0x474/0x6c4 net/core/net_namespace.c:708

At net/core/sock.c:325 in sk_clear_memalloc():

void sk_clear_memalloc(struct sock *sk)
{
    sock_reset_flag(sk, SOCK_MEMALLOC);
    sk->sk_allocation &= ~__GFP_MEMALLOC;
    static_branch_dec(&memalloc_socks_key);

    sk_mem_reclaim(sk);
}

sk_mem_reclaim() invokes sk_has_account(sk):

static inline bool sk_has_account(struct sock *sk)
{
    /* return true if protocol supports memory accounting */
    return !sk->sk_prot->memory_allocated;
}

From the crash dump and disassembly:

  • x19 (sk) = 0xffff0000c737ec00 (which is old6, read from wg->sock6).
  • Offset 0x28 of sk (sk->sk_prot) is loaded into x8. In this crash, x8 = 0x0 (NULL).
  • The code then executes add x20, x8, #0x100 (offset of proto::memory_allocated) resulting in x20 = 0x100.
  • Dereferencing 0x100 (via KASAN shadow address dfff800000000020) generates an immediate page translation fault and oopses.

2. Root Cause Mechanism

  1. Dangling / Stale Reference in wg->sock6: In wg_socket_reinit(wg, NULL, NULL):

    mutex_lock(&wg->socket_update_lock);
    old4 = rcu_dereference_protected(wg->sock4, lockdep_is_held(&wg->socket_update_lock));
    old6 = rcu_dereference_protected(wg->sock6, lockdep_is_held(&wg->socket_update_lock));
    rcu_assign_pointer(wg->sock4, new4);
    rcu_assign_pointer(wg->sock6, new6);
    ...
    mutex_unlock(&wg->socket_update_lock);
    synchronize_net();
    sock_free(old4);
    sock_free(old6);
    

    old4 is freed first without error. Next, sock_free(old6) is executed. Normally, any socket allocated via sk_alloc() has sk->sk_prot initialized to a valid protocol structure (udpv6_prot), and no code in the socket lifecycle ever clears sk->sk_prot to NULL.

  2. Memory Lifecycle & Allocator Interaction: The kernel configuration has CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y. When old6 was previously released (or its refcount prematurely dropped to 0 via another teardown path, socket release, or failure recovery), the underlying slab object was freed. Subsequent allocation and zero-initialization of that memory caused all fieldsβ€”including sk->sk_prot at offset 0x28β€”to become 0x0, while the KASAN shadow for that memory block became valid/unpoisoned. Consequently, preceding field writes in sk_clear_memalloc() (sock_reset_flag at offset 0x60 and sk->sk_allocation at offset 0x3D0) succeeded silently, mutating foreign memory, until the dereference of sk->sk_prot->memory_allocated tripped over the NULL pointer.

3. Scope and Unverified Hypotheses

  • Verified:
    • The crash occurs specifically on old6 (wg->sock6), after old4 was freed.
    • old6 (0xffff0000c737ec00) points to a zeroed/reallocated memory chunk whose sk_prot is NULL, demonstrating that wg->sock6 held a dangling pointer to an already-freed socket.
    • Mutation of sk->sk_flags and sk->sk_allocation on that reallocated memory occurs before the crash.
  • Inconclusive / Unverified:
    • The exact earlier call path that dropped the final reference on wg->sock6 prior to netns teardown (e.g. an asynchronous IPv6 stack netns release vs. an error unwind path or interface stop race) cannot be definitively isolated from the crash dump alone, as the freeing event occurred prior to the cleanup_net work execution.
▶ ▼ ✨ AI Jobs (3)
ID Workflow Result Correct Bug Created Started Finished Revision
44cbf79f repro-c πŸƒ BUG: unable to handle kernel paging request in wg_socket_reinit 2026/11/13 00:00 2026/11/13 00:00 c0087d7f
b5b67aa0 repro-c πŸ’₯ BUG: unable to handle kernel paging request in wg_socket_reinit 2026/11/12 00:00 2026/11/12 00:00 2026/11/12 10:30 8d68b303
225c4c19 assessment-security DenialOfService: βœ… Exploitable: βœ… FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: βœ… NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ❌ UserNamespace: βœ… VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ BUG: unable to handle kernel paging request in wg_socket_reinit 2026/11/09 03:06 2026/11/09 03:06 2026/11/09 03:31 5cecaf1f

Sample crash report:
bridge0: port 2(bridge_slave_1) entered disabled state
bridge_slave_0: left allmulticast mode
bridge_slave_0: left promiscuous mode
bridge0: port 1(bridge_slave_0) entered disabled state
Unable to handle kernel paging request at virtual address dfff800000000020
KASAN: null-ptr-deref in range [0x0000000000000100-0x0000000000000107]
Mem abort info:
  ESR = 0x0000000096000005
  EC = 0x25: DABT (current EL), IL = 32 bits
  SET = 0, FnV = 0
  EA = 0, S1PTW = 0
  FSC = 0x05: level 1 translation fault
Data abort info:
  ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
  CM = 0, WnR = 0, TnD = 0, TagAccess = 0
  GCS = 0, Overlay = 0, DirtyBit = 0
[dfff800000000020] address between user and kernel address ranges
Internal error: Oops: 0000000096000005 [#1]  SMP
Modules linked in:
CPU: 0 UID: 0 PID: 1206 Comm: kworker/u8:6 Not tainted syzkaller #0 PREEMPT 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/06/2026
Workqueue: netns cleanup_net
pstate: 83400005 (Nzcv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
pc : sk_has_account include/net/sock.h:1578 [inline]
pc : sk_mem_reclaim include/net/sock.h:1626 [inline]
pc : sk_clear_memalloc+0x9c/0x254 net/core/sock.c:325
lr : sk_clear_memalloc+0x78/0x254 net/core/sock.c:316
sp : ffff800094be7880
x29: ffff800094be7880 x28: 0000000000000000 x27: ffff0000d2b40f00
x26: ffff0000d2b413c8 x25: ffff0000d2b413c0 x24: dfff800000000000
x23: ffff0000c737ec00 x22: dfff800000000000 x21: 0000000000000000
x20: 0000000000000100 x19: ffff0000c737ec00 x18: 1fffe000359cf228
x17: 0000000000000003 x16: ffff8000898b7000 x15: 0000000000000000
x14: 0000000000000001 x13: 0000000000000001 x12: 0000000000000003
x11: 0000000000000000 x10: 0000000000000001 x9 : 0000000000000000
x8 : 0000000000000020 x7 : ffff800080972a20 x6 : 0000000000000000
x5 : 0000000000000000 x4 : 0000000000000001 x3 : ffff80008030f058
x2 : 0000000100000000 x1 : ffff0000c8cd5880 x0 : 0000000000000000
Call trace:
 sk_has_account include/net/sock.h:1578 [inline] (P)
 sk_mem_reclaim include/net/sock.h:1626 [inline] (P)
 sk_clear_memalloc+0x9c/0x254 net/core/sock.c:325 (P)
 sock_free drivers/net/wireguard/socket.c:337 [inline]
 wg_socket_reinit+0x190/0x2bc drivers/net/wireguard/socket.c:435
 wg_netns_exit_rtnl+0xd8/0x1e0 drivers/net/wireguard/device.c:425
 ops_exit_rtnl_list net/core/net_namespace.c:181 [inline]
 ops_undo_list+0x2bc/0x81c net/core/net_namespace.c:249
 cleanup_net+0x474/0x6c4 net/core/net_namespace.c:708
 process_one_work kernel/workqueue.c:3495 [inline]
 process_scheduled_works+0x91c/0x1250 kernel/workqueue.c:3578
 worker_thread+0x798/0xbd0 kernel/workqueue.c:3659
 kthread+0x304/0x3d4 kernel/kthread.c:436
 ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:854
Code: 96fe305d f9400288 91040114 d343fe88 (38766908) 
---[ end trace 0000000000000000 ]---
----------------
Code disassembly (best guess):
   0:	96fe305d 	bl	0xfffffffffbf8c174
   4:	f9400288 	ldr	x8, [x20]
   8:	91040114 	add	x20, x8, #0x100
   c:	d343fe88 	lsr	x8, x20, #3
* 10:	38766908 	ldrb	w8, [x8, x22] <-- trapping instruction

Crashes (1):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/11/09 03:06 git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci 58c1eb84e977 5cecaf1f .config console log report info [disk image] [vmlinux] [kernel image] ci-upstream-gce-arm64 BUG: unable to handle kernel paging request in wg_socket_reinit
* Struck through repros no longer work on HEAD.