Home | History | Annotate | Download | only in chroot
      1 /*
      2  *   Copyright (c) International Business Machines  Corp., 2001
      3  *
      4  *   This program is free software;  you can redistribute it and/or modify
      5  *   it under the terms of the GNU General Public License as published by
      6  *   the Free Software Foundation; either version 2 of the License, or
      7  *   (at your option) any later version.
      8  *
      9  *   This program is distributed in the hope that it will be useful,
     10  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     12  *   the GNU General Public License for more details.
     13  *
     14  *   You should have received a copy of the GNU General Public License
     15  *   along with this program;  if not, write to the Free Software
     16  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     17  */
     18 
     19 /*
     20  *	Testcase to test whether chroot(2) sets errno correctly.
     21  *
     22  *	1.	Test for ENAMETOOLONG:
     23  *		Create a bad directory name with length more than
     24  *		VFS_MAXNAMELEN (Linux kernel variable), and pass it as the
     25  *		path to chroot(2).
     26  *
     27  *	2.	Test for ENOENT:
     28  *		Attempt to chroot(2) on a non-existent directory
     29  *
     30  *	3.	Test for ENOTDIR:
     31  *		Attempt to chdir(2) on a file.
     32  *
     33  *	4.	Test for EFAULT:
     34  *		The pathname parameter to chroot() points to an invalid address,
     35  *		chroot(2) fails with EPERM.
     36  *
     37  *	5.	Test for ELOOP:
     38  *		Too many symbolic links were encountered When resolving the
     39  *		pathname parameter.
     40  *
     41  *	07/2001 Ported by Wayne Boyer
     42  */
     43 
     44 #include <stdio.h>
     45 #include <errno.h>
     46 #include <sys/stat.h>
     47 #include <sys/mman.h>
     48 #include "test.h"
     49 #include <fcntl.h>
     50 #include "safe_macros.h"
     51 
     52 char *TCID = "chroot03";
     53 
     54 static int fd;
     55 static char fname[255];
     56 static char nonexistent_dir[100] = "testdir";
     57 static char bad_dir[] = "abcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyz";
     58 static char symbolic_dir[] = "sym_dir1";
     59 
     60 struct test_case_t {
     61 	char *dir;
     62 	int error;
     63 } TC[] = {
     64 	/*
     65 	 * to test whether chroot() is setting ENAMETOOLONG if the
     66 	 * pathname is more than VFS_MAXNAMELEN
     67 	 */
     68 	{
     69 	bad_dir, ENAMETOOLONG},
     70 	    /*
     71 	     * to test whether chroot() is setting ENOTDIR if the argument
     72 	     * is not a directory.
     73 	     */
     74 	{
     75 	fname, ENOTDIR},
     76 	    /*
     77 	     * to test whether chroot() is setting ENOENT if the directory
     78 	     * does not exist.
     79 	     */
     80 	{
     81 	nonexistent_dir, ENOENT},
     82 #if !defined(UCLINUX)
     83 	    /*
     84 	     * attempt to chroot to a path pointing to an invalid address
     85 	     * and expect EFAULT as errno
     86 	     */
     87 	{
     88 	(char *)-1, EFAULT},
     89 #endif
     90 	{symbolic_dir, ELOOP}
     91 };
     92 
     93 int TST_TOTAL = ARRAY_SIZE(TC);
     94 
     95 static char *bad_addr;
     96 
     97 static void setup(void);
     98 static void cleanup(void);
     99 
    100 int main(int ac, char **av)
    101 {
    102 	int lc;
    103 	int i;
    104 
    105 	tst_parse_opts(ac, av, NULL, NULL);
    106 
    107 	setup();
    108 
    109 	for (lc = 0; TEST_LOOPING(lc); lc++) {
    110 		tst_count = 0;
    111 
    112 		for (i = 0; i < TST_TOTAL; i++) {
    113 			TEST(chroot(TC[i].dir));
    114 
    115 			if (TEST_RETURN != -1) {
    116 				tst_resm(TFAIL, "call succeeded unexpectedly");
    117 				continue;
    118 			}
    119 
    120 			if (TEST_ERRNO == TC[i].error) {
    121 				tst_resm(TPASS | TTERRNO, "failed as expected");
    122 			} else {
    123 				tst_resm(TFAIL | TTERRNO,
    124 					 "didn't fail as expected (expected errno "
    125 					 "= %d : %s)",
    126 					 TC[i].error, strerror(TC[i].error));
    127 			}
    128 		}
    129 	}
    130 
    131 	cleanup();
    132 	tst_exit();
    133 }
    134 
    135 static void setup(void)
    136 {
    137 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
    138 	TEST_PAUSE;
    139 	tst_tmpdir();
    140 
    141 	/*
    142 	 * create a file and use it to test whether chroot() is setting
    143 	 * ENOTDIR if the argument is not a directory.
    144 	 */
    145 	(void)sprintf(fname, "tfile_%d", getpid());
    146 	fd = creat(fname, 0777);
    147 	if (fd == -1)
    148 		tst_brkm(TBROK, cleanup, "Failed to creat a temp file");
    149 
    150 #if !defined(UCLINUX)
    151 	bad_addr = mmap(0, 1, PROT_NONE,
    152 			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
    153 	if (bad_addr == MAP_FAILED)
    154 		tst_brkm(TBROK, cleanup, "mmap failed");
    155 
    156 	TC[3].dir = bad_addr;
    157 #endif
    158 	/*
    159 	 * create two symbolic directory who point to each other to
    160 	 * test ELOOP.
    161 	 */
    162 	SAFE_SYMLINK(cleanup, "sym_dir1/", "sym_dir2");
    163 	SAFE_SYMLINK(cleanup, "sym_dir2/", "sym_dir1");
    164 }
    165 
    166 static void cleanup(void)
    167 {
    168 	close(fd);
    169 	tst_rmdir();
    170 }
    171