CVE-2026-31415
Received Received - Intake
Integer Overflow in Linux Kernel IPv6 Destination Options Causes Local DoS

Publication date: 2026-04-13

Last updated on: 2026-04-18

Assigner: kernel.org

Description
In the Linux kernel, the following vulnerability has been resolved: ipv6: avoid overflows in ip6_datagram_send_ctl() Yiming Qian reported : <quote> 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) 1. `opt_flen` is a 16-bit accumulator: - `include/net/ipv6.h:298` defines `__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 `dst1opt` points to a 2048-byte header. 3. 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()` calls `skb_under_panic()`) - `net/core/skbuff.c:207-214` (`skb_panic()` ends in `BUG()`) - 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---
CVSS Scores
EPSS Scores
Probability:
Percentile:
Meta Information
Published
2026-04-13
Last Modified
2026-04-18
Generated
2026-05-07
AI Q&A
2026-04-13
EPSS Evaluated
2026-05-05
NVD
EUVD
Affected Vendors & Products
Showing 1 associated CPE
Vendor Product Version / Range
linux linux_kernel *
Helpful Resources
Exploitability
CWE
CWE Icon
KEV
KEV Icon
CWE ID Description
CWE-UNKNOWN
Attack-Flow Graph
AI Powered Q&A
Can you explain this vulnerability to me?

This vulnerability exists in the Linux kernel's IPv6 implementation, specifically in the function ip6_datagram_send_ctl(). It involves a mismatch between a 16-bit length accumulator (opt_flen) and a pointer to the last provided destination-options header (dst1opt) when multiple IPV6_DSTOPTS control messages are provided.

The opt_flen variable is a 16-bit unsigned integer that accumulates the length of destination options headers. When multiple IPV6_DSTOPTS control messages are sent, opt_flen is incremented each time without rejecting duplicates, which can cause it to wrap around due to its limited size.

However, the pointer dst1opt still points to the last large destination-options header, which can be much larger than the wrapped opt_flen value suggests. This causes the kernel to underestimate the required buffer size (headroom) when processing these headers.

When the kernel tries to push these headers onto the socket buffer (skb), it uses the wrapped opt_flen for size calculations, leading to insufficient headroom. This triggers an underflow in skb_push(), which calls skb_under_panic(), resulting in a kernel BUG and panic (system crash).

This vulnerability can be triggered locally by a user with CAP_NET_RAW capability or by an unprivileged user if unprivileged user namespaces are enabled and they can create a user namespace with CAP_NET_RAW.


How can this vulnerability impact me? :

This vulnerability can cause a local denial of service (DoS) by crashing the Linux kernel through a BUG/panic triggered by skb_under_panic().

An attacker with the appropriate privileges (CAP_NET_RAW) or an unprivileged user in certain configurations can exploit this to crash the system, causing it to become unavailable until rebooted.

This can disrupt services running on the affected system, potentially leading to downtime and loss of availability.


How does this vulnerability affect compliance with common standards and regulations (like GDPR, HIPAA)?:

The provided CVE description does not include any information about the impact of this vulnerability on compliance with common standards and regulations such as GDPR or HIPAA.


What immediate steps should I take to mitigate this vulnerability?

The vulnerability can be triggered only by processes with CAP_NET_RAW capability in the target network namespace.

Immediate mitigation steps include restricting or removing CAP_NET_RAW capability from untrusted users or processes.

Additionally, disabling unprivileged user namespaces can prevent unprivileged users from gaining CAP_NET_RAW in a user namespace and exploiting this vulnerability.

Applying the vendor's patch or updating the Linux kernel to a fixed version once available is the definitive mitigation.


How can this vulnerability be detected on my network or system? Can you suggest some commands?

This vulnerability is a local kernel bug triggered by sending multiple IPV6_DSTOPTS control messages (cmsgs) with large destination-options headers that cause an overflow and kernel panic. Detection involves identifying attempts to send such crafted IPv6 packets with repeated IPV6_DSTOPTS ancillary data.

Since the vulnerability requires CAP_NET_RAW capability and is triggered locally, detection can focus on monitoring for processes using raw sockets or sending IPv6 packets with multiple destination options headers.

Suggested commands to help detect potential exploitation attempts include:

  • Use auditd or similar to monitor usage of raw sockets: audit rules can watch for syscalls like socket(AF_INET6, SOCK_RAW, IPPROTO_RAW).
  • Check for processes with CAP_NET_RAW capability: `capsh --print` or `getpcaps <pid>`.
  • Use packet capture tools (tcpdump, wireshark) to filter for IPv6 packets with destination options headers: `tcpdump -i <interface> 'ip6[6] == 60'` (where 60 is the Next Header value for Destination Options).
  • Look for kernel logs indicating skb_under_panic or BUG() calls related to skb_push failures, e.g., `dmesg | grep skb_under_panic` or `dmesg | grep BUG`.

No specific detection scripts or commands are provided in the available information.


Ask Our AI Assistant
Need more information? Ask your question to get an AI reply (Powered by our expertise)
0/70
EPSS Chart