Security Vulnerability Report
中文
CVE-2026-31707 CVSS 7.1 HIGH

CVE-2026-31707

Published: 2026-05-01 14:16:21
Last Modified: 2026-05-06 20:26:39
Source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

Description

In the Linux kernel, the following vulnerability has been resolved: ksmbd: validate response sizes in ipc_validate_msg() ipc_validate_msg() computes the expected message size for each response type by adding (or multiplying) attacker-controlled fields from the daemon response to a fixed struct size in unsigned int arithmetic. Three cases can overflow: KSMBD_EVENT_RPC_REQUEST: msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz; KSMBD_EVENT_SHARE_CONFIG_REQUEST: msg_sz = sizeof(struct ksmbd_share_config_response) + resp->payload_sz; KSMBD_EVENT_LOGIN_REQUEST_EXT: msg_sz = sizeof(struct ksmbd_login_response_ext) + resp->ngroups * sizeof(gid_t); resp->payload_sz is __u32 and resp->ngroups is __s32. Each addition can wrap in unsigned int; the multiplication by sizeof(gid_t) mixes signed and size_t, so a negative ngroups is converted to SIZE_MAX before the multiply. A wrapped value of msg_sz that happens to equal entry->msg_sz bypasses the size check on the next line, and downstream consumers (smb2pdu.c:6742 memcpy using rpc_resp->payload_sz, kmemdup in ksmbd_alloc_user using resp_ext->ngroups) then trust the unverified length. Use check_add_overflow() on the RPC_REQUEST and SHARE_CONFIG_REQUEST paths to detect integer overflow without constraining functional payload size; userspace ksmbd-tools grows NDR responses in 4096-byte chunks for calls like NetShareEnumAll, so a hard transport cap is unworkable on the response side. For LOGIN_REQUEST_EXT, reject resp->ngroups outside the signed [0, NGROUPS_MAX] range up front and report the error from ipc_validate_msg() so it fires at the IPC boundary; with that bound the subsequent multiplication and addition stay well below UINT_MAX. The now-redundant ngroups check and pr_err in ksmbd_alloc_user() are removed. This is the response-side analogue of aab98e2dbd64 ("ksmbd: fix integer overflows on 32 bit systems"), which hardened the request side.

CVSS Details

CVSS Score
7.1
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/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
Linux Kernel (ksmbd module prior to commit d6a6aa81eac2c9bff66dc6e191179cb69a14426b)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
/* * Conceptual PoC for CVE-2026-31707 * Demonstrating the integer overflow logic in ksmbd ipc_validate_msg() */ #include <stdio.h> #include <stdint.h> // Simulate the struct sizes and types mentioned in the vulnerability #define SIZEOF_STRUCT 0x20 // Hypothetical size of struct ksmbd_rpc_command typedef uint32_t __u32; typedef int32_t __s32; struct ksmbd_rpc_command { __u32 payload_sz; // Attacker controlled field }; void check_overflow_poc() { struct ksmbd_rpc_command *resp = malloc(sizeof(struct ksmbd_rpc_command)); // Scenario 1: Integer Overflow in Addition // Goal: Bypass a check where expected msg_sz is 0x1000 (4096) // Calculation: msg_sz = sizeof(struct) + resp->payload_sz // If we want msg_sz to wrap around to 0x1000 // We set payload_sz to a very large value that causes overflow. __u32 target_size = 0x1000; // Calculate payload_sz needed to overflow and result in target_size // (SIZEOF_STRUCT + payload_sz) % UINT_MAX = target_size // payload_sz = target_size - SIZEOF_STRUCT (if no overflow) OR // payload_sz = UINT_MAX - SIZEOF_STRUCT + 1 + target_size __u32 malicious_payload_sz = UINT32_MAX - SIZEOF_STRUCT + 1 + target_size; resp->payload_sz = malicious_payload_sz; // Simulate the vulnerable calculation __u32 msg_sz = SIZEOF_STRUCT + resp->payload_sz; printf("Payload_sz: 0x%x\n", resp->payload_sz); printf("Calculated msg_sz: 0x%x\n", msg_sz); if (msg_sz == target_size) { printf("[+] Check bypassed! Integer overflow successful.\n"); printf("[!] Downstream memcpy will now use huge payload_sz: 0x%x\n", resp->payload_sz); // This leads to heap overflow or OOB read } else { printf("[-] Check failed.\n"); } free(resp); } int main() { check_overflow_poc(); return 0; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-31707", "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "published": "2026-05-01T14:16:20.720", "lastModified": "2026-05-06T20:26:38.560", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nksmbd: validate response sizes in ipc_validate_msg()\n\nipc_validate_msg() computes the expected message size for each\nresponse type by adding (or multiplying) attacker-controlled fields\nfrom the daemon response to a fixed struct size in unsigned int\narithmetic. Three cases can overflow:\n\n KSMBD_EVENT_RPC_REQUEST:\n msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz;\n KSMBD_EVENT_SHARE_CONFIG_REQUEST:\n msg_sz = sizeof(struct ksmbd_share_config_response) +\n resp->payload_sz;\n KSMBD_EVENT_LOGIN_REQUEST_EXT:\n msg_sz = sizeof(struct ksmbd_login_response_ext) +\n resp->ngroups * sizeof(gid_t);\n\nresp->payload_sz is __u32 and resp->ngroups is __s32. Each addition\ncan wrap in unsigned int; the multiplication by sizeof(gid_t) mixes\nsigned and size_t, so a negative ngroups is converted to SIZE_MAX\nbefore the multiply. A wrapped value of msg_sz that happens to\nequal entry->msg_sz bypasses the size check on the next line, and\ndownstream consumers (smb2pdu.c:6742 memcpy using rpc_resp->payload_sz,\nkmemdup in ksmbd_alloc_user using resp_ext->ngroups) then trust the\nunverified length.\n\nUse check_add_overflow() on the RPC_REQUEST and SHARE_CONFIG_REQUEST\npaths to detect integer overflow without constraining functional\npayload size; userspace ksmbd-tools grows NDR responses in 4096-byte\nchunks for calls like NetShareEnumAll, so a hard transport cap is\nunworkable on the response side. For LOGIN_REQUEST_EXT, reject\nresp->ngroups outside the signed [0, NGROUPS_MAX] range up front and\nreport the error from ipc_validate_msg() so it fires at the IPC\nboundary; with that bound the subsequent multiplication and addition\nstay well below UINT_MAX. The now-redundant ngroups check and\npr_err in ksmbd_alloc_user() are removed.\n\nThis is the response-side analogue of aab98e2dbd64 (\"ksmbd: fix\ninteger overflows on 32 bit systems\"), which hardened the request\nside."}], "metrics": {"cvssMetricV31": [{"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H", "baseScore": 7.1, "baseSeverity": "HIGH", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 5.2}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-787"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "5.15", "versionEndExcluding": "6.12.84", "matchCriteriaId": "04651641-C387-4546-B02F-17BA989CC253"}, {"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"}]}]}], "references": [{"url": "https://git.kernel.org/stable/c/299db777ea0cfa5c407e41b045c24a14c034c27b", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/7dd0c858e1909769a4c91842724315ee74f1a5f1", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/99c631d0366c1eab8fb188fe66425f4581ebdde4", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}, {"url": "https://git.kernel.org/stable/c/d6a6aa81eac2c9bff66dc6e191179cb69a14426b", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"]}]}}