• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
main(int ac,char ** av)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 
setup(void)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 = SAFE_CREAT(cleanup, fname, 0777);
147 
148 #if !defined(UCLINUX)
149 	bad_addr = mmap(0, 1, PROT_NONE,
150 			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
151 	if (bad_addr == MAP_FAILED)
152 		tst_brkm(TBROK, cleanup, "mmap failed");
153 
154 	TC[3].dir = bad_addr;
155 #endif
156 	/*
157 	 * create two symbolic directory who point to each other to
158 	 * test ELOOP.
159 	 */
160 	SAFE_SYMLINK(cleanup, "sym_dir1/", "sym_dir2");
161 	SAFE_SYMLINK(cleanup, "sym_dir2/", "sym_dir1");
162 }
163 
cleanup(void)164 static void cleanup(void)
165 {
166 	close(fd);
167 	tst_rmdir();
168 }
169