]> Zhao Yanbai Git Server - minix.git/commitdiff
Fix compilation errors caused by more files not added in previous commit
authorThomas Veerman <thomas@minix3.org>
Sun, 20 Dec 2009 21:31:03 +0000 (21:31 +0000)
committerThomas Veerman <thomas@minix3.org>
Sun, 20 Dec 2009 21:31:03 +0000 (21:31 +0000)
lib/other/initgroups.c [new file with mode: 0644]
lib/syscall/setgroups.s [new file with mode: 0644]
test/test46.c [new file with mode: 0644]

diff --git a/lib/other/initgroups.c b/lib/other/initgroups.c
new file mode 100644 (file)
index 0000000..86a6563
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+initgroups.c
+*/
+#include <sys/param.h>
+#include <unistd.h>
+#include <string.h>
+#include <grp.h>
+
+
+int initgroups(const char *name, gid_t basegid)
+{
+  struct group *gr;
+  int r, found = 0, n = 0;
+  gid_t groups[NGROUPS];
+
+  if((r = setgid(basegid)) < 0)
+       return(r);
+
+  setgrent();
+  while ((gr = getgrent()) != NULL && (n + 1) <= NGROUPS) {
+       char **mem;
+       for(mem = gr->gr_mem; mem && *mem; mem++) {
+               if(!strcmp(name, *mem)) {
+                       groups[n++] = gr->gr_gid;
+                       break;
+               }
+       }
+  }
+
+  endgrent();
+
+  return setgroups(n, groups);
+}
+
diff --git a/lib/syscall/setgroups.s b/lib/syscall/setgroups.s
new file mode 100644 (file)
index 0000000..3cf8b50
--- /dev/null
@@ -0,0 +1,7 @@
+.sect .text
+.extern        __setgroups
+.define        _setgroups
+.align 2
+
+_setgroups:
+       jmp     __setgroups
diff --git a/test/test46.c b/test/test46.c
new file mode 100644 (file)
index 0000000..7d0d0ac
--- /dev/null
@@ -0,0 +1,355 @@
+/* Test46.c
+ *
+ * Test getgroups(...) and setgroups system calls
+ *
+ * Please note that getgroups is POSIX defined, but setgroups is not. Errors
+ * related to setgroups are thus not POSIX conformance issues.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+_PROTOTYPE( void api_test, (void)                                      );
+_PROTOTYPE( void e, (int error_no)                                     );
+_PROTOTYPE( void group_test, (void)                                    );
+_PROTOTYPE( void limit_test, (void)                                    );
+_PROTOTYPE( void group_test_1, (void)                                  );
+_PROTOTYPE( void group_test_2, (void)                                  );
+_PROTOTYPE( void group_test_3, (void)                                  );
+_PROTOTYPE( void group_test_4, (void)                                  );
+_PROTOTYPE( void group_test_5, (void)                                  );
+_PROTOTYPE( int dotest, (void (*testfunc)(void))                               );
+
+int subtest = -1, errorct = 0;
+#define ERROR_MAX 5
+#define IMAGINARY_GID 100
+#define IMAGINARY_GID_STR "100"
+#define IMAGINARY_UID 101
+#define IMAGINARY_UID_STR "101"
+#define SET_CREDENTIALS do { \
+                         setgid((IMAGINARY_GID) + 1 ); \
+                         setuid(IMAGINARY_UID); \
+                       } while(0)
+
+int main(int argc, char *argv[])
+{
+  int superuser;
+  printf("Test 46 ");
+  fflush(stdout);
+
+  superuser = (geteuid() == 0);
+
+  if(!superuser) {
+       if(!(setuid(0) || seteuid(0))) {
+               printf("Test 46 has to be run as root; test aborted\n");
+               exit(1);
+       }
+  }
+
+  limit_test();        /* Perform some tests on POSIX limits */
+  api_test();  /* Perform some very basic API tests */
+  group_test();        /* Perform some tests that mimic actual use */
+
+  if(errorct > 0) {
+       printf("%d error(s)\n", errorct);
+       return(errorct);
+  }
+
+  printf("ok\n");
+  return(0);
+}
+
+void limit_test() {
+/* According to POSIX 2008 a process can have up to NGROUPS_MAX simultaneous
+ * supplementary group IDs. The minimum acceptable value is _POSIX_NGROUPS_MAX.
+ * In turn, _POSIX_NGROUPS_MAX is defined as 8. */
+
+  subtest = 1;
+  if (_POSIX_NGROUPS_MAX < 8) e(1);
+  if (NGROUPS_MAX < _POSIX_NGROUPS_MAX) e(2);
+}
+
+void api_test() {
+/* int getgroups( int gidsetsize, gid_t grouplist[]);
+ * int setgroups( int size_t size, const gid_t grouplist[]);
+ */
+/* The getgroups() function shall fill in the array grouplist with the current
+ * supplementary group IDs of the calling process. It is implementation-
+ * defined whether getgroups() also returns the effective group ID in the
+ * grouplist array.
+ * The gidsetsize argument specifies the number of elements in the array
+ * grouplist. The actual number of group IDs stored in the array shall be
+ * returned. The values of array entries with indices greater than or equal to
+ * the value returned are undefined.
+ * If gidsetsize is 0, getgroups shall return the number of group IDs that it
+ * would otherwise return without modifying the array pointed to by grouplist.
+ *
+ * setgroups() sets the supplementary group IDs for the calling process. The
+ * size argument specifies the number of supplementary group IDs in the buffer
+ * pointed to by grouplist. setgroups() is a privileged operation.
+ */
+
+ /* Minix does not return the effective group ID with the supplementary groups.
+  * Use getegid() to get that value. In order to call setgroups, a process
+  * must have super user privileges.
+  */
+
+  int r, i, nogroups;
+  gid_t *grouplist, *grouplist2;
+  long ngroups_max;
+
+  subtest = 2;
+
+  /* Ask the system how many groups we're allowed to set */
+  ngroups_max = sysconf(_SC_NGROUPS_MAX);
+  grouplist = malloc(ngroups_max *sizeof(gid_t));
+  grouplist2 = malloc(ngroups_max *sizeof(gid_t));
+
+  /* Let's invent some imaginary groups */
+#define START_GID 20001
+  for (i = START_GID; i < START_GID + ngroups_max; i++)
+       grouplist[i - START_GID] = i;
+
+  /* Normal usage */
+  if (setgroups(ngroups_max, grouplist) != 0) e(1);
+
+  /* Try one less than max supported groups */
+  if (setgroups(ngroups_max - 1, grouplist) != 0) e(2);
+
+  /* Try just one group */
+  if (setgroups(1, grouplist) != 0) e(3);
+
+  /* Unset all supplementary groups */
+  if (setgroups(0, grouplist) != 0) e(4);
+
+  /* Should not be allowed to use a negative set size */
+  if (setgroups(-1, grouplist) == 0) e(5);
+  else if(errno != EINVAL) e(6); /* error must be EINVAL */
+
+  /* Should not be allowed to set more groups than supported by the system */
+  if (setgroups(ngroups_max + 1, grouplist) == 0) e(7);
+  else if(errno != EINVAL) e(8); /* error must be EINVAL */
+
+  /* Should not be allowed to provide an invalid grouplist address */
+  if (setgroups(ngroups_max, NULL) == 0) e(9);
+  else if(errno != EFAULT) e(10); /* error must be EFAULT */
+
+  /* The last time we called setgroups with proper parameters, we effectively
+   * cleared the list. Verify that with getgroups(). */
+  if (getgroups(ngroups_max, grouplist2) != 0) e(11);
+
+  /* Repopulate grouplist with values and read them back */
+  if (setgroups(ngroups_max, grouplist) != 0) e(12);
+  if (getgroups(0, grouplist2) != ngroups_max) e(13);
+  if (getgroups(ngroups_max, grouplist2) != ngroups_max) e(14);
+  for (i = 0; i < ngroups_max; i++) {
+       if(grouplist[i] != grouplist2[i]) {
+               e(15); 
+               break; /* One error message should be enough here */ 
+       }
+  }
+
+  /* Should not be able to read less groups than are actually stored. */
+  if (getgroups(ngroups_max - 1, grouplist2) != -1) e(16);
+
+  /* Repopulate grouplist with only half the groups and read them back */
+  memset(grouplist2, 0, ngroups_max * sizeof(gid_t)); /* Clear array */
+#define HALF_LIST_SIZE ngroups_max / 2
+  if (setgroups(HALF_LIST_SIZE, grouplist) != 0) e(17);
+  if (getgroups(0, grouplist2) != HALF_LIST_SIZE) e(18);
+  if (getgroups(HALF_LIST_SIZE, grouplist2) != HALF_LIST_SIZE) e(19);
+  for (i = 0; i < HALF_LIST_SIZE; i++) {
+       if(grouplist[i] != grouplist2[i]) {
+               e(20);
+               break; /* Also here one message ought to be enough */
+       }
+  }
+
+  /* Try to read more groups than we have set */
+  memset(grouplist2, 0, ngroups_max * sizeof(gid_t)); /* Clear array */
+  if (getgroups(ngroups_max, grouplist2) != HALF_LIST_SIZE) e(21);
+  for (i = 0; i < HALF_LIST_SIZE; i++) {
+       /* Anything above indices 'HALF_LIST_SIZE' is undefined */
+       if(grouplist[i] != grouplist2[i]) {
+               e(22);
+               break;
+       }
+  }
+
+  free(grouplist);
+  free(grouplist2);
+}
+
+void group_test() {
+/* To test supplemental group support we're going to create a temporary
+ * directory that can only be accessed (x bit) by members of our imaginary
+ * group, read from (r bit) and written to (w bit). 
+ * Then we're going to create a file in that directory that's only readable and
+ * writable by the owner, also readable, writable, and both (in that order) by
+ * the imaginary group, and readable, writable, and both by everyone else (2). 
+ */
+
+  int r, i, round, test_result;
+  gid_t *grouplist;
+  long ngroups_max;
+#define ROUNDS 8
+
+  subtest = 3;
+
+  ngroups_max = sysconf(_SC_NGROUPS_MAX);
+  grouplist = malloc(ngroups_max *sizeof(gid_t));
+
+  /* Let's invent imaginary groups and user id */
+  grouplist = malloc(ngroups_max * sizeof(gid_t));
+
+  /* Now loop a few tests while using different group set sizes */
+  for(round = 0; round < ROUNDS; round++) {
+       grouplist[round] = IMAGINARY_GID;
+       for(i = 0; i < ngroups_max; i++) {
+               if(i == round) continue;
+               grouplist[i] = IMAGINARY_GID + i + ngroups_max;
+       }
+       setgroups(round+1, grouplist);
+
+       system("rm -r DIR_046 > /dev/null 2>&1");
+       system("mkdir DIR_046");
+       system("chmod u=rwx,g=,o= DIR_046"); /* Only access for superuser */
+       system("chgrp "IMAGINARY_GID_STR" DIR_046"); /* Make imaginary group
+                                                     * owner */
+
+       /* Test group access on directories */
+       if(dotest(group_test_1) != 0) e(1);
+       system("chmod g+r DIR_046"); /* Allow group read access */
+       if(dotest(group_test_1) == 0) e(2);
+
+       system("chmod g= DIR_046");
+       if(dotest(group_test_2) != 0) e(3);
+       system("chmod g+x DIR_046"); /* Allow 'search' (i.e., inode data)
+                                     * access */
+       if(dotest(group_test_2) == 0) e(4);
+
+       if(dotest(group_test_3) != 0) e(5);
+       system("chmod g+w DIR_046"); /* Allow group write access */
+       if(dotest(group_test_3) == 0) e(6);
+
+       system("chmod g-wx DIR_046"); /* Remove write and 'search' permission */
+       if(dotest(group_test_4) != 0) e(7);
+       system("chmod g+w DIR_046"); /* Add write permission */
+       if(dotest(group_test_4) != 0) e(8);
+       system("chmod g+x DIR_046"); /* Add 'search' permission */
+       if(dotest(group_test_4) == 0) e(9);
+
+       /* Subdirectories */
+       system("mkdir -p DIR_046/sub");
+       system("chmod u=rwx,g=,o= DIR_046");
+       system("chmod u=rwx,g=,o= DIR_046/sub");
+       system("chgrp "IMAGINARY_GID_STR" DIR_046/sub"); 
+
+       if(dotest(group_test_1) != 0) e(10);
+       if(dotest(group_test_5) != 0) e(11);
+
+       system("chmod g+r DIR_046");
+       if(dotest(group_test_1) == 0) e(12);
+       if(dotest(group_test_5) != 0) e(13);
+
+       system("chmod g= DIR_046");
+       if(dotest(group_test_5) != 0) e(14);
+       system("chmod g+r DIR_046/sub");
+       if(dotest(group_test_5) != 0) e(15); /* We need search permission for
+                                             * sub directory DIR_046 to be
+                                             * able to read the contents of
+                                             * DIR_046/sub */
+       system("chmod g+x DIR_046");
+       if(dotest(group_test_1) != 0) e(16);
+       if(dotest(group_test_5) == 0) e(17);
+       system("chmod g+r DIR_046");
+       if(dotest(group_test_5) == 0) e(18);
+  }
+  system("rm -r DIR_046");
+  free(grouplist);
+}
+
+int dotest( void (*func)(void) ) {
+  int test_result;
+
+  if(fork() == 0) (*func)();
+  else wait(&test_result);
+
+  return(test_result);
+}
+
+void group_test_1() {
+/* Test x bit for group access. Exit value is 1 when we were able to read from
+ * the directory and 0 otherwise. */
+  DIR *dirp = NULL;
+
+  SET_CREDENTIALS;
+
+  dirp = opendir("DIR_046");
+  exit(dirp != NULL); /* If not NULL, we were able to access it */
+}
+
+void group_test_2() {
+/* Test x bit for group access. Exit value is 1 when we were able to access 
+ * inode data of the directory and 0 otherwise. */
+  struct stat buf;
+  int res;
+
+  SET_CREDENTIALS;
+  res = stat("DIR_046/.", &buf);
+  exit(res == 0);
+}
+
+void group_test_3() {
+/* Test wx bits for group access. Exit value is 1 when we were able to write to 
+ * the directory and 0 otherwise. */
+  int fd;
+  
+  SET_CREDENTIALS;
+
+  fd = open("DIR_046/writetest", O_WRONLY|O_CREAT);
+
+  exit(fd != -1); 
+}
+
+void group_test_4() {
+/* Test w bit for group access. Exit value is 1 when we were able to rename a 
+ * the directory and 0 otherwise. */
+  int res;
+  
+  SET_CREDENTIALS;
+
+  res = rename("DIR_046/writetest", "DIR_046/renametest");
+
+  exit(res == 0); 
+}
+
+void group_test_5() {
+/* Test x bit for group access. Exit value is 1 when we were able to read from
+ * the directory and 0 otherwise. */
+  DIR *dirp = NULL;
+
+  SET_CREDENTIALS;
+
+  dirp = opendir("DIR_046/sub");
+  exit(dirp != NULL); /* If not NULL, we were able to access it */
+}
+
+void e(int error_no) {
+  printf("Subtest %d, error %d\n", subtest, error_no);
+
+  if (errorct++ > ERROR_MAX) {
+       printf("Too many errors, test aborted\n");
+       exit(1);
+  }
+}
+