[GH-ISSUE #69] Heap overflow: device-level I1–I5 attributes are written to the 4 KB netlink buffer without bounds checks #30

Open
opened 2026-10-13 21:02:33 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @rudenko-ks on GitHub (Aug 22, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amneziawg-tools/issues/69

Summary

awg set and awg setconf abort with Segmentation fault or glibc's
Aborted (free(): invalid pointer / double free or corruption) when the
combined size of the I1–I5 junk-packet strings is large enough to push the
netlink request past the message buffer.

The device-level AmneziaWG attributes are written with the unchecked
mnl_attr_put* family, unlike every peer attribute in the same function.

Where

The buffer is min(pagesize, 8192) bytes — 4096 on x86-64:

/* src/netlink.h:70-80 */
static size_t mnl_ideal_socket_buffer_size(void)
{
	size = (size_t)sysconf(_SC_PAGESIZE);
	if (size > 8192)
		size = 8192;
	return size;
}

/* src/netlink.h:754 */
nlg->buf = malloc(mnl_ideal_socket_buffer_size());

The junk strings go in unchecked:

/* src/ipc-linux.h:214-223 */
if (dev->flags & WGDEVICE_HAS_I1)
	mnl_attr_put_strz(nlh, WGDEVICE_A_I1, dev->i1);
if (dev->flags & WGDEVICE_HAS_I2)
	mnl_attr_put_strz(nlh, WGDEVICE_A_I2, dev->i2);
/* … I3, I4, I5 the same */

dev->i1…dev->i5 are char * holding the literal CPS text
(src/containers.h:135), so a Pro-style QUIC profile puts roughly 3.9 KB of
string into a 4 KB buffer that already holds the interface name, private key,
Jc/Jmin/Jmax, S1–S4 and H1–H4.

The peer path in the same function has what the device path lacks: a
bounds-checked nest and a recovery path that finishes the current message and
starts another.

/* src/ipc-linux.h:256 */
peer_nest = mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, 0);
...
/* src/ipc-linux.h:351 — after toobig_*: cancel the nest, send, continue */
goto again;

To be precise, not every peer attribute is checked either — ipc-linux.h:252
and :277-282 use the unchecked variants. But the peer path as a whole can
detect an overflow and split the message, so an oversized peer set degrades
into several messages instead of corrupting the heap. The device-level block
has no check and no split path at all, and I1–I5 are the only device
attributes large enough to overflow.

How to reproduce

On x86-64 Linux with the kernel module loaded:

ip link add awgtest type amneziawg
awg set awgtest private-key <(awg genkey) \
  jc 7 jmin 15 jmax 90 s1 56 s2 80 s3 45 s4 12 \
  h1 5472-69603 h2 117305-167126 h3 219536-273873 h4 316177-387655 \
  i1 "<b 0x$(head -c 1198 /dev/urandom | xxd -p -c 99999)>" \
  i2 "<b 0x$(head -c 604  /dev/urandom | xxd -p -c 99999)>" \
  i3 "<b 0x$(head -c 100  /dev/urandom | xxd -p -c 99999)>" \
  i4 "<b 0x$(head -c 100  /dev/urandom | xxd -p -c 99999)>" \
  i5 "<b 0x$(head -c 100  /dev/urandom | xxd -p -c 99999)>"

Sweeping i5 upward in 4-hex-character steps with i1–i4 held constant, on
amneziawg-tools v3.1.20260812, the transition is sharp and reproducible —
three runs at each step agreed:

combined I1–I5 = 1938 bytes of decoded payload → no crash, 3/3
combined I1–I5 = 1948 bytes of decoded payload → crashed,  3/3

Units matter here and I got them wrong in an earlier draft, so to be explicit:
these are decoded payload bytes, i.e. hex digits / 2. The same quantity as
characters of config text is roughly twice as large plus tag overhead —
1938 payload bytes is about 3906 characters, which is why these figures sit
above the 3868-character crash threshold in the table further down (that sweep
used a full config including a peer; this one sets device attributes only, which
leaves more room).

"No crash" is the honest label rather than "applied": as established below, the
configuration is applied on both sides of this boundary.

The cutoff is not a fixed I-payload size — it is the total message size.
Repeating the sweep while changing only the interface name (whose attribute
occupies 4 + align4(len+1), i.e. 8 / 12 / 20 bytes) moves the I-payload
ceiling in exact lockstep:

interface name len last non-crashing I1–I5 total resulting message size
sw 2 1938 B payload 4088 B
awgb2 5 1936 B payload 4088 B
abcdefghijklmno 15 1932 B payload 4088 B

Three different I-payload ceilings, one identical message size, 8 bytes under
the 4096-byte page — and the probe step was 4 bytes, so the true boundary sits
in 4088…4096. The ratio is 1:2 because the I fields are carried as hex text, so
each extra byte elsewhere in the message costs half a byte of junk payload.

In this setup the H encoding made no difference (h1 5472 and
h1 5472-69603 produced identical ceilings), so the wire encoding appears not
to follow how the value was written.

awg setconf with the same fields in a file fails identically, so this is not
the config parser.

Expected behavior

Either the request is rejected with a clear error ("configuration too large"),
or the message is split the way the peer path already splits it. What should not
happen is writing past the allocated buffer.

Actual behavior

Heap corruption. awg aborts in glibc — but note when: the abort happens in
the tool's own free path, after the netlink message has already been sent
and accepted by the kernel. So the configuration is applied even in the crashing
case. The overflow is a memory-safety bug in the tool, not a failure to
configure the device.

Correction to an earlier version of this report

An earlier draft claimed a middle band where setconf returns 0 and the device
is left completely unconfigured. That was a measurement error on my side and I
withdraw it.
I had read back device state with awg showconf capturing stdout
only. Re-running with the readback's own exit status and stderr captured shows
the device is fully configured; what breaks is reading it. Apologies for the
noise — the corrected picture is below, and it points at a second bug that the
suggested fix here does not address.

The size behaviour, remeasured

Measured on v3.1.20260812 + current kernel module, Ubuntu 24.04, kernel 6.8.
One awg setconf per step with a complete client config (private key, address,
Jc/Jmin/Jmax, S1-S4, H1-H4, five I fields, one peer with a preshared key,
AllowedIPs = 0.0.0.0/0, ::/0, endpoint, keepalive). Only the combined length of
the I1–I5 strings (characters in the config, not decoded payload bytes)
varies; values are well-formed <b 0xHEX> tags:

combined I1-I5 string length, characters setconf exit applied? readable?
≤ 3598 0 yes yes
3600 – 3866 0 yes, fully no: awg show hangs, then EMSGSIZE
≥ 3868 134 yes, fully no

Two independent witnesses that the device really is configured in the upper
bands, neither of which goes through the failing GET path:

  • Shortening one field (awg set <if> i1 '<b 0xdeadbeef>') makes the interface
    readable again immediately: the private key matches what was written, the peer
    public key matches, and I2–I5 still hold their exact character counts.
  • A peer of an unreadable interface reports latest handshake: 7 seconds ago,
    212 B received, 203 B sent, and ip -s link shows TX 4380 B / 20 packets,
    0 errors. A device with no private key cannot complete a handshake.

A genuinely unconfigured device reads back as (none) with exit status 0, which
is plainly distinguishable from both failure modes above.

The GET path fails ~270 characters earlier, and that is the first thing users hit

WGDEVICE_GET builds its reply as a single message: netlink.c:421 sets
int ret = -EMSGSIZE; and the device-attribute block at :464-474 has no way
to continue into a second message, unlike the peer loop at :516-523 which
resumes correctly. Once I1–I5 no longer fit, the whole dump fails.

The practical consequence is that awg show hangs in the 3600–3866 band
(killed by timeout, empty stderr) before it starts returning EMSGSIZE from
~3770. Anything that polls the interface — status pages, monitoring, wrapper
scripts — hangs with it.

This is worth stating plainly because it affects the fix: bounds-checking the
device attributes in the tool (the change suggested below) removes the heap
overflow at ~3868 characters, but a user hits the unreadable-interface bug at
~3598 characters first. Both sides need the same treatment — the device-level
attribute block needs to be splittable, in the tool and in the module's GET
path.

On the host hang mentioned in the original report

The original report described a box that became unreachable — ICMP fine, TCP on
:22 accepted, SSH banner never completing. No hang occurred in these runs, so I
still cannot demonstrate the causal chain. But the fact that awg show hangs
rather than failing in the middle band is at least a plausible mechanism: any
supervisor that polls the interface accumulates stuck processes. Offering that
as a hypothesis only, not as a claim.

Suggested fix

Use the _check variants for the device-level attributes, mirroring the peer
path:

if (dev->flags & WGDEVICE_HAS_I1)
	if (!mnl_attr_put_strz_check(nlh, SOCKET_BUFFER_SIZE, WGDEVICE_A_I1, dev->i1))
		goto toobig_device;

with toobig_device sending what has accumulated and continuing in a fresh
message, as toobig_allowedips and toobig_peers already do.

That fixes the memory-safety bug, which is the part this issue is about. It
does not fix the unreadable interface, since that lives in the module's GET
path — I am happy to file that separately against the kernel module if you would
prefer it kept apart. Mentioning it here only so the ~3598-character failure
isn't mistaken for something this change already covers.

Checked the tracker before filing — the existing I1–I5 reports are about
different failures:

  • #40 — awg-quick crashes when I1–I5 are empty; this one is about
    them being large.
  • #35 — awg-quick fails with a clean Unable to modify interface: Invalid argument on tagged junk strings; no crash and no memory-safety symptom.
  • #59 / #50 / #38 — handling of empty values, all closed.

Environment

  • amneziawg-tools v3.1.20260812, source inspected at commit ee0f0a9
  • amneziawg-linux-kernel-module, Ubuntu 24.04, kernel 6.8.0-138, x86-64
  • page size 4096 (getconf PAGESIZE)
Originally created by @rudenko-ks on GitHub (Aug 22, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amneziawg-tools/issues/69 ## Summary `awg set` and `awg setconf` abort with `Segmentation fault` or glibc's `Aborted` (`free(): invalid pointer` / `double free or corruption`) when the combined size of the `I1`–`I5` junk-packet strings is large enough to push the netlink request past the message buffer. The device-level AmneziaWG attributes are written with the **unchecked** `mnl_attr_put*` family, unlike every peer attribute in the same function. ## Where The buffer is `min(pagesize, 8192)` bytes — 4096 on x86-64: ```c /* src/netlink.h:70-80 */ static size_t mnl_ideal_socket_buffer_size(void) { size = (size_t)sysconf(_SC_PAGESIZE); if (size > 8192) size = 8192; return size; } /* src/netlink.h:754 */ nlg->buf = malloc(mnl_ideal_socket_buffer_size()); ``` The junk strings go in unchecked: ```c /* src/ipc-linux.h:214-223 */ if (dev->flags & WGDEVICE_HAS_I1) mnl_attr_put_strz(nlh, WGDEVICE_A_I1, dev->i1); if (dev->flags & WGDEVICE_HAS_I2) mnl_attr_put_strz(nlh, WGDEVICE_A_I2, dev->i2); /* … I3, I4, I5 the same */ ``` `dev->i1`…`dev->i5` are `char *` holding the literal CPS text (`src/containers.h:135`), so a Pro-style QUIC profile puts roughly 3.9 KB of string into a 4 KB buffer that already holds the interface name, private key, `Jc`/`Jmin`/`Jmax`, `S1`–`S4` and `H1`–`H4`. The peer path in the same function has what the device path lacks: a bounds-checked nest and a recovery path that finishes the current message and starts another. ```c /* src/ipc-linux.h:256 */ peer_nest = mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, 0); ... /* src/ipc-linux.h:351 — after toobig_*: cancel the nest, send, continue */ goto again; ``` To be precise, not every peer attribute is checked either — `ipc-linux.h:252` and `:277-282` use the unchecked variants. But the peer path as a whole can detect an overflow and split the message, so an oversized peer set degrades into several messages instead of corrupting the heap. The device-level block has no check and no split path at all, and `I1`–`I5` are the only device attributes large enough to overflow. ## How to reproduce On x86-64 Linux with the kernel module loaded: ```bash ip link add awgtest type amneziawg awg set awgtest private-key <(awg genkey) \ jc 7 jmin 15 jmax 90 s1 56 s2 80 s3 45 s4 12 \ h1 5472-69603 h2 117305-167126 h3 219536-273873 h4 316177-387655 \ i1 "<b 0x$(head -c 1198 /dev/urandom | xxd -p -c 99999)>" \ i2 "<b 0x$(head -c 604 /dev/urandom | xxd -p -c 99999)>" \ i3 "<b 0x$(head -c 100 /dev/urandom | xxd -p -c 99999)>" \ i4 "<b 0x$(head -c 100 /dev/urandom | xxd -p -c 99999)>" \ i5 "<b 0x$(head -c 100 /dev/urandom | xxd -p -c 99999)>" ``` Sweeping `i5` upward in 4-hex-character steps with `i1`–`i4` held constant, on `amneziawg-tools` v3.1.20260812, the transition is sharp and reproducible — three runs at each step agreed: ``` combined I1–I5 = 1938 bytes of decoded payload → no crash, 3/3 combined I1–I5 = 1948 bytes of decoded payload → crashed, 3/3 ``` Units matter here and I got them wrong in an earlier draft, so to be explicit: these are **decoded payload bytes**, i.e. hex digits / 2. The same quantity as *characters of config text* is roughly twice as large plus tag overhead — 1938 payload bytes is about 3906 characters, which is why these figures sit above the 3868-character crash threshold in the table further down (that sweep used a full config including a peer; this one sets device attributes only, which leaves more room). "No crash" is the honest label rather than "applied": as established below, the configuration is applied on *both* sides of this boundary. **The cutoff is not a fixed I-payload size — it is the total message size.** Repeating the sweep while changing only the interface name (whose attribute occupies `4 + align4(len+1)`, i.e. 8 / 12 / 20 bytes) moves the I-payload ceiling in exact lockstep: | interface | name len | last non-crashing I1–I5 total | resulting message size | |---|---|---|---| | `sw` | 2 | 1938 B payload | 4088 B | | `awgb2` | 5 | 1936 B payload | 4088 B | | `abcdefghijklmno` | 15 | 1932 B payload | 4088 B | Three different I-payload ceilings, one identical message size, 8 bytes under the 4096-byte page — and the probe step was 4 bytes, so the true boundary sits in 4088…4096. The ratio is 1:2 because the I fields are carried as hex text, so each extra byte elsewhere in the message costs half a byte of junk payload. In this setup the `H` encoding made no difference (`h1 5472` and `h1 5472-69603` produced identical ceilings), so the wire encoding appears not to follow how the value was written. `awg setconf` with the same fields in a file fails identically, so this is not the config parser. ## Expected behavior Either the request is rejected with a clear error ("configuration too large"), or the message is split the way the peer path already splits it. What should not happen is writing past the allocated buffer. ## Actual behavior Heap corruption. `awg` aborts in glibc — but note *when*: the abort happens in the tool's own free path, **after** the netlink message has already been sent and accepted by the kernel. So the configuration is applied even in the crashing case. The overflow is a memory-safety bug in the tool, not a failure to configure the device. ### Correction to an earlier version of this report An earlier draft claimed a middle band where `setconf` returns 0 and the device is left completely unconfigured. **That was a measurement error on my side and I withdraw it.** I had read back device state with `awg showconf` capturing stdout only. Re-running with the readback's own exit status and stderr captured shows the device is fully configured; what breaks is *reading* it. Apologies for the noise — the corrected picture is below, and it points at a second bug that the suggested fix here does not address. ### The size behaviour, remeasured Measured on `v3.1.20260812` + current kernel module, Ubuntu 24.04, kernel 6.8. One `awg setconf` per step with a complete client config (private key, address, `Jc/Jmin/Jmax`, `S1-S4`, `H1-H4`, five `I` fields, one peer with a preshared key, `AllowedIPs = 0.0.0.0/0, ::/0`, endpoint, keepalive). Only the combined length of the `I1`–`I5` **strings** (characters in the config, not decoded payload bytes) varies; values are well-formed `<b 0xHEX>` tags: | combined `I1`-`I5` string length, characters | `setconf` exit | applied? | readable? | |---|---|---|---| | ≤ 3598 | 0 | yes | yes | | 3600 – 3866 | 0 | **yes, fully** | **no: `awg show` hangs, then EMSGSIZE** | | ≥ 3868 | 134 | **yes, fully** | no | Two independent witnesses that the device really is configured in the upper bands, neither of which goes through the failing GET path: - Shortening one field (`awg set <if> i1 '<b 0xdeadbeef>'`) makes the interface readable again immediately: the private key matches what was written, the peer public key matches, and `I2`–`I5` still hold their exact character counts. - A peer of an unreadable interface reports `latest handshake: 7 seconds ago`, `212 B received, 203 B sent`, and `ip -s link` shows TX 4380 B / 20 packets, 0 errors. A device with no private key cannot complete a handshake. A genuinely unconfigured device reads back as `(none)` with exit status 0, which is plainly distinguishable from both failure modes above. ### The GET path fails ~270 characters earlier, and that is the first thing users hit `WGDEVICE_GET` builds its reply as a single message: `netlink.c:421` sets `int ret = -EMSGSIZE;` and the device-attribute block at `:464-474` has no way to continue into a second message, unlike the peer loop at `:516-523` which resumes correctly. Once `I1`–`I5` no longer fit, the whole dump fails. The practical consequence is that **`awg show` hangs** in the 3600–3866 band (killed by timeout, empty stderr) before it starts returning EMSGSIZE from ~3770. Anything that polls the interface — status pages, monitoring, wrapper scripts — hangs with it. This is worth stating plainly because it affects the fix: bounds-checking the device attributes in the tool (the change suggested below) removes the heap overflow at ~3868 characters, but a user hits the unreadable-interface bug at ~3598 characters first. Both sides need the same treatment — the device-level attribute block needs to be splittable, in the tool and in the module's GET path. ### On the host hang mentioned in the original report The original report described a box that became unreachable — ICMP fine, TCP on :22 accepted, SSH banner never completing. No hang occurred in these runs, so I still cannot demonstrate the causal chain. But the fact that `awg show` *hangs* rather than failing in the middle band is at least a plausible mechanism: any supervisor that polls the interface accumulates stuck processes. Offering that as a hypothesis only, not as a claim. ## Suggested fix Use the `_check` variants for the device-level attributes, mirroring the peer path: ```c if (dev->flags & WGDEVICE_HAS_I1) if (!mnl_attr_put_strz_check(nlh, SOCKET_BUFFER_SIZE, WGDEVICE_A_I1, dev->i1)) goto toobig_device; ``` with `toobig_device` sending what has accumulated and continuing in a fresh message, as `toobig_allowedips` and `toobig_peers` already do. That fixes the memory-safety bug, which is the part this issue is about. It does not fix the unreadable interface, since that lives in the module's GET path — I am happy to file that separately against the kernel module if you would prefer it kept apart. Mentioning it here only so the ~3598-character failure isn't mistaken for something this change already covers. ## Related, but not duplicates Checked the tracker before filing — the existing `I1`–`I5` reports are about different failures: - **#40** — `awg-quick` crashes when `I1`–`I5` are *empty*; this one is about them being *large*. - **#35** — `awg-quick` fails with a clean `Unable to modify interface: Invalid argument` on tagged junk strings; no crash and no memory-safety symptom. - **#59 / #50 / #38** — handling of empty values, all closed. ## Environment - `amneziawg-tools` v3.1.20260812, source inspected at commit `ee0f0a9` - `amneziawg-linux-kernel-module`, Ubuntu 24.04, kernel 6.8.0-138, x86-64 - page size 4096 (`getconf PAGESIZE`)
Author
Owner

@rudenko-ks commented on GitHub (Aug 31, 2026):

Follow-up on the read side, which this report mentions only as "awg show
hangs and eventually fails with EMSGSIZE". I have since traced what actually
happens, and it is two separate things.

The hang is the kernel, not the tool. When the device attributes leave no
room for the first peer, wg_get_device_dump neither advances its cursor nor
fails: it returns skb->len, netlink asks again, and the same message is
produced forever. Measured: 20 000 identical 3932-byte messages in 0.554 s.
Filed separately against the kernel module — .

The 4 KB is ours, not a kernel limit. The figure in the title is the buffer
this tool hands to recvmsg: min(getpagesize(), 8192), which is 4096 on
x86-64. The kernel sizes the dump skb from what the reader advertises
(nlk->max_recvmsg_len in netlink_dump), so the ceiling is a consequence of
that choice. A reader that asks for more gets more — with a larger buffer the
readable size rises to roughly 31 980 bytes, and the practical limit on I1–I5
disappears.

The tool also leaks while it spins. read_device_cb duplicates the strings
out of every message it receives and nothing frees them, so the endless dump is
not merely an endless loop — it grows. Measured at roughly 164 MB/s; a reader
left running reached 599 MB RSS before it was killed.

So there are two fixes on this side, both independent of the kernel one:

  1. Ask for a larger receive buffer, so an ordinary AWG 2.0/3.x configuration is
    readable at all.
  2. Free what read_device_cb duplicates, so a malformed or oversized dump
    cannot exhaust memory.

The threshold, for reference, is not a constant but a formula:

limit = 3808 − nlaBytes(ifname) − 36·[HeaderProtectionKey set] − P
P = 148 (peer has no endpoint) / 168 (IPv4 endpoint) / 180 (IPv6)

The last term is why this surfaces without any configuration change: the kernel
writes the endpoint at handshake time, so an interface that reads fine before a
client connects can stop being readable afterwards.

Environment: kernel 6.8.0-138, module and tools amneziawg 3.1.20260812.

<!-- gh-comment-id:5479531543 --> @rudenko-ks commented on GitHub (Aug 31, 2026): Follow-up on the read side, which this report mentions only as "`awg show` hangs and eventually fails with EMSGSIZE". I have since traced what actually happens, and it is two separate things. **The hang is the kernel, not the tool.** When the device attributes leave no room for the first peer, `wg_get_device_dump` neither advances its cursor nor fails: it returns `skb->len`, netlink asks again, and the same message is produced forever. Measured: 20 000 identical 3932-byte messages in 0.554 s. Filed separately against the kernel module — <LINK TO NEW ISSUE>. **The 4 KB is ours, not a kernel limit.** The figure in the title is the buffer this tool hands to `recvmsg`: `min(getpagesize(), 8192)`, which is 4096 on x86-64. The kernel sizes the dump skb from what the reader advertises (`nlk->max_recvmsg_len` in `netlink_dump`), so the ceiling is a consequence of that choice. A reader that asks for more gets more — with a larger buffer the readable size rises to roughly 31 980 bytes, and the practical limit on I1–I5 disappears. **The tool also leaks while it spins.** `read_device_cb` duplicates the strings out of every message it receives and nothing frees them, so the endless dump is not merely an endless loop — it grows. Measured at roughly 164 MB/s; a reader left running reached 599 MB RSS before it was killed. So there are two fixes on this side, both independent of the kernel one: 1. Ask for a larger receive buffer, so an ordinary AWG 2.0/3.x configuration is readable at all. 2. Free what `read_device_cb` duplicates, so a malformed or oversized dump cannot exhaust memory. The threshold, for reference, is not a constant but a formula: limit = 3808 − nlaBytes(ifname) − 36·[HeaderProtectionKey set] − P P = 148 (peer has no endpoint) / 168 (IPv4 endpoint) / 180 (IPv6) The last term is why this surfaces without any configuration change: the kernel writes the endpoint at handshake time, so an interface that reads fine before a client connects can stop being readable afterwards. Environment: kernel 6.8.0-138, module and tools `amneziawg 3.1.20260812`.
Author
Owner

@hoaxisr commented on GitHub (Sep 8, 2026):

Same bug from a different angle, with a data point on 4 KB-page MIPS.

Measured on a Linux 4.9-ndm-5, mipsel, page size 4096, amneziawg-tools v3.1.20260812, with a full AWG 3.1 parameter set (Jc/Jmin/Jmax, S1–S4, H1–H4, HeaderProtectionKey, the timing ranges, both 3.1 flags) plus one peer, the interface recreated
between runs so that no state carried over:

sum of I1–I5 = 3710 characters → applied, read back intact
sum of I1–I5 = 3720 characters → awg setconf returns rc=0 with no error,
and awg show/showconf on that interface
then answer "Unable to access interface:
Message too large"

Without recreating the interface the threshold wanders between runs, which matches the report - it is undefined behaviour, not a fixed limit.

<!-- gh-comment-id:5589396957 --> @hoaxisr commented on GitHub (Sep 8, 2026): Same bug from a different angle, with a data point on 4 KB-page MIPS. Measured on a Linux 4.9-ndm-5, mipsel, page size 4096, amneziawg-tools v3.1.20260812, with a full AWG 3.1 parameter set (Jc/Jmin/Jmax, S1–S4, H1–H4, HeaderProtectionKey, the timing ranges, both 3.1 flags) plus one peer, the interface recreated between runs so that no state carried over: sum of I1–I5 = 3710 characters → applied, read back intact sum of I1–I5 = 3720 characters → awg setconf returns rc=0 with no error, and awg show/showconf on that interface then answer "Unable to access interface: Message too large" Without recreating the interface the threshold wanders between runs, which matches the report - it is undefined behaviour, not a fixed limit.
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-tools#30
No description provided.