VYPR
Medium severity4.8NVD Advisory· Published Jun 15, 2026

CVE-2026-10634

CVE-2026-10634

Description

Use-after-free in Zephyr native TCP stack's net_tcp_foreach() due to dropping tcp_lock during callback, allowing crash or potential info disclosure.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Use-after-free in Zephyr native TCP stack's net_tcp_foreach() due to dropping tcp_lock during callback, allowing crash or potential info disclosure.

Vulnerability

A use-after-free vulnerability exists in the native TCP stack of Zephyr RTOS in the function net_tcp_foreach() in subsys/net/ip/tcp.c. This function iterates the global connection list using SYS_SLIST_FOR_EACH_CONTAINER_SAFE, which caches a pointer to the next list node. Prior to the fix, net_tcp_foreach() released the tcp_lock mutex while invoking the per-connection callback and re-acquired it after the callback. This created a race window where a concurrent tcp_conn_release(), running on the dedicated TCP work-queue thread when a connection's reference count drops to zero (e.g., from a remote peer closing or resetting the connection), can remove and k_mem_slab_free() the cached next connection. When the iterator advances, it dereferences the freed slab memory. The defect was introduced with the modern (TCP2) stack in 2020 and affects releases up to and including v4.4.0 [1].

Exploitation

An attacker can trigger the race condition by establishing a TCP connection to a vulnerable Zephyr device and then sending a TCP reset (RST) or initiating a graceful close. The closure causes the reference count of the connection to drop to zero, scheduling tcp_conn_release() on the TCP work-queue thread. Simultaneously, if the system administrator or automated process runs the 'net conn' network shell command (which calls net_tcp_foreach()) or triggers an interface down event (which calls net_tcp_close_all_for_iface()), the race window opens. The attacker must time the connection closure to occur while net_tcp_foreach() is in the middle of iteration, with the lock dropped. No authentication is required; the attacker only needs network access to establish and close TCP connections to the device [1].

Impact

Successful exploitation results in a use-after-free condition that can cause a system crash (denial of service). If the freed slab memory has been reallocated to another object under attacker influence, the callback may operate on that attacker-controlled object, potentially leading to information disclosure or further faults [1]. The impact is limited to availability and potentially confidentiality, with a CVSS v3 severity of 4.8 (Medium).

Mitigation

The fix is provided in commit cd85e0e, which moves the connection/context teardown in tcp_conn_release() inside the tcp_lock critical section and keeps tcp_lock held across the callback in net_tcp_foreach(). The projected fixed version is 4.5.0 (the fix is merged on main but not yet released; this forecast should be confirmed against the actual release). No workaround is explicitly mentioned in the references. Users are advised to update to the patched version once available [1][2].

AI Insight generated on Jun 15, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

4
cd85e0e890ab

net: tcp: fix use-after-free in net_tcp_foreach()

https://github.com/zephyrproject-rtos/zephyrOfir ShemeshApr 8, 2026via body-scan-shorthand
1 file changed · +12 4
  • subsys/net/ip/tcp.c+12 4 modified
    @@ -906,10 +906,9 @@ static void tcp_conn_release(struct k_work *work)
     
     	k_mutex_unlock(&conn->lock);
     
    +	k_mutex_lock(&tcp_lock, K_FOREVER);
     	net_context_unref(conn->context);
     	conn->context = NULL;
    -
    -	k_mutex_lock(&tcp_lock, K_FOREVER);
     	sys_slist_find_and_remove(&tcp_conns, &conn->next);
     	k_mutex_unlock(&tcp_lock);
     
    @@ -4540,10 +4539,19 @@ void net_tcp_foreach(net_tcp_cb_t cb, void *user_data)
     	k_mutex_lock(&tcp_lock, K_FOREVER);
     
     	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp_conns, conn, tmp, next) {
    +		/* Keep tcp_lock held while invoking the callback.
    +		 * tcp_conn_release() removes entries from this list and
    +		 * frees both conn->context and the conn slab under
    +		 * tcp_lock, so dropping the lock here would allow a
    +		 * concurrent release to free the *next* node saved by
    +		 * the _SAFE iterator, causing a use-after-free when the
    +		 * loop advances.
    +		 *
    +		 * All current callbacks are read-only diagnostics and
    +		 * never acquire tcp_lock, so holding it is safe.
    +		 */
     		if (atomic_get(&conn->ref_count) > 0) {
    -			k_mutex_unlock(&tcp_lock);
     			cb(conn, user_data);
    -			k_mutex_lock(&tcp_lock, K_FOREVER);
     		}
     	}
     
    
