[GH-ISSUE #139] Kernel oops (page fault) in jp_spec_applymods → random_byte_modifier during interface teardown #85

Open
opened 2026-10-13 21:06:23 +00:00 by bsakaguchi · 9 comments
Owner

Originally created by @remotetohome on GitHub (Feb 11, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/issues/139

Originally assigned to: @ygurov on GitHub.

Description

Running awg-quick down on an active AWG 2.0 tunnel with I1–I5 CPS parameters causes a kernel oops (page fault) that results in a hard system freeze requiring a power cycle. The crash occurs because the wg-kex handshake worker is still running when jp_spec_free() releases the junk packet spec buffers, leading to a use-after-free in random_byte_modifier → get_random_bytes → chacha_block_generic.

Steps to reproduce

  1. Configure an AWG 2.0 tunnel with I1–I5 CPS parameters (e.g. <r 885><r 374>)
  2. Bring up the tunnel: sudo awg-quick up ./awg_client.conf
  3. Verify handshake completes and tunnel is active
  4. Bring down the tunnel: sudo awg-quick down ./awg_client.conf
  5. System hard-freezes within seconds

Root cause analysis

The wg-kex workqueue (wg_packet_handshake_send_worker) races with interface teardown. During awg-quick down:

  1. The interface teardown path calls jp_spec_free() which does kfree(spec->pkt) and kfree(spec->mods)
  2. Meanwhile, the wg-kex workqueue worker is still executing wg_packet_send_handshake_initiation → jp_spec_applymods
  3. jp_spec_applymods iterates spec->mods[] and calls mod->func(mod->buf, mod->buf_len, peer)
  4. mod->func is random_byte_modifier, which calls get_random_bytes(buf, len) where buf points to freed memory
  5. get_random_bytes → _get_random_bytes → chacha_block_generic tries to write to the freed buffer → page fault

The wg-kex workqueue needs to be flushed/cancelled before jp_spec_free() releases the buffers, or the junk packet specs need reference counting to prevent use-after-free.

This is related to #102 (memory leak in junk.c) — both issues stem from lifecycle management of the jp_spec allocations.

Kernel oops

BUG: unable to handle page fault for address: ffff893e0c323000
#PF: supervisor write access in kernel mode
#PF: error_code(0x0003) - permissions violation
PGD 443201067 P4D 443201067 PUD 6c9f87063 PMD 643151063 PTE 800000070c323121
Oops: 0003 [#1] PREEMPT SMP NOPTI
CPU: 4 PID: 552988 Comm: kworker/u32:3 Tainted: G            E      6.8.0-100-generic #100-Ubuntu
Hardware name: LENOVO 21JT004RGQ/21JT004RGQ, BIOS R2CET45W(1.27) 07/22/2025
Workqueue: wg-kex-awg2-axt-base wg_packet_handshake_send_worker [amneziawg]
RIP: 0010:chacha_block_generic+0x82/0xd0

Call Trace:
 <TASK>
 _get_random_bytes+0xcf/0x1b0
 get_random_bytes+0xe/0x20
 random_byte_modifier+0x11/0x20 [amneziawg]
 jp_spec_applymods+0x40/0x70 [amneziawg]
 wg_packet_send_handshake_initiation+0x11c/0x350 [amneziawg]
 wg_packet_handshake_send_worker+0x19/0x30 [amneziawg]
 process_one_work+0x184/0x3a0
 worker_thread+0x306/0x440
 kthread+0xf2/0x120
 ret_from_fork+0x47/0x70
 ret_from_fork_asm+0x1b/0x30
 </TASK>

Environment

  • OS: Ubuntu 24.04 LTS (kernel 6.8.0-100-generic)
  • Module: amneziawg-dkms 1.0.0 (commit b2e234ba31)
  • Hardware: Lenovo ThinkPad (AMD, 16 cores)
  • AWG config: I1–I5 CPS enabled (<r 885><r 374>, <r 104>, <r 61>, <r 241>, <r 109>)
  • Server: Remote AWG 2.0 peer with matching CPS parameters (active handshake established before teardown)

Workaround

Remove the peer before bringing down the interface to stop handshake attempts:

sudo awg set awg0 peer <SERVER_PUBKEY> remove
sudo awg-quick down ./awg_client.conf
Originally created by @remotetohome on GitHub (Feb 11, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/issues/139 Originally assigned to: @ygurov on GitHub. ## Description Running `awg-quick down` on an active AWG 2.0 tunnel with I1–I5 CPS parameters causes a kernel oops (page fault) that results in a hard system freeze requiring a power cycle. The crash occurs because the `wg-kex` handshake worker is still running when `jp_spec_free()` releases the junk packet spec buffers, leading to a use-after-free in `random_byte_modifier` → `get_random_bytes` → `chacha_block_generic`. ## Steps to reproduce 1. Configure an AWG 2.0 tunnel with I1–I5 CPS parameters (e.g. `<r 885><r 374>`) 2. Bring up the tunnel: `sudo awg-quick up ./awg_client.conf` 3. Verify handshake completes and tunnel is active 4. Bring down the tunnel: `sudo awg-quick down ./awg_client.conf` 5. System hard-freezes within seconds ## Root cause analysis The `wg-kex` workqueue (`wg_packet_handshake_send_worker`) races with interface teardown. During `awg-quick down`: 1. The interface teardown path calls `jp_spec_free()` which does `kfree(spec->pkt)` and `kfree(spec->mods)` 2. Meanwhile, the `wg-kex` workqueue worker is still executing `wg_packet_send_handshake_initiation` → `jp_spec_applymods` 3. `jp_spec_applymods` iterates `spec->mods[]` and calls `mod->func(mod->buf, mod->buf_len, peer)` 4. `mod->func` is `random_byte_modifier`, which calls `get_random_bytes(buf, len)` where `buf` points to freed memory 5. `get_random_bytes` → `_get_random_bytes` → `chacha_block_generic` tries to write to the freed buffer → page fault The `wg-kex` workqueue needs to be flushed/cancelled before `jp_spec_free()` releases the buffers, or the junk packet specs need reference counting to prevent use-after-free. This is related to #102 (memory leak in junk.c) — both issues stem from lifecycle management of the `jp_spec` allocations. ## Kernel oops ``` BUG: unable to handle page fault for address: ffff893e0c323000 #PF: supervisor write access in kernel mode #PF: error_code(0x0003) - permissions violation PGD 443201067 P4D 443201067 PUD 6c9f87063 PMD 643151063 PTE 800000070c323121 Oops: 0003 [#1] PREEMPT SMP NOPTI CPU: 4 PID: 552988 Comm: kworker/u32:3 Tainted: G E 6.8.0-100-generic #100-Ubuntu Hardware name: LENOVO 21JT004RGQ/21JT004RGQ, BIOS R2CET45W(1.27) 07/22/2025 Workqueue: wg-kex-awg2-axt-base wg_packet_handshake_send_worker [amneziawg] RIP: 0010:chacha_block_generic+0x82/0xd0 Call Trace: <TASK> _get_random_bytes+0xcf/0x1b0 get_random_bytes+0xe/0x20 random_byte_modifier+0x11/0x20 [amneziawg] jp_spec_applymods+0x40/0x70 [amneziawg] wg_packet_send_handshake_initiation+0x11c/0x350 [amneziawg] wg_packet_handshake_send_worker+0x19/0x30 [amneziawg] process_one_work+0x184/0x3a0 worker_thread+0x306/0x440 kthread+0xf2/0x120 ret_from_fork+0x47/0x70 ret_from_fork_asm+0x1b/0x30 </TASK> ``` ## Environment - **OS**: Ubuntu 24.04 LTS (kernel 6.8.0-100-generic) - **Module**: amneziawg-dkms 1.0.0 (commit b2e234ba31b7aae65e21dfd2ab2d5250dd8b65b0) - **Hardware**: Lenovo ThinkPad (AMD, 16 cores) - **AWG config**: I1–I5 CPS enabled (`<r 885><r 374>`, `<r 104>`, `<r 61>`, `<r 241>`, `<r 109>`) - **Server**: Remote AWG 2.0 peer with matching CPS parameters (active handshake established before teardown) ## Workaround Remove the peer before bringing down the interface to stop handshake attempts: ```bash sudo awg set awg0 peer <SERVER_PUBKEY> remove sudo awg-quick down ./awg_client.conf ```
Author
Owner

@janusloo commented on GitHub (Mar 17, 2026):

Hi, I encountered the same issue with the CPS (Custom Protocol Signature) chain. Whenever I add/delete profiles the whole container will crash and along with my Pi. I have to power cycle it down to get it back online.

Also after a while, when 1 or more clients are connecting, the container will crash when using CPS for I1 (e.g. <r 32>).

I got this error:

request error] [unhandled] [POST] https://xxxxxxxxx/api/client

 H3Error: Command failed: awg syncconf wg0 <(awg-quick strip wg0)


    at genericNodeError (node:internal/errors:983:15)

    ... 4 lines matching cause stack trace ...

    at ChildProcess._handle.onexit (node:internal/child_process:304:5) {

  cause: Error: Command failed: awg syncconf wg0 <(awg-quick strip wg0)

  

      at genericNodeError (node:internal/errors:983:15)

      at wrappedFn (node:internal/errors:537:14)

      at ChildProcess.exithandler (node:child_process:417:12)

      at ChildProcess.emit (node:events:519:28)

      at maybeClose (node:internal/child_process:1101:16)

      at ChildProcess._handle.onexit (node:internal/child_process:304:5) {

    code: null,

    killed: false,

    signal: 'SIGSEGV',

    cmd: 'awg syncconf wg0 <(awg-quick strip wg0)'

  },

  statusCode: 500,

  fatal: false,

  unhandled: true,

  statusMessage: undefined,

  data: undefined 

There seems to be a "race condition" in the kernel module code where it tries to apply the I1 obfuscation modifiers (jp_spec_applymods) to a packet while the underlying memory for those modifiers is being freed or moved during the sync. This results in the kernel trying to read from a restricted memory address, causing the crash.

Please take a look at this. Thanks in advance!

<!-- gh-comment-id:4077124331 --> @janusloo commented on GitHub (Mar 17, 2026): Hi, I encountered the same issue with the CPS (Custom Protocol Signature) chain. Whenever I add/delete profiles the whole container will crash and along with my Pi. I have to power cycle it down to get it back online. Also after a while, when 1 or more clients are connecting, the container will crash when using CPS for I1 (e.g. <r 32>). I got this error: ``` request error] [unhandled] [POST] https://xxxxxxxxx/api/client H3Error: Command failed: awg syncconf wg0 <(awg-quick strip wg0) at genericNodeError (node:internal/errors:983:15) ... 4 lines matching cause stack trace ... at ChildProcess._handle.onexit (node:internal/child_process:304:5) { cause: Error: Command failed: awg syncconf wg0 <(awg-quick strip wg0) at genericNodeError (node:internal/errors:983:15) at wrappedFn (node:internal/errors:537:14) at ChildProcess.exithandler (node:child_process:417:12) at ChildProcess.emit (node:events:519:28) at maybeClose (node:internal/child_process:1101:16) at ChildProcess._handle.onexit (node:internal/child_process:304:5) { code: null, killed: false, signal: 'SIGSEGV', cmd: 'awg syncconf wg0 <(awg-quick strip wg0)' }, statusCode: 500, fatal: false, unhandled: true, statusMessage: undefined, data: undefined ``` There seems to be a "race condition" in the kernel module code where it tries to apply the I1 obfuscation modifiers (jp_spec_applymods) to a packet while the underlying memory for those modifiers is being freed or moved during the sync. This results in the kernel trying to read from a restricted memory address, causing the crash. Please take a look at this. Thanks in advance!
Author
Owner

@remotetohome commented on GitHub (Mar 25, 2026):

Update: Second failure mode — workqueue deadlock blocking system suspend

Hit this again on the latest DKMS build (26f5df0, March 22 2026). Same race condition, different outcome — instead of a page fault crash, the freed memory was reused by the slab allocator, which corrupted workqueue state and caused flush_workqueue to hang indefinitely.

The ip link delete process gets stuck in D state:

task:ip    state:D    pid:13108
  peer_remove_after_dead [amneziawg]
  wg_peer_remove_all [amneziawg]
  wg_destruct [amneziawg]
  __flush_workqueue

The process is unkillable (D state) and blocks system suspend - the kernel's freeze_processes loop fails with "1 tasks refusing to freeze" and aborts. The only recovery is a reboot. In some ways this is worse than the crash variant, since the system appears to keep running but can never sleep again and the stuck process never clears.

Same root cause: jp_spec_free() in wg_destruct() runs before the workqueues are flushed. Depending on slab timing, the handshake worker hits either unmapped memory (crash) or reused memory (corruption/deadlock).

Same kernel, same hardware as the original report (6.8.0-106-generic, ThinkPad E16 Gen 1 AMD).

<!-- gh-comment-id:4125650211 --> @remotetohome commented on GitHub (Mar 25, 2026): **Update: Second failure mode — workqueue deadlock blocking system suspend** Hit this again on the latest DKMS build (`26f5df0`, March 22 2026). Same race condition, different outcome — instead of a page fault crash, the freed memory was reused by the slab allocator, which corrupted workqueue state and caused `flush_workqueue` to hang indefinitely. The `ip link delete` process gets stuck in D state: ``` task:ip state:D pid:13108 peer_remove_after_dead [amneziawg] wg_peer_remove_all [amneziawg] wg_destruct [amneziawg] __flush_workqueue ``` The process is unkillable (D state) and blocks system suspend - the kernel's freeze_processes loop fails with "1 tasks refusing to freeze" and aborts. The only recovery is a reboot. In some ways this is worse than the crash variant, since the system appears to keep running but can never sleep again and the stuck process never clears. Same root cause: `jp_spec_free()` in `wg_destruct()` runs before the workqueues are flushed. Depending on slab timing, the handshake worker hits either unmapped memory (crash) or reused memory (corruption/deadlock). Same kernel, same hardware as the original report (6.8.0-106-generic, ThinkPad E16 Gen 1 AMD).
Author
Owner

@remotetohome commented on GitHub (Mar 25, 2026):

@ygurov - PS.. definitely using AI to help with the bug diagnosis and prep.. but this is real human reporting. I'm doing AWG2 setups for clients daily and constantly testing tunnels via awg-quick.

I sincerely appreciate all the work on this project.

<!-- gh-comment-id:4125713739 --> @remotetohome commented on GitHub (Mar 25, 2026): @ygurov - PS.. definitely using AI to help with the bug diagnosis and prep.. but this is real human reporting. I'm doing AWG2 setups for clients daily and constantly testing tunnels via awg-quick. I sincerely appreciate all the work on this project.
Author
Owner

@janusloo commented on GitHub (Mar 26, 2026):

When can we expect the PR be merged and released? Thanks!

<!-- gh-comment-id:4136491229 --> @janusloo commented on GitHub (Mar 26, 2026): When can we expect the PR be merged and released? Thanks!
Author
Owner

@Jipok commented on GitHub (Mar 28, 2026):

I just hit same problem:

[ +20.952131] BUG: unable to handle page fault for address: 0000000000007974
[  +0.000141] #PF: supervisor instruction fetch in kernel mode
[  +0.000060] Oops: 0010 [#1] PREEMPT SMP NOPTI
[  +0.000062] CPU: 1 PID: 29 Comm: kworker/u6:0 Tainted: G            E      6.6.129_1 #1
[  +0.000062] Workqueue: wg-kex-awg0 wg_packet_handshake_send_worker [amneziawg]
[  +0.000071] RIP: 0010:0x7974
...
[  +0.000065] Call Trace:
[  +0.000061]  <TASK>
[  +0.000060]  ? jp_spec_applymods+0x3d/0x60 [amneziawg]
[  +0.000066]  ? wg_packet_send_handshake_initiation+0x100/0x2f0 [amneziawg]
[  +0.000066]  ? wg_packet_handshake_send_worker+0x19/0x30 [amneziawg]

Full dmesg log

Instead of using awg-quick, I am managing the interface via my jwg with uses forked wgctrl-go library.

<!-- gh-comment-id:4148088392 --> @Jipok commented on GitHub (Mar 28, 2026): I just hit same problem: ```text [ +20.952131] BUG: unable to handle page fault for address: 0000000000007974 [ +0.000141] #PF: supervisor instruction fetch in kernel mode [ +0.000060] Oops: 0010 [#1] PREEMPT SMP NOPTI [ +0.000062] CPU: 1 PID: 29 Comm: kworker/u6:0 Tainted: G E 6.6.129_1 #1 [ +0.000062] Workqueue: wg-kex-awg0 wg_packet_handshake_send_worker [amneziawg] [ +0.000071] RIP: 0010:0x7974 ... [ +0.000065] Call Trace: [ +0.000061] <TASK> [ +0.000060] ? jp_spec_applymods+0x3d/0x60 [amneziawg] [ +0.000066] ? wg_packet_send_handshake_initiation+0x100/0x2f0 [amneziawg] [ +0.000066] ? wg_packet_handshake_send_worker+0x19/0x30 [amneziawg] ``` [Full dmesg log](https://gist.github.com/Jipok/05606d3678aab16338023069486c5b51) Instead of using `awg-quick`, I am managing the interface via my [jwg](https://github.com/Jipok/jwg) with uses [forked wgctrl-go](https://github.com/Jipok/wgctrl-go) library.
Author
Owner

@Jipok commented on GitHub (Mar 28, 2026):

This crash triggers without bringing the interface down. It happens during a live config sync. M.b. because my tool sets ReplacePeers: true when applying the config.

<!-- gh-comment-id:4148098770 --> @Jipok commented on GitHub (Mar 28, 2026): This crash triggers without bringing the interface down. It happens during a live config sync. M.b. because my tool sets `ReplacePeers: true` when applying the config.
Author
Owner

@alandarev commented on GitHub (Mar 31, 2026):

Encountering the same issue, but during the initial handshake, not teardown. Details below.

I1/I2 parameters cause kernel buffer overflow in jp_spec_applymods → system crash

Environment

  • OS: Arch Linux
  • Kernel: 6.19.6-zen1-1-zen (linux-zen)
  • AmneziaWG module version: 1.0.20251009 (unsigned, DKMS)
  • Hardware: ASUS ROG CROSSHAIR X870E EXTREME, AMD CPU
  • Tunnel setup: running inside a network namespace via awg-quick

Description

Adding S3, S4, I1, I2 parameters to an AmneziaWG config (used for STUN/protocol
camouflage in the 2.0 protocol) causes a kernel page fault during a WireGuard handshake,
cascading into multiple oopses and leaving the system unresponsive.

Root cause (analysis)

I1/I2 use <r 12> to generate 12 random bytes, which calls
get_random_bytes → chacha_block_generic. It appears jp_spec_applymods allocates a
32-byte output buffer, but chacha_block_generic requires 64 bytes — resulting in
a write past the end of the buffer (rbx+0x20 → unmapped page).

The initial oops corrupted kernel memory, which cascaded into 5 more oopses across
unrelated processes (.NET TP Worker, waybar, fd), page table corruption, and
eventually a "scheduling while atomic" BUG that made the kernel unresponsive.

Kernel oops — oops #1 (root cause)

Mar 31 18:08:06 homearch kernel: BUG: unable to handle page fault for address: ffff8b7a048f5000
Mar 31 18:08:06 homearch kernel: #PF: supervisor write access in kernel mode
Mar 31 18:08:06 homearch kernel: #PF: error_code(0x0003) - permissions violation
Mar 31 18:08:06 homearch kernel: Oops: Oops: 0003 [#1] SMP NOPTI
Mar 31 18:08:06 homearch kernel: CPU: 23 UID: 0 PID: 265 Comm: kworker/u129:6 Kdump: loaded Tainted: G           OE       6.19.6-zen1-1-zen #1 PREEMPT(full)
Mar 31 18:08:06 homearch kernel: Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
Mar 31 18:08:06 homearch kernel: Hardware name: ASUS System Product Name/ROG CROSSHAIR X870E EXTREME, BIOS 2004 01/28/2026
Mar 31 18:08:06 homearch kernel: Workqueue: wg-kex-awg-est1 wg_packet_handshake_send_worker [amneziawg]
Mar 31 18:08:06 homearch kernel: RIP: 0010:chacha_block_generic+0x336/0x3d0
Mar 31 18:08:06 homearch kernel: RSP: 0018:ffffcf2601c2fbf0 EFLAGS: 00010282
Mar 31 18:08:06 homearch kernel: RAX: 00000000f13d250d RBX: ffff8b7a048f4fe0
Mar 31 18:08:06 homearch kernel: CR2: ffff8b7a048f5000
Mar 31 18:08:06 homearch kernel: Call Trace:
Mar 31 18:08:06 homearch kernel:  <TASK>
Mar 31 18:08:06 homearch kernel:  get_random_bytes+0xcf/0x140
Mar 31 18:08:06 homearch kernel:  jp_spec_applymods+0x31/0x70 [amneziawg e45aba78d56bbbddfa81e79467eeae52f9514548]
Mar 31 18:08:06 homearch kernel:  wg_packet_handshake_send_worker+0x103/0x4a0 [amneziawg e45aba78d56bbbddfa81e79467eeae52f9514548]
Mar 31 18:08:06 homearch kernel:  process_one_work+0x193/0x350
Mar 31 18:08:06 homearch kernel:  worker_thread+0x260/0x3f0
Mar 31 18:08:06 homearch kernel:  kthread+0xfc/0x240
Mar 31 18:08:06 homearch kernel:  ret_from_fork+0x243/0x280
Mar 31 18:08:06 homearch kernel:  ret_from_fork_asm+0x1a/0x30
Mar 31 18:08:06 homearch kernel:  </TASK>

The fault address ffff8b7a048f5000 is exactly 32 bytes past the RBX buffer base
ffff8b7a048f4fe0 (0xfe0 + 0x20 = 0x1000 → next page, unmapped).

Cascade — oopses #2–#6

The initial memory corruption propagated to unrelated processes within ~2 seconds:

  • #2 — .NET TP Worker: corrupted page table at 7f15f1a55968
  • #3 — waybar: general protection fault in dup_mmap (non-canonical address 0x72d58ae070a97f00)
  • #4 — .NET TP Worker (second instance): corrupted page table
  • #5 — fd: bad page map in rseq_set_ids_get_csaddr
  • #6 — kernel tried "Fixing recursive fault but reboot is needed!" → BUG: scheduling while atomic → unresponsive

Reproduction

  1. Add S3, S4, I1, I2 parameters to an AmneziaWG config (e.g. from the STUN
    camouflage feature in AmneziaWG 2.0).
  2. Bring the tunnel up: awg-quick up <config>.
  3. The crash occurs during the first handshake in wg_packet_handshake_send_worker.

Workaround

Remove S3, S4, I1, I2 from the config. No crashes observed after doing so.

<!-- gh-comment-id:4163895430 --> @alandarev commented on GitHub (Mar 31, 2026): Encountering the same issue, but during the initial handshake, not teardown. Details below. # `I1`/`I2` parameters cause kernel buffer overflow in `jp_spec_applymods` → system crash ## Environment - **OS:** Arch Linux - **Kernel:** `6.19.6-zen1-1-zen` (linux-zen) - **AmneziaWG module version:** `1.0.20251009` (unsigned, DKMS) - **Hardware:** ASUS ROG CROSSHAIR X870E EXTREME, AMD CPU - **Tunnel setup:** running inside a network namespace via `awg-quick` ## Description Adding `S3`, `S4`, `I1`, `I2` parameters to an AmneziaWG config (used for STUN/protocol camouflage in the 2.0 protocol) causes a kernel page fault during a WireGuard handshake, cascading into multiple oopses and leaving the system unresponsive. ## Root cause (analysis) `I1`/`I2` use `<r 12>` to generate 12 random bytes, which calls `get_random_bytes → chacha_block_generic`. It appears `jp_spec_applymods` allocates a **32-byte output buffer**, but `chacha_block_generic` requires **64 bytes** — resulting in a write past the end of the buffer (`rbx+0x20` → unmapped page). The initial oops corrupted kernel memory, which cascaded into 5 more oopses across unrelated processes (`.NET TP Worker`, `waybar`, `fd`), page table corruption, and eventually a "scheduling while atomic" BUG that made the kernel unresponsive. ## Kernel oops — oops #1 (root cause) ``` Mar 31 18:08:06 homearch kernel: BUG: unable to handle page fault for address: ffff8b7a048f5000 Mar 31 18:08:06 homearch kernel: #PF: supervisor write access in kernel mode Mar 31 18:08:06 homearch kernel: #PF: error_code(0x0003) - permissions violation Mar 31 18:08:06 homearch kernel: Oops: Oops: 0003 [#1] SMP NOPTI Mar 31 18:08:06 homearch kernel: CPU: 23 UID: 0 PID: 265 Comm: kworker/u129:6 Kdump: loaded Tainted: G OE 6.19.6-zen1-1-zen #1 PREEMPT(full) Mar 31 18:08:06 homearch kernel: Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE Mar 31 18:08:06 homearch kernel: Hardware name: ASUS System Product Name/ROG CROSSHAIR X870E EXTREME, BIOS 2004 01/28/2026 Mar 31 18:08:06 homearch kernel: Workqueue: wg-kex-awg-est1 wg_packet_handshake_send_worker [amneziawg] Mar 31 18:08:06 homearch kernel: RIP: 0010:chacha_block_generic+0x336/0x3d0 Mar 31 18:08:06 homearch kernel: RSP: 0018:ffffcf2601c2fbf0 EFLAGS: 00010282 Mar 31 18:08:06 homearch kernel: RAX: 00000000f13d250d RBX: ffff8b7a048f4fe0 Mar 31 18:08:06 homearch kernel: CR2: ffff8b7a048f5000 Mar 31 18:08:06 homearch kernel: Call Trace: Mar 31 18:08:06 homearch kernel: <TASK> Mar 31 18:08:06 homearch kernel: get_random_bytes+0xcf/0x140 Mar 31 18:08:06 homearch kernel: jp_spec_applymods+0x31/0x70 [amneziawg e45aba78d56bbbddfa81e79467eeae52f9514548] Mar 31 18:08:06 homearch kernel: wg_packet_handshake_send_worker+0x103/0x4a0 [amneziawg e45aba78d56bbbddfa81e79467eeae52f9514548] Mar 31 18:08:06 homearch kernel: process_one_work+0x193/0x350 Mar 31 18:08:06 homearch kernel: worker_thread+0x260/0x3f0 Mar 31 18:08:06 homearch kernel: kthread+0xfc/0x240 Mar 31 18:08:06 homearch kernel: ret_from_fork+0x243/0x280 Mar 31 18:08:06 homearch kernel: ret_from_fork_asm+0x1a/0x30 Mar 31 18:08:06 homearch kernel: </TASK> ``` The fault address `ffff8b7a048f5000` is exactly 32 bytes past the RBX buffer base `ffff8b7a048f4fe0` (`0xfe0 + 0x20 = 0x1000` → next page, unmapped). ## Cascade — oopses #2–#6 The initial memory corruption propagated to unrelated processes within ~2 seconds: - `#2` — `.NET TP Worker`: corrupted page table at `7f15f1a55968` - `#3` — `waybar`: general protection fault in `dup_mmap` (non-canonical address `0x72d58ae070a97f00`) - `#4` — `.NET TP Worker` (second instance): corrupted page table - `#5` — `fd`: bad page map in `rseq_set_ids_get_csaddr` - `#6` — kernel tried "Fixing recursive fault but reboot is needed!" → BUG: scheduling while atomic → unresponsive ## Reproduction 1. Add `S3`, `S4`, `I1`, `I2` parameters to an AmneziaWG config (e.g. from the STUN camouflage feature in AmneziaWG 2.0). 2. Bring the tunnel up: `awg-quick up <config>`. 3. The crash occurs during the first handshake in `wg_packet_handshake_send_worker`. ## Workaround Remove `S3`, `S4`, `I1`, `I2` from the config. No crashes observed after doing so.
Author
Owner

@h7lv2 commented on GitHub (May 20, 2026):

Me too. Seeing this across two consecutive boots, with slightly different crash signatures each time.

Environment:

  • OS: CachyOS, kernel 7.0.9-1-cachyos
  • Module: AMNEZIAWG-MODULE=1.0.20260329
  • Hardware: Lenovo 21LF (aka Lenovo ThinkBook 14 G6+ AHP)
  • AWG config: Parameters S1 through S4 as well as I1 are set, parameters I2 through I5 are commented out.

Boot −1: exact match — jp_spec_applymods race during active handshake

This is the crash that matches the issue description verbatim. The wg-kex workqueue was mid-handshake inside jp_spec_applymods when it faulted writing into freed ChaCha state:

May 20 23:01:54 kernel: BUG: unable to handle page fault for address: [...]
May 20 23:01:54 kernel: #PF: supervisor write access in kernel mode
May 20 23:01:54 kernel: #PF: error_code(0x0003) - permissions violation
May 20 23:01:54 kernel: Oops: 0003 [#1] SMP NOPTI
May 20 23:01:54 kernel: Workqueue: wg-kex-wg0 wg_packet_handshake_send_worker [amneziawg]
May 20 23:01:54 kernel: RIP: 0010:chacha_block_generic+0x9b/0x140

May 20 23:01:54 kernel: Call Trace:
May 20 23:01:54 kernel:  <TASK>
May 20 23:01:54 kernel:  _get_random_bytes.llvm.[...]+[...]
May 20 23:01:54 kernel:  jp_spec_applymods+0x5f/0x80 [amneziawg]
May 20 23:01:54 kernel:  wg_packet_handshake_send_worker+0xbb/0x... [amneziawg]
May 20 23:01:54 kernel:  process_scheduled_works+0x240/0x610
May 20 23:01:54 kernel:  worker_thread+0x198/0x3c0
May 20 23:01:54 kernel:  kthread+0xfb/0x120
May 20 23:01:54 kernel:  ret_from_fork+0x10c/0x2c0
May 20 23:01:54 kernel:  ret_from_fork_asm+0x1a/0x30
May 20 23:01:54 kernel:  </TASK>

This immediately cascaded: the [D]=DIE taint from the first oops caused follow-on GPFs in amdgpu (__mutex_lock, drm_sched_rq_update_fifo_locked) as other processes tried to use GPU resources on a now-corrupted kernel, ending with:

May 20 23:02:18 kernel: Fixing recursive fault but reboot is needed!
May 20 23:02:23 kernel: watchdog: BUG: soft lockup - CPU#6 stuck [...]
May 20 23:02:23 kernel:   #1–#5: 100% system, 0% softirq, 0% hardirq, 0% idle

Hard freeze, required power cycle.


Boot −2: different crash site — forced reboot while module stuck in partial init

This boot the tunnel hung during init at the bypass.sh / whitelist step (Error: Whitelist file not found). Attempting to ^C out of it left sudo itself hung dead. A normal reboot was triggered via the GUI — systemd then attempted to tear down awg-quick@wg0.service (still in a partially-initialized, hung state) during shutdown. Two page faults fired during that teardown:

Fault 1 — null/low-address deref during fish process exit (mod_node_page_state):

May 20 22:45:28 kernel: BUG: unable to handle page fault for address: 000000000002ab80
May 20 22:45:28 kernel: #PF: supervisor read access in kernel mode
May 20 22:45:28 kernel: #PF: error_code(0x0000) - not-present page
May 20 22:45:28 kernel: Oops: 0000 [#1] SMP NOPTI
May 20 22:45:28 kernel: RIP: 0010:mod_node_page_state+0x13/0xc0

May 20 22:45:28 kernel: Call Trace:
May 20 22:45:28 kernel:  exit_task_stack_account+0x13d/0x1b0
May 20 22:45:28 kernel:  do_exit+0x4a5/0x5b0
May 20 22:45:28 kernel:  __x64_sys_exit+0x17/0x20

Fault 2 — deferred vfree writing to an invalid PFN:

May 20 22:45:28 kernel: BUG: unable to handle page fault for address: fffff59d00000034
May 20 22:45:28 kernel: #PF: supervisor write access in kernel mode
May 20 22:45:28 kernel: #PF: error_code(0x0002) - not-present page
May 20 22:45:28 kernel: Oops: 0002 [#2] SMP NOPTI
May 20 22:45:28 kernel: Workqueue: events delayed_vfree_work
May 20 22:45:28 kernel: RIP: 0010:__free_contig_range+0x3f/0x4e0

May 20 22:45:28 kernel: Call Trace:
May 20 22:45:28 kernel:  vfree.cold+0x61c/0xadd
May 20 22:45:28 kernel:  delayed_vfree_work+0x27/0x40
May 20 22:45:28 kernel:  process_scheduled_works+0x240/0x610

Then Fixing recursive fault but reboot is needed!. Again required power cycle.

The call traces don't name amneziawg directly, but the module is loaded (kernel tainted [O]=OOT_MODULE [E]=UNSIGNED_MODULE) and the crashes fire during systemd's forced teardown of the hung service. The corrupted PFN in fault 2 (fffff59d00000034) suggests a bogus page struct pointer (possibly a buffer whose backing pages were already returned mid-init) consistent with the same class of lifecycle bug.


Neither incident involved a clean awg-quick down: one was a forced reboot with the module stuck mid-init, one was an active tunnel that spontaneously oopsed during handshake. I think the bug surface is wider than just teardown of a fully-established tunnel.


log-boot-minus1.txt
log-boot-minus2.txt

<!-- gh-comment-id:4502540037 --> @h7lv2 commented on GitHub (May 20, 2026): Me too. Seeing this across two consecutive boots, with slightly different crash signatures each time. Environment: - OS: CachyOS, kernel `7.0.9-1-cachyos` - Module: `AMNEZIAWG-MODULE=1.0.20260329` - Hardware: Lenovo 21LF (aka Lenovo ThinkBook 14 G6+ AHP) - AWG config: Parameters `S1` through `S4` as well as `I1` are set, parameters `I2` through `I5` are commented out. --- ### Boot −1: exact match — `jp_spec_applymods` race during active handshake This is the crash that matches the issue description verbatim. The `wg-kex` workqueue was mid-handshake inside `jp_spec_applymods` when it faulted writing into freed ChaCha state: ``` May 20 23:01:54 kernel: BUG: unable to handle page fault for address: [...] May 20 23:01:54 kernel: #PF: supervisor write access in kernel mode May 20 23:01:54 kernel: #PF: error_code(0x0003) - permissions violation May 20 23:01:54 kernel: Oops: 0003 [#1] SMP NOPTI May 20 23:01:54 kernel: Workqueue: wg-kex-wg0 wg_packet_handshake_send_worker [amneziawg] May 20 23:01:54 kernel: RIP: 0010:chacha_block_generic+0x9b/0x140 May 20 23:01:54 kernel: Call Trace: May 20 23:01:54 kernel: <TASK> May 20 23:01:54 kernel: _get_random_bytes.llvm.[...]+[...] May 20 23:01:54 kernel: jp_spec_applymods+0x5f/0x80 [amneziawg] May 20 23:01:54 kernel: wg_packet_handshake_send_worker+0xbb/0x... [amneziawg] May 20 23:01:54 kernel: process_scheduled_works+0x240/0x610 May 20 23:01:54 kernel: worker_thread+0x198/0x3c0 May 20 23:01:54 kernel: kthread+0xfb/0x120 May 20 23:01:54 kernel: ret_from_fork+0x10c/0x2c0 May 20 23:01:54 kernel: ret_from_fork_asm+0x1a/0x30 May 20 23:01:54 kernel: </TASK> ``` This immediately cascaded: the `[D]=DIE` taint from the first oops caused follow-on GPFs in `amdgpu` (`__mutex_lock`, `drm_sched_rq_update_fifo_locked`) as other processes tried to use GPU resources on a now-corrupted kernel, ending with: ``` May 20 23:02:18 kernel: Fixing recursive fault but reboot is needed! May 20 23:02:23 kernel: watchdog: BUG: soft lockup - CPU#6 stuck [...] May 20 23:02:23 kernel: #1–#5: 100% system, 0% softirq, 0% hardirq, 0% idle ``` Hard freeze, required power cycle. --- ### Boot −2: different crash site — forced reboot while module stuck in partial init This boot the tunnel hung during init at the `bypass.sh` / whitelist step (`Error: Whitelist file not found`). Attempting to ^C out of it left `sudo` itself hung dead. A normal reboot was triggered via the GUI — systemd then attempted to tear down `awg-quick@wg0.service` (still in a partially-initialized, hung state) during shutdown. Two page faults fired during that teardown: **Fault 1** — null/low-address deref during `fish` process exit (mod_node_page_state): ``` May 20 22:45:28 kernel: BUG: unable to handle page fault for address: 000000000002ab80 May 20 22:45:28 kernel: #PF: supervisor read access in kernel mode May 20 22:45:28 kernel: #PF: error_code(0x0000) - not-present page May 20 22:45:28 kernel: Oops: 0000 [#1] SMP NOPTI May 20 22:45:28 kernel: RIP: 0010:mod_node_page_state+0x13/0xc0 May 20 22:45:28 kernel: Call Trace: May 20 22:45:28 kernel: exit_task_stack_account+0x13d/0x1b0 May 20 22:45:28 kernel: do_exit+0x4a5/0x5b0 May 20 22:45:28 kernel: __x64_sys_exit+0x17/0x20 ``` **Fault 2** — deferred vfree writing to an invalid PFN: ``` May 20 22:45:28 kernel: BUG: unable to handle page fault for address: fffff59d00000034 May 20 22:45:28 kernel: #PF: supervisor write access in kernel mode May 20 22:45:28 kernel: #PF: error_code(0x0002) - not-present page May 20 22:45:28 kernel: Oops: 0002 [#2] SMP NOPTI May 20 22:45:28 kernel: Workqueue: events delayed_vfree_work May 20 22:45:28 kernel: RIP: 0010:__free_contig_range+0x3f/0x4e0 May 20 22:45:28 kernel: Call Trace: May 20 22:45:28 kernel: vfree.cold+0x61c/0xadd May 20 22:45:28 kernel: delayed_vfree_work+0x27/0x40 May 20 22:45:28 kernel: process_scheduled_works+0x240/0x610 ``` Then `Fixing recursive fault but reboot is needed!`. Again required power cycle. The call traces don't name amneziawg directly, but the module is loaded (kernel tainted `[O]=OOT_MODULE [E]=UNSIGNED_MODULE`) and the crashes fire during systemd's forced teardown of the hung service. The corrupted PFN in fault 2 (`fffff59d00000034`) suggests a bogus page struct pointer (possibly a buffer whose backing pages were already returned mid-init) consistent with the same class of lifecycle bug. --- Neither incident involved a clean `awg-quick down`: one was a forced reboot with the module stuck mid-init, one was an active tunnel that spontaneously oopsed during handshake. I think the bug surface is wider than just teardown of a fully-established tunnel. --- [log-boot-minus1.txt](https://github.com/user-attachments/files/28073789/log-boot-minus1.txt) [log-boot-minus2.txt](https://github.com/user-attachments/files/28073788/log-boot-minus2.txt)
Author
Owner

@JoshuaJakowlew commented on GitHub (Jun 1, 2026):

Faced the same problem on Arch Linux with 7.0.10-arch1-1 kernel. System randomly freeze with active wag interface. Looks like freeze may happen at any time - in some minutes, or in 10-20 hours, regardless of traffic amount.

Here is relevant part of client config:

Jc = 3
Jmin = 38
Jmax = 117
S1 = 107
S2 = 19
S3 = 47
S4 = 12
H1 = 15509220-660337579
H2 = 934957363-971088547
H3 = 1074199209-1775446985
H4 = 1881458520-2053497862
I1 = <r 68>
<!-- gh-comment-id:4591288777 --> @JoshuaJakowlew commented on GitHub (Jun 1, 2026): Faced the same problem on Arch Linux with `7.0.10-arch1-1` kernel. System randomly freeze with active wag interface. Looks like freeze may happen at any time - in some minutes, or in 10-20 hours, regardless of traffic amount. Here is relevant part of client config: ``` Jc = 3 Jmin = 38 Jmax = 117 S1 = 107 S2 = 19 S3 = 47 S4 = 12 H1 = 15509220-660337579 H2 = 934957363-971088547 H3 = 1074199209-1775446985 H4 = 1881458520-2053497862 I1 = <r 68> ```
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amneziawg-linux-kernel-module#85
No description provided.