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