168295f5a16d

net: tcp: fix use-after-free in net_tcp_foreach()

https://github.com/zephyrproject-rtos/zephyrOfir ShemeshApr 8, 2026via body-scan-shorthand
1 file changed · +12 4
  • subsys/net/ip/tcp.c+12 4 modified
    @@ -906,10 +906,9 @@ static void tcp_conn_release(struct k_work *work)
     
     	k_mutex_unlock(&conn->lock);
     
    +	k_mutex_lock(&tcp_lock, K_FOREVER);
     	net_context_unref(conn->context);
     	conn->context = NULL;
    -
    -	k_mutex_lock(&tcp_lock, K_FOREVER);
     	sys_slist_find_and_remove(&tcp_conns, &conn->next);
     	k_mutex_unlock(&tcp_lock);
     
    @@ -4540,10 +4539,19 @@ void net_tcp_foreach(net_tcp_cb_t cb, void *user_data)
     	k_mutex_lock(&tcp_lock, K_FOREVER);
     
     	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp_conns, conn, tmp, next) {
    +		/* Keep tcp_lock held while invoking the callback.
    +		 * tcp_conn_release() removes entries from this list and
    +		 * frees both conn->context and the conn slab under
    +		 * tcp_lock, so dropping the lock here would allow a
    +		 * concurrent release to free the *next* node saved by
    +		 * the _SAFE iterator, causing a use-after-free when the
    +		 * loop advances.
    +		 *
    +		 * All current callbacks are read-only diagnostics and
    +		 * never acquire tcp_lock, so holding it is safe.
    +		 */
     		if (atomic_get(&conn->ref_count) > 0) {
    -			k_mutex_unlock(&tcp_lock);
     			cb(conn, user_data);
    -			k_mutex_lock(&tcp_lock, K_FOREVER);
     		}
     	}
     
    
21a1c71f9dfe

net: tcp: fix use-after-free in net_tcp_foreach()

https://github.com/zephyrproject-rtos/zephyrOfir ShemeshApr 8, 2026via body-scan-shorthand
1 file changed · +12 4
  • subsys/net/ip/tcp.c+12 4 modified
    @@ -809,10 +809,9 @@ static void tcp_conn_release(struct k_work *work)
     
     	k_mutex_unlock(&conn->lock);
     
    +	k_mutex_lock(&tcp_lock, K_FOREVER);
     	net_context_unref(conn->context);
     	conn->context = NULL;
    -
    -	k_mutex_lock(&tcp_lock, K_FOREVER);
     	sys_slist_find_and_remove(&tcp_conns, &conn->next);
     	k_mutex_unlock(&tcp_lock);
     
    @@ -4381,10 +4380,19 @@ void net_tcp_foreach(net_tcp_cb_t cb, void *user_data)
     	k_mutex_lock(&tcp_lock, K_FOREVER);
     
     	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp_conns, conn, tmp, next) {
    +		/* Keep tcp_lock held while invoking the callback.
    +		 * tcp_conn_release() removes entries from this list and
    +		 * frees both conn->context and the conn slab under
    +		 * tcp_lock, so dropping the lock here would allow a
    +		 * concurrent release to free the *next* node saved by
    +		 * the _SAFE iterator, causing a use-after-free when the
    +		 * loop advances.
    +		 *
    +		 * All current callbacks are read-only diagnostics and
    +		 * never acquire tcp_lock, so holding it is safe.
    +		 */
     		if (atomic_get(&conn->ref_count) > 0) {
    -			k_mutex_unlock(&tcp_lock);
     			cb(conn, user_data);
    -			k_mutex_lock(&tcp_lock, K_FOREVER);
     		}
     	}
     
    
f1c38f6cbcf5

net: tcp: fix use-after-free in net_tcp_foreach()

https://github.com/zephyrproject-rtos/zephyrOfir ShemeshApr 8, 2026via body-scan-shorthand
1 file changed · +12 4
  • subsys/net/ip/tcp.c+12 4 modified
    @@ -904,10 +904,9 @@ static void tcp_conn_release(struct k_work *work)
     
     	k_mutex_unlock(&conn->lock);
     
    +	k_mutex_lock(&tcp_lock, K_FOREVER);
     	net_context_unref(conn->context);
     	conn->context = NULL;
    -
    -	k_mutex_lock(&tcp_lock, K_FOREVER);
     	sys_slist_find_and_remove(&tcp_conns, &conn->next);
     	k_mutex_unlock(&tcp_lock);
     
    @@ -4512,10 +4511,19 @@ void net_tcp_foreach(net_tcp_cb_t cb, void *user_data)
     	k_mutex_lock(&tcp_lock, K_FOREVER);
     
     	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp_conns, conn, tmp, next) {
    +		/* Keep tcp_lock held while invoking the callback.
    +		 * tcp_conn_release() removes entries from this list and
    +		 * frees both conn->context and the conn slab under
    +		 * tcp_lock, so dropping the lock here would allow a
    +		 * concurrent release to free the *next* node saved by
    +		 * the _SAFE iterator, causing a use-after-free when the
    +		 * loop advances.
    +		 *
    +		 * All current callbacks are read-only diagnostics and
    +		 * never acquire tcp_lock, so holding it is safe.
    +		 */
     		if (atomic_get(&conn->ref_count) > 0) {
    -			k_mutex_unlock(&tcp_lock);
     			cb(conn, user_data);
    -			k_mutex_lock(&tcp_lock, K_FOREVER);
     		}
     	}
     
    

Vulnerability mechanics

Root cause

"A TOCTOU race condition in net_tcp_foreach() where tcp_lock is dropped across the callback, allowing a concurrent tcp_conn_release() to free the cached next list node, leading to a use-after-free."

Attack vector

An attacker on the same link (AV:A) can trigger the bug by sending ordinary TCP traffic that causes a connection's reference count to drop to zero (e.g. a remote peer closing or resetting the connection). This schedules `tcp_conn_release()` on the dedicated TCP work-queue thread. Meanwhile, if a privileged local user (PR:L) invokes the `net conn` shell command or an interface-down event calls `net_tcp_close_all_for_iface()`, both of which reach `net_tcp_foreach()`, the window between dropping and re-acquiring `tcp_lock` in the iterator allows the concurrent release to free the cached next connection, leading to a use-after-free. The CVSS score is 4.0 (Medium) per the supplied vector [ref_id=1].

Affected code

The bug is in two functions within `subsys/net/ip/tcp.c`: `net_tcp_foreach()` (around line 4540) and `tcp_conn_release()` (around line 906). `net_tcp_foreach()` dropped `tcp_lock` while invoking the per-connection callback and re-acquired it afterwards. `tcp_conn_release()` performed connection teardown (`net_context_unref`, `sys_slist_find_and_remove`, and `k_mem_slab_free`) outside the `tcp_lock` critical section. The fix addresses both locations by keeping `tcp_lock` held across the callback in `net_tcp_foreach()` and moving the teardown operations in `tcp_conn_release()` inside the `tcp_lock` critical section [ref_id=1][patch_id=6083973].

What the fix does

The patch makes two changes in `subsys/net/ip/tcp.c` [patch_id=6083973]. First, in `tcp_conn_release()`, `k_mutex_lock(&tcp_lock, K_FOREVER)` is moved before `net_context_unref(conn->context)` and `conn->context = NULL`, so that the entire teardown—including removing the entry from the list (`sys_slist_find_and_remove`) and freeing the slab—runs under `tcp_lock`. Second, in `net_tcp_foreach()`, the `k_mutex_unlock`/`k_mutex_lock` pair around the callback is removed so that `tcp_lock` remains held while `cb(conn, user_data)` executes. The commit message explains that no current callback acquires `tcp_lock`, making this safe. Together these changes close the window where a concurrent `tcp_conn_release()` could free the next node cached by the `_SAFE` iterator [ref_id=2].

Preconditions

  • networkAttacker and victim must be on the same link (adjacent network per CVSS AV:A).
  • inputAttacker must be able to send TCP segments to trigger a connection close or reset, causing the reference count to drop to zero.
  • authAn unprivileged local user must trigger net_tcp_foreach() via the 'net conn' shell command or an interface-down event must call net_tcp_close_all_for_iface() while the release work item is queued.

Generated on Jun 15, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.