[31663] in CVS-changelog-for-Kerberos-V5
krb5 commit [krb5-1.22]: Fix leaks when decoding GSS buffers in
daemon@ATHENA.MIT.EDU (ghudson@mit.edu)
Mon Nov 9 12:01:28 2026
From: ghudson@mit.edu
To: cvs-krb5@mit.edu
Message-Id: <20261109170122.89FDD105839@krbdev.mit.edu>
Date: Mon, 9 Nov 2026 12:01:22 -0500 (EST)
MIME-Version: 1.0
Reply-To: krbdev@mit.edu
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: cvs-krb5-bounces@mit.edu
https://github.com/krb5/krb5/commit/2a5a57fed898a59c415d06f95fc1187ef9b977e3
commit 2a5a57fed898a59c415d06f95fc1187ef9b977e3
Author: Julien Rische <jrische@redhat.com>
Date: Tue Oct 13 03:56:58 2026 -0400
Fix leaks when decoding GSS buffers in libgssrpc
In xdr_rpc_gss_unwrap_data(), if xdr_rpc_gss_buf() fails, free the
value we tried to decode as it may contain partial results. Also
avoid using gss_release_buffer() on buffers not allocated by GSS APIs.
In gssrpc__svcauth_gss(), avoid leaking partial results if
xdr_rpc_gss_cred() fails.
[ghudson@mit.edu: folded in gss_release_buffer->xdr_free fixes; moved
responsibility to callers of XDR decoders; rewrote commit message]
CVE-2026-112315:
The RPCSEC_GSS authentication routines in lib/rpc/authgss_prot.c in
MIT Kerberos 5 (aka krb5) 1.4 and later do not free partially decoded
buffers on failure, which allows remote attackers to cause a denial of
service (memory leak in kadmind) via crafted RPCSEC_GSS messages.
(cherry picked from commit cc82b42ce92e2d11be09f69e40795c3c061dd990)
ticket: 9256
version_fixed: 1.22.3
src/lib/rpc/authgss_prot.c | 12 +++++++++---
src/lib/rpc/svc_auth_gss.c | 6 +++---
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/src/lib/rpc/authgss_prot.c b/src/lib/rpc/authgss_prot.c
index 5edace5eb..017fa9ae3 100644
--- a/src/lib/rpc/authgss_prot.c
+++ b/src/lib/rpc/authgss_prot.c
@@ -209,13 +209,15 @@ xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
/* Decode databody_integ. */
if (!xdr_rpc_gss_buf(xdrs, &databuf, mem_budget)) {
+ xdr_free((xdrproc_t)xdr_rpc_gss_buf, &databuf);
log_debug("xdr decode databody_integ failed");
return (FALSE);
}
mem_budget -= databuf.length;
/* Decode checksum. */
if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, mem_budget)) {
- gss_release_buffer(&min_stat, &databuf);
+ xdr_free((xdrproc_t)xdr_rpc_gss_buf, &wrapbuf);
+ xdr_free((xdrproc_t)xdr_rpc_gss_buf, &databuf);
log_debug("xdr decode checksum failed");
return (FALSE);
}
@@ -225,7 +227,7 @@ xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
free(wrapbuf.value);
if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
- gss_release_buffer(&min_stat, &databuf);
+ xdr_free((xdrproc_t)xdr_rpc_gss_buf, &databuf);
log_status("gss_verify_mic", maj_stat, min_stat);
return (FALSE);
}
@@ -233,6 +235,7 @@ xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
/* Decode databody_priv. */
if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, GSSRPC_MAX_MESSAGE_SIZE)) {
+ xdr_free((xdrproc_t)xdr_rpc_gss_buf, &wrapbuf);
log_debug("xdr decode databody_priv failed");
return (FALSE);
}
@@ -255,7 +258,10 @@ xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
xdr_stat = (xdr_u_int32(&tmpxdrs, &seq_num) &&
(*xdr_func)(&tmpxdrs, xdr_ptr));
XDR_DESTROY(&tmpxdrs);
- gss_release_buffer(&min_stat, &databuf);
+ if (svc == RPCSEC_GSS_SVC_INTEGRITY)
+ xdr_free((xdrproc_t)xdr_rpc_gss_buf, &databuf);
+ else if (svc == RPCSEC_GSS_SVC_PRIVACY)
+ gss_release_buffer(&min_stat, &databuf);
/* Verify sequence number. */
if (xdr_stat == TRUE && seq_num != seq) {
diff --git a/src/lib/rpc/svc_auth_gss.c b/src/lib/rpc/svc_auth_gss.c
index 4f1d2911b..8f012c891 100644
--- a/src/lib/rpc/svc_auth_gss.c
+++ b/src/lib/rpc/svc_auth_gss.c
@@ -427,6 +427,8 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg,
gc = (struct rpc_gss_cred *)rqst->rq_clntcred;
memset(gc, 0, sizeof(*gc));
+#define ret_freegc(code) do { retstat = code; goto freegc; } while (0)
+
log_debug("calling xdrmem_create()");
log_debug("oa_base=%p, oa_length=%u", rqst->rq_cred.oa_base,
rqst->rq_cred.oa_length);
@@ -437,14 +439,12 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg,
if (!xdr_rpc_gss_cred(&xdrs, gc)) {
log_debug("xdr_rpc_gss_cred() failed");
XDR_DESTROY(&xdrs);
- return (AUTH_BADCRED);
+ ret_freegc (AUTH_BADCRED);
}
XDR_DESTROY(&xdrs);
retstat = AUTH_FAILED;
-#define ret_freegc(code) do { retstat = code; goto freegc; } while (0)
-
/* Check version. */
if (gc->gc_v != RPCSEC_GSS_VERSION)
ret_freegc (AUTH_BADCRED);
_______________________________________________
cvs-krb5 mailing list
cvs-krb5@mit.edu
https://mailman.mit.edu/mailman/listinfo/cvs-krb5