kern/69825: 1st group supplied to setgroups() does not take effect
in file access
Xiaolin Zang
czang at panasas.com
Fri Jul 30 12:50:44 PDT 2004
>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 at 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:
More information about the freebsd-bugs
mailing list