[31663] in CVS-changelog-for-Kerberos-V5

home help back first fref pref prev next nref lref last post

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

home help back first fref pref prev next nref lref last post