public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] sysctl-controlled number of groups.
@ 2003-09-25  3:21 Rusty Russell
  2003-09-25  4:14 ` Tim Hockin
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Rusty Russell @ 2003-09-25  3:21 UTC (permalink / raw)
  To: akpm, neilb, braam, davem, Martin Schwidefsky,
	David Mosberger-Tang
  Cc: tridge, linux-kernel

We have a client (using SAMBA) who has people in 190 groups.  Since NT
has hierarchical groups, this is not all that rare.

What do people think of this patch?

Name: Dynamic Allocation of Groups Array When Required: With Refcounting
Author: Rusty Russell
Status: Tested on 2.6.0-test5-bk5
Depends: Misc/qemu-page-offset.patch.gz

D: This patch allows the maximum number of groups can be varied using
D: sysctl.  To do this, we use a separate group allocation if >
D: NGROUPS_INTERNAL, which we reference count (sharing being
D: v. v. common).
D: 
D: Changes:
D: 1) Remove the NGROUPS define from archs.
D: 2) Fixup the few places which declare [NGROUPS] arrays on the stack.
D: 3) The ia64, s390 and sparc64 ports have their own setgroups/getgroups
D:    implementations: unify them on the ia64 one, which calls the core
D:    functions.
D: 4) Change the task_struct to have an [NGROUPS_INTERNAL] array and
D:    a pointer (not convinced this is worth it at all, might skip it
D:    and always use external).
D: 5) Use a reference counted external array, fix up fork() to deal.
D: 6) Introduce max_groups and use it instead of NGROUPS.
D: 7) Add a sysctl to vary max_groups.
D: 
D: This patch scars nfs: artificially restrict the groups there to 
D: SVC_CRED_NGROUPS (32), which is probably wrong, but won't break if
D: they don't change the default.
D: 
D: This patch breaks intermezzo: I'm not sure how they want to deal
D: with it.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/arch/ia64/ia32/sys_ia32.c .13015-linux-2.6.0-test5-bk11.updated/arch/ia64/ia32/sys_ia32.c
--- .13015-linux-2.6.0-test5-bk11/arch/ia64/ia32/sys_ia32.c	2003-09-25 09:56:18.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/arch/ia64/ia32/sys_ia32.c	2003-09-25 13:08:28.000000000 +1000
@@ -2432,17 +2432,24 @@ asmlinkage long
 sys32_getgroups16 (int gidsetsize, short *grouplist)
 {
 	mm_segment_t old_fs = get_fs();
-	gid_t gl[NGROUPS];
+	gid_t *gl;
 	int ret, i;
 
+	gl = kmalloc(sizeof(gl[0]) * current->ngroups, GFP_KERNEL);
+	if (!gl)
+		return -ENOMEM;
+
 	set_fs(KERNEL_DS);
 	ret = sys_getgroups(gidsetsize, gl);
 	set_fs(old_fs);
 
-	if (gidsetsize && ret > 0 && ret <= NGROUPS)
+	if (gidsetsize && ret > 0)
 		for (i = 0; i < ret; i++, grouplist++)
-			if (put_user(gl[i], grouplist))
-				return -EFAULT;
+			if (put_user(gl[i], grouplist)) {
+				ret = -EFAULT;
+				break;
+			}
+	kfree(gl);
 	return ret;
 }
 
@@ -2452,17 +2459,23 @@ asmlinkage long
 sys32_setgroups16 (int gidsetsize, short *grouplist)
 {
 	mm_segment_t old_fs = get_fs();
-	gid_t gl[NGROUPS];
+	gid_t *gl;
 	int ret, i;
 
-	if ((unsigned) gidsetsize > NGROUPS)
+	if ((unsigned) gidsetsize > max_groups)
 		return -EINVAL;
+	gl = kmalloc(sizeof(gl[0]) * gidsetsize, GFP_KERNEL);
+	if (!gl)
+		return -ENOMEM;
 	for (i = 0; i < gidsetsize; i++, grouplist++)
-		if (get_user(gl[i], grouplist))
+		if (get_user(gl[i], grouplist)) {
+			kfree(gl);
 			return -EFAULT;
+		}
 	set_fs(KERNEL_DS);
 	ret = sys_setgroups(gidsetsize, gl);
 	set_fs(old_fs);
+	kfree(gl);
 	return ret;
 }
 
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/arch/mips/kernel/sysirix.c .13015-linux-2.6.0-test5-bk11.updated/arch/mips/kernel/sysirix.c
--- .13015-linux-2.6.0-test5-bk11/arch/mips/kernel/sysirix.c	2003-09-25 09:56:19.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/arch/mips/kernel/sysirix.c	2003-09-25 12:58:43.000000000 +1000
@@ -368,7 +368,7 @@ asmlinkage int irix_syssgi(struct pt_reg
 			retval = HZ;
 			goto out;
 		case 4:
-			retval = NGROUPS;
+			retval = max_groups;
 			goto out;
 		case 5:
 			retval = NR_OPEN;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/arch/s390/kernel/compat_linux.c .13015-linux-2.6.0-test5-bk11.updated/arch/s390/kernel/compat_linux.c
--- .13015-linux-2.6.0-test5-bk11/arch/s390/kernel/compat_linux.c	2003-09-25 09:56:22.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/arch/s390/kernel/compat_linux.c	2003-09-25 13:08:21.000000000 +1000
@@ -189,40 +189,57 @@ asmlinkage long sys32_setfsgid16(u16 gid
 	return sys_setfsgid((gid_t)gid);
 }
 
-asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
+extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist);
+
+asmlinkage long
+sys32_getgroups16 (int gidsetsize, short *grouplist)
 {
-	u16 groups[NGROUPS];
-	int i,j;
+	mm_segment_t old_fs = get_fs();
+	gid_t *gl;
+	int ret, i;
 
-	if (gidsetsize < 0)
-		return -EINVAL;
-	i = current->ngroups;
-	if (gidsetsize) {
-		if (i > gidsetsize)
-			return -EINVAL;
-		for(j=0;j<i;j++)
-			groups[j] = current->groups[j];
-		if (copy_to_user(grouplist, groups, sizeof(u16)*i))
-			return -EFAULT;
-	}
-	return i;
+	gl = kmalloc(sizeof(gl[0]) * current->ngroups, GFP_KERNEL);
+	if (!gl)
+		return -ENOMEM;
+
+	set_fs(KERNEL_DS);
+	ret = sys_getgroups(gidsetsize, gl);
+	set_fs(old_fs);
+
+	if (gidsetsize && ret > 0)
+		for (i = 0; i < ret; i++, grouplist++)
+			if (put_user(gl[i], grouplist)) {
+				ret = -EFAULT;
+				break;
+			}
+	kfree(gl);
+	return ret;
 }
 
-asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
+extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist);
+
+asmlinkage long
+sys32_setgroups16 (int gidsetsize, short *grouplist)
 {
-	u16 groups[NGROUPS];
-	int i;
+	mm_segment_t old_fs = get_fs();
+	gid_t *gl;
+	int ret, i;
 
-	if (!capable(CAP_SETGID))
-		return -EPERM;
-	if ((unsigned) gidsetsize > NGROUPS)
+	if ((unsigned) gidsetsize > max_groups)
 		return -EINVAL;
-	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
-		return -EFAULT;
-	for (i = 0 ; i < gidsetsize ; i++)
-		current->groups[i] = (gid_t)groups[i];
-	current->ngroups = gidsetsize;
-	return 0;
+	gl = kmalloc(sizeof(gl[0]) * gidsetsize, GFP_KERNEL);
+	if (!gl)
+		return -ENOMEM;
+	for (i = 0; i < gidsetsize; i++, grouplist++)
+		if (get_user(gl[i], grouplist)) {
+			kfree(gl);
+			return -EFAULT;
+		}
+	set_fs(KERNEL_DS);
+	ret = sys_setgroups(gidsetsize, gl);
+	set_fs(old_fs);
+	kfree(gl);
+	return ret;
 }
 
 asmlinkage long sys32_getuid16(void)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/arch/sparc/kernel/sys_sunos.c .13015-linux-2.6.0-test5-bk11.updated/arch/sparc/kernel/sys_sunos.c
--- .13015-linux-2.6.0-test5-bk11/arch/sparc/kernel/sys_sunos.c	2003-09-22 10:27:56.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/arch/sparc/kernel/sys_sunos.c	2003-09-25 12:58:43.000000000 +1000
@@ -896,7 +896,7 @@ extern asmlinkage long sunos_sysconf (in
 		ret = HZ;
 		break;
 	case _SC_NGROUPS_MAX:
-		ret = NGROUPS_MAX;
+		ret = max_groups;
 		break;
 	case _SC_OPEN_MAX:
 		ret = OPEN_MAX;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/arch/sparc64/kernel/sys_sparc32.c .13015-linux-2.6.0-test5-bk11.updated/arch/sparc64/kernel/sys_sparc32.c
--- .13015-linux-2.6.0-test5-bk11/arch/sparc64/kernel/sys_sparc32.c	2003-09-25 09:56:22.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/arch/sparc64/kernel/sys_sparc32.c	2003-09-25 13:08:15.000000000 +1000
@@ -206,40 +206,57 @@ asmlinkage long sys32_setfsgid16(u16 gid
 	return sys_setfsgid((gid_t)gid);
 }
 
-asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
+extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist);
+
+asmlinkage long
+sys32_getgroups16 (int gidsetsize, short *grouplist)
 {
-	u16 groups[NGROUPS];
-	int i,j;
+	mm_segment_t old_fs = get_fs();
+	gid_t *gl;
+	int ret, i;
 
-	if (gidsetsize < 0)
-		return -EINVAL;
-	i = current->ngroups;
-	if (gidsetsize) {
-		if (i > gidsetsize)
-			return -EINVAL;
-		for(j=0;j<i;j++)
-			groups[j] = current->groups[j];
-		if (copy_to_user(grouplist, groups, sizeof(u16)*i))
-			return -EFAULT;
-	}
-	return i;
+	gl = kmalloc(sizeof(gl[0]) * current->ngroups, GFP_KERNEL);
+	if (!gl)
+		return -ENOMEM;
+
+	set_fs(KERNEL_DS);
+	ret = sys_getgroups(gidsetsize, gl);
+	set_fs(old_fs);
+
+	if (gidsetsize && ret > 0)
+		for (i = 0; i < ret; i++, grouplist++)
+			if (put_user(gl[i], grouplist)) {
+				ret = -EFAULT;
+				break;
+			}
+	kfree(gl);
+	return ret;
 }
 
-asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
+extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist);
+
+asmlinkage long
+sys32_setgroups16 (int gidsetsize, short *grouplist)
 {
-	u16 groups[NGROUPS];
-	int i;
+	mm_segment_t old_fs = get_fs();
+	gid_t *gl;
+	int ret, i;
 
-	if (!capable(CAP_SETGID))
-		return -EPERM;
-	if ((unsigned) gidsetsize > NGROUPS)
+	if ((unsigned) gidsetsize > max_groups)
 		return -EINVAL;
-	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
-		return -EFAULT;
-	for (i = 0 ; i < gidsetsize ; i++)
-		current->groups[i] = (gid_t)groups[i];
-	current->ngroups = gidsetsize;
-	return 0;
+	gl = kmalloc(sizeof(gl[0]) * gidsetsize, GFP_KERNEL);
+	if (!gl)
+		return -ENOMEM;
+	for (i = 0; i < gidsetsize; i++, grouplist++)
+		if (get_user(gl[i], grouplist)) {
+			kfree(gl);
+			return -EFAULT;
+		}
+	set_fs(KERNEL_DS);
+	ret = sys_setgroups(gidsetsize, gl);
+	set_fs(old_fs);
+	kfree(gl);
+	return ret;
 }
 
 asmlinkage long sys32_getuid16(void)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/arch/sparc64/kernel/sys_sunos32.c .13015-linux-2.6.0-test5-bk11.updated/arch/sparc64/kernel/sys_sunos32.c
--- .13015-linux-2.6.0-test5-bk11/arch/sparc64/kernel/sys_sunos32.c	2003-09-22 10:27:56.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/arch/sparc64/kernel/sys_sunos32.c	2003-09-25 12:58:43.000000000 +1000
@@ -859,7 +859,7 @@ extern asmlinkage s32 sunos_sysconf (int
 		ret = HZ;
 		break;
 	case _SC_NGROUPS_MAX:
-		ret = NGROUPS_MAX;
+		ret = max_groups;
 		break;
 	case _SC_OPEN_MAX:
 		ret = OPEN_MAX;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/fs/nfsd/auth.c .13015-linux-2.6.0-test5-bk11.updated/fs/nfsd/auth.c
--- .13015-linux-2.6.0-test5-bk11/fs/nfsd/auth.c	2003-09-22 10:21:34.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/fs/nfsd/auth.c	2003-09-25 12:58:43.000000000 +1000
@@ -26,7 +26,7 @@ nfsd_setuser(struct svc_rqst *rqstp, str
 			cred->cr_uid = exp->ex_anon_uid;
 		if (!cred->cr_gid)
 			cred->cr_gid = exp->ex_anon_gid;
-		for (i = 0; i < NGROUPS; i++)
+		for (i = 0; i < SVC_CRED_NGROUPS; i++)
 			if (!cred->cr_groups[i])
 				cred->cr_groups[i] = exp->ex_anon_gid;
 	}
@@ -39,7 +39,9 @@ nfsd_setuser(struct svc_rqst *rqstp, str
 		current->fsgid = cred->cr_gid;
 	else
 		current->fsgid = exp->ex_anon_gid;
-	for (i = 0; i < NGROUPS; i++) {
+
+	/* We can do this because cow_current_groups() was done at birth. */
+	for (i = 0; i < SVC_CRED_NGROUPS; i++) {
 		gid_t group = cred->cr_groups[i];
 		if (group == (gid_t) NOGROUP)
 			break;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/fs/nfsd/nfs4state.c .13015-linux-2.6.0-test5-bk11.updated/fs/nfsd/nfs4state.c
--- .13015-linux-2.6.0-test5-bk11/fs/nfsd/nfs4state.c	2003-09-25 09:56:32.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/fs/nfsd/nfs4state.c	2003-09-25 12:58:43.000000000 +1000
@@ -244,7 +244,7 @@ copy_cred(struct svc_cred *target, struc
 
 	target->cr_uid = source->cr_uid;
 	target->cr_gid = source->cr_gid;
-	for(i = 0; i < NGROUPS; i++)
+	for(i = 0; i < SVC_CREDS_NGROUPS; i++)
 		target->cr_groups[i] = source->cr_groups[i];
 }
 
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/fs/nfsd/nfssvc.c .13015-linux-2.6.0-test5-bk11.updated/fs/nfsd/nfssvc.c
--- .13015-linux-2.6.0-test5-bk11/fs/nfsd/nfssvc.c	2003-09-22 10:26:12.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/fs/nfsd/nfssvc.c	2003-09-25 12:58:43.000000000 +1000
@@ -182,6 +182,11 @@ nfsd(struct svc_rqst *rqstp)
 	daemonize("nfsd");
 	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
 
+	if (cow_current_groups(SVC_CRED_NGROUPS) < 0) {
+		printk("Unable to start nfsd thread: can't set groups\n");
+		goto out;
+	}
+
 	/* After daemonize() this kernel thread shares current->fs
 	 * with the init process. We need to create files with a
 	 * umask of 0 instead of init's umask. */
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-alpha/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-alpha/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-alpha/param.h	2003-09-21 17:27:17.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-alpha/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -19,10 +19,6 @@
 
 #define EXEC_PAGESIZE	8192
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-arm/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-arm/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-arm/param.h	2003-09-22 10:28:10.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-arm/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -26,10 +26,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS         32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP         (-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-arm26/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-arm26/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-arm26/param.h	2003-09-22 10:09:07.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-arm26/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -22,10 +22,6 @@
 # define HZ		100
 #endif
 
-#ifndef NGROUPS
-#define NGROUPS         32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP         (-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-cris/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-cris/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-cris/param.h	2003-09-22 10:23:13.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-cris/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -14,10 +14,6 @@
 
 #define EXEC_PAGESIZE	8192
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-h8300/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-h8300/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-h8300/param.h	2003-09-22 10:07:04.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-h8300/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -14,10 +14,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-i386/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-i386/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-i386/param.h	2003-09-25 12:58:41.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-i386/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -18,10 +18,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-ia64/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-ia64/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-ia64/param.h	2003-09-25 09:56:35.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-ia64/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -10,10 +10,6 @@
 
 #define EXEC_PAGESIZE	65536
 
-#ifndef NGROUPS
-# define NGROUPS	32
-#endif
-
 #ifndef NOGROUP
 # define NOGROUP	(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-m68k/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-m68k/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-m68k/param.h	2003-09-21 17:26:43.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-m68k/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -13,10 +13,6 @@
 
 #define EXEC_PAGESIZE	8192
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-m68knommu/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-m68knommu/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-m68knommu/param.h	2003-09-21 17:31:31.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-m68knommu/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -44,10 +44,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-mips/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-mips/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-mips/param.h	2003-09-22 10:22:44.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-mips/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -33,10 +33,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-parisc/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-parisc/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-parisc/param.h	2003-09-21 17:31:10.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-parisc/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -17,10 +17,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-ppc/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-ppc/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-ppc/param.h	2003-09-22 09:47:27.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-ppc/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -13,10 +13,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-ppc64/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-ppc64/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-ppc64/param.h	2003-09-21 17:26:44.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-ppc64/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -20,10 +20,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-s390/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-s390/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-s390/param.h	2003-09-21 17:29:29.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-s390/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -21,10 +21,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-sh/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-sh/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-sh/param.h	2003-09-22 10:23:00.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-sh/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -17,10 +17,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-sparc/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-sparc/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-sparc/param.h	2003-09-21 17:26:18.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-sparc/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -14,10 +14,6 @@
 
 #define EXEC_PAGESIZE	8192    /* Thanks for sun4's we carry baggage... */
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-sparc64/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-sparc64/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-sparc64/param.h	2003-09-21 17:26:18.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-sparc64/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -14,10 +14,6 @@
 
 #define EXEC_PAGESIZE	8192    /* Thanks for sun4's we carry baggage... */
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-um/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-um/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-um/param.h	2003-09-21 17:28:16.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-um/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -3,10 +3,6 @@
 
 #define EXEC_PAGESIZE   4096
 
-#ifndef NGROUPS
-#define NGROUPS         32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP         (-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-v850/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-v850/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-v850/param.h	2003-09-21 17:31:32.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-v850/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -18,10 +18,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/asm-x86_64/param.h .13015-linux-2.6.0-test5-bk11.updated/include/asm-x86_64/param.h
--- .13015-linux-2.6.0-test5-bk11/include/asm-x86_64/param.h	2003-09-21 17:30:30.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/asm-x86_64/param.h	2003-09-25 12:58:43.000000000 +1000
@@ -13,10 +13,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/linux/init_task.h .13015-linux-2.6.0-test5-bk11.updated/include/linux/init_task.h
--- .13015-linux-2.6.0-test5-bk11/include/linux/init_task.h	2003-09-22 10:27:37.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/linux/init_task.h	2003-09-25 12:58:43.000000000 +1000
@@ -108,6 +108,7 @@
 	.proc_lock	= SPIN_LOCK_UNLOCKED,				\
 	.switch_lock	= SPIN_LOCK_UNLOCKED,				\
 	.journal_info	= NULL,						\
+	.groups		= &(tsk).internal_groups,			\
 }
 
 
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/linux/sched.h .13015-linux-2.6.0-test5-bk11.updated/include/linux/sched.h
--- .13015-linux-2.6.0-test5-bk11/include/linux/sched.h	2003-09-25 09:56:38.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/linux/sched.h	2003-09-25 12:58:43.000000000 +1000
@@ -328,6 +328,17 @@ struct k_itimer {
 struct io_context;			/* See blkdev.h */
 void exit_io_context(void);
 
+/* Size is determined by task_struct's ngroups. */
+struct task_groups
+{
+	atomic_t usage;
+	gid_t groups[0];
+};
+
+extern int max_groups;
+
+#define NGROUPS_INTERNAL 1 /* For testing. */
+
 struct task_struct {
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
 	struct thread_info *thread_info;
@@ -403,7 +414,8 @@ struct task_struct {
 	uid_t uid,euid,suid,fsuid;
 	gid_t gid,egid,sgid,fsgid;
 	int ngroups;
-	gid_t	groups[NGROUPS];
+	gid_t *groups; /* == internal_groups, or task_groups->groups */
+	gid_t internal_groups[NGROUPS_INTERNAL];
 	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
 	int keep_capabilities:1;
 	struct user_struct *user;
@@ -602,6 +614,12 @@ extern int send_group_sigqueue(int, stru
 extern int do_sigaction(int, const struct k_sigaction *, struct k_sigaction *);
 extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long);
 
+/* container_of doesn't like arrays. */
+static inline struct task_groups *task_groups(gid_t *groups)
+{
+	return (void *)groups - offsetof(struct task_groups, groups);
+}
+
 /* These can be the second arg to send_sig_info/send_group_sig_info.  */
 #define SEND_SIG_NOINFO ((struct siginfo *) 0)
 #define SEND_SIG_PRIV	((struct siginfo *) 1)
@@ -678,6 +696,10 @@ extern int do_execve(char *, char __user
 extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
 extern struct task_struct * copy_process(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
 
+/* Copy-on-write current groups to this size, if possible.  0 or -err. */
+extern int cow_current_groups(unsigned int ngroups);
+extern void release_groups(gid_t *groups);
+
 #ifdef CONFIG_SMP
 extern void wait_task_inactive(task_t * p);
 #else
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/linux/sunrpc/svcauth.h .13015-linux-2.6.0-test5-bk11.updated/include/linux/sunrpc/svcauth.h
--- .13015-linux-2.6.0-test5-bk11/include/linux/sunrpc/svcauth.h	2003-09-22 09:47:41.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/linux/sunrpc/svcauth.h	2003-09-25 12:58:43.000000000 +1000
@@ -16,10 +16,12 @@
 #include <linux/sunrpc/cache.h>
 #include <linux/hash.h>
 
+#define SVC_CRED_NGROUPS	32
+
 struct svc_cred {
 	uid_t			cr_uid;
 	gid_t			cr_gid;
-	gid_t			cr_groups[NGROUPS];
+	gid_t			cr_groups[SVC_CRED_NGROUPS];
 };
 
 struct svc_rqst;		/* forward decl */
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/include/linux/sysctl.h .13015-linux-2.6.0-test5-bk11.updated/include/linux/sysctl.h
--- .13015-linux-2.6.0-test5-bk11/include/linux/sysctl.h	2003-09-22 10:28:13.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/include/linux/sysctl.h	2003-09-25 12:58:43.000000000 +1000
@@ -127,6 +127,7 @@ enum
 	KERN_PANIC_ON_OOPS=57,  /* int: whether we will panic on an oops */
 	KERN_HPPA_PWRSW=58,	/* int: hppa soft-power enable */
 	KERN_HPPA_UNALIGNED=59,	/* int: hppa unaligned-trap enable */
+	KERN_MAX_GROUPS=60,	/* int: setgroups limit */
 };
 
 
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/kernel/fork.c .13015-linux-2.6.0-test5-bk11.updated/kernel/fork.c
--- .13015-linux-2.6.0-test5-bk11/kernel/fork.c	2003-09-25 09:56:39.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/kernel/fork.c	2003-09-25 12:58:43.000000000 +1000
@@ -73,6 +73,8 @@ static kmem_cache_t *task_struct_cachep;
 
 static void free_task(struct task_struct *tsk)
 {
+	if (unlikely(tsk->groups != tsk->internal_groups))
+		release_groups(tsk->groups);
 	free_thread_info(tsk->thread_info);
 	free_task_struct(tsk);
 }
@@ -213,6 +215,11 @@ static struct task_struct *dup_task_stru
 	tsk->thread_info = ti;
 	ti->task = tsk;
 
+	if (unlikely(orig->groups != orig->internal_groups))
+		atomic_inc(&task_groups(orig->groups)->usage);
+	else
+		tsk->groups = tsk->internal_groups;
+
 	/* One for us, one for whoever does the "release_task()" (usually parent) */
 	atomic_set(&tsk->usage,2);
 	return tsk;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/kernel/sys.c .13015-linux-2.6.0-test5-bk11.updated/kernel/sys.c
--- .13015-linux-2.6.0-test5-bk11/kernel/sys.c	2003-09-25 09:56:39.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/kernel/sys.c	2003-09-25 12:58:43.000000000 +1000
@@ -1066,6 +1066,67 @@ out:
 	return err;
 }
 
+int max_groups = 32;
+
+/* Caller checks that groups != current->internal_groups */
+void release_groups(gid_t *groups)
+{
+	struct task_groups *tgrp = task_groups(groups);
+
+	if (atomic_dec_and_test(&tgrp->usage))
+		kfree(tgrp);
+}
+
+/* This does the actual copy and changeover.  Caller sets
+ * current->ngroups, once copy is successful. */
+static int alloc_new_groups(unsigned int ngroups)
+{
+	struct task_groups *tgrp;
+
+	if (ngroups < current->ngroups)
+		ngroups = current->ngroups;
+
+	tgrp = kmalloc(sizeof(*tgrp) + sizeof(tgrp->groups[0])*ngroups,
+		       GFP_KERNEL);
+	if (!tgrp)
+		return -ENOMEM;
+	atomic_set(&tgrp->usage, 1);
+
+	memcpy(tgrp->groups, current->groups,
+	       sizeof(tgrp->groups[0]) * current->ngroups);
+
+	if (current->groups != current->internal_groups)
+		release_groups(current->groups);
+
+	current->groups = tgrp->groups;
+	return 0;
+}
+
+/* Unshare and maybe enlarge current groups to this size, if possible.
+ * 0 or -err. */
+int cow_current_groups(unsigned int ngroups)
+{
+	if (ngroups > max_groups)
+		return -EINVAL;
+
+	/* Currently external? */
+	if (unlikely(current->ngroups > NGROUPS_INTERNAL)) {
+		/* Shared? */
+		if (atomic_read(&task_groups(current->groups)->usage) > 1)
+			return alloc_new_groups(ngroups);
+		/* Want more? */
+		if (ngroups > current->ngroups)
+			return alloc_new_groups(ngroups);
+		return 0;
+	}
+
+	/* Internal.  Maybe new one will be too big? */
+	if (ngroups > NGROUPS_INTERNAL)
+		return alloc_new_groups(ngroups);
+
+	return 0;
+}
+
 /*
  * Supplementary group IDs
  */
@@ -1097,21 +1158,29 @@ asmlinkage long sys_getgroups(int gidset
  
 asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist)
 {
-	gid_t groups[NGROUPS];
+	gid_t *groups;
 	int retval;
 
 	if (!capable(CAP_SETGID))
 		return -EPERM;
-	if ((unsigned) gidsetsize > NGROUPS)
-		return -EINVAL;
-	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(gid_t)))
-		return -EFAULT;
+	retval = cow_current_groups(gidsetsize);
+	if (retval < 0)
+		return retval;
+	groups = kmalloc(sizeof(groups[0]) * gidsetsize, GFP_KERNEL);
+	if (!groups)
+		return -ENOMEM;
+	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(gid_t))) {
+		retval = -EFAULT;
+		goto out;
+	}
 	retval = security_task_setgroups(gidsetsize, groups);
 	if (retval)
-		return retval;
+		goto out;
 	memcpy(current->groups, groups, gidsetsize * sizeof(gid_t));
 	current->ngroups = gidsetsize;
-	return 0;
+out:
+	kfree(groups);
+	return retval;
 }
 
 static int supplemental_group_member(gid_t grp)
@@ -1431,6 +1500,7 @@ asmlinkage long sys_prctl(int option, un
 	return error;
 }
 
+EXPORT_SYMBOL(cow_current_groups);
 EXPORT_SYMBOL(notifier_chain_register);
 EXPORT_SYMBOL(notifier_chain_unregister);
 EXPORT_SYMBOL(notifier_call_chain);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/kernel/sysctl.c .13015-linux-2.6.0-test5-bk11.updated/kernel/sysctl.c
--- .13015-linux-2.6.0-test5-bk11/kernel/sysctl.c	2003-09-25 09:56:39.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/kernel/sysctl.c	2003-09-25 12:58:43.000000000 +1000
@@ -581,6 +581,14 @@ static ctl_table kern_table[] = {
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
+	{
+		.ctl_name	= KERN_MAX_GROUPS,
+		.procname	= "max_groups",
+		.data		= &max_groups,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 	{ .ctl_name = 0 }
 };
 
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/kernel/uid16.c .13015-linux-2.6.0-test5-bk11.updated/kernel/uid16.c
--- .13015-linux-2.6.0-test5-bk11/kernel/uid16.c	2003-09-22 10:07:19.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/kernel/uid16.c	2003-09-25 12:58:43.000000000 +1000
@@ -109,7 +109,6 @@ asmlinkage long sys_setfsgid16(old_gid_t
 
 asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist)
 {
-	old_gid_t groups[NGROUPS];
 	int i,j;
 
 	if (gidsetsize < 0)
@@ -118,34 +117,48 @@ asmlinkage long sys_getgroups16(int gids
 	if (gidsetsize) {
 		if (i > gidsetsize)
 			return -EINVAL;
-		for(j=0;j<i;j++)
-			groups[j] = current->groups[j];
-		if (copy_to_user(grouplist, groups, sizeof(old_gid_t)*i))
+		if (!access_ok(VERIFY_WRITE, grouplist, sizeof(old_gid_t)*i))
 			return -EFAULT;
+		for(j=0;j<i;j++) {
+			old_gid_t group;
+			group = current->groups[j];
+			if (copy_to_user(grouplist+j, &group, sizeof(group)))
+				return -EFAULT;
+		}
 	}
 	return i;
 }
 
 asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist)
 {
-	old_gid_t groups[NGROUPS];
-	gid_t new_groups[NGROUPS];
-	int i;
+	old_gid_t *groups;
+	gid_t *new_groups;
+	int i, ret;
 
 	if (!capable(CAP_SETGID))
 		return -EPERM;
-	if ((unsigned) gidsetsize > NGROUPS)
-		return -EINVAL;
+
+	if ((ret = cow_current_groups(gidsetsize)) < 0)
+		return ret;
+	ret = -ENOMEM;
+	groups = kmalloc(sizeof(groups[0]) * gidsetsize, GFP_KERNEL);
+	new_groups = kmalloc(sizeof(new_groups[0]) * gidsetsize, GFP_KERNEL);
+	if (!groups || !new_groups)
+		goto out;
+	ret = -EFAULT;
 	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(old_gid_t)))
-		return -EFAULT;
+		goto out;
 	for (i = 0 ; i < gidsetsize ; i++)
 		new_groups[i] = (gid_t)groups[i];
-	i = security_task_setgroups(gidsetsize, new_groups);
-	if (i)
-		return i;
+	ret = security_task_setgroups(gidsetsize, new_groups);
+	if (ret)
+		goto out;
 	memcpy(current->groups, new_groups, gidsetsize * sizeof(gid_t));
 	current->ngroups = gidsetsize;
-	return 0;
+out:
+	kfree(groups);
+	kfree(groups);
+	return ret;
 }
 
 asmlinkage long sys_getuid16(void)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .13015-linux-2.6.0-test5-bk11/net/sunrpc/svcauth_unix.c .13015-linux-2.6.0-test5-bk11.updated/net/sunrpc/svcauth_unix.c
--- .13015-linux-2.6.0-test5-bk11/net/sunrpc/svcauth_unix.c	2003-09-22 10:23:05.000000000 +1000
+++ .13015-linux-2.6.0-test5-bk11.updated/net/sunrpc/svcauth_unix.c	2003-09-25 12:58:43.000000000 +1000
@@ -434,11 +434,11 @@ svcauth_unix_accept(struct svc_rqst *rqs
 	if (slen > 16 || (len -= (slen + 2)*4) < 0)
 		goto badcred;
 	for (i = 0; i < slen; i++)
-		if (i < NGROUPS)
+		if (i < SVC_CRED_NGROUPS)
 			cred->cr_groups[i] = ntohl(svc_getu32(argv));
 		else
 			svc_getu32(argv);
-	if (i < NGROUPS)
+	if (i < SVC_CRED_NGROUPS)
 		cred->cr_groups[i] = NOGROUP;
 
 	if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
--
  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] sysctl-controlled number of groups.
  2003-09-25  3:21 [PATCH] sysctl-controlled number of groups Rusty Russell
@ 2003-09-25  4:14 ` Tim Hockin
  2003-09-25  8:17   ` Rusty Russell
  2003-09-25  4:19 ` David Mosberger
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Tim Hockin @ 2003-09-25  4:14 UTC (permalink / raw)
  To: Rusty Russell
  Cc: akpm, neilb, braam, davem, Martin Schwidefsky,
	David Mosberger-Tang, tridge, linux-kernel

