CVE-2026-31415
Description
In the Linux kernel, the following vulnerability has been resolved:
ipv6: avoid overflows in ip6_datagram_send_ctl()
Yiming Qian reported :
I believe I found a locally triggerable kernel bug in the IPv6 sendmsg ancillary-data path that can panic the kernel via skb_under_panic() (local DoS).
The core issue is a mismatch between:
- a 16-bit length accumulator (struct ipv6_txoptions::opt_flen, type __u16) and - a pointer to the *last* provided destination-options header (opt->dst1opt)
when multiple IPV6_DSTOPTS control messages (cmsgs) are provided.
- include/net/ipv6.h: - struct ipv6_txoptions::opt_flen is __u16 (wrap possible). (lines 291-307, especially 298) - net/ipv6/datagram.c:ip6_datagram_send_ctl(): - Accepts repeated IPV6_DSTOPTS and accumulates into opt_flen without rejecting duplicates. (lines 909-933) - net/ipv6/ip6_output.c:__ip6_append_data(): - Uses opt->opt_flen + opt->opt_nflen to compute header sizes/headroom decisions. (lines 1448-1466, especially 1463-1465) - net/ipv6/ip6_output.c:__ip6_make_skb(): - Calls ipv6_push_frag_opts() if opt->opt_flen is non-zero. (lines 1930-1934) - net/ipv6/exthdrs.c:ipv6_push_frag_opts() / ipv6_push_exthdr(): - Push size comes from ipv6_optlen(opt->dst1opt) (based on the pointed-to header). (lines 1179-1185 and 1206-1211)
opt_flenis a 16-bit accumulator:
include/net/ipv6.h:298defines__u16 opt_flen; /* after fragment hdr */.
2. ip6_datagram_send_ctl() accepts *repeated* IPV6_DSTOPTS cmsgs and increments opt_flen each time:
- In net/ipv6/datagram.c:909-933, for IPV6_DSTOPTS: - It computes len = ((hdr->hdrlen + 1) << 3); - It checks CAP_NET_RAW using ns_capable(net->user_ns, CAP_NET_RAW). (line 922) - Then it does: - opt->opt_flen += len; (line 927) - opt->dst1opt = hdr; (line 928)
There is no duplicate rejection here (unlike the legacy IPV6_2292DSTOPTS path which rejects duplicates at net/ipv6/datagram.c:901-904).
If enough large IPV6_DSTOPTS cmsgs are provided, opt_flen wraps while dst1opt still points to a large (2048-byte) destination-options header.
In the attached PoC (poc.c):
- 32 cmsgs with
hdrlen=255=>len = (255+1)*8 = 2048 - 1 cmsg with
hdrlen=0=>len = 8 - Total increment:
32*2048 + 8 = 65544, so(__u16)opt_flen == 8 - The last cmsg is 2048 bytes, so
dst1optpoints to a 2048-byte header.
- The transmit path sizes headers using the wrapped
opt_flen:
- In net/ipv6/ip6_output.c:1463-1465: - headersize = sizeof(struct ipv6hdr) + (opt ? opt->opt_flen + opt->opt_nflen : 0) + ...;
With wrapped opt_flen, headersize/headroom decisions underestimate what will be pushed later.
4. When building the final skb, the actual push length comes from dst1opt and is not limited by wrapped opt_flen:
- In net/ipv6/ip6_output.c:1930-1934: - if (opt->opt_flen) proto = ipv6_push_frag_opts(skb, opt, proto); - In net/ipv6/exthdrs.c:1206-1211, ipv6_push_frag_opts() pushes dst1opt via ipv6_push_exthdr(). - In net/ipv6/exthdrs.c:1179-1184, ipv6_push_exthdr() does: - skb_push(skb, ipv6_optlen(opt)); - memcpy(h, opt, ipv6_optlen(opt));
With insufficient headroom, skb_push() underflows and triggers skb_under_panic() -> BUG():
net/core/skbuff.c:2669-2675(skb_push()callsskb_under_panic())net/core/skbuff.c:207-214(skb_panic()ends inBUG())
- The IPV6_DSTOPTS cmsg path requires CAP_NET_RAW in the target netns user namespace (ns_capable(net->user_ns, CAP_NET_RAW)). - Root (or any task with CAP_NET_RAW) can trigger this without user namespaces. - An unprivileged uid=1000 user can trigger this if unprivileged user namespaces are enabled and it can create a userns+netns to obtain namespaced CAP_NET_RAW (the attached PoC does this).
- Local denial of service: kernel BUG/panic (system crash). - ---truncated---
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Affected products
17cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*+ 8 more
- cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*range: >=2.6.14,<5.10.253
- cpe:2.3:o:linux:linux_kernel:7.0:rc1:*:*:*:*:*:*
- cpe:2.3:o:linux:linux_kernel:7.0:rc2:*:*:*:*:*:*
- cpe:2.3:o:linux:linux_kernel:7.0:rc3:*:*:*:*:*:*
- cpe:2.3:o:linux:linux_kernel:7.0:rc4:*:*:*:*:*:*
- cpe:2.3:o:linux:linux_kernel:7.0:rc5:*:*:*:*:*:*
- cpe:2.3:o:linux:linux_kernel:7.0:rc6:*:*:*:*:*:*
- cpe:2.3:o:linux:linux_kernel:7.0:rc7:*:*:*:*:*:*
- (no CPE)
- osv-coords8 versionspkg:rpm/suse/kernel-default&distro=SUSE%20Linux%20Enterprise%20Live%20Patching%2012%20SP5pkg:rpm/suse/kernel-default&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP5-LTSSpkg:rpm/suse/kernel-default&distro=SUSE%20Linux%20Enterprise%20Server%20LTSS%20Extended%20Security%2012%20SP5pkg:rpm/suse/kernel-source&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP5-LTSSpkg:rpm/suse/kernel-source&distro=SUSE%20Linux%20Enterprise%20Server%20LTSS%20Extended%20Security%2012%20SP5pkg:rpm/suse/kernel-syms&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP5-LTSSpkg:rpm/suse/kernel-syms&distro=SUSE%20Linux%20Enterprise%20Server%20LTSS%20Extended%20Security%2012%20SP5pkg:rpm/suse/kgraft-patch-SLE12-SP5_Update_84&distro=SUSE%20Linux%20Enterprise%20Live%20Patching%2012%20SP5
< 4.12.14-122.317.1+ 7 more
- (no CPE)range: < 4.12.14-122.317.1
- (no CPE)range: < 4.12.14-122.317.1
- (no CPE)range: < 4.12.14-122.317.1
- (no CPE)range: < 4.12.14-122.317.1
- (no CPE)range: < 4.12.14-122.317.1
- (no CPE)range: < 4.12.14-122.317.1
- (no CPE)range: < 4.12.14-122.317.1
- (no CPE)range: < 1-8.7.1
Patches
Vulnerability mechanics
References
8- git.kernel.org/stable/c/0bdaf54d3aaddfe8df29371260fa8d4939b4fd6fnvdPatch
- git.kernel.org/stable/c/2dbfb003bbf3fc0e94f07efefab0ebcf83029a2anvdPatch
- git.kernel.org/stable/c/4082f9984a694829153115d28c956a3534f52f29nvdPatch
- git.kernel.org/stable/c/4e453375561fc60820e6b9d8ebeb6b3ee177d42envdPatch
- git.kernel.org/stable/c/5e4ee5dbea134e9257f205e31a96040bed71e83fnvdPatch
- git.kernel.org/stable/c/63fda74885555e6bd1623b5d811feec998740ba4nvdPatch
- git.kernel.org/stable/c/872b74900d5daa37067ac676d9001bb929fc6a2anvdPatch
- git.kernel.org/stable/c/9ed81d692758dfb9471d7799b24bfa7a08224c31nvdPatch
News mentions
0No linked articles in our index yet.