kern/69826: 16th group has no effect when accesing file on freebsd
server
Xiaolin Zang
czang at panasas.com
Fri Jul 30 13:40:30 PDT 2004
>Number: 69826
>Category: kern
>Synopsis: 16th group has no effect when accesing file on freebsd server
>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 20:40:25 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 linux machine, the target file in on freebsd nfs server:
perf-1 > uname
Linux
perf-1 > cc try.c
perf-1 > a.out /net/rack-bsd15/usr0/czang/try 16 14
file /net/rack-bsd15/usr0/czang/try, ngroups 16, slot 14
group vector size 16, groups 8100, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8112, 8113, 8000, 8115,
perf-1 > a.out /net/rack-bsd15/usr0/czang/try 16 15
file /net/rack-bsd15/usr0/czang/try, ngroups 16, slot 15
group vector size 16, groups 8100, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8112, 8113, 8114, 8000,
setting primary group into group vector slot 15 did not work!
tcpdump shows that the linux nfs client does pass the correct group vector
to the server:
UID: 7001
GID: 8001
Auxiliary GIDs
GID: 8100
GID: 8101
GID: 8102
GID: 8103
GID: 8104
GID: 8105
GID: 8106
GID: 8107
GID: 8108
GID: 8109
GID: 8110
GID: 8111
GID: 8112
GID: 8113
GID: 8114
GID: 8000
This is related to another bug I sent (1st group set with setgroups
has no effect). The root problem for both bugs is that freebsd uses
the cr_groups[0] for egid.
>How-To-Repeat:
See the test program in "full description".
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list