On Thu, Sep 25, 2003 at 01:21:01PM +1000, Rusty Russell wrote:
> We have a client (using SAMBA) who has people in 190 groups.  Since NT
> has hierarchical groups, this is not all that rare.
> 
> What do people think of this patch?


Excuse me but JESUS FUCKING CHRIST.  I've been sending that patch since last
year.  when I get in the office tomorrow, I'll look at this further, and
compare it to mine.  check list archives - my most recent retry was a few
months back, but it was done.  No sysctl - I didn't think it was needed at
all.



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] sysctl-controlled number of groups.
  2003-09-25  3:21 [PATCH] sysctl-controlled number of groups Rusty Russell
  2003-09-25  4:14 ` Tim Hockin
@ 2003-09-25  4:19 ` David Mosberger
  2003-09-25  8:08   ` Rusty Russell
  2003-09-25  7:15 ` Arjan van de Ven
  2003-09-25  7:25 ` William Lee Irwin III
  3 siblings, 1 reply; 8+ messages in thread
From: David Mosberger @ 2003-09-25  4:19 UTC (permalink / raw)
  To: Rusty Russell
  Cc: akpm, neilb, braam, davem, Martin Schwidefsky,
	David Mosberger-Tang, tridge, linux-kernel

>From the ia64-side, it looks mostly fine to me.  Some minor things:

 - Typo in first sentence of patch comment (can be -> to be ?)
 - If I'm reading the patch right, there will be identical sys32_getgroups16()
   definitions in .../ia32/sys_ia32.c and and compat_linux.c; did you mean
   to name the latter compat_getgroups16()?  (ditto for setgroups16 and s390
   and sparc64, i think)
 - I suspect removing NGROUPS from param.h will break glibc and/or user-level
   apps.  param.h is one of those kernel files that are directly exposed
   to user-level; may want to keep NGROUPS inside an #ifndef __KERNEL__.

	--david

>>>>> On Thu, 25 Sep 2003 13:21:01 +1000, Rusty Russell <rusty@rustcorp.com.au> said:

  Rusty> We have a client (using SAMBA) who has people in 190 groups.  Since NT
  Rusty> has hierarchical groups, this is not all that rare.

  Rusty> What do people think of this patch?

  Rusty> Name: Dynamic Allocation of Groups Array When Required: With Refcounting
  Rusty> Author: Rusty Russell
  Rusty> Status: Tested on 2.6.0-test5-bk5
  Rusty> Depends: Misc/qemu-page-offset.patch.gz

  Rusty> D: This patch allows the maximum number of groups can be varied using
  Rusty> D: sysctl.  To do this, we use a separate group allocation if >
  Rusty> D: NGROUPS_INTERNAL, which we reference count (sharing being
  Rusty> D: v. v. common).
  Rusty> D: 
  Rusty> D: Changes:
  Rusty> D: 1) Remove the NGROUPS define from archs.
  Rusty> D: 2) Fixup the few places which declare [NGROUPS] arrays on the stack.
  Rusty> D: 3) The ia64, s390 and sparc64 ports have their own setgroups/getgroups
  Rusty> D:    implementations: unify them on the ia64 one, which calls the core
  Rusty> D:    functions.
  Rusty> D: 4) Change the task_struct to have an [NGROUPS_INTERNAL] array and
  Rusty> D:    a pointer (not convinced this is worth it at all, might skip it
  Rusty> D:    and always use external).
  Rusty> D: 5) Use a reference counted external array, fix up fork() to deal.
  Rusty> D: 6) Introduce max_groups and use it instead of NGROUPS.
  Rusty> D: 7) Add a sysctl to vary max_groups.
  Rusty> D: 
  Rusty> D: This patch scars nfs: artificially restrict the groups there to 
  Rusty> D: SVC_CRED_NGROUPS (32), which is probably wrong, but won't break if
  Rusty> D: they don't change the default.
  Rusty> D: 
  Rusty> D: This patch breaks intermezzo: I'm not sure how they want to deal
  Rusty> D: with it.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] sysctl-controlled number of groups.
  2003-09-25  3:21 [PATCH] sysctl-controlled number of groups Rusty Russell
  2003-09-25  4:14 ` Tim Hockin
  2003-09-25  4:19 ` David Mosberger
@ 2003-09-25  7:15 ` Arjan van de Ven
  2003-09-25  7:25 ` William Lee Irwin III
  3 siblings, 0 replies; 8+ messages in thread
From: Arjan van de Ven @ 2003-09-25  7:15 UTC (permalink / raw)
  To: Rusty Russell; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 281 bytes --]

On Thu, 2003-09-25 at 05:21, Rusty Russell wrote:
> We have a client (using SAMBA) who has people in 190 groups.  Since NT
> has hierarchical groups, this is not all that rare.
> 
> What do people think of this patch?

.... FEATURECREEPER .....

(sorry couldn't resist ;)

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] sysctl-controlled number of groups.
  2003-09-25  3:21 [PATCH] sysctl-controlled number of groups Rusty Russell
                   ` (2 preceding siblings ...)
  2003-09-25  7:15 ` Arjan van de Ven
@ 2003-09-25  7:25 ` William Lee Irwin III
  2003-09-25  8:23   ` Rusty Russell
  3 siblings, 1 reply; 8+ messages in thread
From: William Lee Irwin III @ 2003-09-25  7:25 UTC (permalink / raw)
  To: Rusty Russell
  Cc: akpm, neilb, braam, davem, Martin Schwidefsky,
	David Mosberger-Tang, tridge, linux-kernel

On Thu, Sep 25, 2003 at 01:21:01PM +1000, Rusty Russell wrote:
> We have a client (using SAMBA) who has people in 190 groups.  Since NT
> has hierarchical groups, this is not all that rare.
> What do people think of this patch?

I like the idea of raising the microscopic limit. BTW, was the Author:
supposed to be Tim Hockin? ISTR his writing this or something almost
identical to it. Also, I'm not sure if the sysctl is worth anything.


-- wli

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] sysctl-controlled number of groups.
  2003-09-25  4:19 ` David Mosberger
