Skip to contentSkip to conversation

RFC: Patch for >32 groups

PATCH Tim Hockin 1 participant 1 message Oct 4, 2002

Subsystems (5)
lore
Share & tools
lore

Tim Hockin

author
#0 lore raw

All,

Here is a set of patches (against a recent-ish 2.5 BK) that removes the arbitrary limit of 32 groups.

The first patch creates generic qsort() and bsearch() routines (I have another patch to conver XFS to use it, as discussed with Christoph a while back).

The second patch converts task->groups[] into a dynamic, refcounted, CoW array. It does the needed bits for i386 (minor) but not the other architectures. I have (not included here for brevity) patches that convert other arch trees to do the right thing (I think) and convert other usages of NGROUPS and task->groups and task->ngroups. There are still a few issues I am working out with those.

I wanted to post this (and CC: people who have mailed me about it) and see if there are any complaints about the approach. The patches are simple, and have been in use in our own 2.4.x systems or some time. I did make some changes in forward porting, but they are tested on at least one 2.5.x box here :)

This has the side effect of reducing the size of struct task_struct by a bit, too. :)

This should run on any glibc, without mods. Glibc will need to return a different value instead of NGROUPS (32), to be fully correct, though. I suggest INT_MAX :)

We've found a couple apps that needed to be fixed up in the event of >32 groups being used, and when this goes mainline, we'll pop out those patches, too. Another issue: this changes /proc/pid/status to only show 32 groups - not sure what better solution is preferred.

Comments, read-overs, and flames requested. Ideally I'd like to see this go into 2.5.x real soon now. :)

Tim

Signature · 4 lines
Tim Hockin
Systems Software Engineer
Sun Microsystems, Linux Kernel Engineering
[email protected]
include/linux/kernel.h +5 -0
diff -ruN virgin-2.5/include/linux/kernel.h linux-2.5/include/linux/kernel.h
@@ -206,4 +206,9 @@
 #define __FUNCTION__ (__func__)
 #endif
 
+void qsort(void *base, size_t nmemb, size_t size,
+	int (*compar)(const void *, const void *));
+void *bsearch(const void *key, const void *base, size_t nmemb, size_t size,
+	int (*compar)(const void *, const void *));
+
 #endif
lib/Makefile +3 -2
diff -ruN virgin-2.5/lib/Makefile linux-2.5/lib/Makefile
@@ -9,10 +9,11 @@
 L_TARGET := lib.a
 
 export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o \
-	       crc32.o rbtree.o radix-tree.o
+	       crc32.o rbtree.o radix-tree.o qsort.o bsearch.o
 
 obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \
-	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o
+	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
+	 qsort.o bsearch.o
 
 obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
lib/bsearch.c +49 -0

49 lines not on this page · raw message

lib/qsort.c +180 -0

180 lines not on this page · raw message

fs/proc/array.c +1 -1
diff -ruN virgin-2.5/fs/proc/array.c linux-2.5/fs/proc/array.c
@@ -171,7 +171,7 @@
 		p->files ? p->files->max_fds : 0);
 	task_unlock(p);
 
-	for (g = 0; g < p->ngroups; g++)
+	for (g = 0; g < min(p->ngroups, OLD_NGROUPS); g++)
 		buffer += sprintf(buffer, "%d ", p->groups[g]);
 
 	buffer += sprintf(buffer, "\n");
include/asm-i386/param.h +0 -4
diff -ruN virgin-2.5/include/asm-i386/param.h linux-2.5/include/asm-i386/param.h
@@ -13,10 +13,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
include/linux/init_task.h +1 -0
diff -ruN virgin-2.5/include/linux/init_task.h linux-2.5/include/linux/init_task.h
@@ -80,6 +80,7 @@
 	.real_timer	= {						\
 		.function	= it_real_fn				\
 	},								\
+	.ngroups	= 0,						\
 	.cap_effective	= CAP_INIT_EFF_SET,				\
 	.cap_inheritable = CAP_INIT_INH_SET,				\
 	.cap_permitted	= CAP_FULL_SET,					\
include/linux/limits.h +2 -1
diff -ruN virgin-2.5/include/linux/limits.h linux-2.5/include/linux/limits.h
@@ -3,7 +3,6 @@
 
 #define NR_OPEN	        1024
 
-#define NGROUPS_MAX       32	/* supplemental group IDs are available */
 #define ARG_MAX       131072	/* # bytes of args + environ for exec() */
 #define CHILD_MAX        999    /* no limit :-) */
 #define OPEN_MAX         256	/* # open files a process may have */
@@ -19,4 +18,6 @@
 
 #define RTSIG_MAX	  32
 
+#define OLD_NGROUPS       32	/* old limit of supplemental group IDs */
+
 #endif
include/linux/sched.h +2 -1
diff -ruN virgin-2.5/include/linux/sched.h linux-2.5/include/linux/sched.h
@@ -351,7 +351,8 @@
 	uid_t uid,euid,suid,fsuid;
 	gid_t gid,egid,sgid,fsgid;
 	int ngroups;
-	gid_t	groups[NGROUPS];
+	gid_t *groups;
+	atomic_t *groups_refcount;
 	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
 	int keep_capabilities:1;
 	struct user_struct *user;
kernel/exit.c +7 -0
diff -ruN virgin-2.5/kernel/exit.c linux-2.5/kernel/exit.c
@@ -7,6 +7,7 @@
 #include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
 #include <linux/module.h>
@@ -64,6 +65,12 @@
 		BUG();
 	if (p != current)
 		wait_task_inactive(p);
+
+	if (p->ngroups && atomic_dec_and_test(p->groups_refcount)) {
+		vfree(p->groups_refcount);
+		vfree(p->groups);
+	}
+
 	atomic_dec(&p->user->processes);
 	security_ops->task_free_security(p);
 	free_uid(p->user);
kernel/fork.c +4 -0
diff -ruN virgin-2.5/kernel/fork.c linux-2.5/kernel/fork.c
@@ -805,6 +805,10 @@
 	 */
 	clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
 
+	/* increment the groups ref count */
+	if (p->ngroups)
+		atomic_inc(p->groups_refcount);
+
 	/* Our parent execution domain becomes current domain
 	   These must match for thread signalling to apply */
 	   
kernel/sys.c +69 -20

120 lines not on this page · raw message

kernel/uid16.c +48 -15

103 lines not on this page · raw message