svn commit: r194556 - head/sys/kern
Brooks Davis
brooks at FreeBSD.org
Sat Jun 20 20:29:22 UTC 2009
Author: brooks
Date: Sat Jun 20 20:29:21 2009
New Revision: 194556
URL: http://svn.freebsd.org/changeset/base/194556
Log:
Change crsetgroups_locked() (called by crsetgroups()) to sort the
supplemental groups using insertion sort. Use this property in
groupmember() to let us use a binary search instead of the previous
linear search.
Modified:
head/sys/kern/kern_prot.c
Modified: head/sys/kern/kern_prot.c
==============================================================================
--- head/sys/kern/kern_prot.c Sat Jun 20 20:22:11 2009 (r194555)
+++ head/sys/kern/kern_prot.c Sat Jun 20 20:29:21 2009 (r194556)
@@ -86,7 +86,6 @@ static void crextend(struct ucred *cr, i
static void crsetgroups_locked(struct ucred *cr, int ngrp,
gid_t *groups);
-
#ifndef _SYS_SYSPROTO_H_
struct getpid_args {
int dummy;
@@ -1248,13 +1247,30 @@ __setugid(struct thread *td, struct __se
int
groupmember(gid_t gid, struct ucred *cred)
{
- register gid_t *gp;
- gid_t *egp;
+ int l;
+ int h;
+ int m;
+
+ if (cred->cr_groups[0] == gid)
+ return(1);
+
+ /*
+ * If gid was not our primary group, perform a binary search
+ * of the supplemental groups. This is possible because we
+ * sort the groups in crsetgroups().
+ */
+ l = 1;
+ h = cred->cr_ngroups;
+ while (l < h) {
+ m = l + ((h - l) / 2);
+ if (cred->cr_groups[m] < gid)
+ l = m + 1;
+ else
+ h = m;
+ }
+ if ((l < cred->cr_ngroups) && (cred->cr_groups[l] == gid))
+ return (1);
- egp = &(cred->cr_groups[cred->cr_ngroups]);
- for (gp = cred->cr_groups; gp < egp; gp++)
- if (*gp == gid)
- return (1);
return (0);
}
@@ -1986,18 +2002,37 @@ crextend(struct ucred *cr, int n)
}
/*
- * 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
+ * Copy groups in to a credential, preserving any necessary invariants.
+ * Currently this includes the sorting of all supplemental gids.
+ * crextend() must have been called before hand to ensure sufficient
+ * space is available.
*/
static void
crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups)
{
+ int i;
+ int j;
+ gid_t g;
KASSERT(cr->cr_agroups >= ngrp, ("cr_ngroups is too small"));
bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t));
cr->cr_ngroups = ngrp;
+
+ /*
+ * Sort all groups except cr_groups[0] to allow groupmember to
+ * perform a binary search.
+ *
+ * XXX: If large numbers of groups become common this should
+ * be replaced with shell sort like linux uses or possibly
+ * heap sort.
+ */
+ for (i = 2; i < ngrp; i++) {
+ g = cr->cr_groups[i];
+ for (j = i-1; j >= 1 && g < cr->cr_groups[j]; j--)
+ cr->cr_groups[j + 1] = cr->cr_groups[j];
+ cr->cr_groups[j + 1] = g;
+ }
}
/*
More information about the svn-src-head
mailing list