diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/lib/libc/rpc/netname.c ./lib/libc/rpc/netname.c --- /usr/fsvn/head/lib/libc/rpc/netname.c 2009-01-22 10:05:44.000000000 -0600 +++ ./lib/libc/rpc/netname.c 2009-05-14 01:48:22.000000000 -0500 @@ -61,9 +61,6 @@ #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif -#ifndef NGROUPS -#define NGROUPS 16 -#endif #define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/lib/libc/rpc/netnamer.c ./lib/libc/rpc/netnamer.c --- /usr/fsvn/head/lib/libc/rpc/netnamer.c 2009-01-22 10:05:44.000000000 -0600 +++ ./lib/libc/rpc/netnamer.c 2009-05-13 22:51:38.000000000 -0500 @@ -66,10 +66,6 @@ static int getnetid( char *, char * ); static int _getgroups( char *, gid_t * ); -#ifndef NGROUPS -#define NGROUPS 16 -#endif - /* * Convert network-name into unix credential */ @@ -104,7 +100,7 @@ return (0); } *gidp = (gid_t) atol(p); - for (gidlen = 0; gidlen < NGROUPS; gidlen++) { + for (gidlen = 0; gidlen < NGRPS; gidlen++) { p = strsep(&res, "\n,"); if (p == NULL) break; @@ -157,7 +153,7 @@ static int _getgroups(uname, groups) char *uname; - gid_t groups[NGROUPS]; + gid_t groups[NGRPS]; { gid_t ngroups = 0; struct group *grp; @@ -169,7 +165,7 @@ while ((grp = getgrent())) { for (i = 0; grp->gr_mem[i]; i++) if (!strcmp(grp->gr_mem[i], uname)) { - if (ngroups == NGROUPS) { + if (ngroups == NGRPS) { #ifdef DEBUG fprintf(stderr, "initgroups: %s is in too many groups\n", uname); diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/lib/libkvm/kvm_proc.c ./lib/libkvm/kvm_proc.c --- /usr/fsvn/head/lib/libkvm/kvm_proc.c 2009-06-16 15:54:14.000000000 -0500 +++ ./lib/libkvm/kvm_proc.c 2009-05-28 16:40:33.000000000 -0500 @@ -146,8 +146,7 @@ kp->ki_rgid = ucred.cr_rgid; kp->ki_svgid = ucred.cr_svgid; kp->ki_ngroups = ucred.cr_ngroups; - bcopy(ucred.cr_groups, kp->ki_groups, - NGROUPS * sizeof(gid_t)); + kp->ki_groups = ucred.cr_groups; kp->ki_uid = ucred.cr_uid; if (ucred.cr_prison != NULL) { if (KREAD(kd, (u_long)ucred.cr_prison, &pr)) { Files /usr/fsvn/head/share/examples/kld/firmware/fwimage/firmware.img and ./share/examples/kld/firmware/fwimage/firmware.img differ Only in /usr/fsvn/head/sys: .glimpse_exclude Only in /usr/fsvn/head/sys: .glimpse_filenames Only in /usr/fsvn/head/sys: .glimpse_filenames_index Only in /usr/fsvn/head/sys: .glimpse_filetimes Only in /usr/fsvn/head/sys: .glimpse_index Only in /usr/fsvn/head/sys: .glimpse_messages Only in /usr/fsvn/head/sys: .glimpse_partitions Only in /usr/fsvn/head/sys: .glimpse_statistics Only in /usr/fsvn/head/sys: .glimpse_turbo diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/compat/linux/linux_misc.c ./sys/compat/linux/linux_misc.c --- /usr/fsvn/head/sys/compat/linux/linux_misc.c 2009-06-16 15:54:53.000000000 -0500 +++ ./sys/compat/linux/linux_misc.c 2009-06-16 13:56:19.000000000 -0500 @@ -1132,7 +1132,7 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args) { struct ucred *newcred, *oldcred; - l_gid_t linux_gidset[NGROUPS]; + l_gid_t *linux_gidset; gid_t *bsd_gidset; int ngrp, error; struct proc *p; @@ -1140,13 +1140,14 @@ ngrp = args->gidsetsize; if (ngrp < 0 || ngrp >= NGROUPS) return (EINVAL); + linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK); error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); if (error) - return (error); + goto out; newcred = crget(); p = td->td_proc; PROC_LOCK(p); - oldcred = p->p_ucred; + oldcred = crcopysafe(p, newcred); /* * cr_groups[0] holds egid. Setting the whole set from @@ -1157,10 +1158,9 @@ if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) { PROC_UNLOCK(p); crfree(newcred); - return (error); + goto out; } - crcopy(newcred, oldcred); if (ngrp > 0) { newcred->cr_ngroups = ngrp + 1; @@ -1177,14 +1177,17 @@ p->p_ucred = newcred; PROC_UNLOCK(p); crfree(oldcred); - return (0); + error = 0; +out: + free(linux_gidset, M_TEMP); + return (error); } int linux_getgroups(struct thread *td, struct linux_getgroups_args *args) { struct ucred *cred; - l_gid_t linux_gidset[NGROUPS]; + l_gid_t *linux_gidset; gid_t *bsd_gidset; int bsd_gidsetsz, ngrp, error; @@ -1207,13 +1210,16 @@ return (EINVAL); ngrp = 0; + linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), + M_TEMP, M_WAITOK); while (ngrp < bsd_gidsetsz) { linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; ngrp++; } - if ((error = copyout(linux_gidset, args->grouplist, - ngrp * sizeof(l_gid_t)))) + error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t)); + free(linux_gidset, M_TEMP); + if (error) return (error); td->td_retval[0] = ngrp; diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/compat/linux/linux_uid16.c ./sys/compat/linux/linux_uid16.c --- /usr/fsvn/head/sys/compat/linux/linux_uid16.c 2009-06-16 15:54:53.000000000 -0500 +++ ./sys/compat/linux/linux_uid16.c 2009-05-28 16:40:33.000000000 -0500 @@ -98,7 +98,7 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) { struct ucred *newcred, *oldcred; - l_gid16_t linux_gidset[NGROUPS]; + l_gid16_t *linux_gidset; gid_t *bsd_gidset; int ngrp, error; struct proc *p; @@ -111,13 +111,14 @@ ngrp = args->gidsetsize; if (ngrp < 0 || ngrp >= NGROUPS) return (EINVAL); + linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK); error = copyin(args->gidset, linux_gidset, ngrp * sizeof(l_gid16_t)); if (error) return (error); newcred = crget(); p = td->td_proc; PROC_LOCK(p); - oldcred = p->p_ucred; + oldcred = crcopysafe(p, newcred); /* * cr_groups[0] holds egid. Setting the whole set from @@ -128,10 +129,9 @@ if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) { PROC_UNLOCK(p); crfree(newcred); - return (error); + goto out; } - crcopy(newcred, oldcred); if (ngrp > 0) { newcred->cr_ngroups = ngrp + 1; @@ -149,14 +149,17 @@ p->p_ucred = newcred; PROC_UNLOCK(p); crfree(oldcred); - return (0); + error = 0; +out: + free(linux_gidset, M_TEMP); + return (error); } int linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args) { struct ucred *cred; - l_gid16_t linux_gidset[NGROUPS]; + l_gid16_t *linux_gidset; gid_t *bsd_gidset; int bsd_gidsetsz, ngrp, error; @@ -184,12 +187,15 @@ return (EINVAL); ngrp = 0; + linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), + M_TEMP, M_WAITOK); while (ngrp < bsd_gidsetsz) { linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; ngrp++; } error = copyout(linux_gidset, args->gidset, ngrp * sizeof(l_gid16_t)); + free(linux_gidset, M_TEMP); if (error) return (error); diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/fs/nfs/nfs_commonport.c ./sys/fs/nfs/nfs_commonport.c --- /usr/fsvn/head/sys/fs/nfs/nfs_commonport.c 2009-05-29 12:48:03.000000000 -0500 +++ ./sys/fs/nfs/nfs_commonport.c 2009-06-09 08:49:37.000000000 -0500 @@ -220,14 +220,9 @@ void newnfs_copycred(struct nfscred *nfscr, struct ucred *cr) { - int ngroups, i; cr->cr_uid = nfscr->nfsc_uid; - ngroups = (nfscr->nfsc_ngroups < NGROUPS) ? - nfscr->nfsc_ngroups : NGROUPS; - for (i = 0; i < ngroups; i++) - cr->cr_groups[i] = nfscr->nfsc_groups[i]; - cr->cr_ngroups = ngroups; + crsetgroups(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups); } /* diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/fs/nfsclient/nfs_clport.c ./sys/fs/nfsclient/nfs_clport.c --- /usr/fsvn/head/sys/fs/nfsclient/nfs_clport.c 2009-05-29 12:48:03.000000000 -0500 +++ ./sys/fs/nfsclient/nfs_clport.c 2009-06-05 15:33:54.000000000 -0500 @@ -976,14 +976,12 @@ void newnfs_copyincred(struct ucred *cr, struct nfscred *nfscr) { - int ngroups, i; + int i; nfscr->nfsc_uid = cr->cr_uid; - ngroups = (cr->cr_ngroups > NGROUPS) ? NGROUPS : - cr->cr_ngroups; - for (i = 0; i < ngroups; i++) + nfscr->nfsc_ngroups = MIN(cr->cr_ngroups, XU_NGROUPS); + for (i = 0; i < nfscr->nfsc_ngroups; i++) nfscr->nfsc_groups[i] = cr->cr_groups[i]; - nfscr->nfsc_ngroups = ngroups; } diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/fs/nfsserver/nfs_nfsdport.c ./sys/fs/nfsserver/nfs_nfsdport.c --- /usr/fsvn/head/sys/fs/nfsserver/nfs_nfsdport.c 2009-06-05 15:33:50.000000000 -0500 +++ ./sys/fs/nfsserver/nfs_nfsdport.c 2009-06-05 16:02:29.000000000 -0500 @@ -2360,7 +2360,6 @@ nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp, struct ucred *credanon) { - int i; int error = 0; /* @@ -2403,9 +2402,8 @@ (nd->nd_flag & ND_AUTHNONE))) { nd->nd_cred->cr_uid = credanon->cr_uid; nd->nd_cred->cr_gid = credanon->cr_gid; - for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++) - nd->nd_cred->cr_groups[i] = credanon->cr_groups[i]; - nd->nd_cred->cr_ngroups = i; + crsetgroups(nd->nd_cred, credanon->cr_ngroups, + credanon->cr_groups); } return (0); } diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/fs/nfsserver/nfs_nfsdstate.c ./sys/fs/nfsserver/nfs_nfsdstate.c --- /usr/fsvn/head/sys/fs/nfsserver/nfs_nfsdstate.c 2009-06-16 13:55:57.000000000 -0500 +++ ./sys/fs/nfsserver/nfs_nfsdstate.c 2009-06-16 13:56:18.000000000 -0500 @@ -3577,7 +3577,6 @@ nd->nd_repstat = 0; cred->cr_uid = clp->lc_uid; cred->cr_gid = clp->lc_gid; - cred->cr_groups[0] = clp->lc_gid; callback = clp->lc_callback; NFSUNLOCKSTATE(); cred->cr_ngroups = 1; diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/fs/portalfs/portal.h ./sys/fs/portalfs/portal.h --- /usr/fsvn/head/sys/fs/portalfs/portal.h 2009-01-22 10:06:01.000000000 -0600 +++ ./sys/fs/portalfs/portal.h 2009-06-05 15:33:54.000000000 -0500 @@ -43,7 +43,7 @@ int pcr_flag; /* File open mode */ uid_t pcr_uid; /* From ucred */ short pcr_ngroups; /* From ucred */ - gid_t pcr_groups[NGROUPS]; /* From ucred */ + gid_t pcr_groups[XU_NGROUPS]; /* From ucred */ }; #ifdef _KERNEL diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/fs/portalfs/portal_vnops.c ./sys/fs/portalfs/portal_vnops.c --- /usr/fsvn/head/sys/fs/portalfs/portal_vnops.c 2009-01-22 10:06:01.000000000 -0600 +++ ./sys/fs/portalfs/portal_vnops.c 2009-06-05 15:33:54.000000000 -0500 @@ -311,8 +311,9 @@ pcred.pcr_flag = ap->a_mode; pcred.pcr_uid = ap->a_cred->cr_uid; - pcred.pcr_ngroups = ap->a_cred->cr_ngroups; - bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t)); + pcred.pcr_ngroups = MIN(ap->a_cred->cr_ngroups, XU_NGROUPS); + bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, + pcred.pcr_ngroups * sizeof(gid_t)); aiov[0].iov_base = (caddr_t) &pcred; aiov[0].iov_len = sizeof(pcred); aiov[1].iov_base = pt->pt_arg; diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/fs/unionfs/union_vnops.c ./sys/fs/unionfs/union_vnops.c --- /usr/fsvn/head/sys/fs/unionfs/union_vnops.c 2009-04-12 15:26:52.000000000 -0500 +++ ./sys/fs/unionfs/union_vnops.c 2009-06-05 15:33:54.000000000 -0500 @@ -638,7 +638,6 @@ uid_t uid; /* upper side vnode's uid */ gid_t gid; /* upper side vnode's gid */ u_short vmode; /* upper side vnode's mode */ - gid_t *gp; u_short mask; mask = 0; @@ -659,17 +658,14 @@ /* check group */ count = 0; - gp = cred->cr_groups; - for (; count < cred->cr_ngroups; count++, gp++) { - if (gid == *gp) { - if (accmode & VEXEC) - mask |= S_IXGRP; - if (accmode & VREAD) - mask |= S_IRGRP; - if (accmode & VWRITE) - mask |= S_IWGRP; - return ((vmode & mask) == mask ? 0 : EACCES); - } + if (groupmember(gid, cred)) { + if (accmode & VEXEC) + mask |= S_IXGRP; + if (accmode & VREAD) + mask |= S_IRGRP; + if (accmode & VWRITE) + mask |= S_IWGRP; + return ((vmode & mask) == mask ? 0 : EACCES); } /* check other */ diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/i386/ibcs2/ibcs2_misc.c ./sys/i386/ibcs2/ibcs2_misc.c --- /usr/fsvn/head/sys/i386/ibcs2/ibcs2_misc.c 2009-06-16 15:54:53.000000000 -0500 +++ ./sys/i386/ibcs2/ibcs2_misc.c 2009-06-05 16:02:31.000000000 -0500 @@ -657,24 +657,29 @@ struct thread *td; struct ibcs2_getgroups_args *uap; { - ibcs2_gid_t iset[NGROUPS_MAX]; - gid_t gp[NGROUPS_MAX]; + ibcs2_gid_t *iset; + gid_t *gp; u_int i, ngrp; int error; if (uap->gidsetsize < 0) return (EINVAL); ngrp = MIN(uap->gidsetsize, NGROUPS_MAX); + gp = malloc(ngrp * sizeof(*gp), M_TEMP, M_WAITOK); error = kern_getgroups(td, &ngrp, gp); if (error) - return (error); + goto out; if (uap->gidsetsize > 0) { + iset = malloc(ngrp * sizeof(*iset), M_TEMP, M_WAITOK); for (i = 0; i < ngrp; i++) iset[i] = (ibcs2_gid_t)gp[i]; error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t)); + free(iset, M_TEMP); } if (error == 0) td->td_retval[0] = ngrp; +out: + free(gp, M_TEMP); return (error); } @@ -683,21 +688,31 @@ struct thread *td; struct ibcs2_setgroups_args *uap; { - ibcs2_gid_t iset[NGROUPS_MAX]; - gid_t gp[NGROUPS_MAX]; + ibcs2_gid_t *iset; + gid_t *gp; int error, i; if (uap->gidsetsize < 0 || uap->gidsetsize > NGROUPS_MAX) return (EINVAL); - if (uap->gidsetsize && uap->gidset) { + if (uap->gidsetsize && uap->gidset == NULL) + return (EINVAL); + gp = malloc(uap->gidsetsize * sizeof(*gp), M_TEMP, M_WAITOK); + if (uap->gidsetsize) { + iset = malloc(uap->gidsetsize * sizeof(*iset), M_TEMP, M_WAITOK); error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) * uap->gidsetsize); - if (error) - return (error); + if (error) { + free(iset, M_TEMP); + goto out; + } for (i = 0; i < uap->gidsetsize; i++) gp[i] = (gid_t)iset[i]; } - return (kern_setgroups(td, uap->gidsetsize, gp)); + + error = kern_setgroups(td, uap->gidsetsize, gp); +out: + free(gp, M_TEMP); + return (error); } int diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/kern/kern_exec.c ./sys/kern/kern_exec.c --- /usr/fsvn/head/sys/kern/kern_exec.c 2009-06-16 15:54:34.000000000 -0500 +++ ./sys/kern/kern_exec.c 2009-06-12 01:13:11.000000000 -0500 @@ -579,6 +579,7 @@ * reset. */ PROC_LOCK(p); + oldcred = crcopysafe(p, newcred); if (sigacts_shared(p->p_sigacts)) { oldsigacts = p->p_sigacts; PROC_UNLOCK(p); @@ -629,7 +630,6 @@ * XXXMAC: For the time being, use NOSUID to also prohibit * transitions on the file system. */ - oldcred = p->p_ucred; credential_changing = 0; credential_changing |= (attr.va_mode & S_ISUID) && oldcred->cr_uid != attr.va_uid; @@ -683,7 +683,6 @@ /* * Set the new credentials. */ - crcopy(newcred, oldcred); if (attr.va_mode & S_ISUID) change_euid(newcred, euip); if (attr.va_mode & S_ISGID) @@ -723,7 +722,6 @@ */ if (oldcred->cr_svuid != oldcred->cr_uid || oldcred->cr_svgid != oldcred->cr_gid) { - crcopy(newcred, oldcred); change_svuid(newcred, newcred->cr_uid); change_svgid(newcred, newcred->cr_gid); p->p_ucred = newcred; diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/kern/kern_proc.c ./sys/kern/kern_proc.c --- /usr/fsvn/head/sys/kern/kern_proc.c 2009-06-16 15:54:34.000000000 -0500 +++ ./sys/kern/kern_proc.c 2009-06-05 16:02:28.000000000 -0500 @@ -730,10 +730,8 @@ kp->ki_uid = cred->cr_uid; kp->ki_ruid = cred->cr_ruid; kp->ki_svuid = cred->cr_svuid; - /* XXX bde doesn't like KI_NGROUPS */ - kp->ki_ngroups = min(cred->cr_ngroups, KI_NGROUPS); - bcopy(cred->cr_groups, kp->ki_groups, - kp->ki_ngroups * sizeof(gid_t)); + kp->ki_ngroups = cred->cr_ngroups; + kp->ki_groups = cred->cr_groups; kp->ki_rgid = cred->cr_rgid; kp->ki_svgid = cred->cr_svgid; kp->ki_cr_flags = cred->cr_flags; --- /usr/fsvn/head/sys/kern/kern_prot.c 2009-06-16 15:54:34.000000000 -0500 +++ ./sys/kern/kern_prot.c 2009-06-17 18:24:56.000000000 -0500 @@ -82,6 +82,10 @@ SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, "BSD security policy"); +static void crextend(struct ucred *cr, int n); +static void crsetgroups_locked(struct ucred *cr, int ngrp, + gid_t *groups); + #ifndef _SYS_SYSPROTO_H_ struct getpid_args { int dummy; @@ -276,18 +280,21 @@ int getgroups(struct thread *td, register struct getgroups_args *uap) { - gid_t groups[NGROUPS]; + gid_t *groups; u_int ngrp; int error; ngrp = MIN(uap->gidsetsize, NGROUPS); + groups = malloc(ngrp * sizeof(*groups), M_TEMP, M_WAITOK); error = kern_getgroups(td, &ngrp, groups); if (error) - return (error); + goto out; if (uap->gidsetsize > 0) error = copyout(groups, uap->gidset, ngrp * sizeof(gid_t)); if (error == 0) td->td_retval[0] = ngrp; +out: + free(groups, M_TEMP); return (error); } @@ -486,7 +493,10 @@ newcred = crget(); uip = uifind(uid); PROC_LOCK(p); - oldcred = p->p_ucred; + /* + * Copy credentials so other references do not see our changes. + */ + oldcred = crcopysafe(p, newcred); #ifdef MAC error = mac_cred_check_setuid(oldcred, uid); @@ -521,10 +531,6 @@ (error = priv_check_cred(oldcred, PRIV_CRED_SETUID, 0)) != 0) goto fail; - /* - * Copy credentials so other references do not see our changes. - */ - crcopy(newcred, oldcred); #ifdef _POSIX_SAVED_IDS /* * Do we have "appropriate privileges" (are we root or uid == euid) @@ -598,7 +604,10 @@ newcred = crget(); euip = uifind(euid); PROC_LOCK(p); - oldcred = p->p_ucred; + /* + * Copy credentials so other references do not see our changes. + */ + oldcred = crcopysafe(p, newcred); #ifdef MAC error = mac_cred_check_seteuid(oldcred, euid); @@ -612,8 +621,7 @@ goto fail; /* - * Everything's okay, do it. Copy credentials so other references do - * not see our changes. + * Everything's okay, do it. */ crcopy(newcred, oldcred); if (oldcred->cr_uid != euid) { @@ -651,7 +659,7 @@ AUDIT_ARG(gid, gid); newcred = crget(); PROC_LOCK(p); - oldcred = p->p_ucred; + oldcred = crcopysafe(p, newcred); #ifdef MAC error = mac_cred_check_setgid(oldcred, gid); @@ -680,7 +688,6 @@ (error = priv_check_cred(oldcred, PRIV_CRED_SETGID, 0)) != 0) goto fail; - crcopy(newcred, oldcred); #ifdef _POSIX_SAVED_IDS /* * Do we have "appropriate privileges" (are we root or gid == egid) @@ -750,7 +757,7 @@ AUDIT_ARG(egid, egid); newcred = crget(); PROC_LOCK(p); - oldcred = p->p_ucred; + oldcred = crcopysafe(p, newcred); #ifdef MAC error = mac_cred_check_setegid(oldcred, egid); @@ -763,7 +770,6 @@ (error = priv_check_cred(oldcred, PRIV_CRED_SETEGID, 0)) != 0) goto fail; - crcopy(newcred, oldcred); if (oldcred->cr_groups[0] != egid) { change_egid(newcred, egid); setsugid(p); @@ -789,15 +795,19 @@ int setgroups(struct thread *td, struct setgroups_args *uap) { - gid_t groups[NGROUPS]; + gid_t *groups = NULL; int error; if (uap->gidsetsize > NGROUPS) return (EINVAL); + groups = malloc(uap->gidsetsize * sizeof(gid_t), M_TEMP, M_WAITOK); error = copyin(uap->gidset, groups, uap->gidsetsize * sizeof(gid_t)); if (error) - return (error); - return (kern_setgroups(td, uap->gidsetsize, groups)); + goto out; + error = kern_setgroups(td, uap->gidsetsize, groups); +out: + free(groups, M_TEMP); + return (error); } int @@ -811,8 +821,9 @@ return (EINVAL); AUDIT_ARG(groupset, groups, ngrp); newcred = crget(); + crextend(newcred, ngrp); PROC_LOCK(p); - oldcred = p->p_ucred; + oldcred = crcopysafe(p, newcred); #ifdef MAC error = mac_cred_check_setgroups(oldcred, ngrp, groups); @@ -824,11 +835,6 @@ if (error) goto fail; - /* - * XXX A little bit lazy here. We could test if anything has - * changed before crcopy() and setting P_SUGID. - */ - crcopy(newcred, oldcred); if (ngrp < 1) { /* * setgroups(0, NULL) is a legitimate way of clearing the @@ -838,8 +844,7 @@ */ newcred->cr_ngroups = 1; } else { - bcopy(groups, newcred->cr_groups, ngrp * sizeof(gid_t)); - newcred->cr_ngroups = ngrp; + crsetgroups_locked(newcred, ngrp, groups); } setsugid(p); p->p_ucred = newcred; @@ -877,7 +882,7 @@ euip = uifind(euid); ruip = uifind(ruid); PROC_LOCK(p); - oldcred = p->p_ucred; + oldcred = crcopysafe(p, newcred); #ifdef MAC error = mac_cred_check_setreuid(oldcred, ruid, euid); @@ -892,7 +897,6 @@ (error = priv_check_cred(oldcred, PRIV_CRED_SETREUID, 0)) != 0) goto fail; - crcopy(newcred, oldcred); if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { change_euid(newcred, euip); setsugid(p); @@ -942,7 +946,7 @@ AUDIT_ARG(rgid, rgid); newcred = crget(); PROC_LOCK(p); - oldcred = p->p_ucred; + oldcred = crcopysafe(p, newcred); #ifdef MAC error = mac_cred_check_setregid(oldcred, rgid, egid); @@ -957,7 +961,6 @@ (error = priv_check_cred(oldcred, PRIV_CRED_SETREGID, 0)) != 0) goto fail; - crcopy(newcred, oldcred); if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { change_egid(newcred, egid); setsugid(p); @@ -1013,7 +1016,7 @@ euip = uifind(euid); ruip = uifind(ruid); PROC_LOCK(p); - oldcred = p->p_ucred; + oldcred = crcopysafe(p, newcred); #ifdef MAC error = mac_cred_check_setresuid(oldcred, ruid, euid, suid); @@ -1033,7 +1036,6 @@ (error = priv_check_cred(oldcred, PRIV_CRED_SETRESUID, 0)) != 0) goto fail; - crcopy(newcred, oldcred); if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { change_euid(newcred, euip); setsugid(p); @@ -1090,7 +1092,7 @@ AUDIT_ARG(sgid, sgid); newcred = crget(); PROC_LOCK(p); - oldcred = p->p_ucred; + oldcred = crcopysafe(p, newcred); #ifdef MAC error = mac_cred_check_setresgid(oldcred, rgid, egid, sgid); @@ -1110,7 +1112,6 @@ (error = priv_check_cred(oldcred, PRIV_CRED_SETRESGID, 0)) != 0) goto fail; - crcopy(newcred, oldcred); if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { change_egid(newcred, egid); setsugid(p); @@ -1780,6 +1781,7 @@ #ifdef MAC mac_cred_init(cr); #endif + crextend(cr, XU_NGROUPS); return (cr); } @@ -1829,6 +1831,7 @@ #ifdef MAC mac_cred_destroy(cr); #endif + free(cr->cr_groups, M_CRED); free(cr, M_CRED); } } @@ -1854,6 +1857,7 @@ bcopy(&src->cr_startcopy, &dest->cr_startcopy, (unsigned)((caddr_t)&src->cr_endcopy - (caddr_t)&src->cr_startcopy)); + crsetgroups(dest, src->cr_ngroups, src->cr_groups); uihold(dest->cr_uidinfo); uihold(dest->cr_ruidinfo); prison_hold(dest->cr_prison); @@ -1888,12 +1892,16 @@ void cru2x(struct ucred *cr, struct xucred *xcr) { + int ngroups; bzero(xcr, sizeof(*xcr)); xcr->cr_version = XUCRED_VERSION; xcr->cr_uid = cr->cr_uid; - xcr->cr_ngroups = cr->cr_ngroups; - bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups)); + + ngroups = MIN(cr->cr_ngroups, XU_NGROUPS); + xcr->cr_ngroups = ngroups; + bcopy(cr->cr_groups, xcr->cr_groups, + ngroups * sizeof(*cr->cr_groups)); } /* @@ -1915,6 +1923,97 @@ crfree(cred); } +struct ucred * +crcopysafe(struct proc *p, struct ucred *cr) +{ + struct ucred *oldcred; + int groups; + + PROC_LOCK_ASSERT(p, MA_OWNED); + + oldcred = p->p_ucred; + while (cr->cr_agroups < oldcred->cr_agroups) { + groups = oldcred->cr_agroups; + PROC_UNLOCK(p); + crextend(cr, groups); + PROC_LOCK(p); + oldcred = p->p_ucred; + } + crcopy(cr, oldcred); + + return (oldcred); +} + +/* + * Extend the passed in credential to hold n items. + */ +static void +crextend(struct ucred *cr, int n) +{ + int cnt; + + /* Truncate? */ + if (n <= cr->cr_agroups) + return; + + /* + * 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. + */ + if ( n < PAGE_SIZE / sizeof(gid_t) ) { + if (cr->cr_agroups == 0) + cnt = MINALLOCSIZE / sizeof(gid_t); + else + cnt = cr->cr_agroups * 2; + + while (cnt < n) + cnt *= 2; + } else + cnt = roundup2(n, PAGE_SIZE / sizeof(gid_t)); + + /* Free the old array. */ + if (cr->cr_groups) + free(cr->cr_groups, M_CRED); + + cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO); + cr->cr_agroups = cnt; +} + +/* + * Copy groups in to a credential, preserving any necessicary invariants + * (i.e. sorting in the future). crextend() must have been called + * before hand to ensure sufficient space is available. If + */ +static void +crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups) +{ + + KASSERT(cr->cr_agroups >= ngrp, ("cr_ngroups is too small")); + + bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t)); + cr->cr_ngroups = ngrp; +} + +/* + * Copy groups in to a credential after expanding it if required. + * Truncate the list to NGROUPS if it is too large. + */ +void +crsetgroups(struct ucred *cr, int ngrp, gid_t *groups) +{ + + if (ngrp > NGROUPS) + ngrp = NGROUPS; + + crextend(cr, ngrp); + crsetgroups_locked(cr, ngrp, groups); +} + /* * Get login name, if available. */ diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/kern/vfs_export.c ./sys/kern/vfs_export.c --- /usr/fsvn/head/sys/kern/vfs_export.c 2009-05-29 12:48:02.000000000 -0500 +++ ./sys/kern/vfs_export.c 2009-06-05 15:33:54.000000000 -0500 @@ -120,9 +120,8 @@ np->netc_exflags = argp->ex_flags; np->netc_anon = crget(); np->netc_anon->cr_uid = argp->ex_anon.cr_uid; - np->netc_anon->cr_ngroups = argp->ex_anon.cr_ngroups; - bcopy(argp->ex_anon.cr_groups, np->netc_anon->cr_groups, - sizeof(np->netc_anon->cr_groups)); + crsetgroups(np->netc_anon, argp->ex_anon.cr_ngroups, + argp->ex_anon.cr_groups); np->netc_numsecflavors = argp->ex_numsecflavors; bcopy(argp->ex_secflavors, np->netc_secflavors, sizeof(np->netc_secflavors)); @@ -205,9 +204,8 @@ np->netc_exflags = argp->ex_flags; np->netc_anon = crget(); np->netc_anon->cr_uid = argp->ex_anon.cr_uid; - np->netc_anon->cr_ngroups = argp->ex_anon.cr_ngroups; - bcopy(argp->ex_anon.cr_groups, np->netc_anon->cr_groups, - sizeof(np->netc_anon->cr_groups)); + crsetgroups(np->netc_anon, argp->ex_anon.cr_ngroups, + np->netc_anon->cr_groups); np->netc_numsecflavors = argp->ex_numsecflavors; bcopy(argp->ex_secflavors, np->netc_secflavors, sizeof(np->netc_secflavors)); diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/netinet/ipfw/ip_fw2.c ./sys/netinet/ipfw/ip_fw2.c --- /usr/fsvn/head/sys/netinet/ipfw/ip_fw2.c 2009-06-12 00:52:26.000000000 -0500 +++ ./sys/netinet/ipfw/ip_fw2.c 2009-06-17 13:42:23.000000000 -0500 @@ -135,19 +135,6 @@ struct ip_fw *ip_fw_default_rule; /* - * Data structure to cache our ucred related - * information. This structure only gets used if - * the user specified UID/GID based constraints in - * a firewall rule. - */ -struct ip_fw_ugid { - gid_t fw_groups[NGROUPS]; - int fw_ngroups; - uid_t fw_uid; - int fw_prid; -}; - -/* * list of rules for layer 3 */ #ifdef VIMAGE_GLOBALS @@ -2009,22 +1996,10 @@ return (0); } -static void -fill_ugid_cache(struct inpcb *inp, struct ip_fw_ugid *ugp) -{ - struct ucred *cr; - - cr = inp->inp_cred; - ugp->fw_prid = jailed(cr) ? cr->cr_prison->pr_id : -1; - ugp->fw_uid = cr->cr_uid; - ugp->fw_ngroups = cr->cr_ngroups; - bcopy(cr->cr_groups, ugp->fw_groups, sizeof(ugp->fw_groups)); -} - static int check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip, - u_int16_t src_port, struct ip_fw_ugid *ugp, int *ugid_lookupp, + u_int16_t src_port, struct ucred **uc, int *ugid_lookupp, struct inpcb *inp) { INIT_VNET_INET(curvnet); @@ -2032,7 +2007,6 @@ int wildcard; struct inpcb *pcb; int match; - gid_t *gp; /* * Check to see if the UDP or TCP stack supplied us with @@ -2042,7 +2016,7 @@ if (inp && *ugid_lookupp == 0) { INP_LOCK_ASSERT(inp); if (inp->inp_socket != NULL) { - fill_ugid_cache(inp, ugp); + *uc = crhold(inp->inp_cred); *ugid_lookupp = 1; } else *ugid_lookupp = -1; @@ -2075,7 +2049,7 @@ dst_ip, htons(dst_port), wildcard, NULL); if (pcb != NULL) { - fill_ugid_cache(pcb, ugp); + *uc = crhold(inp->inp_cred); *ugid_lookupp = 1; } INP_INFO_RUNLOCK(pi); @@ -2091,16 +2065,11 @@ } } if (insn->o.opcode == O_UID) - match = (ugp->fw_uid == (uid_t)insn->d[0]); - else if (insn->o.opcode == O_GID) { - for (gp = ugp->fw_groups; - gp < &ugp->fw_groups[ugp->fw_ngroups]; gp++) - if (*gp == (gid_t)insn->d[0]) { - match = 1; - break; - } - } else if (insn->o.opcode == O_JAIL) - match = (ugp->fw_prid == (int)insn->d[0]); + match = ((*uc)->cr_uid == (uid_t)insn->d[0]); + else if (insn->o.opcode == O_GID) + match = groupmember((gid_t)insn->d[0], *uc); + else if (insn->o.opcode == O_JAIL) + match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]); return match; } @@ -2178,8 +2147,8 @@ * these types of constraints, as well as decrease contention * on pcb related locks. */ - struct ip_fw_ugid fw_ugid_cache; - int ugid_lookup = 0; + struct ucred *ucred_cache = NULL; + int ucred_lookup = 0; /* * divinput_flags If non-zero, set to the IP_FW_DIVERT_*_FLAG @@ -2641,8 +2610,8 @@ (ipfw_insn_u32 *)cmd, proto, oif, dst_ip, dst_port, - src_ip, src_port, &fw_ugid_cache, - &ugid_lookup, args->inp); + src_ip, src_port, &ucred_cache, + &ucred_lookup, args->inp); break; case O_RECV: @@ -3270,6 +3239,8 @@ /* XXX statistic */ /* drop packet */ IPFW_RUNLOCK(chain); + if (ucred_cache != NULL) + crfree(ucred_cache); return (IP_FW_DENY); } dt = (struct divert_tag *)(mtag+1); @@ -3475,6 +3446,8 @@ } /* end of outer for, scan rules */ printf("ipfw: ouch!, skip past end of rules, denying packet\n"); IPFW_RUNLOCK(chain); + if (ucred_cache != NULL) + crfree(ucred_cache); return (IP_FW_DENY); done: @@ -3483,6 +3456,8 @@ f->bcnt += pktlen; f->timestamp = time_uptime; IPFW_RUNLOCK(chain); + if (ucred_cache != NULL) + crfree(ucred_cache); return (retval); pullup_failed: diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/nfsserver/nfs_srvsock.c ./sys/nfsserver/nfs_srvsock.c --- /usr/fsvn/head/sys/nfsserver/nfs_srvsock.c 2009-06-16 15:54:40.000000000 -0500 +++ ./sys/nfsserver/nfs_srvsock.c 2009-06-09 08:49:37.000000000 -0500 @@ -370,11 +370,11 @@ } tl = nfsm_dissect_nonblock(u_int32_t *, (len + 2) * NFSX_UNSIGNED); for (i = 1; i <= len; i++) - if (i < NGROUPS) + if (i < XU_NGROUPS) nd->nd_cr->cr_groups[i] = fxdr_unsigned(gid_t, *tl++); else tl++; - nd->nd_cr->cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1); + nd->nd_cr->cr_ngroups = MIN(XU_NGROUPS, len + 1); if (nd->nd_cr->cr_ngroups > 1) nfsrvw_sort(nd->nd_cr->cr_groups, nd->nd_cr->cr_ngroups); len = fxdr_unsigned(int, *++tl); diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/nfsserver/nfs_srvsubs.c ./sys/nfsserver/nfs_srvsubs.c --- /usr/fsvn/head/sys/nfsserver/nfs_srvsubs.c 2009-05-29 12:48:04.000000000 -0500 +++ ./sys/nfsserver/nfs_srvsubs.c 2009-06-05 15:33:54.000000000 -0500 @@ -1181,9 +1181,7 @@ cred = nfsd->nd_cr; if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { cred->cr_uid = credanon->cr_uid; - for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++) - cred->cr_groups[i] = credanon->cr_groups[i]; - cred->cr_ngroups = i; + crsetgroups(cred, credanon->cr_ngroups, credanon->cr_groups); } if (exflags & MNT_EXRDONLY) *rdonlyp = 1; diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c ./sys/rpc/rpcsec_gss/svc_rpcsec_gss.c --- /usr/fsvn/head/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c 2009-06-16 13:55:57.000000000 -0500 +++ ./sys/rpc/rpcsec_gss/svc_rpcsec_gss.c 2009-06-16 13:56:18.000000000 -0500 @@ -449,11 +449,7 @@ cr = client->cl_cred = crget(); cr->cr_uid = cr->cr_ruid = cr->cr_svuid = uc->uid; cr->cr_rgid = cr->cr_svgid = uc->gid; - cr->cr_ngroups = uc->gidlen; - if (cr->cr_ngroups > NGROUPS) - cr->cr_ngroups = NGROUPS; - for (i = 0; i < cr->cr_ngroups; i++) - cr->cr_groups[i] = uc->gidlist[i]; + crsetgroups(cr, uc->gidlen, uc->gidlist); *crp = crhold(cr); return (TRUE); diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/rpc/svc_auth.c ./sys/rpc/svc_auth.c --- /usr/fsvn/head/sys/rpc/svc_auth.c 2009-06-12 00:52:17.000000000 -0500 +++ ./sys/rpc/svc_auth.c 2009-06-12 01:13:12.000000000 -0500 @@ -166,7 +166,7 @@ svc_getcred(struct svc_req *rqst, struct ucred **crp, int *flavorp) { struct ucred *cr = NULL; - int flavor, i; + int flavor; struct xucred *xcr; flavor = rqst->rq_cred.oa_flavor; @@ -178,9 +178,7 @@ xcr = (struct xucred *) rqst->rq_clntcred; cr = crget(); cr->cr_uid = cr->cr_ruid = cr->cr_svuid = xcr->cr_uid; - cr->cr_ngroups = xcr->cr_ngroups; - for (i = 0; i < xcr->cr_ngroups; i++) - cr->cr_groups[i] = xcr->cr_groups[i]; + crsetgroups(cr, xcr->cr_ngroups, xcr->cr_groups); cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0]; cr->cr_prison = &prison0; prison_hold(cr->cr_prison); diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/rpc/svc_auth_unix.c ./sys/rpc/svc_auth_unix.c --- /usr/fsvn/head/sys/rpc/svc_auth_unix.c 2009-01-22 10:05:57.000000000 -0600 +++ ./sys/rpc/svc_auth_unix.c 2009-06-09 08:49:37.000000000 -0500 @@ -95,13 +95,13 @@ goto done; } for (i = 0; i < gid_len; i++) { - if (i + 1 < NGROUPS) + if (i + 1 < XU_NGROUPS) xcr->cr_groups[i + 1] = IXDR_GET_INT32(buf); else buf++; } - if (gid_len + 1 > NGROUPS) - xcr->cr_ngroups = NGROUPS; + if (gid_len + 1 > XU_NGROUPS) + xcr->cr_ngroups = XU_NGROUPS; else xcr->cr_ngroups = gid_len + 1; diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/sys/param.h ./sys/sys/param.h --- /usr/fsvn/head/sys/sys/param.h 2009-06-16 13:55:59.000000000 -0500 +++ ./sys/sys/param.h 2009-06-16 13:56:20.000000000 -0500 @@ -77,7 +77,7 @@ #define MAXLOGNAME 17 /* max login name length (incl. NUL) */ #define MAXUPRC CHILD_MAX /* max simultaneous processes */ #define NCARGS ARG_MAX /* max bytes for an exec function */ -#define NGROUPS NGROUPS_MAX /* max number groups */ +#define NGROUPS NGROUPS_MAX+1 /* max number groups */ #define NOFILE OPEN_MAX /* max open files per process */ #define NOGROUP 65535 /* marker for empty group set member */ #define MAXHOSTNAMELEN 256 /* max hostname size */ diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/sys/syslimits.h ./sys/sys/syslimits.h --- /usr/fsvn/head/sys/sys/syslimits.h 2009-01-22 10:06:22.000000000 -0600 +++ ./sys/sys/syslimits.h 2009-06-08 23:57:36.000000000 -0500 @@ -54,7 +54,9 @@ #define MAX_CANON 255 /* max bytes in term canon input line */ #define MAX_INPUT 255 /* max bytes in terminal input */ #define NAME_MAX 255 /* max bytes in a file name */ -#define NGROUPS_MAX 16 /* max supplemental group id's */ +#ifndef NGROUPS_MAX +#define NGROUPS_MAX 1023 /* max supplemental group id's */ +#endif #ifndef OPEN_MAX #define OPEN_MAX 64 /* max open files per process */ #endif --- /usr/fsvn/head/sys/sys/ucred.h 2009-06-16 15:54:53.000000000 -0500 +++ ./sys/sys/ucred.h 2009-06-17 18:23:49.000000000 -0500 @@ -48,8 +48,7 @@ uid_t cr_uid; /* effective user id */ uid_t cr_ruid; /* real user id */ uid_t cr_svuid; /* saved user id */ - short cr_ngroups; /* number of groups */ - gid_t cr_groups[NGROUPS]; /* groups */ + int cr_ngroups; /* number of groups */ gid_t cr_rgid; /* real group id */ gid_t cr_svgid; /* saved group id */ struct uidinfo *cr_uidinfo; /* per euid resource consumption */ @@ -61,11 +60,15 @@ #define cr_endcopy cr_label struct label *cr_label; /* MAC label */ struct auditinfo_addr cr_audit; /* Audit properties. */ + gid_t *cr_groups; /* groups */ + int cr_agroups; /* Available groups */ }; #define NOCRED ((struct ucred *)0) /* no credential available */ #define FSCRED ((struct ucred *)-1) /* filesystem credential */ #endif /* _KERNEL || _WANT_UCRED */ +#define XU_NGROUPS 16 + /* * This is the external representation of struct ucred. */ @@ -73,7 +76,7 @@ u_int cr_version; /* structure layout version */ uid_t cr_uid; /* effective user id */ short cr_ngroups; /* number of groups */ - gid_t cr_groups[NGROUPS]; /* groups */ + gid_t cr_groups[XU_NGROUPS]; /* groups */ void *_cr_unused1; /* compatibility with old ucred */ }; #define XUCRED_VERSION 0 @@ -82,6 +85,7 @@ #define cr_gid cr_groups[0] #ifdef _KERNEL +struct proc; struct thread; void change_egid(struct ucred *newcred, gid_t egid); @@ -91,6 +95,7 @@ void change_svgid(struct ucred *newcred, gid_t svgid); void change_svuid(struct ucred *newcred, uid_t svuid); void crcopy(struct ucred *dest, struct ucred *src); +struct ucred *crcopysafe(struct proc *p, struct ucred *cr); struct ucred *crdup(struct ucred *cr); void cred_update_thread(struct thread *td); void crfree(struct ucred *cr); @@ -98,6 +103,7 @@ struct ucred *crhold(struct ucred *cr); int crshared(struct ucred *cr); void cru2x(struct ucred *cr, struct xucred *xcr); +void crsetgroups(struct ucred *cr, int n, gid_t *groups); int groupmember(gid_t gid, struct ucred *cred); #endif /* _KERNEL */ diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/sys/user.h ./sys/sys/user.h --- /usr/fsvn/head/sys/sys/user.h 2009-06-16 15:54:53.000000000 -0500 +++ ./sys/sys/user.h 2009-06-05 16:02:34.000000000 -0500 @@ -85,7 +85,7 @@ */ #define KI_NSPARE_INT 9 #define KI_NSPARE_LONG 12 -#define KI_NSPARE_PTR 7 +#define KI_NSPARE_PTR 6 #ifdef __amd64__ #define KINFO_PROC_SIZE 1088 @@ -117,7 +117,6 @@ #define OCOMMLEN 16 /* size of returned thread name */ #define COMMLEN 19 /* size of returned ki_comm name */ #define KI_EMULNAMELEN 16 /* size of returned ki_emul */ -#define KI_NGROUPS 16 /* number of groups in ki_groups */ #define LOGNAMELEN 17 /* size of returned ki_login */ struct kinfo_proc { @@ -151,7 +150,7 @@ gid_t ki_svgid; /* Saved effective group id */ short ki_ngroups; /* number of groups */ short ki_spare_short2; /* unused (just here for alignment) */ - gid_t ki_groups[KI_NGROUPS]; /* groups */ + uint32_t __was_ki_groups[16]; /* unused; left for bin compat */ vm_size_t ki_size; /* virtual size */ segsz_t ki_rssize; /* current resident set size in pages */ segsz_t ki_swrss; /* resident set size before last swap */ @@ -201,6 +200,7 @@ struct pcb *ki_pcb; /* kernel virtual addr of pcb */ void *ki_kstack; /* kernel virtual addr of stack */ void *ki_udata; /* User convenience pointer */ + gid_t *ki_groups; /* groups */ /* * When adding new variables, take space for pointers from the * front of ki_spareptrs, and longs from the end of ki_sparelongs. diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/sys/ufs/ufs/ufs_vnops.c ./sys/ufs/ufs/ufs_vnops.c --- /usr/fsvn/head/sys/ufs/ufs/ufs_vnops.c 2009-06-16 13:55:57.000000000 -0500 +++ ./sys/ufs/ufs/ufs_vnops.c 2009-06-16 13:56:20.000000000 -0500 @@ -2266,6 +2266,7 @@ { #ifdef QUOTA struct ucred ucred, *ucp; + gid_t ucred_group; ucp = cnp->cn_cred; #endif /* @@ -2292,6 +2293,7 @@ refcount_init(&ucred.cr_ref, 1); ucred.cr_uid = ip->i_uid; ucred.cr_ngroups = 1; + ucred.cr_groups = &ucred_group; ucred.cr_groups[0] = pdir->i_gid; ucp = &ucred; #endif diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/usr.sbin/mount_portalfs/portald.h ./usr.sbin/mount_portalfs/portald.h --- /usr/fsvn/head/usr.sbin/mount_portalfs/portald.h 2009-01-22 10:05:31.000000000 -0600 +++ ./usr.sbin/mount_portalfs/portald.h 2009-06-17 13:41:26.000000000 -0500 @@ -36,6 +36,7 @@ */ #include +#include #include /* diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/usr.sbin/mountd/mountd.c ./usr.sbin/mountd/mountd.c --- /usr/fsvn/head/usr.sbin/mountd/mountd.c 2009-06-16 15:54:05.000000000 -0500 +++ ./usr.sbin/mountd/mountd.c 2009-06-17 15:25:33.000000000 -0500 @@ -2644,7 +2644,7 @@ char *names; struct passwd *pw; struct group *gr; - gid_t groups[NGROUPS + 1]; + gid_t groups[XU_NGROUPS + 1]; int ngroups; cr->cr_version = XUCRED_VERSION; @@ -2672,7 +2672,7 @@ return; } cr->cr_uid = pw->pw_uid; - ngroups = NGROUPS + 1; + ngroups = XU_NGROUPS + 1; if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) syslog(LOG_ERR, "too many groups"); /* @@ -2697,7 +2697,7 @@ return; } cr->cr_ngroups = 0; - while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { + while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) { name = strsep(&names, ":"); if (isdigit(*name) || *name == '-') { cr->cr_groups[cr->cr_ngroups++] = atoi(name); @@ -2709,7 +2709,7 @@ cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; } } - if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) + if (names != NULL && *names != '\0' && cr->cr_ngroups == XU_NGROUPS) syslog(LOG_ERR, "too many groups"); }