A critical memory corruption vulnerability has been discovered in ESnet iperf3, the open-source network measurement and bandwidth benchmarking standard utilized by cloud service providers, telecommunication operators, and data center engineers globally. Assigned CVE-2026-101276 and designated under GitHub Security Advisory GHSA-pmgg-x2vj-36cv with a maximum CVSS v3.1 rating of 9.8 (Critical), the flaw enables unauthenticated remote attackers to trigger a heap use-after-free condition on public-facing iperf3 listening servers, causing immediate daemon termination or potentially arbitrary remote code execution.
The Role of iperf3 in Global Backbone Infrastructure
Maintained by Energy Sciences Network (ESnet) at Lawrence Berkeley National Laboratory, iperf3 is the definitive benchmarking engine for characterizing TCP, UDP, and SCTP link performance. Enterprise network architectures routinely run iperf3 daemons (iperf3 -s) within cloud VPCs, edge nodes, and automated latency validation pipelines. Because the daemon must handle concurrent high-speed streams while guarding against hung client connections, it incorporates a watchdog timer system to terminate overdue testing sessions.
Root Cause Analysis: Unsynchronized Thread Tear-Down (CWE-416)
In iperf3 version 3.21, the vulnerability arises from a race condition between the server's per-test watchdog handler server_timer_proc() and active stream worker threads executing in iperf_tcp_worker() or iperf_udp_worker():
// Vulnerable Logic in iperf3 v3.21 (src/iperf_server_api.c)
void server_timer_proc(TimerClientData client_data, struct iperf_time *nowP) {
struct iperf_test *test = client_data.p;
struct iperf_stream *sp;
// Watchdog timer fires because client stalled or exceeded max time
SLIST_FOREACH(sp, &test->streams, streams) {
// Stream data structure freed immediately on the heap
iperf_free_stream(sp);
}
// Worker threads were NEVER cancelled or joined before free!
}
When an unauthenticated remote client initiates a multi-stream test and deliberately stalls network packet delivery or manipulates TCP window sizes, the watchdog timer fires. The master thread executes server_timer_proc(), which calls iperf_free_stream(), releasing the memory holding the iperf_stream struct back to the glibc heap.
Simultaneously, the worker thread blocked in recv() or select() unblocks as the socket teardown occurs. The thread proceeds to update statistical telemetry counters:
// Worker Thread dereferences dangling heap pointer
void *iperf_worker(void *data) {
struct iperf_stream *sp = (struct iperf_stream *) data;
// sp has ALREADY been freed by server_timer_proc()!
sp->result->bytes_received += bytes; // Heap Use-After-Free Write
}
Because the thread dereferences a deallocated chunk of heap memory that may have already been reallocated to incoming network buffers, an attacker capable of manipulating heap layouts can hijack function pointers or cause deterministic memory corruption.
Lifecycle Comparison: iperf3 Stream Management
| Phase | Vulnerable Behavior (v3.21) | Remediated Architecture (v3.22) |
|---|---|---|
| Watchdog Expiration | Iterates streams and calls free() without thread synchronization |
Signals worker threads to cancel and performs pthread_join() |
| Worker State | Worker continues execution accessing dangling heap pointers | Worker thread cleanly terminates prior to any memory deallocation |
| Memory Safety | Heap UAF write leads to segmentation fault or code execution | Deterministic lifecycle; zero use-after-free or double-free conditions |
Remediation & Defense Actions
- Deploy iperf3 v3.22: Upgrade all testing nodes immediately. Version 3.22 resolves the issue by ensuring all worker threads are joined and verified terminated before any stream objects are released from memory.
- Firewall iperf3 Ports: Never expose the default iperf3 port (
TCP 5201) to the public internet. Restrict access strictly to designated bastion hosts or VPN networks. - Enforce One-Shot Execution: Where persistent daemons are required, execute iperf3 with the
-1(one-off) flag under systemd, ensuring the service process terminates completely after each test and is re-spawned with fresh ASLR heap entropy.



