MEDIUM 6.4

CVE-2026-10653: Zephyr net_buf Double-Free Race Condition

Zephyr's network buffer library has a race condition in how it tracks when buffers are no longer in use. The library uses reference counts to know when a buffer can be safely freed, but these counts are updated using regular (non-atomic) operations. When multiple threads or tasks share the same buffer and call the unref function simultaneously, a timing race can cause the library to think two different holders are the last user—leading to the same buffer being freed twice, memory corruption, and potential use-after-free conditions. The vulnerability affects multiple subsystems including networking, Bluetooth, USB, and message passing. Actual exploitation requires genuine concurrency, shared buffer architecture in the application, and precise timing; external attackers have limited ability to trigger it directly.

Source data · NVD / CISA · public domain

CVSS
3.1 · 6.4 MEDIUM · CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:H
Weaknesses (CWE)
CWE-415
Affected products
1 configuration(s)
Published / Modified
2026-06-30 / 2026-08-06

NVD description (verbatim)

The Zephyr net_buf library (lib/net_buf/buf.c) manipulated both of its reference counts -- the per-header buf->ref and the per-data-block ref_count at the start of each variable/heap data allocation -- with plain non-atomic C operators (buf->ref++, if (--buf->ref > 0), if (--(*ref_count))). The API is documented as self-synchronizing: callers may share one buffer across threads (e.g. via k_fifo) and each holder independently calls net_buf_unref() with no surrounding lock. Under true concurrency (SMP, or single-core preemption between the non-atomic load and store while another context unrefs the same buffer), two holders can both observe the same prior reference value and both conclude they are the last reference. For heap/variable-data pools (mem_pool_data_unref/heap_data_unref, used by zbus message subscribers, the IP stack RX/TX buffers when CONFIG_NET_BUF_FIXED_DATA_SIZE=n, capture, wireguard, ISO-TP and usbip) this produces a double k_heap_free()/k_free() of the same block -- heap-metadata corruption and a use-after-free on the heap-hardening poison pattern. For the per-header refcount the buffer is returned to the pool free LIFO twice for any pool type (including fixed-data pools used by Bluetooth and networking), corrupting the free list so a later allocation hands the same buffer to two owners. The fix converts both refcounts to atomic_inc/atomic_dec (overlaying buf->ref in an atomic_t-sized union and changing the data-block refcount from uint8_t to atomic_t). Impact is gated on genuine concurrency and on an application architecture that shares one buffer among multiple independent unref'ers; the trigger is a refcount/timing race rather than packet content, so an external attacker has at most weak indirect influence over the race window. Affects all Zephyr releases through v4.4.0. This fix is not being backported to v3.7-branch (LTS). The backport was attempted and closed unmerged (#111181): the v3.7 networking tree has diverged from main, and the new atomic word-packing -- together with the assertions it adds -- turns pre-existing v3.7-only reference-counting defects elsewhere in the stack into hard faults, so landing the change faithfully would mean pulling an open-ended set of additional v3.7-only fixes into an LTS branch. v3.7 remains affected. Applications on v3.7 that share one net_buf across threads should serialize their own net_buf_unref() calls rather than rely on the documented self-synchronizing behaviour. The fix is on main and has been backported to v4.3-branch (#110852) and v4.4-branch (#110853).

2 reference(s) · View on NVD →

SEC.co analysis · AI-assisted, reviewed against source

Technical summary

CVE-2026-10653 is a use-after-free and double-free vulnerability in lib/net_buf/buf.c stemming from non-atomic manipulation of reference counts. The library maintains two refcount mechanisms: buf->ref (per-buffer header) and a per-data-block ref_count for heap allocations. Both are incremented and decremented using plain C operators (buf->ref++, --buf->ref, --(*ref_count)) without atomic guarantees. Under concurrent access—whether on multicore systems or via task preemption on single-core—two threads can load the same refcount value, decrement it non-atomically, and both observe themselves as the final holder. For heap-allocated data (used by zbus, networking RX/TX with variable sizing, capture, WireGuard, ISO-TP, and USB IP), this triggers a double heap_free(). For fixed-data pools (Bluetooth, standard networking), the buffer header is returned to the free list twice, corrupting the allocator's linked structure. The fix converts both refcounts to atomic_t operations. The race is timing-dependent rather than packet-driven, limiting direct external attacker control. Affects Zephyr v4.4.0 and earlier; v3.7-LTS remains unpatched due to architectural divergence and risk of cascading v3.7-only fixes.

Business impact

For products and services built on Zephyr, this vulnerability creates two failure modes: either silent memory corruption (heap metadata corruption and use-after-free on heap-allocated buffers) or data-structure integrity loss (free-list corruption in fixed pools). In production deployments sharing buffers across threads—typical in networked IoT, wireless (Bluetooth/802.15.4), and industrial applications—these conditions can lead to unexplained crashes, data corruption, or security properties being undermined. The risk is probabilistic: it depends on application architecture and concurrency patterns, not on external input, which may allow some deployments to avoid exposure. Organizations running Zephyr-based products should assess whether their applications share net_buf objects across independent code paths; if so, upgrade urgency is high despite the MEDIUM CVSS score.

Affected systems

All Zephyr releases through v4.4.0 are affected. Zephyr v4.3-branch and v4.4-branch have received patches. v3.7-LTS does not have a backport and remains vulnerable. Subsystems at risk include: the net_buf core allocator and freeing logic, zbus message subscribers (IPC), IP stack RX/TX when CONFIG_NET_BUF_FIXED_DATA_SIZE is disabled, capture (packet logging), WireGuard, ISO-TP, USB IP stack, and Bluetooth (for the per-header refcount corruption risk). Any application architecture that passes a single net_buf between threads without external synchronization is at risk.

