Date: Fri, 30 Jul 2004 19:48:37 GMT From: Xiaolin Zang <czang@panasas.com> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/69825: 1st group supplied to setgroups() does not take effect in file access Message-ID: <200407301948.i6UJmbL6040421@www.freebsd.org> Resent-Message-ID: <200407301950.i6UJoLXp072764@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 69825 >Category: kern >Synopsis: 1st group supplied to setgroups() does not take effect in file access >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Jul 30 19:50:21 GMT 2004 >Closed-Date: >Last-Modified: >Originator: Xiaolin Zang >Release: 4.6.2 >Organization: Panasas, Inc >Environment: FreeBSD rack-bsd14 4.6.2-RELEASE FreeBSD 4.6.2-RELEASE #0: Wed Aug 14 21:23:26 GMT 2002 murray@builder.freebsdmall.com:/usr/src/sys/compile/GENERIC i386 >Description: Demonstrated with the following program: #include <sys/types.h> #include <unistd.h> #include <stdio.h> /* * This program takes three arguments: The file to try (use full path of * the file system), the limit of groups on your machine (16 or 32) and * the slot in the group vector you want gid 8000 (file's owning group) * to be set. * * Run the program as root. It creates a file owned by uid 7000 and gid 8000. * Then it changes the process's euid, egid and group vector so that the * process has no write permission to the fie. Then it sets gid 8000 into * the specified slot in the group vector and see if the file becomes * writable. */ main( int argc, char **argv) { char *path = argv[1]; int ngroups = atoi(argv[2]); int slot = atoi(argv[3]); FILE *fh; gid_t gids[32], get_gids[32]; int i, real_ngroups; printf("file %s, ngroups %d, slot %d\n", path, ngroups, slot); for (i = 0; i < 32; i++) { gids[i] = 8100 + i; get_gids[i] = 0; } /* * create a file and set owner/group to 7000/8000. * group has write permission. */ unlink(path); fh = fopen(path, "w+"); fwrite("abcd", 1, 5, fh); fclose(fh); chmod(path, 0664); chown(path, 7000, 8000); /* * Set the credentials to make sure the requestor is not the owner, nor * the owning group, and expect the open to fail. */ seteuid(0); setgroups(ngroups, gids); setegid(8001); seteuid(7001); fh = fopen(path, "w+"); if (fh) { printf("open for write should fail but did not!\n"); } /* * Try slot 15 againt an nfs server on freebsd from any client * you'll get permission error. * * Try slot 0 on a freebsd machine using any file system you'll get * permission error. */ gids[slot] = 8000; seteuid(0); setgroups(ngroups, gids); setegid(8001); seteuid(7001); real_ngroups = getgroups(ngroups, get_gids); printf("group vector size %d, groups ", real_ngroups); for (i = 0; i < real_ngroups; i++) { printf("%d, ", get_gids[i]); } printf("\n"); fh = fopen(path, "w+"); if (!fh) { printf("setting primary group into group vector slot %d did not work!\n", slot); } } On a freebsd machine: rack-bsd14 > a.out /usr0/czang/try 16 0 file /usr0/czang/try, ngroups 16, slot 0 group vector size 16, groups 8001, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8112, 8113, 8114, 8115, setting primary group into group vector slot 0 did not work! On a solaris machine: icarus > a.out /usr0/czang/try 16 0 file /usr0/czang/try, ngroups 16, slot 0 group vector size 16, groups 8000, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8112, 8113, 8114, 8115, On a linux machine: perf-1 > a.out /usr0/czang/try 16 0 file /usr0/czang/try, ngroups 16, slot 0 group vector size 16, groups 8000, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8112, 8113, 8114, 8115, Freebsd has this practice of using cr_groups[0] for egid. I personally don't see why this is necessary. But let's just say this is OK. Then at least two things should be fixed: 1) In the document say the effective size of the group vector is 15 instead of 16 and 2) Do not drop the first group (slot 0) when handling a setgroups call (drop the ones at the high end of the gid array supplied). I think the best fix is not to use cr_groups[0] for egid. The assumption that cr_groups[0] is egid is in freebsd's nfs client and server, too. >How-To-Repeat: See the test program in the "full descrition" part. >Fix: >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200407301948.i6UJmbL6040421>