CVE-2026-10640
Description
Use-after-free in Zephyr's IPv6 Neighbor Discovery send paths allows unauthenticated on-link attackers to cause denial of service or limited memory corruption.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Use-after-free in Zephyr's IPv6 Neighbor Discovery send paths allows unauthenticated on-link attackers to cause denial of service or limited memory corruption.
Vulnerability
In subsys/net/ip/ipv6_nbr.c, the functions net_ipv6_send_na, net_ipv6_send_ns, and net_ipv6_send_rs update per-interface ICMP-sent statistics by calling net_pkt_iface(pkt) after net_send_data(pkt) has returned successfully. On the success path, the network stack owns and releases the packet's reference, so the net_pkt slab block can be freed before the statistics line runs. This results in a use-after-free (CWE-416) when CONFIG_NET_STATISTICS_PER_INTERFACE is enabled. Affected versions are from v3.3.0 through v4.4.0 [1].
Exploitation
An unauthenticated on-link attacker can trigger the vulnerable Neighbor Advertisement path simply by sending ICMPv6 Neighbor Solicitations to a Zephyr node with native IPv6 enabled. The race window occurs synchronously when no TX queue thread is configured, or via a concurrent TX thread otherwise [1].
Impact
A successful exploit leads to reading and incrementing memory from a freed slab block, resulting in corrupted statistics, a fault/crash (denial of service), or potential limited memory corruption. The attacker does not gain code execution but can cause a denial-of-service condition [1].
Mitigation
The fix is merged in commit aaed833 and is projected to be included in version 4.5.0 [1][2]. As a workaround, disable per-interface statistics (CONFIG_NET_STATISTICS_PER_INTERFACE) or restrict untrusted on-link traffic. No other mitigations are available in the affected versions [1].
AI Insight generated on Jun 16, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2(expand)+ 1 more
- (no CPE)
- (no CPE)range: >=3.3.0, <=4.4.0
Patches
4aaed8332a62bnet: ipv6: nbr: fix use-after-free
1 file changed · +3 −3
subsys/net/ip/ipv6_nbr.c+3 −3 modified@@ -1222,7 +1222,7 @@ int net_ipv6_send_na(struct net_if *iface, const struct net_in6_addr *src, goto drop; } - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0; @@ -2177,7 +2177,7 @@ int net_ipv6_send_ns(struct net_if *iface, net_ipv6_nbr_unlock(); - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0; @@ -2249,7 +2249,7 @@ int net_ipv6_send_rs(struct net_if *iface) goto drop; } - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0;
3cab8170460fnet: ipv6: nbr: fix use-after-free
1 file changed · +3 −3
subsys/net/ip/ipv6_nbr.c+3 −3 modified@@ -1221,7 +1221,7 @@ int net_ipv6_send_na(struct net_if *iface, const struct in6_addr *src, goto drop; } - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0; @@ -2169,7 +2169,7 @@ int net_ipv6_send_ns(struct net_if *iface, net_ipv6_nbr_unlock(); - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0; @@ -2241,7 +2241,7 @@ int net_ipv6_send_rs(struct net_if *iface) goto drop; } - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0;
a96ab665bd57net: ipv6: nbr: fix use-after-free
1 file changed · +3 −3
subsys/net/ip/ipv6_nbr.c+3 −3 modified@@ -1222,7 +1222,7 @@ int net_ipv6_send_na(struct net_if *iface, const struct net_in6_addr *src, goto drop; } - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0; @@ -2158,7 +2158,7 @@ int net_ipv6_send_ns(struct net_if *iface, net_ipv6_nbr_unlock(); - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0; @@ -2230,7 +2230,7 @@ int net_ipv6_send_rs(struct net_if *iface) goto drop; } - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0;
ef293d8b5e5dnet: ipv6: nbr: fix use-after-free
1 file changed · +3 −3
subsys/net/ip/ipv6_nbr.c+3 −3 modified@@ -1135,7 +1135,7 @@ int net_ipv6_send_na(struct net_if *iface, const struct in6_addr *src, goto drop; } - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0; @@ -2063,7 +2063,7 @@ int net_ipv6_send_ns(struct net_if *iface, net_ipv6_nbr_unlock(); - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0; @@ -2135,7 +2135,7 @@ int net_ipv6_send_rs(struct net_if *iface) goto drop; } - net_stats_update_icmp_sent(net_pkt_iface(pkt)); + net_stats_update_icmp_sent(iface); net_stats_update_ipv6_nd_sent(iface); return 0;
Vulnerability mechanics
Root cause
"Use-after-free in IPv6 Neighbor Discovery send paths where `net_pkt_iface(pkt)` is called on a freed packet after `net_send_data(pkt)` returns success."
Attack vector
An unauthenticated on-link attacker triggers the bug by sending ICMPv6 Neighbor Solicitations to a Zephyr node with native IPv6 enabled, which invokes `handle_ns_input` -> `net_ipv6_send_na` [ref_id=1]. After `net_send_data(pkt)` succeeds, the L2/driver unrefs and frees the packet slab before the statistics line reads `pkt->iface` from freed memory, resulting in a use-after-free [ref_id=1]. With `CONFIG_NET_STATISTICS_PER_INTERFACE` enabled, the stale `iface` pointer is dereferenced to increment `iface->stats.icmp.sent`, causing corrupted statistics, a fault/crash (denial of service), or potential limited memory corruption if the slab is reallocated [ref_id=1].
What the fix does
All three patches replace `net_stats_update_icmp_sent(net_pkt_iface(pkt))` with `net_stats_update_icmp_sent(iface)` in `net_ipv6_send_na`, `net_ipv6_send_ns`, and `net_ipv6_send_rs` [patch_id=6189715][patch_id=6189718][patch_id=6189717][ref_id=2]. The fix avoids reading `pkt->iface` from the packet slab after `net_send_data(pkt)` has succeeded and ownership has transferred to the driver, which may have already unreferenced and freed the packet [ref_id=1]. By reusing the `iface` argument that these functions already possess, the statistics update no longer dereferences freed memory.
Preconditions
- configZephyr node must have native IPv6 enabled and CONFIG_NET_STATISTICS_PER_INTERFACE must be set
- networkAttacker must be on the same link as the target to send ICMPv6 Neighbor Solicitations
- authNo authentication required
Generated on Jun 16, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.