[PATCH] SUNRPC: avoid possible page reuse from svcauth_gss_wrap_integ()

From: Michael Lowman via B4 Relay

Date: Thu Oct 22 2026 - 09:13:49 EST


From: Michael Lowman <michael.d.lowman@xxxxxxxxx>

Commit 7702378ac4d4 ("SUNRPC: Convert svcauth_gss_wrap_integ() to
use xdr_stream()") and its parent changed from calculating the
integrity checksum in-place in an unused part of the response buffer
to calculating in a scratch buffer and appending it to the response
stream. While the unused part of the response buffer happened to
always end on the first page, the append always occurs on the last.

If less than 32 bytes remain before the page boundary, some or all
of the checksum will be written to the next page. But since the xdr
functions do not update the response's page accounting, the page
will be immediately available for reuse. Data from another request
will overwrite the portion of the checksum on the new page.

Avoid this by marking the page as used when needed.

Signed-off-by: Michael Lowman <michael.d.lowman@xxxxxxxxx>
Fixes: 7702378ac4d4 ("SUNRPC: Convert svcauth_gss_wrap_integ() to use xdr_stream()")
---
When running several reads in parallel from an NFSv4 mount using
sec=krb5i, I find that the checksum is often invalid; of ten 64k
reads of ten different files launched in parallel, usually eight fail.
I observed that this did not occur when using sec=krb5p, and that
part of the checksum appeared to be overwritten with valid data
from other packets. After building with the attached change, I
no longer experience read failures.
---
net/sunrpc/auth_gss/svcauth_gss.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 43839e805531..4219cfb2e88a 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1835,6 +1835,17 @@ static int svcauth_gss_wrap_integ(struct svc_rqst *rqstp)
goto wrap_failed;
xdr_commit_encode(xdr);

+ /**
+ * While the data protocol normally accounts for pages
+ * used in the encode of the operation, the checksum is
+ * written by the above xdr_stream_encode_opaque and can therefore
+ * end up in the next page.
+ * Update the request's bookkeeping to avoid reusing the page for the
+ * next request while it's still referenced by this one.
+ */
+ if (xdr->page_ptr + 1 > rqstp->rq_next_page)
+ rqstp->rq_next_page = xdr->page_ptr + 1;
+
out:
return 0;


---
base-commit: eafb6de800781f0a1be5cdd98d150620041d8b27
change-id: 20261017-integ-page-reuse-0d053e8b0ca2

Best regards,
--
Michael Lowman <michael.d.lowman@xxxxxxxxx>