@ 2003-09-25  8:08   ` Rusty Russell
  0 siblings, 0 replies; 8+ messages in thread
From: Rusty Russell @ 2003-09-25  8:08 UTC (permalink / raw)
  To: davidm; +Cc: akpm, neilb, braam, davem, Martin Schwidefsky, tridge,
	linux-kernel

In message <16242.27867.715648.392875@napali.hpl.hp.com> you write:
> >From the ia64-side, it looks mostly fine to me.  Some minor things:
> 
>  - Typo in first sentence of patch comment (can be -> to be ?)

Thanks, fixed.

>  - If I'm reading the patch right, there will be identical sys32_getgroups16()
>    definitions in .../ia32/sys_ia32.c and and compat_linux.c; did you mean
>    to name the latter compat_getgroups16()?  (ditto for setgroups16 and s390
>    and sparc64, i think)

You're not reading it right: I didn't change the names, but since
these (your) versions call the normal ones, I added the extern decl.

>  - I suspect removing NGROUPS from param.h will break glibc and/or user-level
>    apps.  param.h is one of those kernel files that are directly exposed
>    to user-level; may want to keep NGROUPS inside an #ifndef __KERNEL__.

AFAICT, they should use NGROUPS_MAX from limits.h, which I left.

Thanks,
Rusty.
--
  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] sysctl-controlled number of groups.
  2003-09-25  4:14 ` Tim Hockin
