diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/linux/linux_misc.c | 24 | ||||
-rw-r--r-- | sys/compat/linux/linux_uid16.c | 18 | ||||
-rw-r--r-- | sys/fs/nfs/nfs_commonport.c | 7 | ||||
-rw-r--r-- | sys/fs/nfsclient/nfs_clport.c | 8 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdport.c | 6 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdstate.c | 1 | ||||
-rw-r--r-- | sys/fs/portalfs/portal.h | 2 | ||||
-rw-r--r-- | sys/fs/portalfs/portal_vnops.c | 5 | ||||
-rw-r--r-- | sys/fs/unionfs/union_vnops.c | 20 | ||||
-rw-r--r-- | sys/i386/ibcs2/ibcs2_misc.c | 33 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_proc.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_prot.c | 170 | ||||
-rw-r--r-- | sys/kern/vfs_export.c | 10 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw2.c | 61 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvsock.c | 4 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvsubs.c | 4 | ||||
-rw-r--r-- | sys/rpc/rpcsec_gss/svc_rpcsec_gss.c | 6 | ||||
-rw-r--r-- | sys/rpc/svc_auth.c | 6 | ||||
-rw-r--r-- | sys/rpc/svc_auth_unix.c | 6 | ||||
-rw-r--r-- | sys/sys/param.h | 2 | ||||
-rw-r--r-- | sys/sys/syslimits.h | 4 | ||||
-rw-r--r-- | sys/sys/ucred.h | 12 | ||||
-rw-r--r-- | sys/sys/user.h | 6 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 2 |
25 files changed, 256 insertions, 171 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 9595fed..267da07 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -1132,7 +1132,7 @@ int 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 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args) 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 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args) 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 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args) 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 @@ linux_getgroups(struct thread *td, struct linux_getgroups_args *args) 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 --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c index 2685eaa..b49bf78 100644 --- a/sys/compat/linux/linux_uid16.c +++ b/sys/compat/linux/linux_uid16.c @@ -98,7 +98,7 @@ int 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 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) 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 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) 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 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) 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 @@ linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args) 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 --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c index 0369113..bf982aa 100644 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -220,14 +220,9 @@ nfsrv_lookupfilename(struct nameidata *ndp, char *fname, NFSPROC_T *p) 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 --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c index 3b5e367..5b747c7 100644 --- a/sys/fs/nfsclient/nfs_clport.c +++ b/sys/fs/nfsclient/nfs_clport.c @@ -976,14 +976,12 @@ nfscl_getmyip(struct nfsmount *nmp, int *isinet6p) 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 --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 730a750..8f5cc94 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -2360,7 +2360,6 @@ int nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp, struct ucred *credanon) { - int i; int error = 0; /* @@ -2403,9 +2402,8 @@ nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp, (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 --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index 077ce2a..7794278 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -3577,7 +3577,6 @@ nfsrv_docallback(struct nfsclient *clp, int procnum, 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 --git a/sys/fs/portalfs/portal.h b/sys/fs/portalfs/portal.h index 6606ccc..1fd2d99 100644 --- a/sys/fs/portalfs/portal.h +++ b/sys/fs/portalfs/portal.h @@ -43,7 +43,7 @@ struct portal_cred { 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 --git a/sys/fs/portalfs/portal_vnops.c b/sys/fs/portalfs/portal_vnops.c index 8b49ad3..8d30ebb 100644 --- a/sys/fs/portalfs/portal_vnops.c +++ b/sys/fs/portalfs/portal_vnops.c @@ -311,8 +311,9 @@ portal_open(ap) 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 --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 8505cac..11671cb 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -638,7 +638,6 @@ unionfs_check_corrected_access(accmode_t accmode, 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 @@ unionfs_check_corrected_access(accmode_t accmode, /* 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 --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c index 1906fd7..17d8fe7 100644 --- a/sys/i386/ibcs2/ibcs2_misc.c +++ b/sys/i386/ibcs2/ibcs2_misc.c @@ -657,24 +657,29 @@ ibcs2_getgroups(td, uap) 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 @@ ibcs2_setgroups(td, uap) 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 --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 4e66c95..8e37dba 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -579,6 +579,7 @@ interpret: * 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 @@ interpret: * 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 @@ interpret: /* * 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 @@ interpret: */ 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 --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 0ee630f..4e2ff7e 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -730,10 +730,8 @@ fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp) 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; diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 5deff69..17cba9c 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -82,6 +82,11 @@ static MALLOC_DEFINE(M_CRED, "cred", "credentials"); 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 +281,21 @@ struct getgroups_args { 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 +494,10 @@ setuid(struct thread *td, struct setuid_args *uap) 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 +532,6 @@ setuid(struct thread *td, struct setuid_args *uap) (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 +605,10 @@ seteuid(struct thread *td, struct seteuid_args *uap) 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 +622,7 @@ seteuid(struct thread *td, struct seteuid_args *uap) 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 +660,7 @@ setgid(struct thread *td, struct setgid_args *uap) 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 +689,6 @@ setgid(struct thread *td, struct setgid_args *uap) (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 +758,7 @@ setegid(struct thread *td, struct setegid_args *uap) 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 +771,6 @@ setegid(struct thread *td, struct setegid_args *uap) (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 +796,19 @@ struct setgroups_args { 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 +822,9 @@ kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups) 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 +836,6 @@ kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups) 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 +845,7 @@ kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups) */ 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 +883,7 @@ setreuid(register struct thread *td, struct setreuid_args *uap) 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 +898,6 @@ setreuid(register struct thread *td, struct setreuid_args *uap) (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 +947,7 @@ setregid(register struct thread *td, struct setregid_args *uap) 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 +962,6 @@ setregid(register struct thread *td, struct setregid_args *uap) (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 +1017,7 @@ setresuid(register struct thread *td, struct setresuid_args *uap) 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 +1037,6 @@ setresuid(register struct thread *td, struct setresuid_args *uap) (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 +1093,7 @@ setresgid(register struct thread *td, struct setresgid_args *uap) 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 +1113,6 @@ setresgid(register struct thread *td, struct setresgid_args *uap) (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 +1782,7 @@ crget(void) #ifdef MAC mac_cred_init(cr); #endif + crextend(cr, XU_NGROUPS); return (cr); } @@ -1829,6 +1832,7 @@ crfree(struct ucred *cr) #ifdef MAC mac_cred_destroy(cr); #endif + free(cr->cr_groups, M_CRED); free(cr, M_CRED); } } @@ -1854,6 +1858,7 @@ 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)); + crsetgroups(dest, src->cr_ngroups, src->cr_groups); uihold(dest->cr_uidinfo); uihold(dest->cr_ruidinfo); prison_hold(dest->cr_prison); @@ -1888,12 +1893,16 @@ crdup(struct ucred *cr) 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 +1924,97 @@ cred_update_thread(struct thread *td) 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 --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 6ac4cc2..ee8a35b 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -120,9 +120,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_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 @@ 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_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 --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c index 51518ff..6f5c956 100644 --- a/sys/netinet/ipfw/ip_fw2.c +++ b/sys/netinet/ipfw/ip_fw2.c @@ -135,19 +135,6 @@ static uma_zone_t ipfw_dyn_rule_zone; 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 @@ dump_table(struct ip_fw_chain *ch, ipfw_table *tbl) 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 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, 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 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, 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 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, 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 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, } } 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 @@ ipfw_chk(struct ip_fw_args *args) * 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 @@ check_body: (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 @@ check_body: /* 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 @@ next_rule:; /* try next rule */ } /* 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 @@ done: f->bcnt += pktlen; f->timestamp = time_uptime; IPFW_RUNLOCK(chain); + if (ucred_cache != NULL) + crfree(ucred_cache); return (retval); pullup_failed: diff --git a/sys/nfsserver/nfs_srvsock.c b/sys/nfsserver/nfs_srvsock.c index 13679ef..0bb4128 100644 --- a/sys/nfsserver/nfs_srvsock.c +++ b/sys/nfsserver/nfs_srvsock.c @@ -370,11 +370,11 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header) } 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 --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c index 3f54664..87fda28 100644 --- a/sys/nfsserver/nfs_srvsubs.c +++ b/sys/nfsserver/nfs_srvsubs.c @@ -1181,9 +1181,7 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, int *vfslockedp, 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 --git a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c index 9653c91..13fcce9 100644 --- a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c +++ b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c @@ -449,11 +449,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; - 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 --git a/sys/rpc/svc_auth.c b/sys/rpc/svc_auth.c index 2d2b73d..5d83c8d 100644 --- a/sys/rpc/svc_auth.c +++ b/sys/rpc/svc_auth.c @@ -166,7 +166,7 @@ int 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 @@ svc_getcred(struct svc_req *rqst, struct ucred **crp, int *flavorp) 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 --git a/sys/rpc/svc_auth_unix.c b/sys/rpc/svc_auth_unix.c index 0c11a4a..19ff40a 100644 --- a/sys/rpc/svc_auth_unix.c +++ b/sys/rpc/svc_auth_unix.c @@ -95,13 +95,13 @@ _svcauth_unix(struct svc_req *rqst, struct rpc_msg *msg) 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 --git a/sys/sys/param.h b/sys/sys/param.h index 06ddf32..06745f8 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -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 --git a/sys/sys/syslimits.h b/sys/sys/syslimits.h index 28a5eba..c38648f 100644 --- a/sys/sys/syslimits.h +++ b/sys/sys/syslimits.h @@ -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 diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h index 626b501..c7474b7 100644 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -48,8 +48,7 @@ struct ucred { 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 @@ struct ucred { #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 @@ struct xucred { 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 @@ struct xucred { #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_ruid(struct ucred *newcred, struct uidinfo *ruip); 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 *crget(void); 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 --git a/sys/sys/user.h b/sys/sys/user.h index ba3dfb0..a9dfceb 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -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 @@ struct kinfo_proc { 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 kinfo_proc { 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 --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 371c462..110262b 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -2266,6 +2266,7 @@ ufs_makeinode(mode, dvp, vpp, cnp) { #ifdef QUOTA struct ucred ucred, *ucp; + gid_t ucred_group; ucp = cnp->cn_cred; #endif /* @@ -2292,6 +2293,7 @@ ufs_makeinode(mode, dvp, vpp, cnp) 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 |