From nobody Fri Dec 19 09:19:10 2025 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4dXhmv100Tz6L9v5 for ; Fri, 19 Dec 2025 09:19:11 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4dXhmt5P8Fz44Tp for ; Fri, 19 Dec 2025 09:19:10 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1766135950; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=5ILIAAQRMeCZGWY0G013wa+jb6y3b8tuts2klLJZMgs=; b=pPNs8EBGOW5HCfUWInQy1Hi+eNp7c0/YsSktVUd9I48cjwF2F+Rf+tLJuLkx0OU0xpfK6p GkyZRl/ddTaZZ7sSeO34uile/XzcpdT9UpJgHj4xu/+SQf340hyTe5e9Y/cFEi3jZaFIQi wyD/TiyrccUHVDBxjnI9RDagQxmA/Qo67t2uuvFRnKnkph24apc5Uiu2f24MAycVCzJkMb 1R8VoyvuB9wvxlr4r/EakZMuES3YW1dYxJWgJvQDrdVDUGdGpNGTvaiSXrOFkZeNuZx4bD zZQcoiwNTFtXnOrvT6WhsCN92erVvI9Jn+FFiyXpc21DY0riXi+MX5sni97ygA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1766135950; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=5ILIAAQRMeCZGWY0G013wa+jb6y3b8tuts2klLJZMgs=; b=oNfBss6O5jTf97F5VlM7XyURQi6aNJRsSQSTj4jWA0zGvWfWWytoSnZx3+FFbgWnj21sdj b6K0gOPDtrHVfCTTYnVbXiJoRrsKn0wX6e12oTpsH3R39Ka8zwzceXYcbIxdmy/RIdUNj4 JvhtJgit6LecUAsq/gbwYSHsMkwycZEE1XSmv1WGsI1qHbEr+YFc1kQdeA9OKRLDqtuRoq G5s9kIkd8IXdrmzltm8X8B1ofTk04JXcOV7hJvQ+qjqalOOmKiMXunEGlJjcn2lqRB5Rh/ Os/1W9JzoHhJ0JwJNj+kmpiCxEhDNz4kD+MH06mNKyuPpk6k/HnFCi+YHEceMQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1766135950; a=rsa-sha256; cv=none; b=xccIOxlWGrPQJYVlR/498d0RyAk4DWfQoyie1x1ong0tFgLkvSXJ/vuoozT74HcKyA3ihz O81LDzpwJyfek41ObbXCzT5RZ7NQ07UhAZhrssDtP250kXDzXZkMaG8+o6lW1bBXQTKN1K i1JxaqpZP0edVXcUtjCuegW12zuOEmpGJzDNPFB2N9PxW2LpgylI4tuPwuJfQU/r7ZhmGS 2ZnWfg2uDAN0PWGcgPc/FxPrmAXmKe3lgDQAChWuFT55vNgM3YKFYYo2hQ0C+WmfeGosFJ uQyNoQcVo6cW7N+KxV8hYA7zzDsFGEI8j3074JPK6yTg9S5wYrmIN1TYcEGJPQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4dXhmt4b8lz1GKs for ; Fri, 19 Dec 2025 09:19:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3f0f8 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 19 Dec 2025 09:19:10 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Olivier Certner Subject: git: 8807380a7400 - stable/14 - sys/rpc: UNIX auth: Fix OOB reads on too short message List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: olce X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 8807380a7400d0ea1ef788c81e70b3a363f632a9 Auto-Submitted: auto-generated Date: Fri, 19 Dec 2025 09:19:10 +0000 Message-Id: <6945188e.3f0f8.fa9a98a@gitrepo.freebsd.org> The branch stable/14 has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=8807380a7400d0ea1ef788c81e70b3a363f632a9 commit 8807380a7400d0ea1ef788c81e70b3a363f632a9 Author: Olivier Certner AuthorDate: 2025-10-07 15:51:16 +0000 Commit: Olivier Certner CommitDate: 2025-12-19 09:16:45 +0000 sys/rpc: UNIX auth: Fix OOB reads on too short message In the inline version (_svcauth_unix()), fix multiple possible OOB reads when the credentials part of a request is too short to contain mandatory fields or with respect to the hostname length or number of groups it advertises. The previously existing check was arriving too late and relied on possibly wrong data coming from earlier OOB reads. While here, use 'uint32_t' as the length/size type, as it is more than enough and removes the need for conversions, explicit or implicit. While here, factor out setting 'stat' to AUTH_BADCRED and then jumping to 'done' on error, through the new 'badcred' label. While here, through comments, refer to what the non-inline version is doing (xdr_authunix_parms() in 'authunix_prot.c') and the reasons. Reviewed by: rmacklem Fixes: dfdcada31e79 ("Add the new kernel-mode NFS Lock Manager.") MFC after: 2 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D52964 (cherry picked from commit d4cc791f3b2e1b6926420649a481eacaf3bf268e) --- sys/rpc/svc_auth_unix.c | 99 ++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 39 deletions(-) diff --git a/sys/rpc/svc_auth_unix.c b/sys/rpc/svc_auth_unix.c index 97fd08de7f2b..7222fd6d95c0 100644 --- a/sys/rpc/svc_auth_unix.c +++ b/sys/rpc/svc_auth_unix.c @@ -63,11 +63,8 @@ _svcauth_unix(struct svc_req *rqst, struct rpc_msg *msg) enum auth_stat stat; XDR xdrs; int32_t *buf; - uint32_t time; struct xucred *xcr; - u_int auth_len; - size_t str_len, supp_ngroups; - u_int i; + uint32_t auth_len, time; xcr = rqst->rq_clntcred; auth_len = (u_int)msg->rm_call.cb_cred.oa_length; @@ -75,51 +72,71 @@ _svcauth_unix(struct svc_req *rqst, struct rpc_msg *msg) XDR_DECODE); buf = XDR_INLINE(&xdrs, auth_len); if (buf != NULL) { - time = IXDR_GET_UINT32(buf); - str_len = (size_t)IXDR_GET_UINT32(buf); - if (str_len > AUTH_SYS_MAX_HOSTNAME) { - stat = AUTH_BADCRED; - goto done; + /* 'time', 'str_len', UID, GID and 'supp_ngroups'. */ + const uint32_t min_len = 5 * BYTES_PER_XDR_UNIT; + uint32_t str_len, supp_ngroups; + + if (auth_len < min_len) { + (void)printf("AUTH_SYS: Too short credentials (%u)\n", + auth_len); + goto badcred; } + time = IXDR_GET_UINT32(buf); + str_len = IXDR_GET_UINT32(buf); + if (str_len > AUTH_SYS_MAX_HOSTNAME) + goto badcred; str_len = RNDUP(str_len); + /* + * Recheck message length now that we know the value of + * 'str_len' (and that it won't cause an overflow in additions + * below) to protect access to the credentials part. + */ + if (auth_len < min_len + str_len) { + (void)printf("AUTH_SYS: Inconsistent credentials and " + "host name lengths (%u, %u)\n", + auth_len, str_len); + goto badcred; + } buf += str_len / sizeof (int32_t); xcr->cr_uid = IXDR_GET_UINT32(buf); xcr->cr_gid = IXDR_GET_UINT32(buf); - supp_ngroups = (size_t)IXDR_GET_UINT32(buf); - if (supp_ngroups > AUTH_SYS_MAX_GROUPS) { - stat = AUTH_BADCRED; - goto done; - } - for (i = 0; i < supp_ngroups; i++) { - /* - * Note that this is a `struct xucred`, which maintains - * its historical layout of preserving the egid in - * cr_ngroups and cr_groups[0] == egid. - */ - if (i + 1 < XU_NGROUPS) - xcr->cr_groups[i + 1] = IXDR_GET_INT32(buf); - else - buf++; + supp_ngroups = IXDR_GET_UINT32(buf); + /* + * See the herald comment before a similar test at the end of + * xdr_authunix_parms() for why we strictly respect RFC 5531 and + * why we may have to drop the last supplementary group when + * there are AUTH_SYS_MAX_GROUPS of them. + */ + if (supp_ngroups > AUTH_SYS_MAX_GROUPS) + goto badcred; + /* + * Final message length check, as we now know how much we will + * read in total. + */ + if (auth_len < min_len + str_len + + supp_ngroups * BYTES_PER_XDR_UNIT) { + (void)printf("AUTH_SYS: Inconsistent lengths " + "(credentials %u, machine name %u, " + "supplementary groups %u)\n", + auth_len, str_len, + supp_ngroups * BYTES_PER_XDR_UNIT); + goto badcred; } - if (supp_ngroups + 1 > XU_NGROUPS) - xcr->cr_ngroups = XU_NGROUPS; - else - xcr->cr_ngroups = supp_ngroups + 1; /* - * five is the smallest unix credentials structure - - * timestamp, hostname len (0), uid, gid, and gids len (0). + * Note that 'xcr' is a 'struct xucred', which still has the + * historical layout where the effective GID is in cr_groups[0] + * and is accounted in 'cr_ngroups'. */ - if ((5 + supp_ngroups) * BYTES_PER_XDR_UNIT + str_len > auth_len) { - (void) printf("bad auth_len gid %ld str %ld auth %u\n", - (long)supp_ngroups, (long)str_len, auth_len); - stat = AUTH_BADCRED; - goto done; + for (uint32_t i = 0; i < supp_ngroups; ++i) { + if (i < XU_NGROUPS - 1) + xcr->cr_groups[i + 1] = IXDR_GET_INT32(buf); + else + buf++; } - } else if (! xdr_authunix_parms(&xdrs, &time, xcr)) { - stat = AUTH_BADCRED; - goto done; - } + xcr->cr_ngroups = MIN(supp_ngroups + 1, XU_NGROUPS); + } else if (! xdr_authunix_parms(&xdrs, &time, xcr)) + goto badcred; rqst->rq_verf = _null_auth; stat = AUTH_OK; @@ -127,6 +144,10 @@ done: XDR_DESTROY(&xdrs); return (stat); + +badcred: + stat = AUTH_BADCRED; + goto done; }