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