From nobody Fri Nov 15 13:00:52 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 4XqcZr6Q9Gz5d70F; Fri, 15 Nov 2024 13:00:52 +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 4XqcZr4KXGz4pKv; Fri, 15 Nov 2024 13:00:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1731675652; 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=hV+AXewl/gjVWCZu3ejTu8rdBZVjjuZpCtsme3KFjdE=; b=AU+a3lpuleQmU7Ms2YC1/KOY10qcl5STbviy79lnuarAfhERS+8cK2BFrB8W7x7MCo6EtJ 6eE2DVef3VLRzM2pWaPuI3DnGUmae/k75jQ492iTjyAnQdVIWb0RjNAc6uGvH6VBvawdxN 765PQ0UVDk+Qqv2SVLUR16QSetmN0GOf1cG930FJuVpQHd3V/FdcgwJ/v0plIVe83WHEU6 omhjQXIi/y+tLoiPH9dxmdyEZnhCBAeOd8sNNhzNwJblxyVKgiqs7nTkOoCiJ+UXTREwg9 V5ZgGn+yU4uoVUige1Ba+zk5r6DxeV4Eb27h0JAwGqv1hSHNCJH2z0W4JaL4tQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1731675652; 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=hV+AXewl/gjVWCZu3ejTu8rdBZVjjuZpCtsme3KFjdE=; b=xuR7fuB2ogz2rtMecSj18K41fOsSS3cQpDdMnesJxZJ6DEcphKxc4kzf7zc+UpZksCGx73 OB6ryT0QAifkcKWQk6vPvnyrLYmkGFcPpLuc2iiZpI+Exw8ZXnne3vB6yUu3maBzN8eQj/ whQILMzw11OIceYWj8UnKlSWGHkTi0GgAZxJPdsesX+F8jkdW25gxdet10bTGAz03Y+WBh Hwc6It8X7nsKrSU99RUklrBvV1uox5RCM41XVR0mX7ko84wtylGd7W3NOd6glU3vsRX7Cc HGlNbB7Rvtj9DoQ1el3DTZDSzKor4RnT/HpgZrMXf486p6en5vnLYo72rQJijw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1731675652; a=rsa-sha256; cv=none; b=KGRadkmh4t5oNWFgFsA/+SmrkopNEe1P+Dv+SEjKm6bHu0VOufm9uJqft2hj15BDwNKnVm HNz5mBD7aBzcTjfljb9qxcdyPig6IspHHqVY/Pk20GzmPfxa8Kb5VF3xldchhFBQBLsf5n R1mB8GaJhjneDpzZJCIzPZdUaHRXhUvIF3RKHu8Szpes+6/tzEvZN/d8/gwJ79kudbDo8r ZjXLtOf9eyrCmG0Bdaw863VhO/QiYD3DmrRd+dYwqV9bnuraey8e6lnEhASMXxJFAlN8UT L8pstm17W2dAydpjvsfiu/q+glx8MyE303asF9NOiSLKHDvMfsURTPzkrMhQoA== 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 4XqcZr3Kw2zNnX; Fri, 15 Nov 2024 13:00:52 +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 4AFD0qdf071280; Fri, 15 Nov 2024 13:00:52 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 4AFD0q98071277; Fri, 15 Nov 2024 13:00:52 GMT (envelope-from git) Date: Fri, 15 Nov 2024 13:00:52 GMT Message-Id: <202411151300.4AFD0q98071277@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: a10de3d1167a - stable/13 - cred: crextend(): Harden, simplify 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/13 X-Git-Reftype: branch X-Git-Commit: a10de3d1167a5e5039dedfa3848afd3158faeb93 Auto-Submitted: auto-generated The branch stable/13 has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=a10de3d1167a5e5039dedfa3848afd3158faeb93 commit a10de3d1167a5e5039dedfa3848afd3158faeb93 Author: Olivier Certner AuthorDate: 2024-10-01 14:37:11 +0000 Commit: Olivier Certner CommitDate: 2024-11-15 12:59:09 +0000 cred: crextend(): Harden, simplify Harden by adding more assertions, and a plain panic in case of an unrepresentable size for the groups array (this can never happen after the change of the 'kern.ngroups' computation to impose some not too high maximum value a few commits ago). Fix an impact in kern_setgroups(). Simplify by removing the iterative process whose purpose is actually to determine the closest power of two that is greater than the wanted number of bytes. Using the proper target quantity (number of bytes) incidentally helps with eliminating divisions (and the reliance on sizeof(gid_t) being a power of two). Reviewed by: mhorne (older version) Approved by: markj (mentor) MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D46915 (cherry picked from commit ea26c0e797525634dd25dede233ff2ded053cf2d) Approved by: markj (mentor) --- sys/kern/kern_prot.c | 55 +++++++++++++++++++++++++++++++--------------------- sys/sys/ucred.h | 6 +++++- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index ede79f7d6bd2..ae3667146519 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -884,7 +884,8 @@ kern_setgroups(struct thread *td, int *ngrpp, gid_t *groups) ngrp = *ngrpp; } newcred = crget(); - crextend(newcred, ngrp); + if (ngrp != 0) + crextend(newcred, ngrp); PROC_LOCK(p); oldcred = crcopysafe(p, newcred); @@ -2224,6 +2225,13 @@ crcopy(struct ucred *dest, struct ucred *src) bcopy(&src->cr_startcopy, &dest->cr_startcopy, (unsigned)((caddr_t)&src->cr_endcopy - (caddr_t)&src->cr_startcopy)); + /* + * Avoids an assertion in crsetgroups() -> crextend(). Ideally, + * 'cr_ngroups' should be moved out of 'struct ucred''s bcopied area, + * but this would break the ABI, so is deferred until there is a real + * need to change the ABI. + */ + dest->cr_ngroups = 0; crsetgroups(dest, src->cr_ngroups, src->cr_groups); uihold(dest->cr_uidinfo); uihold(dest->cr_ruidinfo); @@ -2358,45 +2366,48 @@ crcopysafe(struct proc *p, struct ucred *cr) } /* - * Extend the passed in credential to hold n items. + * Extend the passed-in credentials to hold n groups. + * + * Must not be called after groups have been set. */ void crextend(struct ucred *cr, int n) { - int cnt; + size_t nbytes; MPASS2(cr->cr_ref == 1, "'cr_ref' must be 1 (referenced, unshared)"); + MPASS2(cr->cr_ngroups == 0, "groups on 'cr' already set!"); + groups_check_positive_len(n); + groups_check_max_len(n); - /* Truncate? */ if (n <= cr->cr_agroups) return; + nbytes = n * sizeof(gid_t); + if (nbytes < n) + panic("Too many groups (memory size overflow)! " + "Computation of 'kern.ngroups' should have prevented this, " + "please fix it. In the meantime, reduce 'kern.ngroups'."); + /* - * We extend by 2 each time since we're using a power of two - * allocator until we need enough groups to fill a page. - * Once we're allocating multiple pages, only allocate as many - * as we actually need. The case of processes needing a - * non-power of two number of pages seems more likely than - * a real world process that adds thousands of groups one at a - * time. + * We allocate a power of 2 larger than 'nbytes', except when that + * exceeds PAGE_SIZE, in which case we allocate the right multiple of + * pages. We assume PAGE_SIZE is a power of 2 (the call to roundup2() + * below) but do not need to for sizeof(gid_t). */ - if ( n < PAGE_SIZE / sizeof(gid_t) ) { - if (cr->cr_agroups == 0) - cnt = MAX(1, MINALLOCSIZE / sizeof(gid_t)); - else - cnt = cr->cr_agroups * 2; - - while (cnt < n) - cnt *= 2; + if (nbytes < PAGE_SIZE) { + if (!powerof2(nbytes)) + /* fls*() return a bit index starting at 1. */ + nbytes = 1 << flsl(nbytes); } else - cnt = roundup2(n, PAGE_SIZE / sizeof(gid_t)); + nbytes = roundup2(nbytes, PAGE_SIZE); /* Free the old array. */ if (cr->cr_groups != cr->cr_smallgroups) free(cr->cr_groups, M_CRED); - cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO); - cr->cr_agroups = cnt; + cr->cr_groups = malloc(nbytes, M_CRED, M_WAITOK | M_ZERO); + cr->cr_agroups = nbytes / sizeof(gid_t); } /* diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h index 8152f962f3cb..eb5f0ad839e5 100644 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -74,6 +74,10 @@ struct ucred { uid_t cr_uid; /* effective user id */ uid_t cr_ruid; /* real user id */ uid_t cr_svuid; /* saved user id */ + /* + * XXXOC: On the next ABI change, please move 'cr_ngroups' out of the + * copied area (crcopy() already copes with this change). + */ int cr_ngroups; /* number of groups */ gid_t cr_rgid; /* real group id */ gid_t cr_svgid; /* saved group id */ @@ -82,7 +86,7 @@ struct ucred { struct prison *cr_prison; /* jail(2) */ struct loginclass *cr_loginclass; /* login class */ u_int cr_flags; /* credential flags */ - void *cr_pspare2[2]; /* general use 2 */ + void *cr_pspare2[2]; /* general use 2 */ #define cr_endcopy cr_label struct label *cr_label; /* MAC label */ gid_t *cr_groups; /* groups */