[CBR 7.9] CVE-2025-40240, CVE-2026-31402, CVE-2018-16885#1350
Open
pvts-mat wants to merge 2 commits into
Open
Conversation
jira VULN-180160 cve CVE-2026-31402 commit-author Jeff Layton <jlayton@kernel.org> commit 5133b61 upstream-diff Used `post_err_offset' instead of `op_status_offset + XDR_UNIT' in the `read_bytes_from_xdr_buf()' call, as the CBR 7.9 version is missing ef3675b ("NFSD: Encode COMPOUND operation status on page boundaries") The NFSv4.0 replay cache uses a fixed 112-byte inline buffer (rp_ibuf[NFSD4_REPLAY_ISIZE]) to store encoded operation responses. This size was calculated based on OPEN responses and does not account for LOCK denied responses, which include the conflicting lock owner as a variable-length field up to 1024 bytes (NFS4_OPAQUE_LIMIT). When a LOCK operation is denied due to a conflict with an existing lock that has a large owner, nfsd4_encode_operation() copies the full encoded response into the undersized replay buffer via read_bytes_from_xdr_buf() with no bounds check. This results in a slab-out-of-bounds write of up to 944 bytes past the end of the buffer, corrupting adjacent heap memory. This can be triggered remotely by an unauthenticated attacker with two cooperating NFSv4.0 clients: one sets a lock with a large owner string, then the other requests a conflicting lock to provoke the denial. We could fix this by increasing NFSD4_REPLAY_ISIZE to allow for a full opaque, but that would increase the size of every stateowner, when most lockowners are not that large. Instead, fix this by checking the encoded response length against NFSD4_REPLAY_ISIZE before copying into the replay buffer. If the response is too large, set rp_buflen to 0 to skip caching the replay payload. The status is still cached, and the client already received the correct response on the original request. Fixes: 1da177e ("Linux-2.6.12-rc2") Cc: stable@kernel.org Reported-by: Nicholas Carlini <npc@anthropic.com> Tested-by: Nicholas Carlini <npc@anthropic.com> Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> (cherry picked from commit 5133b61) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
jira VULN-176137 cve CVE-2025-40240 commit-author Alexey Simakov <bigalex934@gmail.com> commit 441f064 upstream-diff Same change as in upstream, except for ciqcbr7_9's SCTP_INC_STATS_BH macro instead of upstream's __SCTP_INC_STATS. It's the same macro, renamed on upstream in 13415e4 ("net: snmp: kill STATS_BH macros") chunk->skb pointer is dereferenced in the if-block where it's supposed to be NULL only. chunk->skb can only be NULL if chunk->head_skb is not. Check for frag_list instead and do it just before replacing chunk->skb. We're sure that otherwise chunk->skb is non-NULL because of outer if() condition. Fixes: 90017ac ("sctp: Add GSO support") Signed-off-by: Alexey Simakov <bigalex934@gmail.com> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Link: https://patch.msgid.link/20251021130034.6333-1-bigalex934@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> (cherry picked from commit 441f064) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
d83471a to
9f7bcac
Compare
|
🤖 Validation Checks In Progress Workflow run: https://github.com/ctrliq/kernel-src-tree/actions/runs/27696065423 |
🔍 Interdiff Analysis
================================================================================
* DELTA DIFFERENCES - code changes that differ between the patches *
================================================================================
--- b/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -4469,10 +4469,8 @@
int len = xdr->buf->len - post_err_offset;
so->so_replay.rp_status = op->status;
- if (len <= NFSD4_REPLAY_ISIZE) {
- so->so_replay.rp_buflen = len;
- read_bytes_from_xdr_buf(xdr->buf,
- post_err_offset,
+ so->so_replay.rp_buflen = len;
+ read_bytes_from_xdr_buf(xdr->buf, post_err_offset,
so->so_replay.rp_buf, len);
} else {
so->so_replay.rp_buflen = 0;
################################################################################
! REJECTED PATCH2 HUNKS - could not be compared; manual review needed !
################################################################################
--- b/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -6281,8 +6281,10 @@
int len = xdr->buf->len - (op_status_offset + XDR_UNIT);
so->so_replay.rp_status = op->status;
- so->so_replay.rp_buflen = len;
- read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT,
+ if (len <= NFSD4_REPLAY_ISIZE) {
+ so->so_replay.rp_buflen = len;
+ read_bytes_from_xdr_buf(xdr->buf,
+ op_status_offset + XDR_UNIT,
so->so_replay.rp_buf, len);
}
status:
================================================================================
* CONTEXT DIFFERENCES - surrounding code differences between the patches *
================================================================================
--- b/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -4466,8 +4467,8 @@
so->so_replay.rp_status = op->status;
so->so_replay.rp_buflen = len;
- read_bytes_from_xdr_buf(xdr->buf, post_err_offset,
+ read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT,
so->so_replay.rp_buf, len);
}
status:
- /* Note that op->status is already in network byte order: */
+ op->status = nfsd4_map_status(op->status,
================================================================================
* DELTA DIFFERENCES - code changes that differ between the patches *
================================================================================
--- b/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -187,12 +187,17 @@
/* skbs with "cover letter" */
if (chunk->head_skb && chunk->skb->data_len == chunk->skb->len) {
if (WARN_ON(!skb_shinfo(chunk->skb)->frag_list)) {
- SCTP_INC_STATS_BH(dev_net(chunk->skb->dev),
- SCTP_MIB_IN_PKT_DISCARDS);
+ __SCTP_INC_STATS(dev_net(chunk->skb->dev),
+ SCTP_MIB_IN_PKT_DISCARDS);
sctp_chunk_free(chunk);
goto next_chunk;
}
chunk->skb = skb_shinfo(chunk->skb)->frag_list;
+
+ if (WARN_ON(!chunk->skb)) {
+ SCTP_INC_STATS_BH(dev_net(chunk->skb->dev), SCTP_MIB_IN_PKT_DISCARDS);
+ sctp_chunk_free(chunk);
+ goto next_chunk;
}
}
################################################################################
! REJECTED PATCH2 HUNKS - could not be compared; manual review needed !
################################################################################
--- b/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -177,11 +183,6 @@
/* skbs with "cover letter" */
if (chunk->head_skb && chunk->skb->data_len == chunk->skb->len)
chunk->skb = skb_shinfo(chunk->skb)->frag_list;
-
- if (WARN_ON(!chunk->skb)) {
- __SCTP_INC_STATS(dev_net(chunk->skb->dev), SCTP_MIB_IN_PKT_DISCARDS);
- sctp_chunk_free(chunk);
- goto next_chunk;
}
}
================================================================================
* CONTEXT DIFFERENCES - surrounding code differences between the patches *
================================================================================
--- b/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -189,7 +173,7 @@
chunk->skb = skb_shinfo(chunk->skb)->frag_list;
if (WARN_ON(!chunk->skb)) {
- SCTP_INC_STATS_BH(dev_net(chunk->skb->dev), SCTP_MIB_IN_PKT_DISCARDS);
+ __SCTP_INC_STATS(dev_net(chunk->skb->dev), SCTP_MIB_IN_PKT_DISCARDS);
sctp_chunk_free(chunk);
goto next_chunk;
}This is an automated interdiff check for backported commits. |
JIRA PR Check Results2 commit(s) with issues found: Commit
|
|
❌ Validation checks completed with issues View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/27696065423 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[CBR 7.9]
Commits
CVE-2025-40240
CVE-2026-31402
CVE-2018-16885
CBR 7.9 is not affected by this bug since c3ad1c3.
Situation
On December 21, 2018 RH published a bug, described as
From the same page:
There is no upstream commit (or any other for that matter) identified as the fix, neither on RH CVE-2018-16885 page nor others (NIST, CVE.org). No more detailed explanation of the problem was found anywhere.
On August 6, 2019 an errata page RHSA-2019:2029 was published containing the fix for RHEL 7, version
kernel-0:3.10.0-1062.el7(https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2018-16885.json), with the fix identified asThis specific kernel version can be found in CBR 7.9 history at c3ad1c3. It contains only four line changes in the
net/core/iovec.cfile (the one containingmemcpy_fromiovecend()function mentioned), aligning perfectly with the short problem description given in the bug page:The "similar functions" mentioned in the bug description apparently are
csum_partial_copy_fromiovecend(),memcpy_fromiovecend_partial_nocache()andmemcpy_fromiovecend_partial_flushcache().On May 26, 2026 RH published an errata page RHSA-2026:14925 for RHEL 7 ELS containing the same fix
and linking to the same bug page. The patched kernel version was
kernel-0:3.10.0-1160.149.1.el7, strongly suggesting that the CVE-2018-16885 fix was already in place from thekernel-0:3.10.0-1062.el7patched revision. The reason for RH patching this kernel again is not clear.The bug
Consider the
memcpy_fromiovecend()function from before c3ad1c3 (centos_kernel-3.10.0-1062.el7tag):kernel-src-tree/net/core/iovec.c
Lines 163 to 185 in 460ce23
It implements the vectorized I/O scatter/gather pattern. It copies
lenbytes of data scattered across the user-spaceiovarray to the contiguous kernel bufferkdata. Theoffsetargument allows to skip initialoffsetbytes of copying, so the sumoffset + lenmust not be greater than the total number of bytes in theiovchunks. Thestruct iovecspecifies a single chunk of data and has a simple "pointer + size" definition:kernel-src-tree/include/uapi/linux/uio.h
Lines 16 to 20 in 460ce23
The size of
iovarray is not given explicitly (let alone bound-checked) anywhere; instead it's assumed the user knows how many bytes collectively theiovchunks contain and doesn't request withoffset + lenany more than that (failure to ensure that was the exact reason for the bug described in https://lists.openvz.org/pipermail/devel/2018-December/072970.html - more on that later).Different elements of the
memcpy_fromiovecend()mechanism can be graphed as follows (all labels denote variables, unless quoted):Note that, despite forming a line above, the
iovchunks are not necessarily contiguous in memory - they were put in line just to better illustrate the sizes arithmetics.The CVE-2018-16885 bug occurs in the first stage of skipping the "finished iovecs":
kernel-src-tree/net/core/iovec.c
Lines 167 to 170 in 460ce23
If the initial
offsetequals the total number of bytes contained in theiovchunks, then the loop above, upon ultimately reaching the end ofiovand reducingoffsetto0(perhaps without any iterations ifiovwas empty andoffsetwas0from the start), will attempt to execute an additional iteration for theiovpointer laying outside the boundary of the originaliovarray.This problem is actually more general than what CVE-2018-16885 description states, namely
memcpy_fromiovecend()not being able to cope withoffset = N, whereNis the total size of data contained iniov. The bug page describes the special case ofN = 0.The issue may be fixed by checking whether
offsetbecame0and breaking the loop right then. This is exactly what the change in c3ad1c3 does:kernel-src-tree/net/core/iovec.c
Lines 167 to 170 in c3ad1c3
Similar code
It was evaluated whether the additional fixing of CVE-2018-16885 in RHEL 7 ELS was associated with other instances of
offset >= iov->iov_lenpattern in thenet/core/iovec.cfile, for example inmemcpy_toiovecend():kernel-src-tree/net/core/iovec.c
Lines 81 to 100 in 460ce23
(Similar situation in
memcpy_toiovecend_partial()andmemcpy_toiovecend_partial_mcsafe().) However, unlikememcpy_fromiovecend()and similar, thememcpy_toiovecend()family guardsoffset >= iov->iov_lenchecks withlen > 0condition. Assuming that these functions are called properly, that is withoffset + len <= Ncondition fulfilled, the problematicoffset = Nsituation implieslen = 0, which would prevent the "finished iovecs skipping" loop from falling out ofiovbounds, as it happens inmemcpy_fromiovecend().Discussion of other solutions
Three other solutions (to not necessarily the same problem) surfaced on the RH's bug page. They are discussed below to shed more light on the issue.
UFO removal
UFO stands for "UDP Fragmentation Offload" feature. It was removed in a branch merged in 5c3c608:
This solution is not mutually exclusive with checking if
offsetis0, as was done in0:3.10.0-1062.el7- removing UFO may get rid of problematicmemcpy_fromiovecend()calls, but leavememcpy_fromiovecend()itself bugged.In any case UFO removal cannot be backported, as that would be a feature change.
Commit 21226ab
The commit mentioned doesn't really "fix"
memcpy_fromiovecend(), but simply drops its usage, replacing it with a neweriov_iterinterface (see https://lwn.net/Articles/625077/). In fact it's a part of a three-commits patch resulting in the eventual removal ofmemcpy_fromiovecend()function altogether:It's possible that the re-application of the CVE-2018-16885 patch in RH's
kernel-0:3.10.0-1160.149.1.el7kernel was the shift toiov_iterinterface as well. Backporting this commit generates conflicts in nearly all modified files though, and solving them would require accounting for (at least) one prerequisite c0371da, which probably can't be backported in full. In short - it's not trivial and was left as an option to evaluate by the reviewers before putting effort into it.Guarding the
vhost_chr_write_iter()callThe issue described in that mail is similar to what CVE-2018-16885 identifies only in the outcome of accessing
iovarray outside of bounds. The mechanism is entirely different and boils down to requestingmemcpy_fromiovecend()to copy more bytes than the data chunks iniovcontain. It may therefore be understood as improper use ofmemcpy_fromiovecend()and not necessarily a bug in the function itself. For the record, the patch given there is present in CBR 7.9 as well, in the same commit as the CVE-2018-16885 fix - c3ad1c3. Seekernel-src-tree/drivers/vhost/net.c
Lines 1437 to 1453 in c3ad1c3
kABI check: passed
Boot test: passed
boot-test.log
Kselftests: passed relative
Reference
kselftests–ciqcbr7_9–run1.log
Patch
kselftests–ciqcbr7_9-CVE-batch-35–run1.log
kselftests–ciqcbr7_9-CVE-batch-35–run2.log
Comparison
The tests results were compared manually with
meld. No results differences were found.