CVE-2026-64535 Overview
CVE-2026-64535 is a use-after-free vulnerability in the Linux kernel's NVMe over TCP target driver (nvmet-tcp). The flaw resides in the data digest error path of nvmet_tcp_try_recv_ddgst(). When data digest is enabled and a digest mismatch occurs on a non-final H2C_DATA PDU during an R2T-based transfer, the error handler calls nvmet_req_uninit() without marking the command as completed. Subsequent queue teardown iterates the command list and calls nvmet_req_uninit() a second time on the same command, producing a double percpu_ref_put() against a single percpu_ref_get(). The vulnerability was reported by Shivam Kumar via vulnerability testing.
Critical Impact
A network-adjacent attacker able to establish an NVMe/TCP session with data digest enabled can trigger memory corruption in the kernel, leading to denial of service and potential remote code execution in kernel context.
Affected Products
- Linux kernel builds containing the nvmet-tcp target driver with data digest support
- Storage servers exposing NVMe over Fabrics (NVMe-oF) TCP targets
- Distributions shipping vulnerable stable kernel branches prior to the fixing commits
Discovery Timeline
- Vulnerability reported by Shivam Kumar via vulnerability testing
- 2026-07-27 - CVE-2026-64535 published to NVD
- 2026-07-30 - Last updated in NVD database
Technical Details for CVE-2026-64535
Vulnerability Analysis
The defect is a use-after-free triggered by an unbalanced reference count on the NVMe target submission queue. nvmet-tcp implements the NVMe/TCP target-side protocol, including optional CRC32C data digests on Host-to-Controller (H2C_DATA) PDUs. When digest verification fails mid-transfer, the driver must abort the command and clean up state consistently.
The bug allows the same request object to be uninitialized twice, decrementing the per-CPU reference count on the submission queue below its owned count. Once the reference reaches zero prematurely, the queue and associated command structures can be freed while other kernel paths still hold pointers to them, leading to memory corruption. An attacker capable of sending crafted H2C_DATA PDUs with invalid digests to a listening NVMe/TCP target can weaponize the condition.
Root Cause
The digest error handler in nvmet_tcp_try_recv_ddgst() invokes nvmet_req_uninit(), which performs percpu_ref_put() on the submission queue, but leaves the command in an inconsistent state. It does not set cqe->status, does not update rbytes_done, and does not clear the flag indicating the command still expects data. During fatal-error queue teardown, nvmet_tcp_uninit_data_in_cmds() iterates all commands and evaluates nvmet_tcp_need_data_in(). Because rbytes_done < transfer_len and cqe->status == 0, the command appears to still require data, so nvmet_req_uninit() runs a second time on the same command.
Attack Vector
Exploitation requires network reachability to an NVMe/TCP target with data digest negotiated on the connection. During an R2T-based write, the attacker transmits a non-final H2C_DATA PDU whose payload does not match its declared CRC32C digest. The digest mismatch triggers the flawed error path. When the connection subsequently encounters a fatal error, teardown re-uninitializes the same command and corrupts the reference counting on kernel memory.
See the upstream fixes for technical details: Kernel commit 088ee46c18d9, commit 6f9442983a3e, commit 96fe2513df59, commit dbbd07d0a702, and commit e091ff83d962.
Detection Methods for CVE-2026-64535
Indicators of Compromise
- Kernel log entries from nvmet_tcp reporting data digest mismatches followed by queue teardown or fatal-error messages on the target host.
- KASAN or slab-use-after-free splats referencing nvmet_req_uninit, percpu_ref_put, or nvmet_tcp_uninit_data_in_cmds in dmesg.
- Unexpected NVMe/TCP client disconnects correlated with malformed H2C_DATA PDUs on port 4420 or other configured NVMe-oF listeners.
Detection Strategies
- Monitor kernel ring buffers on NVMe-oF target servers for repeated ddgst mismatch events, which precede exploitation attempts.
- Inspect NVMe/TCP flows for anomalous rates of digest failures from a single initiator IP, a strong signal of protocol fuzzing.
- Correlate storage-target kernel oopses or BUG: traces with prior NVMe/TCP session activity from untrusted networks.
Monitoring Recommendations
- Forward /var/log/kern.log and journald output from storage targets to a centralized log platform and alert on nvmet_tcp error strings.
- Track NVMe-oF listener connections in flow logs and baseline expected initiator addresses, alerting on new or external sources.
- Enable kernel crash reporting (kdump) on NVMe/TCP targets so that any exploitation attempt produces analyzable artifacts.
How to Mitigate CVE-2026-64535
Immediate Actions Required
- Update to a Linux kernel version containing the upstream fixes referenced in the kernel.org stable commits listed above.
- Restrict network access to NVMe/TCP listener ports (default TCP 4420) to trusted initiator subnets using host firewalls or network ACLs.
- Audit which hosts export NVMe-oF targets and disable the nvmet_tcp module on systems that do not require it.
Patch Information
The fix is distributed across five stable-tree commits. Apply the kernel build that includes commits 088ee46c18d9, 6f9442983a3e, 96fe2513df59, dbbd07d0a702, and e091ff83d962, which ensure the digest error path fully completes the command, sets cqe->status, and prevents the second nvmet_req_uninit() call during queue teardown. Distribution vendors are backporting these patches into their supported kernel streams.
Workarounds
- Disable data digest negotiation on NVMe/TCP target configurations until patched kernels are deployed.
- Unload the nvmet_tcp kernel module on servers that are not actively serving NVMe-oF traffic: modprobe -r nvmet_tcp.
- Enforce IPsec or mutual TLS-terminated tunnels in front of NVMe/TCP listeners so untrusted hosts cannot deliver crafted PDUs.
# Configuration example: block untrusted access to NVMe/TCP listener and unload module if unused
sudo iptables -A INPUT -p tcp --dport 4420 ! -s 10.0.0.0/24 -j DROP
sudo modprobe -r nvmet_tcp 2>/dev/null || echo "nvmet_tcp in use; schedule patched kernel reboot"
uname -r # verify kernel version includes the upstream fix commits
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