@ 2003-09-25  8:17   ` Rusty Russell
  0 siblings, 0 replies; 8+ messages in thread
From: Rusty Russell @ 2003-09-25  8:17 UTC (permalink / raw)
  To: Tim Hockin
  Cc: akpm, neilb, braam, davem, Martin Schwidefsky,
	David Mosberger-Tang, tridge, linux-kernel

In message <20030924211417.A16753@hockin.org> you write:
> On Thu, Sep 25, 2003 at 01:21:01PM +1000, Rusty Russell wrote:
> > We have a client (using SAMBA) who has people in 190 groups.  Since NT
> > has hierarchical groups, this is not all that rare.
> > 
> > What do people think of this patch?
> 
> Excuse me but JESUS FUCKING CHRIST.  I've been sending that patch since last
> year.

Yes, I saw this (google sent me to a much older version when I looked,
but I just found your more recent one).

I like the fact that you have no internal array, but I like the fact
that I preserve the raw groups pointer.  You go furthur and try to do
better than linear search, too, I was aiming for minimalism.

> No sysctl - I didn't think it was needed at all.

Perhaps, but I was being cautious.  With the default setting, it's
identical to the current situation.

Cheers,
Rusty.
--
  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] sysctl-controlled number of groups.
  2003-09-25  7:25 ` William Lee Irwin III
