Bug 2478446 (CVE-2026-112314) - CVE-2026-112314 krb5: MIT krb5 GSS-RPC client memory leak on XID mismatch retries
Summary: CVE-2026-112314 krb5: MIT krb5 GSS-RPC client memory leak on XID mismatch ret...
Keywords:
Status: NEW
Alias: CVE-2026-112314
Deadline: 2026-11-09
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Product Security DevOps Team
QA Contact:
URL:
Whiteboard:
Depends On: 2569239
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-05-18 03:35 UTC by OSIDB Bzimport
Modified: 2026-11-09 18:26 UTC (History)
5 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-05-18 03:35:07 UTC
AI_ONLY_REPORT
package: krb5-1.21.3-8.el10_0
------
Summary: Unbounded Memory Leak in `clnttcp_call` on XID Mismatch (plus  
retry leak on `AUTH_REFRESH`): a malicious RPC peer or on-path attacker can  
cause unbounded client-side memory growth and denial of service by sending  
accepted TCP RPC replies with mismatched transaction IDs and non-empty  
verifiers.
Requirements to exploit: An application using the TCP RPC client path in  
`krb5-1.21.3-8.el10_0` must issue a call through `clnttcp_call`, and the  
attacker must be able to act as the RPC server or inject syntactically  
valid reply records on the connection before a matching reply is processed.
Component affected: `krb5-1.21.3-8.el10_0`, `src/lib/rpc/clnt_tcp.c`,  
`clnttcp_call` (with verifier allocation reached through  
`xdr_opaque_auth()` and `xdr_bytes()`)
Version affected: `krb5-1.21.3-8.el10_0` when the TCP RPC client path in  
`clnttcp_call` is used
Patch available: no released package fix established; proposed patch  
included below
Version fixed: unknown
Upstream coordination: Not notified.
CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 7.5 (HIGH)
AV:N - A malicious RPC peer, or an attacker able to inject replies on  
the network path, can trigger the flaw remotely.
AC:L - The attack requires only syntactically valid `REPLY` messages  
with a mismatched `rm_xid` and a non-empty verifier.
PR:N - No privileges on the client are required.
UI:N - No additional user interaction is required once the vulnerable  
client performs the RPC call.
S:U - The impact is confined to the client process using the affected  
library path.
C:N - No confidentiality impact is established by the available evidence.
I:N - No integrity impact is established by the available evidence.
A:H - Each mismatched accepted reply can leak up to `MAX_AUTH_BYTES`  
(`400`) and the mismatch loop is unbounded for the duration of the call,  
allowing sustained memory growth and possible process termination.
Impact: Moderate. Red Hat classifies remote denial-of-service issues as  
Important when they are easy and broadly exploitable, but this case is  
narrower: it affects a specific client-side RPC path, requires an  
attacker-controlled or intercepted peer, and the demonstrated consequence  
is denial of service of the consuming client process only. The available  
evidence does not establish confidentiality, integrity, or broader system  
compromise.
Embargo: no
Reason: This is an availability-only, client-side issue that requires a  
malicious RPC server or an on-path attacker while the affected TCP RPC  
client path is in use; the current evidence does not show broad compromise  
or wormable behavior.
Acknowledgement: Aisle Research
Vulnerability Details: In `clnttcp_call`, reply headers are decoded in a  
loop until `reply_msg.rm_xid == x_id`. For each iteration,  
`reply_msg.acpted_rply.ar_verf` is reset to `gssrpc__null_auth` before  
`xdr_replymsg()` decodes the reply. When a syntactically valid accepted  
reply carries a non-matching XID, the loop continues without freeing the  
verifier buffer that may have been allocated during decode.
```c
while (TRUE) {
reply_msg.acpted_rply.ar_verf = gssrpc__null_auth;
reply_msg.acpted_rply.ar_results.where = NULL;
reply_msg.acpted_rply.ar_results.proc = xdr_void;
if (! xdrrec_skiprecord(xdrs))
return (ct->ct_error.re_status);
/* now decode and validate the response header */
if (! xdr_replymsg(xdrs, &reply_msg)) {
/*
Free some stuff allocated by xdr_replymsg()
		 * to avoid leaks, since it may allocate
		 * memory from partially successful decodes.
		 */
		enum xdr_op op = xdrs->x_op;
		xdrs->x_op = XDR_FREE;
		xdr_replymsg(xdrs, &reply_msg);
		xdrs->x_op = op;
		if (ct->ct_error.re_status == RPC_SUCCESS)
			continue;
		return (ct->ct_error.re_status);
	}
	if (reply_msg.rm_xid == x_id)
		break;
}
```


The final verifier cleanup runs only after the loop exits, and the retry  
path can also bypass that cleanup:
```c
else {
/* maybe our credentials need to be refreshed ... */
if (refreshes-- && AUTH_REFRESH(h->cl_auth, &reply_msg))
goto call_again;
}
/* free verifier ... */
if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
(reply_msg.acpted_rply.ar_verf.oa_base != NULL)) {
xdrs->x_op = XDR_FREE;
(void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
}
```
`xdr_opaque_auth()` decodes `ar_verf` through `xdr_bytes()`, which  
allocates `oa_base` on decode and releases it only under `XDR_FREE`. On an  
XID mismatch, the next loop iteration overwrites `ar_verf` before that free  
occurs, so the previous pointer is lost. A second leak exists when  
`AUTH_REFRESH()` succeeds and jumps to `call_again` before verifier  
cleanup. The retry-path leak is bounded by the refresh count and is  
secondary; the main issue is the unbounded mismatch loop. The available  
evidence supports availability impact only.
Steps to reproduce:
1. Build with ASan, or run under Valgrind, and exercise any client path  
that uses `clnttcp_call`.
2. Connect the client to a controlled TCP RPC server, or position an  
on-path interceptor, that repeatedly sends syntactically valid `REPLY`  
records with `rm_direction = REPLY`, `rp_stat = MSG_ACCEPTED`,  
`ar_verf.oa_length > 0` (up to `MAX_AUTH_BYTES`), and `rm_xid != client  
x_id`.
3. Keep sending mismatched replies while the client waits for the  
legitimate response.
4. Observe monotonic memory growth in the client process through RSS, ASan,  
or Valgrind.
5. Optionally, return replies that trigger an auth error followed by a  
successful `AUTH_REFRESH()` to reproduce the retry-path leak.
Mitigation: No complete runtime mitigation is established in the package.  
Exposure can be reduced by limiting this TCP RPC client path to trusted  
servers and protected networks, and by using conservative RPC timeouts so a  
waiting call cannot be held open indefinitely. These measures reduce  
exposure but do not remove the underlying leak.
Proposed Fix: Free the verifier for non-matching accepted replies before  
the next decode, and free it before retrying `call_again` on successful  
`AUTH_REFRESH()`.
```diff
diff --git a/src/lib/rpc/clnt_tcp.c b/src/lib/rpc/clnt_tcp.c
— a/src/lib/rpc/clnt_tcp.c
+++ b/src/lib/rpc/clnt_tcp.c
@@ -320,6 +320,15 @@ clnttcp_call(CLIENT *h, rpcproc_t proc, xdrproc_t  
xdr_args, void *args_ptr,
if (reply_msg.rm_xid == x_id)
break;
+		/* Free verifier from non-matching replies before next decode. */
+		if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+		    (reply_msg.acpted_rply.ar_verf.oa_base != NULL)) {
+			enum xdr_op op = xdrs->x_op;
+			xdrs->x_op = XDR_FREE;
+			(void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
+			xdrs->x_op = op;
+		}
}
@@ -340,8 +349,18 @@ clnttcp_call(CLIENT *h, rpcproc_t proc, xdrproc_t  
xdr_args, void *args_ptr,
else {
/* maybe our credentials need to be refreshed ... */
if (refreshes- && AUTH_REFRESH(h->cl_auth, &reply_msg))
+		if (refreshes-- && AUTH_REFRESH(h->cl_auth, &reply_msg)) {
+			/* Free verifier before retrying call_again. */
+			if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+			    (reply_msg.acpted_rply.ar_verf.oa_base != NULL)) {
+				enum xdr_op op = xdrs->x_op;
+				xdrs->x_op = XDR_FREE;
+				(void)xdr_opaque_auth(xdrs,
+						      &(reply_msg.acpted_rply.ar_verf));
+				xdrs->x_op = op;
+			}
goto call_again;
+		}
}
```
------
This report was generated using AI technology. Always review AI-generated  
content prior to use


Note You need to log in before you can comment on or make changes to this bug.