CVE-2026-31664 Overview
CVE-2026-31664 is an information disclosure vulnerability in the Linux kernel's IPsec transformation (xfrm) subsystem. The flaw resides in the build_polexpire() function, which fails to clear trailing padding bytes in the struct xfrm_user_polexpire structure before transmission. As a result, uninitialized kernel heap memory is leaked to userspace via netlink multicast messages sent to XFRMNLGRP_EXPIRE listeners. A local user with permission to subscribe to the relevant netlink group can passively collect leaked kernel memory contents, potentially revealing sensitive data such as cryptographic material, pointers, or other transient kernel state.
Critical Impact
Local attackers can read uninitialized kernel heap memory via netlink multicast, enabling reconnaissance and potential bypass of kernel address space layout randomization (KASLR).
Affected Products
- Linux Kernel (multiple stable branches affected, fixes backported across six commits)
- Linux Kernel versions from 2.6.12 onward containing the build_polexpire() netlink expire notification path
- Distributions shipping vulnerable kernels prior to applying the upstream memset_after() fix
Discovery Timeline
- 2026-04-24 - CVE-2026-31664 published to the National Vulnerability Database (NVD)
- 2026-04-27 - Last updated in NVD database
Technical Details for CVE-2026-31664
Vulnerability Analysis
The Linux kernel xfrm subsystem notifies userspace when a security association (SA) or policy expires. Two analogous helpers build these notifications: build_expire() for SA expirations and build_polexpire() for policy expirations. The former correctly invokes memset_after() to zero the padding bytes that follow the __u8 hard field in struct xfrm_user_expire. The latter omits this step for struct xfrm_user_polexpire.
The notification message is allocated from the kernel heap. After populating the structure fields, the trailing padding remains uninitialized and retains whatever bytes were previously stored at that address. The kernel then broadcasts the message through netlink multicast to processes listening on the XFRMNLGRP_EXPIRE group, exposing the residual heap contents to userspace.
Root Cause
The root cause is missing initialization of structure padding bytes prior to copying kernel data to userspace, classified under the broader category of Uninitialized Memory Use and Information Exposure. Compiler-inserted padding between or after structure fields is not covered by member-by-member assignment, and the kernel relies on explicit memset_after() calls to ensure deterministic zeroing. The upstream fix adds the missing memset_after() invocation in build_polexpire() to mirror the existing pattern in build_expire().
Attack Vector
Exploitation requires local access and the ability to open a netlink socket and join the XFRMNLGRP_EXPIRE multicast group, typically gated by CAP_NET_ADMIN or equivalent capability within a user namespace. An attacker triggers or waits for policy expiration events and captures the resulting multicast messages. By repeatedly collecting leaked padding bytes across many notifications, the attacker can recover fragments of adjacent heap allocations. The leaked data may include kernel pointers useful for defeating KASLR or sensitive material from prior heap users.
No public proof-of-concept exploit is available, and the issue is not listed in the CISA Known Exploited Vulnerabilities catalog.
Detection Methods for CVE-2026-31664
Indicators of Compromise
- Unprivileged or unexpected processes binding to AF_NETLINK sockets of family NETLINK_XFRM and joining the XFRMNLGRP_EXPIRE multicast group
- Anomalous volumes of xfrm policy churn (rapid creation, modification, or deletion of policies) intended to generate expiration notifications
- Processes running with CAP_NET_ADMIN from non-standard binaries or containers reading xfrm netlink traffic
Detection Strategies
- Audit kernel version inventories against the fixed commits (71a98248, ac698590, b1dfd6b2, c221ed63, e1af65c6, eda30846) using configuration management and vulnerability scanners.
- Monitor auditd records for socket() syscalls creating NETLINK_XFRM sockets correlated with setsockopt() calls joining multicast groups.
- Apply eBPF-based tracing to log processes invoking xfrm-related netlink operations and flag unusual subscribers.
Monitoring Recommendations
- Track usage of CAP_NET_ADMIN within containers and user namespaces, as this capability gates access to the affected netlink group.
- Alert on unexpected kernel module or userspace tooling that interacts with the IPsec policy database outside change windows.
- Review host telemetry for processes reading large volumes of netlink data without a corresponding operational role.
How to Mitigate CVE-2026-31664
Immediate Actions Required
- Identify all Linux hosts running kernels that include the unfixed build_polexpire() path and prioritize patching for systems using IPsec or running multi-tenant workloads.
- Apply the vendor-provided kernel update from your distribution as soon as it becomes available.
- Restrict CAP_NET_ADMIN within containers and limit user namespace creation where it is not operationally required.
Patch Information
The upstream fix adds the missing memset_after() call in build_polexpire() so that trailing padding in struct xfrm_user_polexpire is explicitly zeroed before the message is multicast. The fix is available in the following stable kernel commits: Kernel Git Commit 71a9824, Kernel Git Commit ac69859, Kernel Git Commit b1dfd6b, Kernel Git Commit c221ed6, Kernel Git Commit e1af65c, and Kernel Git Commit eda3084.
Workarounds
- Disable or unload the xfrm subsystem on hosts that do not require IPsec functionality to remove the vulnerable code path.
- Restrict creation of unprivileged user namespaces via sysctl -w kernel.unprivileged_userns_clone=0 on distributions that expose this control.
- Use seccomp or LSM policies (AppArmor, SELinux) to deny NETLINK_XFRM socket creation for workloads that do not require it.
# Configuration example: disable unprivileged user namespaces to limit CAP_NET_ADMIN acquisition
sysctl -w kernel.unprivileged_userns_clone=0
# Verify currently running kernel against fixed stable branches
uname -r
# Audit which processes hold NETLINK_XFRM sockets
ss -f netlink | grep -i xfrm
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

