• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************/
2 /* This program is free software;  you can redistribute it and/or modify      */
3 /* it under the terms of the GNU General Public License as published by       */
4 /* the Free Software Foundation; either version 2 of the License, or          */
5 /* (at your option) any later version.                                        */
6 /*                                                                            */
7 /* This program is distributed in the hope that it will be useful,            */
8 /* but WITHOUT ANY WARRANTY;  without even the implied warranty of            */
9 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                  */
10 /* the GNU General Public License for more details.                           */
11 /*                                                                            */
12 /* You should have received a copy of the GNU General Public License          */
13 /* along with this program;  if not, write to the Free Software               */
14 /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    */
15 /*                                                                            */
16 /******************************************************************************/
17 /*
18  * tomoyo_file_test.c
19  *
20  * Testing program for security/tomoyo/
21  *
22  * Copyright (C) 2005-2010  NTT DATA CORPORATION
23  */
24 #include "include.h"
25 
26 static int should_fail = 0;
27 
show_prompt(const char * str)28 static void show_prompt(const char *str)
29 {
30 	printf("Testing %35s: (%s) ", str,
31 	       should_fail ? "must fail" : "should success");
32 	errno = 0;
33 }
34 
show_result(int result)35 static void show_result(int result)
36 {
37 	if (should_fail) {
38 		if (result == EOF) {
39 			if (errno == EPERM)
40 				printf("OK: Permission denied.\n");
41 			else
42 				printf("FAILED: %s\n", strerror(errno));
43 		} else {
44 			printf("BUG!\n");
45 		}
46 	} else {
47 		if (result != EOF)
48 			printf("OK\n");
49 		else
50 			printf("%s\n", strerror(errno));
51 	}
52 }
53 
54 static const char *dev_null_path = "/dev/null";
55 static const char *truncate_path = "/tmp/truncate_test";
56 static const char *ftruncate_path = "/tmp/ftruncate_test";
57 static const char *open_creat_path = "/tmp/open_test";
58 static const char *mknod_reg_path = "/tmp/mknod_reg_test";
59 static const char *mknod_chr_path = "/tmp/mknod_chr_test";
60 static const char *mknod_blk_path = "/tmp/mknod_blk_test";
61 static const char *mknod_fifo_path = "/tmp/mknod_fifo_test";
62 static const char *mknod_sock_path = "/tmp/mknod_sock_test";
63 static const char *unlink_path = "/tmp/unlink_test";
64 static const char *mkdir_path = "/tmp/mkdir_test";
65 static const char *rmdir_path = "/tmp/rmdir_test";
66 static const char *link_source_path = "/tmp/link_source_test";
67 static const char *link_dest_path = "/tmp/link_dest_test";
68 static const char *symlink_source_path = "/tmp/symlink_source_test";
69 static const char *symlink_dest_path = "/tmp/symlink_dest_test";
70 static const char *rename_source_path = "/tmp/rename_source_test";
71 static const char *rename_dest_path = "/tmp/rename_dest_test";
72 static const char *socket_path = "/tmp/socket_test";
73 
74 static int ftruncate_fd = EOF;
75 
stage_file_test(void)76 static void stage_file_test(void)
77 {
78 	int fd;
79 	{
80 		const char buffer[] = "32768 61000";
81 		show_prompt("sysctl(READ)");
82 		show_result(read_sysctl(TEST_SYSCTL_PATH, NULL, 0));
83 		show_prompt("sysctl(WRITE)");
84 		show_result(write_sysctl(TEST_SYSCTL_PATH, buffer));
85 	}
86 
87 	/* QUESTION: Is there a file which can be passed to uselib()? */
88 	show_prompt("uselib()");
89 	show_result(uselib("/bin/true"));
90 
91 	{
92 		int pipe_fd[2] = { EOF, EOF };
93 		int error = 0;
94 		fflush(stdout);
95 		fflush(stderr);
96 		if (pipe(pipe_fd) == -1)
97 			err(1, "pipe");
98 		if (fork() == 0) {
99 			execl("/bin/true", "/bin/true", NULL);
100 			if (write(pipe_fd[1], &errno, sizeof(errno)) == -1)
101 				err(1, "write");
102 			_exit(0);
103 		}
104 		close(pipe_fd[1]);
105 		(void)read(pipe_fd[0], &error, sizeof(error));
106 		show_prompt("execve()");
107 		errno = error;
108 		show_result(error ? EOF : 0);
109 	}
110 
111 	show_prompt("open(O_RDONLY)");
112 	fd = open(dev_null_path, O_RDONLY);
113 	show_result(fd);
114 	if (fd != EOF)
115 		close(fd);
116 
117 	show_prompt("open(O_WRONLY)");
118 	fd = open(dev_null_path, O_WRONLY);
119 	show_result(fd);
120 	if (fd != EOF)
121 		close(fd);
122 
123 	show_prompt("open(O_RDWR)");
124 	fd = open(dev_null_path, O_RDWR);
125 	show_result(fd);
126 	if (fd != EOF)
127 		close(fd);
128 
129 	show_prompt("open(O_CREAT | O_EXCL)");
130 	fd = open(open_creat_path, O_CREAT | O_EXCL, 0666);
131 	show_result(fd);
132 	if (fd != EOF)
133 		close(fd);
134 
135 	show_prompt("open(O_TRUNC)");
136 	fd = open(truncate_path, O_TRUNC);
137 	show_result(fd);
138 	if (fd != EOF)
139 		close(fd);
140 
141 	show_prompt("truncate()");
142 	show_result(truncate(truncate_path, 0));
143 
144 	show_prompt("ftruncate()");
145 	show_result(ftruncate(ftruncate_fd, 0));
146 
147 	show_prompt("mknod(S_IFREG)");
148 	show_result(mknod(mknod_reg_path, S_IFREG, 0));
149 
150 	show_prompt("mknod(S_IFCHR)");
151 	show_result(mknod(mknod_chr_path, S_IFCHR, MKDEV(1, 3)));
152 
153 	show_prompt("mknod(S_IFBLK)");
154 	show_result(mknod(mknod_blk_path, S_IFBLK, MKDEV(1, 0)));
155 
156 	show_prompt("mknod(S_IFIFO)");
157 	show_result(mknod(mknod_fifo_path, S_IFIFO, 0));
158 
159 	show_prompt("mknod(S_IFSOCK)");
160 	show_result(mknod(mknod_sock_path, S_IFSOCK, 0));
161 
162 	show_prompt("mkdir()");
163 	show_result(mkdir(mkdir_path, 0600));
164 
165 	show_prompt("rmdir()");
166 	show_result(rmdir(rmdir_path));
167 
168 	show_prompt("unlink()");
169 	show_result(unlink(unlink_path));
170 
171 	show_prompt("symlink()");
172 	show_result(symlink(symlink_dest_path, symlink_source_path));
173 
174 	show_prompt("link()");
175 	show_result(link(link_source_path, link_dest_path));
176 
177 	show_prompt("rename()");
178 	show_result(rename(rename_source_path, rename_dest_path));
179 
180 	{
181 		struct sockaddr_un addr;
182 		int fd;
183 		memset(&addr, 0, sizeof(addr));
184 		addr.sun_family = AF_UNIX;
185 		strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
186 		fd = socket(AF_UNIX, SOCK_STREAM, 0);
187 		show_prompt("unix_bind()");
188 		show_result(bind(fd, (struct sockaddr *)&addr, sizeof(addr)));
189 		if (fd != EOF)
190 			close(fd);
191 	}
192 
193 	printf("\n\n");
194 }
195 
create_files(void)196 static void create_files(void)
197 {
198 	mkdir(rmdir_path, 0700);
199 	close(creat(link_source_path, 0600));
200 	close(creat(rename_source_path, 0600));
201 	close(creat(truncate_path, 0600));
202 	close(creat(unlink_path, 0600));
203 	ftruncate_fd = open(ftruncate_path, O_WRONLY | O_CREAT, 0600);
204 }
205 
creanup_files(void)206 static void creanup_files(void)
207 {
208 	if (ftruncate_fd != EOF)
209 		close(ftruncate_fd);
210 	ftruncate_fd = EOF;
211 	unlink(open_creat_path);
212 	unlink(mknod_reg_path);
213 	unlink(mknod_chr_path);
214 	unlink(mknod_blk_path);
215 	unlink(mknod_fifo_path);
216 	unlink(mknod_sock_path);
217 	rmdir(mkdir_path);
218 	unlink(symlink_source_path);
219 	unlink(symlink_dest_path);
220 	unlink(link_source_path);
221 	unlink(link_dest_path);
222 	unlink(rename_source_path);
223 	unlink(rename_dest_path);
224 	unlink(truncate_path);
225 	unlink(ftruncate_path);
226 	unlink(socket_path);
227 }
228 
set_file_enforce(int enforce)229 static void set_file_enforce(int enforce)
230 {
231 	if (enforce) {
232 		set_profile(3, "file::execute");
233 		set_profile(3, "file::open");
234 		set_profile(3, "file::create");
235 		set_profile(3, "file::unlink");
236 		set_profile(3, "file::mkdir");
237 		set_profile(3, "file::rmdir");
238 		set_profile(3, "file::mkfifo");
239 		set_profile(3, "file::mksock");
240 		set_profile(3, "file::truncate");
241 		set_profile(3, "file::symlink");
242 		set_profile(3, "file::rewrite");
243 		set_profile(3, "file::mkblock");
244 		set_profile(3, "file::mkchar");
245 		set_profile(3, "file::link");
246 		set_profile(3, "file::rename");
247 		set_profile(3, "file::chmod");
248 		set_profile(3, "file::chown");
249 		set_profile(3, "file::chgrp");
250 		set_profile(3, "file::ioctl");
251 		set_profile(3, "file::chroot");
252 		set_profile(3, "file::mount");
253 		set_profile(3, "file::umount");
254 		set_profile(3, "file::pivot_root");
255 	} else {
256 		set_profile(0, "file::execute");
257 		set_profile(0, "file::open");
258 		set_profile(0, "file::create");
259 		set_profile(0, "file::unlink");
260 		set_profile(0, "file::mkdir");
261 		set_profile(0, "file::rmdir");
262 		set_profile(0, "file::mkfifo");
263 		set_profile(0, "file::mksock");
264 		set_profile(0, "file::truncate");
265 		set_profile(0, "file::symlink");
266 		set_profile(0, "file::rewrite");
267 		set_profile(0, "file::mkblock");
268 		set_profile(0, "file::mkchar");
269 		set_profile(0, "file::link");
270 		set_profile(0, "file::rename");
271 		set_profile(0, "file::chmod");
272 		set_profile(0, "file::chown");
273 		set_profile(0, "file::chgrp");
274 		set_profile(0, "file::ioctl");
275 		set_profile(0, "file::chroot");
276 		set_profile(0, "file::mount");
277 		set_profile(0, "file::umount");
278 		set_profile(0, "file::pivot_root");
279 	}
280 }
281 
main(void)282 int main(void)
283 {
284 	tomoyo_test_init();
285 
286 	printf("***** Testing file hooks in enforce mode. *****\n");
287 	create_files();
288 	should_fail = 1;
289 	set_file_enforce(1);
290 	stage_file_test();
291 	set_file_enforce(0);
292 	clear_status();
293 	creanup_files();
294 
295 	printf("***** Testing file hooks in permissive mode. *****\n");
296 	should_fail = 0;
297 	create_files();
298 	set_file_enforce(0);
299 	stage_file_test();
300 	creanup_files();
301 
302 	clear_status();
303 	return 0;
304 }
305