The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=28f618fcc2b42066f68a9459e4178adffe08d35b
commit 28f618fcc2b42066f68a9459e4178adffe08d35b Author: Kyle Evans <kev...@freebsd.org> AuthorDate: 2025-08-04 23:09:58 +0000 Commit: Kyle Evans <kev...@freebsd.org> CommitDate: 2025-08-04 23:09:58 +0000 kern: fix a panic in crcopysafe() found by syzkaller crcopysafe() attempts to crextend() the new ucred's group allocation with the number of allocated group slots (`cr_asize`) from the ucred to copy rather than the latter's actual number of supplementary groups. However, the number of allocated group slots can exceed `ngroups_max` for certain values of it (because of rounding to the next power-of-2 or page on allocation), making `crextend()` trip on a check that the passed value should be lower than `ngroups_max`. This was not a problem before be1f7435ef218b1 because the effective max storage was NGROUPS_MAX + 1 (1024) to account for the egid being included in cr_groups. Now that we're back down to NGROUPS_MAX, the max allocation will tend to be 1024 and exceed our max groups. Switch crcopysafe() to extend until we have enough allocated to fit the previous group set, and call crextend() with the number of groups that the old ucred had. This avoids relying on implementation details of crextend() up-sizing our requests and ensures we only have as large of an allocation as we need to fulfill the request. Reviewed by: olce Reported by: syzbot+4e68da43c26f357a2...@syzkaller.appspotmail.com Fixes: be1f7435ef218b1 ("kern: start tracking cr_gid outside [...]") Differential Revision: https://reviews.freebsd.org/D51660 --- sys/kern/kern_prot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 6bdef84a34c1..bbb622547598 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -2773,8 +2773,8 @@ crcopysafe(struct proc *p, struct ucred *cr) PROC_LOCK_ASSERT(p, MA_OWNED); oldcred = p->p_ucred; - while (cr->cr_agroups < oldcred->cr_agroups) { - groups = oldcred->cr_agroups; + while (cr->cr_agroups < oldcred->cr_ngroups) { + groups = oldcred->cr_ngroups; PROC_UNLOCK(p); crextend(cr, groups); PROC_LOCK(p);