svn commit: r192998 - in projects/ngroups: lib/libkvm
sys/compat/linux sys/i386/ibcs2 sys/kern sys/nfsserver sys/sys
Brooks Davis
brooks at FreeBSD.org
Thu May 28 21:41:02 UTC 2009
Author: brooks
Date: Thu May 28 21:41:01 2009
New Revision: 192998
URL: http://svn.freebsd.org/changeset/base/192998
Log:
More work toward increasing NGROUPS_MAX and/or allowing kern.ngroups to
be increased at boot time.
* Replace the embedded cr_groups[NGROUPS] member of struct cred with
a pointer to malloc'd storage and a cr_agroups value which tracks
the number of allocated group slots. When more space is required
crextend() is used to add more space. The new crcopysafe() function
calls crextend as needed when saving a copy of a credential from a
process before modification.
* Introduce a new #define, XU_NGROUPS which is always 16 and is used to
set the array size in struct xucred and will be used other places
where the 16 group limit needs to be preserved.
* Replace the embedded ki_groups[KI_NGROUPS] entry in struct kinfo_proc
with a pointer and adapt libkvm accordingly.
Submitted by: Isilon Systems (Matthew Fleming)
Modified:
projects/ngroups/lib/libkvm/kvm_proc.c
projects/ngroups/sys/compat/linux/linux_misc.c
projects/ngroups/sys/compat/linux/linux_uid16.c
projects/ngroups/sys/i386/ibcs2/ibcs2_misc.c
projects/ngroups/sys/kern/kern_exec.c
projects/ngroups/sys/kern/kern_proc.c
projects/ngroups/sys/kern/kern_prot.c
projects/ngroups/sys/nfsserver/nfs_srvsock.c
projects/ngroups/sys/sys/ucred.h
projects/ngroups/sys/sys/user.h
Modified: projects/ngroups/lib/libkvm/kvm_proc.c
==============================================================================
--- projects/ngroups/lib/libkvm/kvm_proc.c Thu May 28 21:37:40 2009 (r192997)
+++ projects/ngroups/lib/libkvm/kvm_proc.c Thu May 28 21:41:01 2009 (r192998)
@@ -146,9 +146,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcn
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 < KI_NGROUPS ? NGROUPS : KI_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)) {
Modified: projects/ngroups/sys/compat/linux/linux_misc.c
==============================================================================
--- projects/ngroups/sys/compat/linux/linux_misc.c Thu May 28 21:37:40 2009 (r192997)
+++ projects/ngroups/sys/compat/linux/linux_misc.c Thu May 28 21:41:01 2009 (r192998)
@@ -1124,7 +1124,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;
@@ -1132,13 +1132,14 @@ linux_setgroups(struct thread *td, struc
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
@@ -1149,10 +1150,9 @@ linux_setgroups(struct thread *td, struc
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;
@@ -1169,14 +1169,17 @@ linux_setgroups(struct thread *td, struc
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;
@@ -1199,13 +1202,16 @@ linux_getgroups(struct thread *td, struc
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;
Modified: projects/ngroups/sys/compat/linux/linux_uid16.c
==============================================================================
--- projects/ngroups/sys/compat/linux/linux_uid16.c Thu May 28 21:37:40 2009 (r192997)
+++ projects/ngroups/sys/compat/linux/linux_uid16.c Thu May 28 21:41:01 2009 (r192998)
@@ -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, str
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, str
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, str
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, str
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);
Modified: projects/ngroups/sys/i386/ibcs2/ibcs2_misc.c
==============================================================================
--- projects/ngroups/sys/i386/ibcs2/ibcs2_misc.c Thu May 28 21:37:40 2009 (r192997)
+++ projects/ngroups/sys/i386/ibcs2/ibcs2_misc.c Thu May 28 21:41:01 2009 (r192998)
@@ -659,24 +659,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);
}
@@ -685,21 +690,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
Modified: projects/ngroups/sys/kern/kern_exec.c
==============================================================================
--- projects/ngroups/sys/kern/kern_exec.c Thu May 28 21:37:40 2009 (r192997)
+++ projects/ngroups/sys/kern/kern_exec.c Thu May 28 21:41:01 2009 (r192998)
@@ -580,6 +580,7 @@ interpret:
* reset.
*/
PROC_LOCK(p);
+ oldcred = crcopysafe(p, newcred);
if (sigacts_shared(p->p_sigacts)) {
oldsigacts = p->p_sigacts;
PROC_UNLOCK(p);
@@ -630,7 +631,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;
@@ -684,7 +684,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)
@@ -724,7 +723,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;
Modified: projects/ngroups/sys/kern/kern_proc.c
==============================================================================
--- projects/ngroups/sys/kern/kern_proc.c Thu May 28 21:37:40 2009 (r192997)
+++ projects/ngroups/sys/kern/kern_proc.c Thu May 28 21:41:01 2009 (r192998)
@@ -730,10 +730,8 @@ fill_kinfo_proc_only(struct proc *p, str
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;
/* If jailed(cred), emulate the old P_JAILED flag. */
Modified: projects/ngroups/sys/kern/kern_prot.c
==============================================================================
--- projects/ngroups/sys/kern/kern_prot.c Thu May 28 21:37:40 2009 (r192997)
+++ projects/ngroups/sys/kern/kern_prot.c Thu May 28 21:41:01 2009 (r192998)
@@ -276,18 +276,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 +489,10 @@ setuid(struct thread *td, struct setuid_
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 +527,6 @@ setuid(struct thread *td, struct setuid_
(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 +600,10 @@ seteuid(struct thread *td, struct seteui
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 +617,7 @@ seteuid(struct thread *td, struct seteui
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 +655,7 @@ setgid(struct thread *td, struct setgid_
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 +684,6 @@ setgid(struct thread *td, struct setgid_
(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 +753,7 @@ setegid(struct thread *td, struct setegi
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 +766,6 @@ setegid(struct thread *td, struct setegi
(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 +791,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 +817,9 @@ kern_setgroups(struct thread *td, u_int
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 +831,6 @@ kern_setgroups(struct thread *td, u_int
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
@@ -877,7 +879,7 @@ setreuid(register struct thread *td, str
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 +894,6 @@ setreuid(register struct thread *td, str
(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 +943,7 @@ setregid(register struct thread *td, str
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 +958,6 @@ setregid(register struct thread *td, str
(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 +1013,7 @@ setresuid(register struct thread *td, st
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 +1033,6 @@ setresuid(register struct thread *td, st
(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 +1089,7 @@ setresgid(register struct thread *td, st
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 +1109,6 @@ setresgid(register struct thread *td, st
(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);
@@ -1786,6 +1784,7 @@ crget(void)
#ifdef MAC
mac_cred_init(cr);
#endif
+ crextend(cr, XU_NGROUPS);
return (cr);
}
@@ -1830,6 +1829,7 @@ crfree(struct ucred *cr)
#ifdef MAC
mac_cred_destroy(cr);
#endif
+ free(cr->cr_groups, M_CRED);
free(cr, M_CRED);
}
}
@@ -1855,6 +1855,9 @@ crcopy(struct ucred *dest, struct ucred
bcopy(&src->cr_startcopy, &dest->cr_startcopy,
(unsigned)((caddr_t)&src->cr_endcopy -
(caddr_t)&src->cr_startcopy));
+ crextend(dest, src->cr_agroups);
+ memcpy(dest->cr_groups, src->cr_groups,
+ src->cr_ngroups * sizeof(gid_t));
uihold(dest->cr_uidinfo);
uihold(dest->cr_ruidinfo);
if (jailed(dest))
@@ -1886,12 +1889,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[0]));
}
/*
@@ -1913,6 +1920,59 @@ 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.
+ */
+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.
+ */
+ if (cr->cr_agroups)
+ cnt = cr->cr_agroups * 2;
+ else
+ cnt = MINALLOCSIZE / sizeof(gid_t);
+
+ while (cnt < n)
+ cnt *= 2;
+
+ /* 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;
+}
+
/*
* Get login name, if available.
*/
Modified: projects/ngroups/sys/nfsserver/nfs_srvsock.c
==============================================================================
--- projects/ngroups/sys/nfsserver/nfs_srvsock.c Thu May 28 21:37:40 2009 (r192997)
+++ projects/ngroups/sys/nfsserver/nfs_srvsock.c Thu May 28 21:41:01 2009 (r192998)
@@ -371,11 +371,11 @@ nfs_getreq(struct nfsrv_descript *nd, st
}
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 = (len >= XU_NGROUPS) ? 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);
Modified: projects/ngroups/sys/sys/ucred.h
==============================================================================
--- projects/ngroups/sys/sys/ucred.h Thu May 28 21:37:40 2009 (r192997)
+++ projects/ngroups/sys/sys/ucred.h Thu May 28 21:41:01 2009 (r192998)
@@ -49,7 +49,6 @@ struct ucred {
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 */
gid_t cr_rgid; /* real group id */
gid_t cr_svgid; /* saved group id */
struct uidinfo *cr_uidinfo; /* per euid resource consumption */
@@ -60,11 +59,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 */
+ short 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.
*/
@@ -72,7 +75,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
@@ -81,6 +84,7 @@ struct xucred {
#define cr_gid cr_groups[0]
#ifdef _KERNEL
+struct proc;
struct thread;
void change_egid(struct ucred *newcred, gid_t egid);
@@ -90,6 +94,7 @@ void change_ruid(struct ucred *newcred,
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 *, struct ucred *);
struct ucred *crdup(struct ucred *cr);
void cred_update_thread(struct thread *td);
void crfree(struct ucred *cr);
@@ -97,6 +102,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 crextend(struct ucred *cr, int n);
int groupmember(gid_t gid, struct ucred *cred);
#endif /* _KERNEL */
Modified: projects/ngroups/sys/sys/user.h
==============================================================================
--- projects/ngroups/sys/sys/user.h Thu May 28 21:37:40 2009 (r192997)
+++ projects/ngroups/sys/sys/user.h Thu May 28 21:41:01 2009 (r192998)
@@ -85,7 +85,7 @@
*/
#define KI_NSPARE_INT 10
#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 */
@@ -200,6 +199,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.
More information about the svn-src-projects
mailing list