[PR #187] [CLOSED] fix: heap buffer overflow via negative-length junk-packet tags #224

Closed
opened 2026-10-13 21:07:47 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/pull/187
Author: @pattyboi
Created: 7/20/2026
Status: ❌ Closed

Base: master ← Head: fix/junk-tag-negative-length-heap-overflow


📝 Commits (1)

  • e81f737 fix: heap buffer overflow via negative-length junk-packet tags

📊 Changes

1 file changed (+7 additions, -1 deletions)

View changed files

📝 src/junk.c (+7 -1)

📄 Description

parse_r_tag(), parse_rc_tag(), and parse_rd_tag() parse the length
argument of , , and junk-packet tags (used in the
I1-I5 config options) via kstrtoint(), which accepts negative decimal
values. The result was stored into tag->pkt_size unchecked.

jp_spec_setup() sums every tag's pkt_size into a single int and
allocates a buffer of that size, bounds-checking only the sum against
MESSAGE_MAX_SIZE (never checking for a negative sum), then a second
pass copies each tag's individual size into the allocated buffer.

This lets a config combine a large real tag (e.g. <b 0x...1000 bytes
of hex...>) with a negative-length tag so the summed pkt_size
comes out small and positive (passing the bounds check and producing
a small kzalloc'd buffer), while the fill loop still memcpy()s the
full-size real tag into that undersized buffer -- an immediate heap
buffer overflow. A negative-length tag surviving into the modifier
list can also reach random_byte_modifier() -> get_random_bytes(buf,
len), where the negative int len sign-extends to a huge size_t,
causing a massive out-of-bounds write.

Since I1-I5 come directly from a .conf file's [Interface] section,
this is reachable by anyone who applies an AmneziaWG profile from an
untrusted source (a shared/downloaded config), not just local root
misconfiguration.

Fix: reject len < 0 (and > MESSAGE_MAX_SIZE) in all three tag parsers,
and add a matching lower-bound check on the aggregate pkt_size in
jp_spec_setup() as defense in depth.

Verified: on an unpatched module, 'awg set i1 "<r -100>"' is
silently accepted; with this fix it's rejected with -EINVAL, while
valid tags like '<r 50>' continue to work normally.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/pull/187 **Author:** [@pattyboi](https://github.com/pattyboi) **Created:** 7/20/2026 **Status:** ❌ Closed **Base:** `master` ← **Head:** `fix/junk-tag-negative-length-heap-overflow` --- ### 📝 Commits (1) - [`e81f737`](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/commit/e81f7376f6091e11bd7421086d990dc13e2d4ddd) fix: heap buffer overflow via negative-length junk-packet tags ### 📊 Changes **1 file changed** (+7 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `src/junk.c` (+7 -1) </details> ### 📄 Description parse_r_tag(), parse_rc_tag(), and parse_rd_tag() parse the length argument of <r N>, <rc N>, and <rd N> junk-packet tags (used in the I1-I5 config options) via kstrtoint(), which accepts negative decimal values. The result was stored into tag->pkt_size unchecked. jp_spec_setup() sums every tag's pkt_size into a single int and allocates a buffer of that size, bounds-checking only the sum against MESSAGE_MAX_SIZE (never checking for a negative sum), then a second pass copies each tag's *individual* size into the allocated buffer. This lets a config combine a large real tag (e.g. <b 0x...1000 bytes of hex...>) with a negative-length <r> tag so the summed pkt_size comes out small and positive (passing the bounds check and producing a small kzalloc'd buffer), while the fill loop still memcpy()s the full-size real tag into that undersized buffer -- an immediate heap buffer overflow. A negative-length <r> tag surviving into the modifier list can also reach random_byte_modifier() -> get_random_bytes(buf, len), where the negative int len sign-extends to a huge size_t, causing a massive out-of-bounds write. Since I1-I5 come directly from a .conf file's [Interface] section, this is reachable by anyone who applies an AmneziaWG profile from an untrusted source (a shared/downloaded config), not just local root misconfiguration. Fix: reject len < 0 (and > MESSAGE_MAX_SIZE) in all three tag parsers, and add a matching lower-bound check on the aggregate pkt_size in jp_spec_setup() as defense in depth. Verified: on an unpatched module, 'awg set <if> i1 "<r -100>"' is silently accepted; with this fix it's rejected with -EINVAL, while valid tags like '<r 50>' continue to work normally. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-13 21:07:47 +00:00
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#224
No description provided.