Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145241429
D51489.id159386.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D51489.id159386.diff
View Options
diff --git a/share/man/man9/ucred.9 b/share/man/man9/ucred.9
--- a/share/man/man9/ucred.9
+++ b/share/man/man9/ucred.9
@@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
.\" DAMAGE.
.\"
-.Dd January 23, 2019
+.Dd July 29, 2025
.Dt UCRED 9
.Os
.Sh NAME
@@ -119,8 +119,7 @@
groups.
No other mechanism should be used to modify the
.Va cr_groups
-array except for updating the primary group via assignment to
-.Va cr_groups[0] .
+array.
.Pp
The
.Fn cru2x
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -1030,47 +1030,32 @@
{
struct ucred *newcred, *oldcred;
l_gid_t *linux_gidset;
- gid_t *bsd_gidset;
int ngrp, error;
struct proc *p;
ngrp = args->gidsetsize;
- if (ngrp < 0 || ngrp >= ngroups_max + 1)
+ if (ngrp < 0 || ngrp >= ngroups_max)
return (EINVAL);
linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK);
error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t));
if (error)
goto out;
newcred = crget();
- crextend(newcred, ngrp + 1);
+ crextend(newcred, ngrp);
p = td->td_proc;
PROC_LOCK(p);
oldcred = p->p_ucred;
crcopy(newcred, oldcred);
- /*
- * cr_groups[0] holds egid. Setting the whole set from
- * the supplied set will cause egid to be changed too.
- * Keep cr_groups[0] unchanged to prevent that.
- */
-
if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS)) != 0) {
PROC_UNLOCK(p);
crfree(newcred);
goto out;
}
- if (ngrp > 0) {
- newcred->cr_ngroups = ngrp + 1;
-
- bsd_gidset = newcred->cr_groups;
- ngrp--;
- while (ngrp >= 0) {
- bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
- ngrp--;
- }
- } else
- newcred->cr_ngroups = 1;
+ newcred->cr_ngroups = ngrp;
+ for (int i = 0; i < ngrp; i++)
+ newcred->cr_groups[i] = linux_gidset[i];
setsugid(p);
proc_set_cred(p, newcred);
@@ -1092,13 +1077,7 @@
cred = td->td_ucred;
bsd_gidset = cred->cr_groups;
- bsd_gidsetsz = cred->cr_ngroups - 1;
-
- /*
- * cr_groups[0] holds egid. Returning the whole set
- * here will cause a duplicate. Exclude cr_groups[0]
- * to prevent that.
- */
+ bsd_gidsetsz = cred->cr_ngroups;
if ((ngrp = args->gidsetsize) == 0) {
td->td_retval[0] = bsd_gidsetsz;
@@ -1112,7 +1091,7 @@
linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset),
M_LINUX, M_WAITOK);
while (ngrp < bsd_gidsetsz) {
- linux_gidset[ngrp] = bsd_gidset[ngrp + 1];
+ linux_gidset[ngrp] = bsd_gidset[ngrp];
ngrp++;
}
diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c
--- a/sys/compat/linux/linux_uid16.c
+++ b/sys/compat/linux/linux_uid16.c
@@ -87,12 +87,11 @@
{
struct ucred *newcred, *oldcred;
l_gid16_t *linux_gidset;
- gid_t *bsd_gidset;
int ngrp, error;
struct proc *p;
ngrp = args->gidsetsize;
- if (ngrp < 0 || ngrp >= ngroups_max + 1)
+ if (ngrp < 0 || ngrp >= ngroups_max)
return (EINVAL);
linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK);
error = copyin(args->gidset, linux_gidset, ngrp * sizeof(l_gid16_t));
@@ -106,12 +105,6 @@
PROC_LOCK(p);
oldcred = crcopysafe(p, newcred);
- /*
- * cr_groups[0] holds egid. Setting the whole set from
- * the supplied set will cause egid to be changed too.
- * Keep cr_groups[0] unchanged to prevent that.
- */
-
if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS)) != 0) {
PROC_UNLOCK(p);
crfree(newcred);
@@ -121,18 +114,9 @@
goto out;
}
- if (ngrp > 0) {
- newcred->cr_ngroups = ngrp + 1;
-
- bsd_gidset = newcred->cr_groups;
- ngrp--;
- while (ngrp >= 0) {
- bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
- ngrp--;
- }
- }
- else
- newcred->cr_ngroups = 1;
+ newcred->cr_ngroups = ngrp;
+ for (int i = 0; i < ngrp; i++)
+ newcred->cr_groups[i] = linux_gidset[i];
setsugid(td->td_proc);
proc_set_cred(p, newcred);
@@ -155,13 +139,7 @@
cred = td->td_ucred;
bsd_gidset = cred->cr_groups;
- bsd_gidsetsz = cred->cr_ngroups - 1;
-
- /*
- * cr_groups[0] holds egid. Returning the whole set
- * here will cause a duplicate. Exclude cr_groups[0]
- * to prevent that.
- */
+ bsd_gidsetsz = cred->cr_ngroups;
if ((ngrp = args->gidsetsize) == 0) {
td->td_retval[0] = bsd_gidsetsz;
@@ -175,7 +153,7 @@
linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset),
M_LINUX, M_WAITOK);
while (ngrp < bsd_gidsetsz) {
- linux_gidset[ngrp] = bsd_gidset[ngrp + 1];
+ linux_gidset[ngrp] = bsd_gidset[ngrp];
ngrp++;
}
diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c
--- a/sys/fs/nfs/nfs_commonport.c
+++ b/sys/fs/nfs/nfs_commonport.c
@@ -380,8 +380,7 @@
cred->cr_uid = 0;
cred->cr_gid = 0;
- /* XXXKE Fix this if cr_gid gets separated out. */
- cred->cr_ngroups = 1;
+ cred->cr_ngroups = 0;
}
/*
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -6934,8 +6934,7 @@
tcred = NFSNEWCRED(cred);
tcred->cr_uid = flp->nfsfl_ffm[mirror].user;
tcred->cr_gid = flp->nfsfl_ffm[mirror].group;
- /* XXXKE Fix this if cr_gid gets separated out. */
- tcred->cr_ngroups = 1;
+ tcred->cr_ngroups = 0;
} else
tcred = cred;
if (rwflag == NFSV4OPEN_ACCESSREAD)
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -3464,12 +3464,12 @@
(nd->nd_flag & ND_AUTHNONE) != 0) {
nd->nd_cred->cr_uid = credanon->cr_uid;
/*
- * 'credanon' is already a 'struct ucred' that was built
- * internally with calls to crsetgroups_fallback(), so
- * we don't need a fallback here.
+ * credanon was previously built with
+ * crsetgroups_fallback, but we use it anyways because
+ * we still want to set the effective GID here.
*/
- crsetgroups(nd->nd_cred, credanon->cr_ngroups,
- credanon->cr_groups);
+ crsetgroups_fallback(nd->nd_cred, credanon->cr_ngroups,
+ credanon->cr_groups, credanon->cr_gid);
} else if ((nd->nd_flag & ND_GSS) == 0) {
/*
* If using AUTH_SYS, call nfsrv_getgrpscred() to see
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -99,12 +99,11 @@
groups_check_positive_len(int ngrp)
{
MPASS2(ngrp >= 0, "negative number of groups");
- MPASS2(ngrp != 0, "at least one group expected (effective GID)");
}
static inline void
groups_check_max_len(int ngrp)
{
- MPASS2(ngrp <= ngroups_max + 1, "too many groups");
+ MPASS2(ngrp <= ngroups_max, "too many supplementary groups");
}
static void groups_normalize(int *ngrp, gid_t *groups);
@@ -321,10 +320,17 @@
sys_getgroups(struct thread *td, struct getgroups_args *uap)
{
struct ucred *cred;
+ gid_t *ugidset;
int ngrp, error;
cred = td->td_ucred;
- ngrp = cred->cr_ngroups;
+
+ /*
+ * cr_gid has been moved out of cr_groups, but we'll continue exporting
+ * the egid as groups[0] for the time being until we audit userland for
+ * any surprises.
+ */
+ ngrp = cred->cr_ngroups + 1;
if (uap->gidsetsize == 0) {
error = 0;
@@ -333,7 +339,17 @@
if (uap->gidsetsize < ngrp)
return (EINVAL);
- error = copyout(cred->cr_groups, uap->gidset, ngrp * sizeof(gid_t));
+ ugidset = uap->gidset;
+ error = copyout(&cred->cr_gid, ugidset, sizeof(*ugidset));
+ if (error != 0)
+ goto out;
+
+ if (ngrp > 1) {
+ ugidset++;
+
+ error = copyout(cred->cr_groups, ugidset,
+ (ngrp - 1) * sizeof(*ugidset));
+ }
out:
td->td_retval[0] = ngrp;
return (error);
@@ -499,8 +515,8 @@
}
/*
- * Final storage for groups (including the effective GID) will be returned via
- * 'groups'. '*groups' must be NULL on input, and if not equal to 'smallgroups'
+ * Final storage for supplementary groups will be returned via 'groups'.
+ * '*groups' must be NULL on input, and if not equal to 'smallgroups'
* on output, must be freed (M_TEMP) *even if* an error is returned.
*/
static int
@@ -525,15 +541,15 @@
* now, to avoid having to allocate and copy again the
* supplementary groups.
*/
- *groups = wcred->sc_supp_groups_nb < CRED_SMALLGROUPS_NB ?
- smallgroups : malloc((wcred->sc_supp_groups_nb + 1) *
+ *groups = wcred->sc_supp_groups_nb <= CRED_SMALLGROUPS_NB ?
+ smallgroups : malloc(wcred->sc_supp_groups_nb *
sizeof(*groups), M_TEMP, M_WAITOK);
- error = copyin(wcred->sc_supp_groups, *groups + 1,
+ error = copyin(wcred->sc_supp_groups, *groups,
wcred->sc_supp_groups_nb * sizeof(*groups));
if (error != 0)
return (error);
- wcred->sc_supp_groups = *groups + 1;
+ wcred->sc_supp_groups = *groups;
} else {
wcred->sc_supp_groups_nb = 0;
wcred->sc_supp_groups = NULL;
@@ -652,9 +668,8 @@
* CAUTION: This function normalizes groups in 'wcred'.
*
* If 'preallocated_groups' is non-NULL, it must be an already allocated array
- * of size 'wcred->sc_supp_groups_nb + 1', with the supplementary groups
- * starting at index 1, and 'wcred->sc_supp_groups' then must point to the first
- * supplementary group.
+ * of size 'wcred->sc_supp_groups_nb' containing the supplementary groups, and
+ * 'wcred->sc_supp_groups' then must point to it.
*/
int
kern_setcred(struct thread *const td, const u_int flags,
@@ -685,13 +700,14 @@
return (EINVAL);
if (preallocated_groups != NULL) {
groups = preallocated_groups;
- MPASS(preallocated_groups + 1 == wcred->sc_supp_groups);
+ MPASS(preallocated_groups == wcred->sc_supp_groups);
} else {
- groups = wcred->sc_supp_groups_nb < CRED_SMALLGROUPS_NB ?
- smallgroups :
- malloc((wcred->sc_supp_groups_nb + 1) *
- sizeof(*groups), M_TEMP, M_WAITOK);
- memcpy(groups + 1, wcred->sc_supp_groups,
+ if (wcred->sc_supp_groups_nb <= CRED_SMALLGROUPS_NB)
+ groups = smallgroups;
+ else
+ groups = malloc(wcred->sc_supp_groups_nb *
+ sizeof(*groups), M_TEMP, M_WAITOK);
+ memcpy(groups, wcred->sc_supp_groups,
wcred->sc_supp_groups_nb * sizeof(*groups));
}
}
@@ -726,16 +742,12 @@
if (flags & SETCREDF_SVGID)
AUDIT_ARG_SGID(wcred->sc_svgid);
if (flags & SETCREDF_SUPP_GROUPS) {
- int ngrp = wcred->sc_supp_groups_nb;
-
/*
* Output the raw supplementary groups array for better
* traceability.
*/
- AUDIT_ARG_GROUPSET(groups + 1, ngrp);
- ++ngrp;
- groups_normalize(&ngrp, groups);
- wcred->sc_supp_groups_nb = ngrp - 1;
+ AUDIT_ARG_GROUPSET(groups, wcred->sc_supp_groups_nb);
+ groups_normalize(&wcred->sc_supp_groups_nb, groups);
}
/*
@@ -746,7 +758,7 @@
new_cred = crget();
to_free_cred = new_cred;
if (flags & SETCREDF_SUPP_GROUPS)
- crextend(new_cred, wcred->sc_supp_groups_nb + 1);
+ crextend(new_cred, wcred->sc_supp_groups_nb);
#ifdef MAC
mac_cred_setcred_enter();
@@ -778,9 +790,7 @@
* ones.
*/
if (flags & SETCREDF_SUPP_GROUPS) {
- groups[0] = flags & SETCREDF_GID ? wcred->sc_gid :
- new_cred->cr_gid;
- crsetgroups_internal(new_cred, wcred->sc_supp_groups_nb + 1,
+ crsetgroups_internal(new_cred, wcred->sc_supp_groups_nb,
groups);
} else if (flags & SETCREDF_GID)
change_egid(new_cred, wcred->sc_gid);
@@ -1206,6 +1216,7 @@
* setgroups() differ.
*/
gidsetsize = uap->gidsetsize;
+ /* XXXKE Limit to ngroups_max when we change the userland interface. */
if (gidsetsize > ngroups_max + 1 || gidsetsize < 0)
return (EINVAL);
@@ -1233,17 +1244,29 @@
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
int ngrp, error;
+ gid_t egid;
ngrp = *ngrpp;
/* Sanity check size. */
+ /* XXXKE Limit to ngroups_max when we change the userland interface. */
if (ngrp < 0 || ngrp > ngroups_max + 1)
return (EINVAL);
AUDIT_ARG_GROUPSET(groups, ngrp);
if (ngrp != 0) {
/* We allow and treat 0 specially below. */
- groups_normalize(ngrpp, groups);
- ngrp = *ngrpp;
+
+ /*
+ * To maintain userland compat for now, we use the first group
+ * as our egid and we'll use the rest as our supplemental
+ * groups.
+ */
+ egid = groups[0];
+ ngrp--;
+ groups++;
+
+ groups_normalize(&ngrp, groups);
+ *ngrpp = ngrp;
}
newcred = crget();
if (ngrp != 0)
@@ -1252,10 +1275,14 @@
oldcred = crcopysafe(p, newcred);
#ifdef MAC
- error = ngrp == 0 ?
- /* If 'ngrp' is 0, we'll keep just the current effective GID. */
- mac_cred_check_setgroups(oldcred, 1, oldcred->cr_groups) :
- mac_cred_check_setgroups(oldcred, ngrp, groups);
+ /*
+ * We pass NULL here explicitly if we don't have any supplementary
+ * groups mostly for the sake of normalization, but also to avoid/detect
+ * a situation where a MAC module has some assumption about the layout
+ * of `groups` matching historical behavior.
+ */
+ error = mac_cred_check_setgroups(oldcred, ngrp,
+ ngrp == 0 ? NULL : groups);
if (error)
goto fail;
#endif
@@ -1265,15 +1292,11 @@
goto fail;
if (ngrp == 0) {
- /*
- * setgroups(0, NULL) is a legitimate way of clearing the
- * groups vector on non-BSD systems (which generally do not
- * have the egid in the groups[0]). We risk security holes
- * when running non-BSD software if we do not do the same.
- */
- newcred->cr_ngroups = 1;
- } else
+ newcred->cr_ngroups = 0;
+ } else {
+ newcred->cr_gid = egid;
crsetgroups_internal(newcred, ngrp, groups);
+ }
setsugid(p);
proc_set_cred(p, newcred);
@@ -1693,11 +1716,11 @@
groups_check_positive_len(ngrp);
groups_check_max_len(ngrp);
- if (ngrp == 1)
+ if (ngrp <= 1)
return;
- prev_g = groups[1];
- for (int i = 2; i < ngrp; ++i) {
+ prev_g = groups[0];
+ for (int i = 1; i < ngrp; ++i) {
const gid_t g = groups[i];
if (prev_g >= g)
@@ -1723,7 +1746,7 @@
* Perform a binary search of the supplementary groups. This is
* possible because we sort the groups in crsetgroups().
*/
- return (bsearch(&gid, cred->cr_groups + 1, cred->cr_ngroups - 1,
+ return (bsearch(&gid, cred->cr_groups, cred->cr_ngroups,
sizeof(gid), gidp_cmp) != NULL);
}
@@ -2588,11 +2611,6 @@
crcopy(struct ucred *dest, struct ucred *src)
{
- /*
- * Ideally, 'cr_ngroups' should be moved out of 'struct ucred''s bcopied
- * area, but this would break the ABI, so is deferred until there is
- * a compelling need to change it.
- */
bcopy(&src->cr_startcopy, &dest->cr_startcopy,
(unsigned)((caddr_t)&src->cr_endcopy -
(caddr_t)&src->cr_startcopy));
@@ -2634,11 +2652,17 @@
bzero(xcr, sizeof(*xcr));
xcr->cr_version = XUCRED_VERSION;
xcr->cr_uid = cr->cr_uid;
+ xcr->cr_gid = cr->cr_gid;
- ngroups = MIN(cr->cr_ngroups, XU_NGROUPS);
+ /*
+ * We use a union to alias cr_gid to cr_groups[0] in the xucred, so
+ * this is kind of ugly; cr_ngroups still includes the egid for our
+ * purposes to avoid bumping the xucred version.
+ */
+ ngroups = MIN(cr->cr_ngroups + 1, nitems(xcr->cr_groups));
xcr->cr_ngroups = ngroups;
- bcopy(cr->cr_groups, xcr->cr_groups,
- ngroups * sizeof(*cr->cr_groups));
+ bcopy(cr->cr_groups, xcr->cr_sgroups,
+ (ngroups - 1) * sizeof(*cr->cr_groups));
}
void
@@ -2809,12 +2833,8 @@
/*
* Normalizes a set of groups to be applied to a 'struct ucred'.
*
- * The set of groups is an array that must comprise the effective GID as its
- * first element (so its length cannot be 0).
- *
- * Normalization ensures that elements after the first, which stand for the
- * supplementary groups, are sorted in ascending order and do not contain
- * duplicates.
+ * Normalization ensures that the supplementary groups are sorted in ascending
+ * order and do not contain duplicates.
*/
static void
groups_normalize(int *ngrp, gid_t *groups)
@@ -2825,15 +2845,15 @@
groups_check_positive_len(*ngrp);
groups_check_max_len(*ngrp);
- if (*ngrp == 1)
+ if (*ngrp <= 1)
return;
- qsort(groups + 1, *ngrp - 1, sizeof(*groups), gidp_cmp);
+ qsort(groups, *ngrp, sizeof(*groups), gidp_cmp);
/* Remove duplicates. */
- prev_g = groups[1];
- ins_idx = 2;
- for (int i = 2; i < *ngrp; ++i) {
+ prev_g = groups[0];
+ ins_idx = 1;
+ for (int i = ins_idx; i < *ngrp; ++i) {
const gid_t g = groups[i];
if (g != prev_g) {
@@ -2876,7 +2896,7 @@
* Copy groups in to a credential after expanding it if required.
*
* May sleep in order to allocate memory (except if, e.g., crextend() was called
- * before with 'ngrp' or greater). Truncates the list to (ngroups_max + 1) if
+ * before with 'ngrp' or greater). Truncates the list to ngroups_max if
* it is too large. Array 'groups' doesn't need to be sorted. 'ngrp' must be
* strictly positive.
*/
@@ -2884,8 +2904,8 @@
crsetgroups(struct ucred *cr, int ngrp, const gid_t *groups)
{
- if (ngrp > ngroups_max + 1)
- ngrp = ngroups_max + 1;
+ if (ngrp > ngroups_max)
+ ngrp = ngroups_max;
/*
* crextend() asserts that groups are not set, as it may allocate a new
* backing storage without copying the content of the old one. Since we
@@ -2893,6 +2913,9 @@
* consider the old ones thrown away.
*/
cr->cr_ngroups = 0;
+ if (ngrp == 0)
+ return;
+
crextend(cr, ngrp);
crsetgroups_internal(cr, ngrp, groups);
groups_normalize(&cr->cr_ngroups, cr->cr_groups);
@@ -2902,18 +2925,22 @@
* Same as crsetgroups() but accepts an empty groups array.
*
* This function ensures that an effective GID is always present in credentials.
- * An empty array is treated as a one-size one holding the passed effective GID
- * fallback.
+ * An empty array will only set the effective GID to the fallback, while a
+ * non-empty array will peel off groups[0] to set as the effective GID and use
+ * the remainder, if any, as supplementary groups.
*/
void
crsetgroups_fallback(struct ucred *cr, int ngrp, const gid_t *groups,
const gid_t fallback)
{
- if (ngrp == 0)
- /* Shortcut. */
- crsetgroups_internal(cr, 1, &fallback);
- else
- crsetgroups(cr, ngrp, groups);
+ if (ngrp == 0) {
+ cr->cr_gid = fallback;
+ cr->cr_ngroups = 0;
+ return;
+ }
+
+ crsetgroups(cr, ngrp - 1, groups + 1);
+ cr->cr_gid = groups[0];
}
/*
diff --git a/sys/rpc/authunix_prot.c b/sys/rpc/authunix_prot.c
--- a/sys/rpc/authunix_prot.c
+++ b/sys/rpc/authunix_prot.c
@@ -96,8 +96,12 @@
if (!xdr_uint32_t(xdrs, &cred->cr_gid))
return (FALSE);
- /* XXXKE Fix this is cr_gid gets separated out. */
if (xdrs->x_op == XDR_ENCODE) {
+ /*
+ * Note that this is a `struct xucred`, which maintains its
+ * historical layout of preserving the egid in cr_ngroups and
+ * cr_groups[0] == egid.
+ */
ngroups = cred->cr_ngroups - 1;
if (ngroups > NGRPS)
ngroups = NGRPS;
diff --git a/sys/rpc/svc_auth_unix.c b/sys/rpc/svc_auth_unix.c
--- a/sys/rpc/svc_auth_unix.c
+++ b/sys/rpc/svc_auth_unix.c
@@ -89,8 +89,12 @@
stat = AUTH_BADCRED;
goto done;
}
- /* XXXKE Fix this if cr_gid gets separated out. */
for (i = 0; i < gid_len; i++) {
+ /*
+ * Note that this is a `struct xucred`, which maintains
+ * its historical layout of preserving the egid in
+ * cr_ngroups and cr_groups[0] == egid.
+ */
if (i + 1 < XU_NGROUPS)
xcr->cr_groups[i + 1] = IXDR_GET_INT32(buf);
else
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -76,15 +76,12 @@
u_int cr_users; /* (c) proc + thread using this cred */
u_int cr_flags; /* credential flags */
struct auditinfo_addr cr_audit; /* Audit properties. */
+ int cr_ngroups; /* number of supplementary groups */
#define cr_startcopy cr_uid
uid_t cr_uid; /* effective user id */
uid_t cr_ruid; /* real user id */
uid_t cr_svuid; /* saved user id */
- /*
- * XXXOC: On the next ABI change, please move 'cr_ngroups' out of the
- * copied area (crcopy() already copes with this change).
- */
- int cr_ngroups; /* number of groups */
+ gid_t cr_gid; /* effective group id */
gid_t cr_rgid; /* real group id */
gid_t cr_svgid; /* saved group id */
struct uidinfo *cr_uidinfo; /* per euid resource consumption */
@@ -111,8 +108,20 @@
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[XU_NGROUPS]; /* groups */
+ short cr_ngroups; /* number of groups (incl. cr_gid). */
+ union {
+ /*
+ * Special little hack to avoid needing a cr_gid macro, which
+ * would cause problems if one were to use it with struct ucred
+ * which also has a cr_groups member.
+ */
+ struct {
+ gid_t cr_gid; /* effective group id */
+ gid_t cr_sgroups[XU_NGROUPS - 1];
+ };
+
+ gid_t cr_groups[XU_NGROUPS]; /* groups */
+ };
union {
void *_cr_unused1; /* compatibility with old ucred */
pid_t cr_pid;
@@ -120,9 +129,6 @@
};
#define XUCRED_VERSION 0
-/* This can be used for both ucred and xucred structures. */
-#define cr_gid cr_groups[0]
-
struct mac;
/*
* Structure to pass as an argument to the setcred() system call.
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -2037,7 +2037,6 @@
{
#ifdef QUOTA
struct ucred ucred, *ucp;
- gid_t ucred_group;
ucp = cnp->cn_cred;
#endif
/*
@@ -2064,13 +2063,8 @@
*/
ucred.cr_ref = 1;
ucred.cr_uid = ip->i_uid;
-
- /*
- * XXXKE Fix this is cr_gid gets separated out
- */
- ucred.cr_ngroups = 1;
- ucred.cr_groups = &ucred_group;
- ucred.cr_gid = ucred_group = dp->i_gid;
+ ucred.cr_gid = dp->i_gid;
+ ucred.cr_ngroups = 0;
ucp = &ucred;
}
#endif
@@ -2801,7 +2795,6 @@
{
#ifdef QUOTA
struct ucred ucred, *ucp;
- gid_t ucred_group;
ucp = cnp->cn_cred;
#endif
/*
@@ -2827,13 +2820,8 @@
*/
ucred.cr_ref = 1;
ucred.cr_uid = ip->i_uid;
-
- /*
- * XXXKE Fix this is cr_gid gets separated out
- */
- ucred.cr_ngroups = 1;
- ucred.cr_groups = &ucred_group;
- ucred.cr_gid = ucred_group = pdir->i_gid;
+ ucred.cr_gid = pdir->i_gid;
+ ucred.cr_ngroups = 0;
ucp = &ucred;
#endif
} else {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Feb 18, 12:07 PM (3 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28846268
Default Alt Text
D51489.id159386.diff (21 KB)
Attached To
Mode
D51489: kern: start tracking cr_gid outside of cr_groups[]
Attached
Detach File
Event Timeline
Log In to Comment