From nobody Fri Nov 15 10:49:03 2024 X-Original-To: dev-commits-src-all@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 4XqYfm31smz5d07N; Fri, 15 Nov 2024 10:49:04 +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 "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4XqYfm0Rdcz4X4t; Fri, 15 Nov 2024 10:49:04 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1731667744; 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=j1YEDJ0nMQ6Ns9VoSredmsouZET+V19+ClXvA3akus4=; b=nGrVSWXVMvM2/fKpdHkVnIKi6QnluFfH0GzaLDEYjU1Q0cuYSunaP7d/psLiAy5lyw1ArA swM6YzQJmKyksjbjK9iEcUrBVG+tat6sIWNL7f3TV+HEreyGDDK6+VFNP6S6+dI0dNMGAp 79B5uIW27nqMInjfnFVyfKh8wKWrArpmaKlK+nysRl2rMjtPT0NCu93AJyfFICgJ3EYlDt JPD3AJbQDqK8+o0hdez9jk/Xua2WC8xvziIpceGOz92mP+woBCXDg5z9iwKxq6uM4teEMf n82Mv9F25PeNjdQLvKSpFJzQETaW06JvSELVTS71AfihwDSj8Jv+KAx2L8NA/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1731667744; 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=j1YEDJ0nMQ6Ns9VoSredmsouZET+V19+ClXvA3akus4=; b=rvJteVJqsrJha/kWxA89S7wb7nt2m8A7Igybba9kK3USCeHu7ALQXOkMRwxJLF7u0hYOdI vA7SZk2SDp5RdUL6NuRwvqHabuhW6UiteosuQafGd93AtfRfTHf5WI3iaUmKCETpXAMRUT PTF7mYKflT6gWS60cFlCOQnsF1bWbEb20A4UGR7jRUL31GhR6ET3D1GhJ6f4UElaeQGHQC tYGW66kARjjNBEGjqeojNwNCdjG7t1SScFhKHNHlDUo8orGl5VZfnniWqazfkm6iwXRDuD eZL2uq95a2qj+80d4Ko3S7Qe6kOX4VDLO8iDNohQfGBFOFhoeaulke7+LPW27A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1731667744; a=rsa-sha256; cv=none; b=d5vqPd+tvaUF/13F73oXmodlaw8Mau7ltbC2FBbUfe8vVN92oqNHitwzEI66NfbPoAlE3b b2pw11xIHnCfujvmTlempINPKOsgvMBQgVihO4Z1+vvRjyTOkjDGmP0qjbr1Aoldc2z1vC wLuLdMfyNtyxAxHmXs3uEyF9g/Y3zcFABlRzDB+7gDW/EB5Meu6OSsQL6Gq81vounDVijw 9S/rO+sSPuRBVmzAIM69q6ixk3kcOtVDdcFSXHvuHqszDU7oMthymiQBpjgobskVXhjO0S gQNnD6jeylax8S/WAbJy8CI088RCBATXhgRZWeTbo2+ReZ80vOyvKqWJEe8aTQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4XqYfl4BQBzKj6; Fri, 15 Nov 2024 10:49:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 4AFAn35C018207; Fri, 15 Nov 2024 10:49:03 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 4AFAn385018204; Fri, 15 Nov 2024 10:49:03 GMT (envelope-from git) Date: Fri, 15 Nov 2024 10:49:03 GMT Message-Id: <202411151049.4AFAn385018204@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Olivier Certner Subject: git: 7b20967a1a17 - stable/14 - nfs, rpc: Ensure kernel credentials have at least one group List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@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: 7b20967a1a172c6398b7f1a56ec96440d78469d2 Auto-Submitted: auto-generated The branch stable/14 has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=7b20967a1a172c6398b7f1a56ec96440d78469d2 commit 7b20967a1a172c6398b7f1a56ec96440d78469d2 Author: Olivier Certner AuthorDate: 2024-10-02 14:28:59 +0000 Commit: Olivier Certner CommitDate: 2024-11-15 10:47:43 +0000 nfs, rpc: Ensure kernel credentials have at least one group This fixes several bugs where some 'struct ucred' in the kernel, constructed from user input (via nmount(2)) or obtained from other servers (e.g., gssd(8)), could have an unfilled 'cr_groups' field and whose 'cr_groups[0]' (or 'cr_gid', which is an alias) was later accessed, causing an uninitialized access giving random access rights. Use crsetgroups_fallback() to enforce a fallback group when possible. For NFS, the chosen fallback group is that of the NFS server in the current VNET (NFSD_VNET(nfsrv_defaultgid)). There does not seem to be any sensible fallback available in rpc code (sys/rpc/svc_auth.c, svc_getcred()) on AUTH_UNIX (TLS or not), so just fail credential retrieval there. Stock NSS sources, rpc.tlsservd(8) or rpc.tlsclntd(8) provide non-empty group lists, so will not be impacted. Discussed with: rmacklem (by mail) Approved by: markj (mentor) MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D46918 (cherry picked from commit cfbe7a62dc62e8a5d7520cb5eb8ad7c4a9418e26) Approved by: markj (mentor) --- sys/fs/nfs/nfs_commonport.c | 4 +++- sys/fs/nfs/nfs_commonsubs.c | 5 +++-- sys/fs/nfsserver/nfs_nfsdport.c | 6 +++++- sys/fs/nfsserver/nfs_nfsdsocket.c | 6 ++---- sys/kern/vfs_export.c | 12 ++++++++---- sys/rpc/rpcsec_gss/svc_rpcsec_gss.c | 2 +- sys/rpc/svc_auth.c | 8 ++++++-- 7 files changed, 28 insertions(+), 15 deletions(-) diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c index 2db9af5b9ea9..11f31d1a0e9f 100644 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -75,6 +75,7 @@ NFSD_VNET_DEFINE(struct nfsstatsv1 *, nfsstatsv1_p); NFSD_VNET_DECLARE(struct nfssockreq, nfsrv_nfsuserdsock); NFSD_VNET_DECLARE(nfsuserd_state, nfsrv_nfsuserd); +NFSD_VNET_DECLARE(gid_t, nfsrv_defaultgid); int nfs_pnfsio(task_fn_t *, void *); @@ -258,7 +259,8 @@ newnfs_copycred(struct nfscred *nfscr, struct ucred *cr) KASSERT(nfscr->nfsc_ngroups >= 0, ("newnfs_copycred: negative nfsc_ngroups")); cr->cr_uid = nfscr->nfsc_uid; - crsetgroups(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups); + crsetgroups_fallback(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups, + NFSD_VNET(nfsrv_defaultgid)); } /* diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 9f0e98bc93ce..29f5a9569b12 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -4037,8 +4037,9 @@ nfssvc_idname(struct nfsd_idargs *nidp) */ cr = crget(); cr->cr_uid = cr->cr_ruid = cr->cr_svuid = nidp->nid_uid; - crsetgroups(cr, nidp->nid_ngroup, grps); - cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0]; + crsetgroups_fallback(cr, nidp->nid_ngroup, grps, + NFSD_VNET(nfsrv_defaultgid)); + cr->cr_rgid = cr->cr_svgid = cr->cr_gid; cr->cr_prison = curthread->td_ucred->cr_prison; prison_hold(cr->cr_prison); #ifdef MAC diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 767bdcd80709..84b579def954 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -3293,7 +3293,11 @@ nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp, NFSVNO_EXPORTANON(exp) || (nd->nd_flag & ND_AUTHNONE) != 0) { nd->nd_cred->cr_uid = credanon->cr_uid; - nd->nd_cred->cr_gid = credanon->cr_gid; + /* + * 'credanon' is already a 'struct ucred' that was built + * internally with calls to crsetgroups_fallback(), so + * we don't need a fallback here. + */ crsetgroups(nd->nd_cred, credanon->cr_ngroups, credanon->cr_groups); } else if ((nd->nd_flag & ND_GSS) == 0) { diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c index df0c0edd1b59..d1b6198ba0e1 100644 --- a/sys/fs/nfsserver/nfs_nfsdsocket.c +++ b/sys/fs/nfsserver/nfs_nfsdsocket.c @@ -1422,13 +1422,11 @@ static struct ucred * nfsrv_createrootcred(void) { struct ucred *cr; - gid_t grp; cr = crget(); cr->cr_uid = cr->cr_ruid = cr->cr_svuid = UID_ROOT; - grp = GID_WHEEL; - crsetgroups(cr, 1, &grp); - cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0]; + crsetgroups_fallback(cr, 0, NULL, GID_WHEEL); + cr->cr_rgid = cr->cr_svgid = cr->cr_gid; cr->cr_prison = curthread->td_ucred->cr_prison; prison_hold(cr->cr_prison); #ifdef MAC diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 3ff9608b0614..4649a05665e5 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -63,6 +63,10 @@ #include #include +#include + +NFSD_VNET_DECLARE(gid_t, nfsrv_defaultgid); + static MALLOC_DEFINE(M_NETADDR, "export_host", "Export host address structure"); #if defined(INET) || defined(INET6) @@ -135,8 +139,8 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep, np->netc_exflags = argp->ex_flags; np->netc_anon = crget(); np->netc_anon->cr_uid = argp->ex_uid; - crsetgroups(np->netc_anon, argp->ex_ngroups, - argp->ex_groups); + crsetgroups_fallback(np->netc_anon, argp->ex_ngroups, + argp->ex_groups, NFSD_VNET(nfsrv_defaultgid)); np->netc_anon->cr_prison = &prison0; prison_hold(np->netc_anon->cr_prison); np->netc_numsecflavors = argp->ex_numsecflavors; @@ -214,8 +218,8 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep, np->netc_exflags = argp->ex_flags; np->netc_anon = crget(); np->netc_anon->cr_uid = argp->ex_uid; - crsetgroups(np->netc_anon, argp->ex_ngroups, - argp->ex_groups); + crsetgroups_fallback(np->netc_anon, argp->ex_ngroups, argp->ex_groups, + NFSD_VNET(nfsrv_defaultgid)); np->netc_anon->cr_prison = &prison0; prison_hold(np->netc_anon->cr_prison); np->netc_numsecflavors = argp->ex_numsecflavors; diff --git a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c index 89526544639a..64038240ab37 100644 --- a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c +++ b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c @@ -538,7 +538,7 @@ rpc_gss_svc_getcred(struct svc_req *req, struct ucred **crp, int *flavorp) cr = client->cl_cred = crget(); cr->cr_uid = cr->cr_ruid = cr->cr_svuid = uc->uid; cr->cr_rgid = cr->cr_svgid = uc->gid; - crsetgroups(cr, uc->gidlen, uc->gidlist); + crsetgroups_fallback(cr, uc->gidlen, uc->gidlist, uc->gid); cr->cr_prison = curthread->td_ucred->cr_prison; prison_hold(cr->cr_prison); *crp = crhold(cr); diff --git a/sys/rpc/svc_auth.c b/sys/rpc/svc_auth.c index 86ce7d9aefd2..edb11426bd72 100644 --- a/sys/rpc/svc_auth.c +++ b/sys/rpc/svc_auth.c @@ -192,10 +192,12 @@ svc_getcred(struct svc_req *rqst, struct ucred **crp, int *flavorp) if ((xprt->xp_tls & (RPCTLS_FLAGS_CERTUSER | RPCTLS_FLAGS_DISABLED)) == RPCTLS_FLAGS_CERTUSER && flavor == AUTH_UNIX) { + if (xprt->xp_ngrps <= 0) + return (FALSE); cr = crget(); cr->cr_uid = cr->cr_ruid = cr->cr_svuid = xprt->xp_uid; crsetgroups(cr, xprt->xp_ngrps, xprt->xp_gidp); - cr->cr_rgid = cr->cr_svgid = xprt->xp_gidp[0]; + cr->cr_rgid = cr->cr_svgid = cr->cr_gid; cr->cr_prison = curthread->td_ucred->cr_prison; prison_hold(cr->cr_prison); *crp = cr; @@ -205,10 +207,12 @@ svc_getcred(struct svc_req *rqst, struct ucred **crp, int *flavorp) switch (flavor) { case AUTH_UNIX: xcr = (struct xucred *) rqst->rq_clntcred; + if (xcr->cr_ngroups <= 0) + return (FALSE); cr = crget(); cr->cr_uid = cr->cr_ruid = cr->cr_svuid = xcr->cr_uid; crsetgroups(cr, xcr->cr_ngroups, xcr->cr_groups); - cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0]; + cr->cr_rgid = cr->cr_svgid = cr->cr_gid; cr->cr_prison = curthread->td_ucred->cr_prison; prison_hold(cr->cr_prison); *crp = cr;