From owner-freebsd-bugs@FreeBSD.ORG Fri Jul 30 19:50:43 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id F073616A4CF for ; Fri, 30 Jul 2004 19:50:43 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id D206643D62 for ; Fri, 30 Jul 2004 19:50:43 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.11/8.12.11) with ESMTP id i6UJoLfW072765 for ; Fri, 30 Jul 2004 19:50:21 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.11/8.12.11/Submit) id i6UJoLXp072764; Fri, 30 Jul 2004 19:50:21 GMT (envelope-from gnats) Resent-Date: Fri, 30 Jul 2004 19:50:21 GMT Resent-Message-Id: <200407301950.i6UJoLXp072764@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Xiaolin Zang Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id B757E16A4CE for ; Fri, 30 Jul 2004 19:49:26 +0000 (GMT) Received: from www.freebsd.org (www.freebsd.org [216.136.204.117]) by mx1.FreeBSD.org (Postfix) with ESMTP id 99E3C43D3F for ; Fri, 30 Jul 2004 19:49:26 +0000 (GMT) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.12.11/8.12.11) with ESMTP id i6UJmb5I040422 for ; Fri, 30 Jul 2004 19:48:37 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.12.11/8.12.11/Submit) id i6UJmbL6040421; Fri, 30 Jul 2004 19:48:37 GMT (envelope-from nobody) Message-Id: <200407301948.i6UJmbL6040421@www.freebsd.org> Date: Fri, 30 Jul 2004 19:48:37 GMT From: Xiaolin Zang To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-2.3 Subject: kern/69825: 1st group supplied to setgroups() does not take effect in file access X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 30 Jul 2004 19:50:44 -0000 >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 #include #include /* * 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: