Index: sys/compat/linux/linux_misc.c =================================================================== --- sys/compat/linux/linux_misc.c (revision 307332) +++ sys/compat/linux/linux_misc.c (working copy) @@ -1316,8 +1316,7 @@ error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); if (error) goto out; - newcred = crget(); - crextend(newcred, ngrp + 1); + newcred = crget(ngrp + 1); p = td->td_proc; PROC_LOCK(p); oldcred = p->p_ucred; Index: sys/compat/linux/linux_uid16.c =================================================================== --- sys/compat/linux/linux_uid16.c (revision 307332) +++ sys/compat/linux/linux_uid16.c (working copy) @@ -179,8 +179,8 @@ free(linux_gidset, M_LINUX); return (error); } - newcred = crget(); p = td->td_proc; + newcred = crget(p->p_ucred->cr_agroups); PROC_LOCK(p); oldcred = crcopysafe(p, newcred); Index: sys/fs/nfs/nfs_commonsubs.c =================================================================== --- sys/fs/nfs/nfs_commonsubs.c (revision 307332) +++ sys/fs/nfs/nfs_commonsubs.c (working copy) @@ -3290,7 +3290,7 @@ * Create a credential just like svc_getcred(), * but using the group list provided. */ - cr = crget(); + cr = crget(nidp->nid_ngroup); 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]; Index: sys/kern/init_main.c =================================================================== --- sys/kern/init_main.c (revision 307332) +++ sys/kern/init_main.c (working copy) @@ -517,7 +517,7 @@ callout_init(&td->td_slpcallout, 1); /* Create credentials. */ - newcred = crget(); + newcred = crget(1); newcred->cr_ngroups = 1; /* group 0 */ newcred->cr_uidinfo = uifind(0); newcred->cr_ruidinfo = uifind(0); @@ -841,7 +841,7 @@ panic("cannot fork init: %d\n", error); KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1")); /* divorce init's credentials from the kernel's */ - newcred = crget(); + newcred = crget(initproc->p_ucred->cr_agroups); sx_xlock(&proctree_lock); PROC_LOCK(initproc); initproc->p_flag |= P_SYSTEM | P_INMEM; Index: sys/kern/kern_jail.c =================================================================== --- sys/kern/kern_jail.c (revision 307332) +++ sys/kern/kern_jail.c (working copy) @@ -2403,7 +2403,7 @@ if ((error = pwd_chroot(td, pr->pr_root))) goto e_revert_osd; - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); PROC_LOCK(p); oldcred = crcopysafe(p, newcred); newcred->cr_prison = pr; Index: sys/kern/kern_loginclass.c =================================================================== --- sys/kern/kern_loginclass.c (revision 307332) +++ sys/kern/kern_loginclass.c (working copy) @@ -216,7 +216,7 @@ newlc = loginclass_find(lcname); if (newlc == NULL) return (EINVAL); - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); PROC_LOCK(p); oldcred = crcopysafe(p, newcred); Index: sys/kern/kern_prot.c =================================================================== --- sys/kern/kern_prot.c (revision 307332) +++ sys/kern/kern_prot.c (working copy) @@ -492,7 +492,7 @@ uid = uap->uid; AUDIT_ARG_UID(uid); - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); uip = uifind(uid); PROC_LOCK(p); /* @@ -606,7 +606,7 @@ euid = uap->euid; AUDIT_ARG_EUID(euid); - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); euip = uifind(euid); PROC_LOCK(p); /* @@ -661,7 +661,7 @@ gid = uap->gid; AUDIT_ARG_GID(gid); - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); PROC_LOCK(p); oldcred = crcopysafe(p, newcred); @@ -759,7 +759,7 @@ egid = uap->egid; AUDIT_ARG_EGID(egid); - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); PROC_LOCK(p); oldcred = crcopysafe(p, newcred); @@ -831,8 +831,8 @@ MPASS(ngrp <= ngroups_max + 1); AUDIT_ARG_GROUPSET(groups, ngrp); - newcred = crget(); - crextend(newcred, ngrp); + newcred = crget(ngrp); + /* crextend(newcred, ngrp); */ PROC_LOCK(p); oldcred = crcopysafe(p, newcred); @@ -889,7 +889,7 @@ ruid = uap->ruid; AUDIT_ARG_EUID(euid); AUDIT_ARG_RUID(ruid); - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); euip = uifind(euid); ruip = uifind(ruid); PROC_LOCK(p); @@ -958,7 +958,7 @@ rgid = uap->rgid; AUDIT_ARG_EGID(egid); AUDIT_ARG_RGID(rgid); - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); PROC_LOCK(p); oldcred = crcopysafe(p, newcred); @@ -1026,7 +1026,7 @@ AUDIT_ARG_EUID(euid); AUDIT_ARG_RUID(ruid); AUDIT_ARG_SUID(suid); - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); euip = uifind(euid); ruip = uifind(ruid); PROC_LOCK(p); @@ -1107,7 +1107,7 @@ AUDIT_ARG_EGID(egid); AUDIT_ARG_RGID(rgid); AUDIT_ARG_SGID(sgid); - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); PROC_LOCK(p); oldcred = crcopysafe(p, newcred); @@ -1776,9 +1776,10 @@ /* * Allocate a zeroed cred structure. + * If ngroups > cr_smallgroups, use it to extend the group buffer. */ struct ucred * -crget(void) +crget(int ngroups) { register struct ucred *cr; @@ -1790,9 +1791,12 @@ #ifdef MAC mac_cred_init(cr); #endif - cr->cr_groups = cr->cr_smallgroups; - cr->cr_agroups = - sizeof(cr->cr_smallgroups) / sizeof(cr->cr_smallgroups[0]); + if (ngroups > sizeof (cr->cr_smallgroups) / sizeof (cr->cr_smallgroups[0])) + crextend (cr, ngroups); + else { + cr->cr_groups = cr->cr_smallgroups; + cr->cr_agroups = sizeof(cr->cr_smallgroups) / sizeof(cr->cr_smallgroups[0]); + } return (cr); } @@ -1877,7 +1881,7 @@ { struct ucred *newcr; - newcr = crget(); + newcr = crget(cr->cr_agroups); crcopy(newcr, cr); return (newcr); } @@ -1971,6 +1975,9 @@ /* Truncate? */ if (n <= cr->cr_agroups) return; + /* No need to allocate more than we are willing to use? */ + if (n > ngroups_max + 1) + n = ngroups_max + 1; /* * We extend by 2 each time since we're using a power of two Index: sys/kern/sys_capability.c =================================================================== --- sys/kern/sys_capability.c (revision 307332) +++ sys/kern/sys_capability.c (working copy) @@ -103,8 +103,8 @@ if (IN_CAPABILITY_MODE(td)) return (0); - newcred = crget(); p = td->td_proc; + newcred = crget(p->p_ucred->cr_agroups); PROC_LOCK(p); oldcred = crcopysafe(p, newcred); newcred->cr_flags |= CRED_FLAG_CAPMODE; Index: sys/kern/vfs_export.c =================================================================== --- sys/kern/vfs_export.c (revision 307332) +++ sys/kern/vfs_export.c (working copy) @@ -129,7 +129,7 @@ } np = &nep->ne_defexported; np->netc_exflags = argp->ex_flags; - np->netc_anon = crget(); + np->netc_anon = crget(argp->ex_anon.cr_ngroups); np->netc_anon->cr_uid = argp->ex_anon.cr_uid; crsetgroups(np->netc_anon, argp->ex_anon.cr_ngroups, argp->ex_anon.cr_groups); @@ -208,7 +208,7 @@ goto out; } np->netc_exflags = argp->ex_flags; - np->netc_anon = crget(); + np->netc_anon = crget(argp->ex_anon.cr_ngroups); np->netc_anon->cr_uid = argp->ex_anon.cr_uid; crsetgroups(np->netc_anon, argp->ex_anon.cr_ngroups, argp->ex_anon.cr_groups); Index: sys/rpc/rpcsec_gss/svc_rpcsec_gss.c =================================================================== --- sys/rpc/rpcsec_gss/svc_rpcsec_gss.c (revision 307332) +++ sys/rpc/rpcsec_gss/svc_rpcsec_gss.c (working copy) @@ -445,7 +445,7 @@ } uc = &client->cl_ucred; - cr = client->cl_cred = crget(); + cr = client->cl_cred = crget(uc->gidlen); 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); Index: sys/rpc/svc_auth.c =================================================================== --- sys/rpc/svc_auth.c (revision 307332) +++ sys/rpc/svc_auth.c (working copy) @@ -175,7 +175,7 @@ switch (flavor) { case AUTH_UNIX: xcr = (struct xucred *) rqst->rq_clntcred; - cr = crget(); + cr = crget(xcr->cr_ngroups); 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]; Index: sys/security/audit/audit_syscalls.c =================================================================== --- sys/security/audit/audit_syscalls.c (revision 307332) +++ sys/security/audit/audit_syscalls.c (working copy) @@ -445,11 +445,9 @@ return (EINVAL); if (udata.au_aupinfo.ap_pid < 1) return (ESRCH); - newcred = crget(); - if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) { - crfree(newcred); + if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) return (ESRCH); - } + newcred = crget(tp->p_ucred->cr_agroups); if ((error = p_cansee(td, tp)) != 0) { PROC_UNLOCK(tp); crfree(newcred); @@ -587,7 +585,7 @@ if (error) return (error); audit_arg_auid(id); - newcred = crget(); + newcred = crget(td->td_proc->p_ucred->cr_agroups); PROC_LOCK(td->td_proc); oldcred = td->td_proc->p_ucred; crcopy(newcred, oldcred); @@ -652,7 +650,7 @@ if (error) return (error); audit_arg_auditinfo(&ai); - newcred = crget(); + newcred = crget(td->td_proc->p_ucred->cr_agroups); PROC_LOCK(td->td_proc); oldcred = td->td_proc->p_ucred; crcopy(newcred, oldcred); @@ -715,7 +713,7 @@ if (aia.ai_termid.at_type != AU_IPv6 && aia.ai_termid.at_type != AU_IPv4) return (EINVAL); - newcred = crget(); + newcred = crget(td->td_proc->p_ucred->cr_agroups); PROC_LOCK(td->td_proc); oldcred = td->td_proc->p_ucred; crcopy(newcred, oldcred); Index: sys/security/mac/mac_syscalls.c =================================================================== --- sys/security/mac/mac_syscalls.c (revision 307332) +++ sys/security/mac/mac_syscalls.c (working copy) @@ -192,9 +192,8 @@ if (error) goto out; - newcred = crget(); - p = td->td_proc; + newcred = crget(p->p_ucred->cr_agroups); PROC_LOCK(p); oldcred = p->p_ucred; Index: sys/security/mac_lomac/mac_lomac.c =================================================================== --- sys/security/mac_lomac/mac_lomac.c (revision 307332) +++ sys/security/mac_lomac/mac_lomac.c (working copy) @@ -2235,7 +2235,7 @@ if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) { dodrop = 0; mtx_unlock(&subj->mtx); - newcred = crget(); + newcred = crget(p->p_ucred->cr_agroups); /* * Prevent a lock order reversal in mac_proc_vm_revoke; * ideally, the other user of subj->mtx wouldn't be holding Index: sys/sys/ucred.h =================================================================== --- sys/sys/ucred.h (revision 307332) +++ sys/sys/ucred.h (working copy) @@ -109,7 +109,7 @@ void proc_set_cred_init(struct proc *p, struct ucred *cr); struct ucred *proc_set_cred(struct proc *p, struct ucred *cr); void crfree(struct ucred *cr); -struct ucred *crget(void); +struct ucred *crget(int ngroups); struct ucred *crhold(struct ucred *cr); void cru2x(struct ucred *cr, struct xucred *xcr); void crsetgroups(struct ucred *cr, int n, gid_t *groups);