Exploitability

Exploitation requires three conditions: (1) genuine concurrency (multicore, or preemption between refcount load and store on single-core), (2) application design sharing one buffer across multiple independent unref'ers, and (3) timing alignment of the race window. An external attacker cannot reliably control these conditions via packet crafting or API calls; the race is internal to memory management. Local or privileged code running on the same device could potentially increase race-window collision likelihood through careful scheduling, but this is not a remote attack vector. The vulnerability is highest risk in heavily multithreaded applications and systems with high CPU contention.

Remediation

Upgrade to Zephyr v4.3 or later (which includes the backport), or v4.4 or later. If v3.7-LTS is in use and cannot be upgraded, applications must serialize their own net_buf_unref() calls; do not rely on the documented self-synchronizing behavior. Callers should wrap unref operations in a common lock if the same buffer is held by multiple threads. Verify your application's buffer-sharing patterns: if buffers are passed between threads without explicit ownership handoff, you are likely affected.

Patch guidance

The fix has been merged into Zephyr main and backported to v4.3-branch (PR #110852) and v4.4-branch (PR #110853). For mainline tracking: check that your Zephyr version is later than the commit implementing atomic reference counts in lib/net_buf/buf.c. For v3.7-LTS users: a faithful backport was attempted (PR #111181) but closed unmerged due to divergence in the v3.7 networking tree and pre-existing reference-counting defects elsewhere that would cascade as hard faults. Upgrading to v4.3-LTS or v4.4-LTS is strongly recommended. If stuck on v3.7, implement application-level synchronization around net_buf_unref() as an interim measure and plan migration.

Detection guidance

Monitor for signs of heap corruption (e.g., malloc/free errors, poison-pattern violations in heap metadata, sudden segmentation faults in memory allocators) correlated with network activity or message passing. Enabling Zephyr's CONFIG_HEAP_MEM_POOL_STATS and heap debugging facilities may surface double-free events. On v3.7, check application logs for crashes in k_heap_free or buf_free_data paths. Static analysis scanning for patterns of buf->ref++ and buf->ref-- without atomic guards would flag the vulnerable code. Runtime tools like TSAN (Thread Sanitizer) can catch data races on refcount accesses if the application is compiled and run in a test environment with those tools enabled, though Zephyr's RTOS context may limit TSAN availability. Assess your application's buffer-sharing topology: if multiple tasks independently call net_buf_unref on the same buffer, you are in the vulnerable code path.

Why prioritize this

Despite a MEDIUM CVSS score (6.4), this issue warrants prompt attention because: (1) the memory corruption and use-after-free consequences are severe (potential code execution or denial of service), (2) the vulnerability is embedded in a core allocator used across multiple Zephyr subsystems, (3) exploitability, while requiring specific concurrency, is not exotic in real-world multithreaded systems, and (4) v3.7-LTS users have no patch and must either upgrade or implement workarounds. The CVSS score reflects that direct remote triggering is difficult; local and application-architectural factors dominate risk. If your product uses Zephyr and employs multithreaded buffer sharing, treat this as high-priority.

Risk score, explained

CVSS 3.1 score 6.4 (MEDIUM) reflects: AV:A (adjacent network access—requires local or network-local attacker position, not internet-wide), AC:H (attack complexity is high—race condition is timing-dependent and not deterministic), PR:N (no privileges required to trigger the race itself, but see AC:H), UI:N (no user interaction), S:U (scope unchanged), C:L (low confidentiality impact—use-after-free may leak data but is not a primary exposure), I:L (low integrity impact—corruption is primarily memory-internal), A:H (high availability impact—double-free and heap corruption cause denial of service). The score does not account for application architecture; systems with tight buffer-sharing and high concurrency carry higher real-world risk despite the base score.

Frequently asked questions

Does this require network traffic to trigger, or is it purely an internal concurrency bug?

It is purely internal to concurrency and memory management. No specific packet content or external input is needed; the race occurs between threads or tasks sharing the same buffer. Network traffic is not a direct trigger, though networking applications that use shared buffers in concurrent contexts are at higher risk.

Our application uses Zephyr 4.4 but we have not yet upgraded. How do we know if we are affected?

Check whether your application (1) passes net_buf objects between threads, (2) relies on the documented self-synchronizing behavior of net_buf_unref(), or (3) uses zbus, variable-sized networking buffers, or USB/WireGuard/ISO-TP subsystems. If any of these apply and you have concurrent tasks, you are potentially exposed. Upgrade to the patched version in your branch (v4.3-branch or v4.4-branch) or to main.

Can we work around this on v3.7-LTS without upgrading?

Yes, but it requires application changes. Wrap all net_buf_unref() calls on shared buffers with a mutex or spinlock to serialize them. This restores the intended self-synchronizing guarantee manually. This is an interim measure; migration to a newer LTS branch is recommended for long-term support.

Is there a way to detect if this race condition has already occurred in a running system?

Detection is difficult at runtime because the consequences (heap metadata corruption, use-after-free) may not immediately crash. Enabling Zephyr heap statistics (CONFIG_HEAP_MEM_POOL_STATS) and running with heap guards enabled may surface corruption. In a test environment, compiling with TSAN or other dynamic race detectors can catch the refcount data races before they cause memory corruption.

This analysis is provided for informational and defensive security purposes. The details reflect publicly available information and the vendor advisory as of the publication date. Organizations should verify patch availability and applicability for their specific Zephyr version and configuration. Testing patches in a non-production environment before deployment is strongly recommended. This write-up does not constitute legal advice or a guarantee of security; it is one input to your organization's risk assessment and patch management process. Source: NVD (public-domain), retrieved 2026-08-09. Analysis generated by SEC.co (claude-haiku-4-5).