Back to index

glibc  2.9
tst-chmod.c
Go to the documentation of this file.
00001 /* Test for chmod functions.
00002    Copyright (C) 2000, 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <dirent.h>
00022 #include <errno.h>
00023 #include <error.h>
00024 #include <fcntl.h>
00025 #include <mcheck.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <unistd.h>
00030 #include <sys/stat.h>
00031 
00032 
00033 #define OUT_OF_MEMORY \
00034   do {                                                               \
00035     puts ("cannot allocate memory");                                        \
00036     result = 1;                                                             \
00037     goto fail;                                                              \
00038   } while (0)
00039 
00040 static int
00041 do_test (int argc, char *argv[])
00042 {
00043   const char *builddir;
00044   struct stat64 st1;
00045   struct stat64 st2;
00046   char *buf;
00047   char *testdir;
00048   char *testfile = NULL;
00049   char *startdir;
00050   size_t buflen;
00051   int fd;
00052   int result = 0;
00053   DIR *dir;
00054 
00055   mtrace ();
00056 
00057   if (argc <= 1)
00058     error (EXIT_FAILURE, 0, "no parameters");
00059 
00060   /* This is where we will create the test files.  */
00061   builddir = argv[1];
00062   buflen = strlen (builddir) + 50;
00063 
00064   startdir = getcwd (NULL, 0);
00065   if (startdir == NULL)
00066     {
00067       printf ("cannot get current directory: %m\n");
00068       exit (EXIT_FAILURE);
00069     }
00070 
00071   /* A buffer large enough for everything we need.  */
00072   buf = (char *) alloca (buflen);
00073 
00074   /* Create the directory name.  */
00075   snprintf (buf, buflen, "%s/chmoddirXXXXXX", builddir);
00076 
00077   if (mkdtemp (buf) == NULL)
00078     {
00079       printf ("cannot create test directory: %m\n");
00080       exit (EXIT_FAILURE);
00081     }
00082 
00083   if (chmod ("", 0600) == 0)
00084     {
00085       puts ("chmod(\"\", 0600 didn't fail");
00086       result = 1;
00087     }
00088   else if (errno != ENOENT)
00089     {
00090       puts ("chmod(\"\",0600) does not set errno to ENOENT");
00091       result = 1;
00092     }
00093 
00094   /* Create a duplicate.  */
00095   testdir = strdup (buf);
00096   if (testdir == NULL)
00097     OUT_OF_MEMORY;
00098 
00099   if (stat64 (testdir, &st1) != 0)
00100     {
00101       printf ("cannot stat test directory: %m\n");
00102       exit (1);
00103     }
00104   if (!S_ISDIR (st1.st_mode))
00105     {
00106       printf ("file not created as directory: %m\n");
00107       exit (1);
00108     }
00109 
00110   /* We have to wait for a second to make sure the ctime changes.  */
00111   sleep (1);
00112 
00113   /* Remove all access rights from the directory.  */
00114   if (chmod (testdir, 0) != 0)
00115     {
00116       printf ("cannot change mode of test directory: %m\n");
00117       result = 1;
00118       goto fail;
00119     }
00120 
00121   if (stat64 (testdir, &st2) != 0)
00122     {
00123       printf ("cannot stat test directory: %m\n");
00124       result = 1;
00125       goto fail;
00126     }
00127 
00128   /* Compare result.  */
00129   if ((st2.st_mode & ALLPERMS) != 0)
00130     {
00131       printf ("chmod(...,0) on directory left bits nonzero: %o\n",
00132              st2.st_mode & ALLPERMS);
00133       result = 1;
00134     }
00135   if (st1.st_ctime >= st2.st_ctime)
00136     {
00137       puts ("chmod(...,0) did not set ctime correctly");
00138       result = 1;
00139     }
00140 
00141   /* Name of a file in the directory.  */
00142   snprintf (buf, buflen, "%s/file", testdir);
00143   testfile = strdup (buf);
00144   if (testfile == NULL)
00145     OUT_OF_MEMORY;
00146 
00147   fd = creat (testfile, 0);
00148   if (fd != -1)
00149     {
00150       if (getuid () != 0)
00151        {
00152          puts ("managed to create test file in protected directory");
00153          result = 1;
00154        }
00155       close (fd);
00156     }
00157   else if (errno != EACCES)
00158     {
00159       puts ("creat didn't generate correct errno value");
00160       result = 1;
00161     }
00162 
00163   /* With this mode it still shouldn't be possible to create a file.  */
00164   if (chmod (testdir, 0600) != 0)
00165     {
00166       printf ("cannot change mode of test directory to 0600: %m\n");
00167       result = 1;
00168       goto fail;
00169     }
00170 
00171   fd = creat (testfile, 0);
00172   if (fd != -1)
00173     {
00174       if (getuid () != 0)
00175        {
00176          puts ("managed to create test file in no-x protected directory");
00177          result = 1;
00178        }
00179       close (fd);
00180     }
00181   else if (errno != EACCES)
00182     {
00183       puts ("creat didn't generate correct errno value");
00184       result = 1;
00185     }
00186 
00187   /* Change the directory mode back to allow creating a file.  This
00188      time with fchmod.  */
00189   dir = opendir (testdir);
00190   if (dir != NULL)
00191     {
00192       if (fchmod (dirfd (dir), 0700) != 0)
00193        {
00194          printf ("cannot change mode of test directory to 0700: %m\n");
00195          result = 1;
00196          closedir (dir);
00197          goto fail;
00198        }
00199 
00200       closedir (dir);
00201     }
00202   else
00203     {
00204       printf ("cannot open directory: %m\n");
00205       result = 1;
00206 
00207       if (chmod (testdir, 0700) != 0)
00208        {
00209          printf ("cannot change mode of test directory to 0700: %m\n");
00210          goto fail;
00211        }
00212     }
00213 
00214   fd = creat (testfile, 0);
00215   if (fd == -1)
00216     {
00217       puts ("still didn't manage to create test file in protected directory");
00218       result = 1;
00219       goto fail;
00220     }
00221   if (fstat64 (fd, &st1) != 0)
00222     {
00223       printf ("cannot stat new file: %m\n");
00224       result = 1;
00225     }
00226   else if ((st1.st_mode & ALLPERMS) != 0)
00227     {
00228       puts ("file not created with access mode 0");
00229       result = 1;
00230     }
00231   close (fd);
00232 
00233   snprintf (buf, buflen, "%s/..", testdir);
00234   chdir (buf);
00235   /* We are now in the directory above the one we create the test
00236      directory in.  */
00237 
00238   sleep (1);
00239   snprintf (buf, buflen, "./%s/../%s/file",
00240            basename (testdir), basename (testdir));
00241   if (chmod (buf, 0600) != 0)
00242     {
00243       printf ("cannot change mode of file to 0600: %m\n");
00244       result = 1;
00245       goto fail;
00246     }
00247   snprintf (buf, buflen, "./%s//file", basename (testdir));
00248   if (stat64 (buf, &st2) != 0)
00249     {
00250       printf ("cannot stat new file: %m\n");
00251       result = 1;
00252     }
00253   else if ((st2.st_mode & ALLPERMS) != 0600)
00254     {
00255       puts ("file mode not changed to 0600");
00256       result = 1;
00257     }
00258   else if (st1.st_ctime >= st2.st_ctime)
00259     {
00260       puts ("chmod(\".../file\",0600) did not set ctime correctly");
00261       result = 1;
00262     }
00263 
00264   if (chmod (buf, 0777 | S_ISUID | S_ISGID) != 0)
00265     {
00266       printf ("cannot change mode of file to %o: %m\n",
00267              0777 | S_ISUID | S_ISGID);
00268       result = 1;
00269     }
00270   if (stat64 (buf, &st2) != 0)
00271     {
00272       printf ("cannot stat test file: %m\n");
00273       result = 1;
00274     }
00275   else if ((st2.st_mode & ALLPERMS) != (0777 | S_ISUID | S_ISGID))
00276     {
00277       puts ("file mode not changed to 0777 | S_ISUID | S_ISGID");
00278       result = 1;
00279     }
00280 
00281   if (chmod (basename (testdir), 0777 | S_ISUID | S_ISGID | S_ISVTX) != 0)
00282     {
00283       printf ("cannot change mode of test directory to %o: %m\n",
00284              0777 | S_ISUID | S_ISGID | S_ISVTX);
00285       result = 1;
00286     }
00287   if (stat64 (basename (testdir), &st2) != 0)
00288     {
00289       printf ("cannot stat test directory: %m\n");
00290       result = 1;
00291     }
00292   else if ((st2.st_mode & ALLPERMS) != (0777 | S_ISUID | S_ISGID | S_ISVTX))
00293     {
00294       puts ("directory mode not changed to 0777 | S_ISUID | S_ISGID | S_ISGID");
00295       result = 1;
00296     }
00297 
00298   snprintf (buf, buflen, "./%s/no-such-file", basename (testdir));
00299   if (chmod (buf, 0600) != -1)
00300     {
00301       puts ("chmod(\".../no-such-file\",0600) did not fail");
00302       result = 1;
00303     }
00304   else if (errno != ENOENT)
00305     {
00306       puts ("chmod(\".../no-such-file\",0600) does not set errno to ENOENT");
00307       result = 1;
00308     }
00309 
00310   snprintf (buf, buflen, "%s/", basename (testdir));
00311   if (chmod (basename (testdir), 0677) != 0)
00312     {
00313       printf ("cannot change mode of test directory to 0677: %m\n");
00314       result = 1;
00315     }
00316   else
00317     {
00318       snprintf (buf, buflen, "./%s/file", basename (testdir));
00319       if (chmod (buf, 0600) == 0)
00320        {
00321          if (getuid () != 0)
00322            {
00323              puts ("chmod(\".../file\") with no-exec directory succeeded");
00324              result = 1;
00325            }
00326        }
00327       else if (errno != EACCES)
00328        {
00329          puts ("chmod(\".../file\") with no-exec directory didn't set EACCES");
00330          result = 1;
00331        }
00332     }
00333 
00334   if (chmod (basename (testdir), 0777) != 0)
00335     {
00336       printf ("cannot change mode of test directory to 0777: %m\n");
00337       result = 1;
00338       goto fail;
00339     }
00340 
00341   snprintf (buf, buflen, "%s/file/cannot-be", basename (testdir));
00342   if (chmod (buf, 0600) == 0)
00343     {
00344       puts ("chmod(\".../file/cannot-be\",0600) did not fail");
00345       result = 1;
00346     }
00347   else if (errno != ENOTDIR)
00348     {
00349       puts ("chmod(\".../file/cannot-be\",0600) does not set errno to ENOTDIR");
00350       result = 1;
00351     }
00352 
00353  fail:
00354   chdir (startdir);
00355 
00356   /* Remove all the files.  */
00357   chmod (testdir, 0700);
00358   if (testfile != NULL)
00359     {
00360       chmod (testfile, 0700);
00361       unlink (testfile);
00362     }
00363   rmdir (testdir);
00364 
00365   /* Free the resources.  */
00366   free (testfile);
00367   free (testdir);
00368   free (startdir);
00369 
00370   return result;
00371 }
00372 
00373 
00374 /* We need a few seconds since we have a few sleeps in the code.  */
00375 #define TIMEOUT      20
00376 
00377 
00378 #include "../test-skeleton.c"