/******************************************************************************/ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ /* the GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* */ /******************************************************************************/ /* * tomoyo_new_file_test.c * * Testing program for security/tomoyo/ * * Copyright (C) 2005-2010 NTT DATA CORPORATION */ #include "include.h" static const char *policy = ""; static void show_result(int result, char should_success) { int error = errno; printf("%s : ", policy); if (should_success) { if (result != EOF) printf("OK\n"); else printf("FAILED: %s\n", strerror(error)); } else { if (result == EOF) { if (error == EPERM) printf("OK: Permission denied.\n"); else printf("FAILED: %s\n", strerror(error)); } else { printf("BUG: didn't fail.\n"); } } } static void create2(const char *pathname) { set_profile(0, "file::create"); set_profile(0, "file::open"); close(creat(pathname, 0600)); set_profile(3, "file::create"); set_profile(3, "file::open"); errno = 0; } static void mkdir2(const char *pathname) { set_profile(0, "file::mkdir"); mkdir(pathname, 0600); set_profile(3, "file::mkdir"); errno = 0; } static void unlink2(const char *pathname) { set_profile(0, "file::unlink"); unlink(pathname); set_profile(3, "file::unlink"); errno = 0; } static void rmdir2(const char *pathname) { set_profile(0, "file::rmdir"); rmdir(pathname); set_profile(3, "file::rmdir"); errno = 0; } static void mkfifo2(const char *pathname) { set_profile(0, "file::mkfifo"); mkfifo(pathname, 0600); set_profile(3, "file::mkfifo"); errno = 0; } static void stage_file_test(void) { const char buffer[] = "32768 61000"; int pipe_fd[2] = { EOF, EOF }; int error = 0; int fd; char pbuffer[1024]; struct stat sbuf; struct sockaddr_un addr; struct ifreq ifreq; char *filename = ""; set_profile(3, "file::execute"); set_profile(3, "file::open"); set_profile(3, "file::create"); set_profile(3, "file::unlink"); set_profile(3, "file::mkdir"); set_profile(3, "file::rmdir"); set_profile(3, "file::mkfifo"); set_profile(3, "file::mksock"); set_profile(3, "file::truncate"); set_profile(3, "file::symlink"); set_profile(3, "file::rewrite"); set_profile(3, "file::mkblock"); set_profile(3, "file::mkchar"); set_profile(3, "file::link"); set_profile(3, "file::rename"); set_profile(3, "file::chmod"); set_profile(3, "file::chown"); set_profile(3, "file::chgrp"); set_profile(3, "file::ioctl"); set_profile(3, "file::chroot"); set_profile(3, "file::mount"); set_profile(3, "file::umount"); set_profile(3, "file::pivot_root"); policy = "allow_read /proc/sys/net/ipv4/ip_local_port_range"; write_domain_policy(policy, 0); show_result(read_sysctl(TEST_SYSCTL_PATH, NULL, 0), 1); write_domain_policy(policy, 1); show_result(read_sysctl(TEST_SYSCTL_PATH, NULL, 0), 0); policy = "allow_write /proc/sys/net/ipv4/ip_local_port_range"; write_domain_policy(policy, 0); show_result(write_sysctl(TEST_SYSCTL_PATH, buffer), 1); write_domain_policy(policy, 1); show_result(write_sysctl(TEST_SYSCTL_PATH, buffer), 0); policy = "allow_read/write /proc/sys/net/ipv4/ip_local_port_range"; write_domain_policy(policy, 0); show_result(read_sysctl(TEST_SYSCTL_PATH, NULL, 0) && write_sysctl(TEST_SYSCTL_PATH, buffer), 1); write_domain_policy(policy, 1); show_result(read_sysctl(TEST_SYSCTL_PATH, NULL, 0) && write_sysctl(TEST_SYSCTL_PATH, buffer), 0); policy = "allow_read /bin/true"; write_domain_policy(policy, 0); show_result(uselib("/bin/true"), 1); write_domain_policy(policy, 1); show_result(uselib("/bin/true"), 0); policy = "allow_execute /bin/true"; write_domain_policy(policy, 0); fflush(stdout); fflush(stderr); if (pipe(pipe_fd) == -1) err(1, "pipe"); if (fork() == 0) { execl("/bin/true", "/bin/true", NULL); if (write(pipe_fd[1], &errno, sizeof(errno)) == -1) err(1, "write"); exit(0); } close(pipe_fd[1]); (void)read(pipe_fd[0], &error, sizeof(error)); close(pipe_fd[0]); wait(NULL); errno = error; show_result(error ? EOF : 0, 1); write_domain_policy(policy, 1); fflush(stdout); fflush(stderr); if (pipe(pipe_fd) == -1) err(1, "pipe"); if (fork() == 0) { execl("/bin/true", "/bin/true", NULL); if (write(pipe_fd[1], &errno, sizeof(errno)) == -1) err(1, "write"); _exit(0); } close(pipe_fd[1]); (void)read(pipe_fd[0], &error, sizeof(error)); close(pipe_fd[0]); wait(NULL); errno = error; show_result(errno ? EOF : 0, 0); policy = "allow_read /dev/null"; write_domain_policy(policy, 0); fd = open("/dev/null", O_RDONLY); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open("/dev/null", O_RDONLY); show_result(fd, 0); if (fd != EOF) close(fd); policy = "allow_read /dev/null"; write_domain_policy(policy, 0); fd = open("/dev/null", O_RDONLY); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open("/dev/null", O_RDONLY); show_result(fd, 0); if (fd != EOF) close(fd); policy = "allow_read /dev/null"; write_domain_policy(policy, 0); fd = open("/dev/null", O_RDONLY); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open("/dev/null", O_RDONLY); show_result(fd, 0); if (fd != EOF) close(fd); policy = "allow_read /dev/null"; write_domain_policy(policy, 0); fd = open("/dev/null", O_RDONLY); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open("/dev/null", O_RDONLY); show_result(fd, 0); if (fd != EOF) close(fd); set_profile(3, "file::mkfifo"); policy = "allow_mkfifo /tmp/mknod_fifo_test 0644"; write_domain_policy(policy, 0); filename = "/tmp/mknod_fifo_test"; show_result(mknod(filename, S_IFIFO | 0644, 0), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(mknod(filename, S_IFIFO | 0644, 0), 0); memset(pbuffer, 0, sizeof(pbuffer)); memset(&sbuf, 0, sizeof(sbuf)); filename = "/dev/null"; stat(filename, &sbuf); snprintf(pbuffer, sizeof(pbuffer) - 1, "allow_write %s", filename); policy = pbuffer; write_domain_policy(policy, 0); fd = open(filename, O_WRONLY); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open(filename, O_WRONLY); show_result(fd, 0); if (fd != EOF) close(fd); policy = "allow_read/write /tmp/fifo"; mkfifo2("/tmp/fifo"); write_domain_policy(policy, 0); fd = open("/tmp/fifo", O_RDWR); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open("/tmp/fifo", O_RDWR); show_result(fd, 0); if (fd != EOF) close(fd); policy = "allow_read /dev/null"; write_domain_policy(policy, 0); fd = open("/dev/null", O_RDONLY); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open("/dev/null", O_RDONLY); show_result(fd, 0); if (fd != EOF) close(fd); policy = "allow_write /dev/null"; write_domain_policy(policy, 0); fd = open("/dev/null", O_WRONLY); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open("/dev/null", O_WRONLY); show_result(fd, 0); if (fd != EOF) close(fd); policy = "allow_read/write /dev/null"; write_domain_policy(policy, 0); fd = open("/dev/null", O_RDWR); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open("/dev/null", O_RDWR); show_result(fd, 0); if (fd != EOF) close(fd); policy = "allow_create /tmp/open_test 0644"; write_domain_policy(policy, 0); policy = "allow_write /tmp/open_test"; write_domain_policy(policy, 0); fd = open("/tmp/open_test", O_WRONLY | O_CREAT | O_EXCL, 0644); show_result(fd, 1); if (fd != EOF) close(fd); unlink2("/tmp/open_test"); write_domain_policy(policy, 1); fd = open("/tmp/open_test", O_WRONLY | O_CREAT | O_EXCL, 0644); show_result(fd, 0); if (fd != EOF) close(fd); unlink2("/tmp/open_test"); policy = "allow_create /tmp/open_test 0644"; write_domain_policy(policy, 1); policy = "allow_write /tmp/open_test"; write_domain_policy(policy, 0); policy = "allow_create /tmp/open_test 0644"; write_domain_policy(policy, 0); fd = open("/tmp/open_test", O_WRONLY | O_CREAT | O_EXCL, 0644); show_result(fd, 1); if (fd != EOF) close(fd); unlink2("/tmp/open_test"); write_domain_policy(policy, 1); fd = open("/tmp/open_test", O_WRONLY | O_CREAT | O_EXCL, 0644); show_result(fd, 0); if (fd != EOF) close(fd); unlink2("/tmp/open_test"); policy = "allow_write /tmp/open_test"; write_domain_policy(policy, 1); filename = "/tmp/truncate_test"; create2(filename); policy = "allow_truncate /tmp/truncate_test"; write_domain_policy(policy, 0); policy = "allow_write /tmp/truncate_test"; write_domain_policy(policy, 0); fd = open(filename, O_WRONLY | O_TRUNC); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open(filename, O_WRONLY | O_TRUNC); show_result(fd, 0); if (fd != EOF) close(fd); policy = "allow_truncate /tmp/truncate_test"; write_domain_policy(policy, 1); policy = "allow_write /tmp/truncate_test"; write_domain_policy(policy, 0); policy = "allow_truncate /tmp/truncate_test"; write_domain_policy(policy, 0); fd = open(filename, O_WRONLY | O_TRUNC); show_result(fd, 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); fd = open(filename, O_WRONLY | O_TRUNC); show_result(fd, 0); if (fd != EOF) close(fd); policy = "allow_write /tmp/truncate_test"; write_domain_policy(policy, 1); policy = "allow_truncate /tmp/truncate_test"; write_domain_policy(policy, 0); show_result(truncate(filename, 0), 1); write_domain_policy(policy, 1); show_result(truncate(filename, 0), 0); policy = "allow_truncate /tmp/truncate_test"; write_domain_policy(policy, 0); set_profile(0, "file::open"); fd = open(filename, O_WRONLY); set_profile(3, "file::open"); show_result(ftruncate(fd, 0), 1); write_domain_policy(policy, 1); show_result(ftruncate(fd, 0), 0); if (fd != EOF) close(fd); unlink2(filename); policy = "allow_create /tmp/mknod_reg_test 0644"; write_domain_policy(policy, 0); filename = "/tmp/mknod_reg_test"; show_result(mknod(filename, S_IFREG | 0644, 0), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(mknod(filename, S_IFREG | 0644, 0), 0); policy = "allow_mkchar /tmp/mknod_chr_test 0644 1 3"; write_domain_policy(policy, 0); filename = "/tmp/mknod_chr_test"; show_result(mknod(filename, S_IFCHR | 0644, MKDEV(1, 3)), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(mknod(filename, S_IFCHR | 0644, MKDEV(1, 3)), 0); policy = "allow_mkblock /tmp/mknod_blk_test 0644 1 0"; write_domain_policy(policy, 0); filename = "/tmp/mknod_blk_test"; show_result(mknod(filename, S_IFBLK | 0644, MKDEV(1, 0)), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(mknod(filename, S_IFBLK | 0644, MKDEV(1, 0)), 0); policy = "allow_mkfifo /tmp/mknod_fifo_test 0644"; write_domain_policy(policy, 0); filename = "/tmp/mknod_fifo_test"; show_result(mknod(filename, S_IFIFO | 0644, 0), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(mknod(filename, S_IFIFO | 0644, 0), 0); policy = "allow_mksock /tmp/mknod_sock_test 0644"; write_domain_policy(policy, 0); filename = "/tmp/mknod_sock_test"; show_result(mknod(filename, S_IFSOCK | 0644, 0), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(mknod(filename, S_IFSOCK | 0644, 0), 0); policy = "allow_mkdir /tmp/mkdir_test/ 0600"; write_domain_policy(policy, 0); filename = "/tmp/mkdir_test"; show_result(mkdir(filename, 0600), 1); write_domain_policy(policy, 1); rmdir2(filename); show_result(mkdir(filename, 0600), 0); policy = "allow_rmdir /tmp/rmdir_test/"; write_domain_policy(policy, 0); filename = "/tmp/rmdir_test"; mkdir2(filename); show_result(rmdir(filename), 1); write_domain_policy(policy, 1); mkdir2(filename); show_result(rmdir(filename), 0); rmdir2(filename); policy = "allow_unlink /tmp/unlink_test"; write_domain_policy(policy, 0); filename = "/tmp/unlink_test"; create2(filename); show_result(unlink(filename), 1); write_domain_policy(policy, 1); create2(filename); show_result(unlink(filename), 0); unlink2(filename); policy = "allow_symlink /tmp/symlink_source_test"; write_domain_policy(policy, 0); filename = "/tmp/symlink_source_test"; show_result(symlink("/tmp/symlink_dest_test", filename), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(symlink("/tmp/symlink_dest_test", filename), 0); policy = "allow_symlink /tmp/symlink_source_test"; write_domain_policy(policy, 0); filename = "/tmp/symlink_source_test"; show_result(symlink("/tmp/symlink_dest_test", filename), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(symlink("/tmp/symlink_dest_test", filename), 0); policy = "allow_symlink /tmp/symlink_source_test"; write_domain_policy(policy, 0); filename = "/tmp/symlink_source_test"; show_result(symlink("/tmp/symlink_dest_test", filename), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(symlink("/tmp/symlink_dest_test", filename), 0); policy = "allow_symlink /tmp/symlink_source_test"; write_domain_policy(policy, 0); filename = "/tmp/symlink_source_test"; show_result(symlink("/tmp/symlink_dest_test", filename), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(symlink("/tmp/symlink_dest_test", filename), 0); policy = "allow_symlink /tmp/symlink_source_test"; write_domain_policy(policy, 0); filename = "/tmp/symlink_source_test"; show_result(symlink("/tmp/symlink_dest_test", filename), 1); write_domain_policy(policy, 1); unlink2(filename); show_result(symlink("/tmp/symlink_dest_test", filename), 0); policy = "allow_link /tmp/link_source_test /tmp/link_dest_test"; write_domain_policy(policy, 0); filename = "/tmp/link_source_test"; create2(filename); show_result(link(filename, "/tmp/link_dest_test"), 1); write_domain_policy(policy, 1); unlink2("/tmp/link_dest_test"); show_result(link(filename, "/tmp/link_dest_test"), 0); unlink2(filename); policy = "allow_rename /tmp/rename_source_test /tmp/rename_dest_test"; write_domain_policy(policy, 0); filename = "/tmp/rename_source_test"; create2(filename); show_result(rename(filename, "/tmp/rename_dest_test"), 1); write_domain_policy(policy, 1); unlink2("/tmp/rename_dest_test"); create2(filename); show_result(rename(filename, "/tmp/rename_dest_test"), 0); unlink2(filename); policy = "allow_mksock /tmp/socket_test 0755"; write_domain_policy(policy, 0); filename = "/tmp/socket_test"; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, filename, sizeof(addr.sun_path) - 1); fd = socket(AF_UNIX, SOCK_STREAM, 0); show_result(bind(fd, (struct sockaddr *)&addr, sizeof(addr)), 1); if (fd != EOF) close(fd); write_domain_policy(policy, 1); unlink2(filename); fd = socket(AF_UNIX, SOCK_STREAM, 0); show_result(bind(fd, (struct sockaddr *)&addr, sizeof(addr)), 0); if (fd != EOF) close(fd); filename = "/tmp/rewrite_test"; create2(filename); policy = "allow_read/write /tmp/rewrite_test"; write_domain_policy(policy, 0); write_exception_policy("deny_rewrite /tmp/rewrite_test", 0); policy = "allow_truncate /tmp/rewrite_test"; write_domain_policy(policy, 0); fd = open(filename, O_RDONLY); show_result(fd, 1); if (fd != EOF) close(fd); fd = open(filename, O_WRONLY | O_APPEND); show_result(fd, 1); if (fd != EOF) close(fd); fd = open(filename, O_WRONLY); show_result(fd, 0); if (fd != EOF) close(fd); fd = open(filename, O_WRONLY | O_TRUNC); show_result(fd, 0); if (fd != EOF) close(fd); fd = open(filename, O_WRONLY | O_TRUNC | O_APPEND); show_result(fd, 0); if (fd != EOF) close(fd); show_result(truncate(filename, 0), 0); set_profile(0, "file::open"); fd = open(filename, O_WRONLY | O_APPEND); set_profile(3, "file::open"); show_result(ftruncate(fd, 0), 0); show_result(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_APPEND), 0); if (fd != EOF) close(fd); write_domain_policy(policy, 1); policy = "allow_read/write /tmp/rewrite_test"; write_domain_policy(policy, 1); write_exception_policy("deny_rewrite /tmp/rewrite_test", 1); unlink2(filename); policy = "allow_ioctl socket:[family=2:type=2:protocol=17] " "35122-35124"; write_domain_policy(policy, 0); fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); memset(&ifreq, 0, sizeof(ifreq)); snprintf(ifreq.ifr_name, sizeof(ifreq.ifr_name) - 1, "lo"); show_result(ioctl(fd, 35123, &ifreq), 1); write_domain_policy(policy, 1); policy = "allow_ioctl " "socket:[family=2:type=2:protocol=17] 0-35122"; write_domain_policy(policy, 0); show_result(ioctl(fd, 35123, &ifreq), 0); write_domain_policy(policy, 1); if (fd != EOF) close(fd); } int main(int argc, char *argv[]) { tomoyo_test_init(); fprintf(domain_fp, "%s /bin/true\n", self_domain); fprintf(domain_fp, "use_profile 255\n"); fprintf(domain_fp, "select pid=%u\n", pid); fprintf(profile_fp, "255-PREFERENCE::audit={ max_reject_log=1024 }\n"); stage_file_test(); fprintf(domain_fp, "use_profile 0\n"); clear_status(); return 0; }