@ 2003-09-25  8:23   ` Rusty Russell
  0 siblings, 0 replies; 8+ messages in thread
From: Rusty Russell @ 2003-09-25  8:23 UTC (permalink / raw)
  To: William Lee Irwin III
  Cc: akpm, neilb, braam, davem, Martin Schwidefsky,
	David Mosberger-Tang, tridge, linux-kernel

In message <20030925072502.GL4306@holomorphy.com> you write:
> On Thu, Sep 25, 2003 at 01:21:01PM +1000, Rusty Russell wrote:
> > We have a client (using SAMBA) who has people in 190 groups.  Since NT
> > has hierarchical groups, this is not all that rare.
> > What do people think of this patch?
> 
> I like the idea of raising the microscopic limit. BTW, was the Author:
> supposed to be Tim Hockin? ISTR his writing this or something almost
> identical to it. Also, I'm not sure if the sysctl is worth anything.

Nope, it's mine.  Tim's is v. similar, and I think a merge of the two
would produce something fine.  But as he says, it's fairly simple...

Cheers,
Rusty.
--
  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2003-09-25  8:28 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-09-25  3:21 [PATCH] sysctl-controlled number of groups Rusty Russell
2003-09-25  4:14 ` Tim Hockin
2003-09-25  8:17   ` Rusty Russell
2003-09-25  4:19 ` David Mosberger
2003-09-25  8:08   ` Rusty Russell
2003-09-25  7:15 ` Arjan van de Ven
2003-09-25  7:25 ` William Lee Irwin III
2003-09-25  8:23   ` Rusty Russell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox