high CVSS 7.8

CVE-2024-26958·Kernel vulnerability

In the Linux kernel, the following vulnerability has been resolved: nfs: fix UAF in direct writes In production we have been hitting the following warning consistently ------------[ cut here ]------------ refcount_t: underflow; use-after-free. WARNING: CPU: 17 PID: 1800359 at lib/refcount.c:28 refcount_warn_saturate+0x9c/0xe0 Workqueue: nfsiod nfs_direct_write_schedule_work [nfs] RIP: 0010:refcount_warn_saturate+0x9c/0xe0 PKRU: 55555554 Call Trace: <TASK> ? __warn+0x9f/0x130 ? refcount_warn_saturate+0x9c/0xe0 ? report_bug+0xcc/0x150 ? handle_bug+0x3d/0x70 ? exc_invalid_op+0x16/0x40 ? asm_exc_invalid_op+0x16/0x20 ? refcount_warn_saturate+0x9c/0xe0 nfs_direct_write_schedule_work+0x237/0x250 [nfs] process_one_work+0x12f/0x4a0 worker_thread+0x14e/0x3b0 ? ZSTD_getCParams_internal+0x220/0x220 kthread+0xdc/0x120 ? __btf_name_valid+0xa0/0xa0 ret_from_fork+0x1f/0x30 This is because we're completing the nfs_direct_request twice in a row. The source of this is when we have our commit requests to submit, we process them and send them off, and then in the completion path for the commit requests we have if (nfs_commit_end(cinfo.mds)) nfs_direct_write_complete(dreq); However since we're submitting asynchronous requests we sometimes have one that completes before we submit the next one, so we end up calling complete on the nfs_direct_request twice. The only other place we use nfs_generic_commit_list() is in __nfs_commit_inode, which wraps this call in a nfs_commit_begin(); nfs_commit_end(); Which is a common pattern for this style of completion handling, one that is also repeated in the direct code with get_dreq()/put_dreq() calls around where we process events as well as in the completion paths. Fix this by using the same pattern for the commit requests. Before with my 200 node rocksdb stress running this warning would pop every 10ish minutes. With my patch the stress test has been running for several hours without popping.

Severity
high
Software
Kernel
Fixed in
6.8.3
Published
2024-05-01

Affected versions

From: 6.8

Until: 6.8.3

Fixed in: 6.8.3

How to fix this CVE

Update your Linux kernel to version 6.8.3 or later to resolve this use-after-free vulnerability in NFS direct write operations. This patch corrects a reference counting issue that caused double-completion of NFS direct requests, leading to memory safety violations. Affected systems running kernel versions 6.8 through 6.8.2 should prioritize this update immediately.

sudo dnf update kernel kernel-devel

Defensia detects this vulnerability

How to check if you are affected

  1. Check your current kernel version: uname -r
  2. Verify if you are running an affected version (6.8.0 through 6.8.2): uname -r | grep -E '6\.8\.[0-2]($|-)'
  3. Search kernel logs for the refcount underflow warning: grep -i 'refcount_t: underflow' /var/log/kern.log /var/log/messages
  4. Monitor dmesg for nfs_direct_write_schedule_work warnings: dmesg | grep -A5 'nfs_direct_write_schedule_work'
  5. After patching, confirm the new kernel version: uname -r (should be 6.8.3 or later)

FAQ

What is CVE-2024-26958?

CVE-2024-26958 is a use-after-free vulnerability in the Linux kernel's NFS subsystem where asynchronous commit requests in direct write operations can cause double-completion of NFS requests, triggering reference count underflow warnings and potential memory corruption.

Is CVE-2024-26958 being actively exploited?

No, CVE-2024-26958 is not currently listed as being actively exploited in the CISA Known Exploited Vulnerabilities (KEV) catalog, and no public exploits are available.

What versions of Kernel are affected by CVE-2024-26958?

Linux kernel versions 6.8.0 through 6.8.2 are affected; the vulnerability is resolved in kernel 6.8.3 and later versions.

How do I check if my server is vulnerable to CVE-2024-26958?

Run 'uname -r' to check your kernel version; if it matches 6.8.0, 6.8.1, or 6.8.2, your system is vulnerable. You can also search your kernel logs with 'grep -i refcount_t: /var/log/kern.log' for exploitation indicators.

What is the root cause of this vulnerability?

The vulnerability stems from improper reference counting in NFS commit request handling where asynchronous completion callbacks can fire before all commit requests are submitted, causing the same NFS direct request to be completed twice.

Does Defensia detect CVE-2024-26958?

