Home | History | Annotate | Download | only in tomoyo
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    282 int main(int argc, char *argv[])
    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