Yes — Defensia's CVE advisory scanner compares installed package versions against the NVD database. If the Linux kernel is installed on a monitored server, CVE-2024-26958 will appear in your dashboard with remediation steps.

Related Kernel CVEs

CVE-2026-43501CVSS 9.8In the Linux kernel, the following vulnerability has been resolved: ipv6: rpl: reserve mac_len headroom when recompressed SRH grows ipv6_rpl_srh_rcv() decompresses an RFC 6554 Source Routing Header, swaps the next segment into ipv6_hdr->daddr, recompresses, then pulls the old header and pushes the new one plus the IPv6 header back. The recompressed header can be larger than the received one when the swap reduces the common-prefix length the segments share with daddr (CmprI=0, CmprE>0, seg[0][0] != daddr[0] gives the maximum +8 bytes). pskb_expand_head() was gated on segments_left == 0, so on earlier segments the push consumed unchecked headroom. Once skb_push() leaves fewer than skb->mac_len bytes in front of data, skb_mac_header_rebuild()'s call to: skb_set_mac_header(skb, -skb->mac_len); will store (data - head) - mac_len into the u16 mac_header field, which wraps to ~65530, and the following memmove() writes mac_len bytes ~64KiB past skb->head. A single AF_INET6/SOCK_RAW/IPV6_HDRINCL packet over lo with a two segment type-3 SRH (CmprI=0, CmprE=15) reaches headroom 8 after one pass; KASAN reports a 14-byte OOB write in ipv6_rthdr_rcv. Fix this by expanding the head whenever the remaining room is less than the push size plus mac_len, and request that much extra so the rebuilt MAC header fits afterwards.
CVE-2026-64385CVSS 9.8In the Linux kernel, the following vulnerability has been resolved: smb: client: fix double-free in SMB2_ioctl() replay A response-bearing attempt can return a replayable error and free its response buffer. If SMB2_ioctl_init() fails before the next send, cleanup retains the previous buffer type and frees that response again. Reset response bookkeeping before each attempt to prevent the stale free.
CVE-2026-64391CVSS 9.8In the Linux kernel, the following vulnerability has been resolved: ksmbd: use opener credentials for ADS I/O Alternate data streams are stored as xattrs. Unlike regular file I/O, their read and write paths therefore call VFS xattr helpers which recheck inode permissions and LSM policy using the current task credentials. Run ADS I/O with the credentials captured when the SMB handle was opened.
CVE-2026-64383CVSS 9.8In the Linux kernel, the following vulnerability has been resolved: smb: client: fix double-free in SMB2_flush() replay SMB2_flush() keeps its response buffer bookkeeping across replay attempts. If a replayable flush response is received and the retry then fails before cifs_send_recv() stores a replacement response, flush_exit will free the stale response pointer a second time. Reinitialize resp_buftype and rsp_iov at the top of the replay loop so cleanup only acts on response state produced by the current attempt. This fixes a double-free without changing replay handling for successful requests.
CVE-2026-53176CVSS 9.8In the Linux kernel, the following vulnerability has been resolved: IB/isert: Reject login PDUs shorter than ISER_HEADERS_LEN In drivers/infiniband/ulp/isert/ib_isert.c, isert_login_recv_done() computes the login request payload length as wc->byte_len minus ISER_HEADERS_LEN with no lower bound, and login_req_len is a signed int. A remote iSER initiator can post a login Send work request carrying fewer than ISER_HEADERS_LEN (76) bytes, so the subtraction underflows and login_req_len becomes negative. isert_rx_login_req() then reads that negative length back into a signed int, takes size = min(rx_buflen, MAX_KEY_VALUE_PAIRS), and because the min() is signed it keeps the negative value; the value is then passed as the memcpy() length and sign-extended to a multi-gigabyte size_t. The copy into the 8192-byte login->req_buf runs far out of bounds and faults, crashing the target node. The login phase precedes iSCSI authentication, so no credentials are required to reach this path. Reject any login PDU shorter than ISER_HEADERS_LEN before the subtraction, mirroring the existing early return on a failed work completion, so login_req_len can never go negative. The upper bound was already safe: a posted login buffer cannot deliver more than ISER_RX_PAYLOAD_SIZE, so the difference stays at or below MAX_KEY_VALUE_PAIRS and the existing min() clamps it; only the missing lower bound needs to be added.

References

Track CVEs across your fleet automatically

Defensia scans your Linux servers and tells you exactly which ones are running vulnerable versions — including CVE-2024-26958. Free for 1 server.

Get started free