From: semarie Date: Fri, 9 Oct 2015 06:44:13 +0000 (+0000) Subject: follow tame->pledge in regress X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=70bd4cc89ffd82cf6611540cc17a113837fca5ce;p=openbsd follow tame->pledge in regress --- diff --git a/regress/sys/kern/pledge/Makefile b/regress/sys/kern/pledge/Makefile new file mode 100644 index 00000000000..cd2ac4d4a8c --- /dev/null +++ b/regress/sys/kern/pledge/Makefile @@ -0,0 +1,7 @@ +# $OpenBSD: Makefile,v 1.1 2015/10/09 06:44:13 semarie Exp $ + +SUBDIR += sigabrt +SUBDIR += sigkill +SUBDIR += generic + +.include diff --git a/regress/sys/kern/pledge/generic/Makefile b/regress/sys/kern/pledge/generic/Makefile new file mode 100644 index 00000000000..28f2da0f1c7 --- /dev/null +++ b/regress/sys/kern/pledge/generic/Makefile @@ -0,0 +1,21 @@ +# $OpenBSD: Makefile,v 1.1 2015/10/09 06:44:13 semarie Exp $ +PROG= generic +SRCS+= main.c manager.c +NOMAN= yes + +CFLAGS+= -Wall -Werror + +REGRESS_TARGETS+= test_normal test_systrace +REGRESS_SKIP_TARGETS+= test_systrace + +test_normal: ${PROG} + ./${PROG} | diff -I OpenBSD -u ${.CURDIR}/tests.out - + +test_systrace: ${PROG} + systrace -A ./${PROG} | diff -I OpenBSD -u ${.CURDIR}/tests.out - + +regenerate: ${PROG} + echo '# $$OpenBSD: Makefile,v 1.1 2015/10/09 06:44:13 semarie Exp $$' > ${.CURDIR}/tests.out + ./${PROG} | tee -a ${.CURDIR}/tests.out + +.include diff --git a/regress/sys/kern/pledge/generic/main.c b/regress/sys/kern/pledge/generic/main.c new file mode 100644 index 00000000000..23fbbcb9edd --- /dev/null +++ b/regress/sys/kern/pledge/generic/main.c @@ -0,0 +1,338 @@ +/* $OpenBSD: main.c,v 1.1 2015/10/09 06:44:13 semarie Exp $ */ +/* + * Copyright (c) 2015 Sebastien Marie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "manager.h" + +static void +test_nop() +{ + /* nop */ +} + +static void +test_inet() +{ + int fd = socket(AF_INET, SOCK_STREAM, 0); + int saved_errno = errno; + close(fd); + errno = saved_errno ? saved_errno : errno; +} + +static void +test_kill() +{ + kill(0, SIGINT); +} + +static void +test_allowed_syscalls() +{ + clock_getres(CLOCK_MONOTONIC, NULL); + clock_gettime(CLOCK_MONOTONIC, NULL); + /* fchdir(); */ + getdtablecount(); + getegid(); + geteuid(); + getgid(); + getgroups(0, NULL); + getitimer(ITIMER_REAL, NULL); + getlogin(); + getpgid(0); + getpgrp(); + getpid(); + getppid(); + /* getresgid(); */ + /* getresuid(); */ + { struct rlimit rl; getrlimit(RLIMIT_CORE, &rl); } + getsid(0); + getthrid(); + { struct timeval tp; gettimeofday(&tp, NULL); } + getuid(); + geteuid(); + issetugid(); + /* nanosleep(); */ + /* sigreturn(); */ + umask(0000); + /* wait4(); */ +} + + +static void +open_close(const char *filename) +{ + int fd; + int saved_errno; + + errno = 0; + printf("\n open_close(\"%s\")", filename); + fd = open(filename, O_RDONLY); + saved_errno = errno; + printf(" fd=%d errno=%d", fd, errno); + if (fd != -1) + close(fd); + errno = saved_errno; +} + +static void +test_wpaths() +{ + /* absolute file */ + open_close("/etc/passwd"); + + /* relative */ + open_close("generic"); + + /* relative */ + open_close("../../../../../../../../../../../../../../../etc/passwd"); + + /* ENOENT */ + open_close("/nonexistent"); + + /* calling exit to flush stdout */ + printf("\n"); + exit(EXIT_SUCCESS); +} + +static void +test_pledge() +{ + const char *wpaths[] = { "/sbin", NULL }; + + if (pledge("stdio rpath", wpaths) != 0) + _exit(errno); +} + +static void +do_stat(const char *path) +{ + char resolved[PATH_MAX]; + struct stat sb; + + printf("\n stat(\"%s\"):", path); + + /* call realpath(3) */ + errno = 0; + if (realpath(path, resolved) != NULL) + printf(" realpath=\"%s\"", resolved); + else + printf(" realpath=failed(%d)", errno); + + /* call stat(2) */ + errno = 0; + if (stat(path, &sb) == 0) + printf(" uid=%d gid=%d mode=%04o", sb.st_uid, sb.st_gid, + sb.st_mode); + else + printf(" errno=%d", errno); +} + +static void +test_stat() +{ + /* in whitelisted path */ + do_stat("/usr/share/man/man8/afterboot.8"); + do_stat("/usr/share/man/man8/"); + do_stat("/usr/share/man"); + + /* parent of whitelisted path */ + do_stat("/usr/share"); + do_stat("/usr"); + do_stat("/"); + + /* outside whitelisted path */ + do_stat("/usr/bin/gzip"); + + /* calling exit to flush stdout */ + printf("\n"); + exit(EXIT_SUCCESS); +} + +static void +test_mmap() +{ + int fd; + void * data; + + if ((fd = open("/dev/zero", O_RDONLY, 0)) == -1) + _exit(errno); + + data = mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FILE|MAP_SHARED, fd, 0); + + if (data == MAP_FAILED) + _exit(errno); + + munmap(data, 4096); + close(fd); +} + +static void +test_rpath() +{ + int fd; + char data[512]; + + if ((fd = open("/dev/zero", O_RDONLY, 0)) == -1) + _exit(errno); + + if (read(fd, data, sizeof(data)) == -1) + _exit(errno); + + close(fd); +} + +static void +test_wpath() +{ + int fd; + char data[] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; + + if ((fd = open("/dev/null", O_WRONLY, 0)) == -1) + _exit(errno); + + if (write(fd, data, sizeof(data)) == -1) + _exit(errno); + + close(fd); +} + +static void +test_cpath() +{ + const char filename[] = "/tmp/generic-test-cpath"; + + if (mkdir(filename, S_IRWXU) == -1) + _exit(errno); + + if (rmdir(filename) == -1) + _exit(errno); +} + +int +main(int argc, char *argv[]) +{ + int ret = EXIT_SUCCESS; + + if (argc != 1) + errx(1, "usage: %s", argv[0]); + + /* + * testsuite + */ + + /* _exit is always allowed, and nothing else under flags=0 */ + start_test(&ret, "", NULL, test_nop); + start_test(&ret, "", NULL, test_inet); + + /* test coredump */ + start_test(&ret, "abort", NULL, test_inet); + + /* inet under inet is ok */ + start_test(&ret, "inet", NULL, test_inet); + + /* kill under inet is forbidden */ + start_test(&ret, "inet", NULL, test_kill); + + /* kill under proc is allowed */ + start_test(&ret, "proc", NULL, test_kill); + + /* tests PLEDGE_SELF for permitted syscalls */ + start_test(&ret, "malloc", NULL, test_allowed_syscalls); + start_test(&ret, "rw", NULL, test_allowed_syscalls); + start_test(&ret, "stdio", NULL, test_allowed_syscalls); + start_test(&ret, "rpath", NULL, test_allowed_syscalls); + start_test(&ret, "wpath", NULL, test_allowed_syscalls); + start_test(&ret, "tmppath", NULL, test_allowed_syscalls); + start_test(&ret, "inet", NULL, test_allowed_syscalls); + start_test(&ret, "unix", NULL, test_allowed_syscalls); + start_test(&ret, "dns", NULL, test_allowed_syscalls); + start_test(&ret, "getpw", NULL, test_allowed_syscalls); + + /* tests req without PLEDGE_SELF for "permitted syscalls" */ + // XXX it is a documentation bug + start_test(&ret, "cmsg", NULL, test_allowed_syscalls); + start_test(&ret, "ioctl", NULL, test_allowed_syscalls); + start_test(&ret, "proc", NULL, test_allowed_syscalls); + start_test(&ret, "cpath", NULL, test_allowed_syscalls); + start_test(&ret, "abort", NULL, test_allowed_syscalls); + start_test(&ret, "fattr", NULL, test_allowed_syscalls); + + start_test(&ret, "rpath", NULL, test_rpath); + start_test(&ret, "wpath", NULL, test_wpath); + start_test(&ret, "cpath", NULL, test_cpath); + + /* + * test whitelist path + */ + start_test(&ret, "stdio rpath", NULL, test_wpaths); + start_test1(&ret, "stdio rpath", NULL, test_wpaths); + start_test1(&ret, "stdio rpath", "/", test_wpaths); + start_test1(&ret, "stdio rpath", "/etc", test_wpaths); + start_test1(&ret, "stdio rpath", "/etc/", test_wpaths); + start_test1(&ret, "stdio rpath", "/etc/passwd", test_wpaths); + // XXX start_test1(&ret, "stdio rpath", "/etc/passwd/", test_wpaths); + start_test1(&ret, "stdio rpath", "/bin", test_wpaths); + start_test1(&ret, "stdio rpath", "generic", test_wpaths); + start_test1(&ret, "stdio rpath", "", test_wpaths); + start_test1(&ret, "stdio rpath", ".", test_wpaths); + + /* + * test pledge(2) arguments + */ + /* same request */ + start_test(&ret, "stdio rpath", NULL, test_pledge); + /* same request (stdio = malloc rw) */ + start_test(&ret, "malloc rw rpath", NULL, test_pledge); + /* reduce request */ + start_test(&ret, "stdio rpath wpath", NULL, test_pledge); + /* reduce request (with same/other wpaths) */ + start_test1(&ret, "stdio rpath wpath", "/sbin", test_pledge); + start_test1(&ret, "stdio rpath wpath", "/", test_pledge); + /* add request */ + start_test(&ret, "stdio", NULL, test_pledge); + /* change request */ + start_test(&ret, "unix", NULL, test_pledge); + + /* test stat(2) */ + start_test1(&ret, "stdio rpath", "/usr/share/man", test_stat); + + /* mmap */ + start_test1(&ret, "rpath malloc prot_exec", "/dev/zero", test_mmap); + start_test1(&ret, "rpath malloc", "/dev/zero", test_mmap); + + return (ret); +} diff --git a/regress/sys/kern/pledge/generic/manager.c b/regress/sys/kern/pledge/generic/manager.c new file mode 100644 index 00000000000..800316aed68 --- /dev/null +++ b/regress/sys/kern/pledge/generic/manager.c @@ -0,0 +1,334 @@ +/* $OpenBSD: manager.c,v 1.1 2015/10/09 06:44:13 semarie Exp $ */ +/* + * Copyright (c) 2015 Sebastien Marie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char *__progname; + +static const char * +coredump_name() +{ + static char coredump[PATH_MAX] = ""; + + if (*coredump) + return (coredump); + + if (strlcpy(coredump, __progname, sizeof(coredump)) >= sizeof(coredump)) + errx(1, "coredump: strlcpy"); + + if (strlcat(coredump, ".core", sizeof(coredump)) >= sizeof(coredump)) + errx(1, "coredump: strlcat"); + + return (coredump); +} + + +static int +check_coredump() +{ + const char *coredump = coredump_name(); + int fd; + + if ((fd = open(coredump, O_RDONLY)) == -1) { + if (errno == ENOENT) + return (1); /* coredump not found */ + else + return (-1); /* error */ + } + + (void)close(fd); + return (0); /* coredump found */ +} + + +static int +clear_coredump(int *ret, const char *test_name) +{ + int saved_errno = errno; + int u; + + if (((u = unlink(coredump_name())) != 0) && (errno != ENOENT)) { + warn("test(%s): clear_coredump", test_name); + *ret = EXIT_FAILURE; + return (-1); + } + errno = saved_errno; + + return (0); +} + + +static int +grab_syscall(pid_t pid) +{ + int ret = -1; + char *search = NULL; + int searchlen; + FILE *fd; + char line[1024]; + char *end; + + /* build searched string */ + if ((searchlen = asprintf(&search, "%s(%d): syscall ", __progname, pid)) + <= 0) + goto out; + + /* call dmesg */ + if ((fd = popen("/sbin/dmesg", "r")) == NULL) + goto out; + + /* search the string */ + while (1) { + /* read a line */ + fgets(line, sizeof(line), fd); + + /* error checking */ + if (ferror(fd)) { + ret = -1; + goto out; + } + + /* quit */ + if (feof(fd)) + break; + + /* strip trailing '\n' */ + end = strchr(line, '\n'); + if (*end == '\n') + *end = '\0'; + + /* check if found */ + if (strncmp(search, line, searchlen) == 0) { + const char *errstr = NULL; + /* found */ + ret = strtonum(line + searchlen, 0, 255, &errstr); + if (errstr) { + warn("strtonum: line=%s err=%s", line, errstr); + return (-1); + } + } + } + + /* cleanup */ + if (pclose(fd) == -1) + goto out; + + /* not found */ + if (ret == -1) + ret = 0; + +out: + free(search); + return (ret); +} + +/* mainly stolen from src/bin/cat/cat.c */ +static int +drainfd(int rfd, int wfd) +{ + char buf[1024]; + ssize_t nr, nw, off; + + while ((nr = read(rfd, buf, sizeof(buf))) != -1 && nr != 0) + for (off = 0; nr; nr -= nw, off += nw) + if ((nw = write(wfd, buf + off, (size_t)nr)) == 0 || + nw == -1) + return (-1); + if (nr < 0) + return (-1); + + return (0); +} + +void +_start_test(int *ret, const char *test_name, const char *request, + const char *paths[], void (*test_func)(void)) +{ + int fildes[2]; + pid_t pid; + int status; + int i; + + /* early print testname */ + printf("test(%s): pledge=", test_name); + if (request) { + printf("(\"%s\",", request); + if (paths) { + printf("{"); + for (i = 0; paths[i] != NULL; i++) + printf("\"%s\",", paths[i]); + printf("NULL})"); + } else + printf("NULL)"); + } else + printf("not-called"); + + /* unlink previous coredump (if exists) */ + if (clear_coredump(ret, test_name) == -1) + return; + + /* flush outputs (for STDOUT_FILENO manipulation) */ + if (fflush(NULL) != 0) { + warn("test(%s) fflush", test_name); + *ret = EXIT_FAILURE; + return; + } + + /* make pipe to grab output */ + if (pipe(fildes) != 0) { + warn("test(%s) pipe", test_name); + *ret = EXIT_FAILURE; + return; + } + + /* fork and launch the test */ + switch (pid = fork()) { + case -1: + (void)close(fildes[0]); + (void)close(fildes[1]); + + warn("test(%s) fork", test_name); + *ret = EXIT_FAILURE; + return; + + case 0: + /* output to pipe */ + (void)close(fildes[0]); + while (dup2(fildes[1], STDOUT_FILENO) == -1) + if (errno != EINTR) + err(errno, "dup2"); + + /* create a new session (for kill) */ + setsid(); + + /* set pledge policy */ + if (request && pledge(request, paths) != 0) + err(errno, "pledge"); + + /* reset errno and launch test */ + errno = 0; + test_func(); + + if (errno != 0) + _exit(errno); + + _exit(EXIT_SUCCESS); + /* NOTREACHED */ + } + + /* copy pipe to output */ + (void)close(fildes[1]); + if (drainfd(fildes[0], STDOUT_FILENO) != 0) { + warn("test(%s): drainfd", test_name); + *ret = EXIT_FAILURE; + return; + } + if (close(fildes[0]) != 0) { + warn("test(%s): close", test_name); + *ret = EXIT_FAILURE; + return; + } + + /* wait for test to terminate */ + while (waitpid(pid, &status, 0) < 0) { + if (errno == EAGAIN) + continue; + warn("test(%s): waitpid", test_name); + *ret = EXIT_FAILURE; + return; + } + + /* show status and details */ + printf(" status=%d", status); + + if (WIFCONTINUED(status)) + printf(" continued"); + + if (WIFEXITED(status)) { + int e = WEXITSTATUS(status); + printf(" exit=%d", e); + if (e > 0 && e <= ELAST) + printf(" (errno: \"%s\")", strerror(e)); + } + + if (WIFSIGNALED(status)) { + int signal = WTERMSIG(status); + printf(" signal=%d", signal); + + /* check if core file is really here ? */ + if (WCOREDUMP(status)) { + int coredump = check_coredump(); + + switch(coredump) { + case -1: /* error */ + warn("test(%s): check_coredump", test_name); + *ret = EXIT_FAILURE; + return; + + case 0: /* found */ + printf(" coredump=present"); + break; + + case 1: /* not found */ + printf(" coredump=absent"); + break; + + default: + warnx("test(%s): unknown coredump code %d", + test_name, coredump); + *ret = EXIT_FAILURE; + return; + } + + } + + /* grab pledged syscall from dmesg */ + if ((signal == SIGKILL) || (signal = SIGABRT)) { + int syscall = grab_syscall(pid); + switch (syscall) { + case -1: /* error */ + warn("test(%s): grab_syscall pid=%d", test_name, + pid); + *ret = EXIT_FAILURE; + return; + + case 0: /* not found */ + printf(" pledged_syscall=not_found"); + break; + + default: + printf(" pledged_syscall=%d", syscall); + } + } + } + + if (WIFSTOPPED(status)) + printf(" stop=%d", WSTOPSIG(status)); + + printf("\n"); +} diff --git a/regress/sys/kern/pledge/generic/manager.h b/regress/sys/kern/pledge/generic/manager.h new file mode 100644 index 00000000000..13c52eea75a --- /dev/null +++ b/regress/sys/kern/pledge/generic/manager.h @@ -0,0 +1,32 @@ +/* $OpenBSD: manager.h,v 1.1 2015/10/09 06:44:13 semarie Exp $ */ +/* + * Copyright (c) 2015 Sebastien Marie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _MANAGER_H_ +#define _MANAGER_H_ + +void _start_test(int *ret, const char *test_name, const char *request, + const char *paths[], void (*test_func)(void)); + +#define start_test(ret,req,paths,func) \ + _start_test(ret,#func,req,paths,func) + +#define start_test1(ret,req,path,func) \ + do { \ + const char *_paths[] = {path, NULL}; \ + start_test(ret,req,_paths,func); \ + } while (0) + +#endif /* _MANAGER_H_ */ diff --git a/regress/sys/kern/pledge/generic/tests.out b/regress/sys/kern/pledge/generic/tests.out new file mode 100644 index 00000000000..5fc8fd7e192 --- /dev/null +++ b/regress/sys/kern/pledge/generic/tests.out @@ -0,0 +1,104 @@ +# $OpenBSD: tests.out,v 1.1 2015/10/09 06:44:13 semarie Exp $ +test(test_nop): pledge=("",NULL) status=0 exit=0 +test(test_inet): pledge=("",NULL) status=9 signal=9 pledged_syscall=97 +test(test_inet): pledge=("abort",NULL) status=134 signal=6 coredump=present pledged_syscall=97 +test(test_inet): pledge=("inet",NULL) status=0 exit=0 +test(test_kill): pledge=("inet",NULL) status=9 signal=9 pledged_syscall=37 +test(test_kill): pledge=("proc",NULL) status=2 signal=2 pledged_syscall=not_found +test(test_allowed_syscalls): pledge=("malloc",NULL) status=0 exit=0 +test(test_allowed_syscalls): pledge=("rw",NULL) status=0 exit=0 +test(test_allowed_syscalls): pledge=("stdio",NULL) status=0 exit=0 +test(test_allowed_syscalls): pledge=("rpath",NULL) status=0 exit=0 +test(test_allowed_syscalls): pledge=("wpath",NULL) status=0 exit=0 +test(test_allowed_syscalls): pledge=("tmppath",NULL) status=0 exit=0 +test(test_allowed_syscalls): pledge=("inet",NULL) status=0 exit=0 +test(test_allowed_syscalls): pledge=("unix",NULL) status=0 exit=0 +test(test_allowed_syscalls): pledge=("dns",NULL) status=0 exit=0 +test(test_allowed_syscalls): pledge=("getpw",NULL) status=0 exit=0 +test(test_allowed_syscalls): pledge=("cmsg",NULL) status=9 signal=9 pledged_syscall=89 +test(test_allowed_syscalls): pledge=("ioctl",NULL) status=9 signal=9 pledged_syscall=89 +test(test_allowed_syscalls): pledge=("proc",NULL) status=9 signal=9 pledged_syscall=89 +test(test_allowed_syscalls): pledge=("cpath",NULL) status=9 signal=9 pledged_syscall=89 +test(test_allowed_syscalls): pledge=("abort",NULL) status=134 signal=6 coredump=present pledged_syscall=89 +test(test_allowed_syscalls): pledge=("fattr",NULL) status=9 signal=9 pledged_syscall=89 +test(test_rpath): pledge=("rpath",NULL) status=0 exit=0 +test(test_wpath): pledge=("wpath",NULL) status=0 exit=0 +test(test_cpath): pledge=("cpath",NULL) status=0 exit=0 +test(test_wpaths): pledge=("stdio rpath",NULL) + open_close("/etc/passwd") fd=3 errno=0 + open_close("generic") fd=3 errno=0 + open_close("../../../../../../../../../../../../../../../etc/passwd") fd=3 errno=0 + open_close("/nonexistent") fd=-1 errno=2 + status=0 exit=0 +test(test_wpaths): pledge=("stdio rpath",{NULL}) + open_close("/etc/passwd") fd=-1 errno=2 + open_close("generic") fd=-1 errno=2 + open_close("../../../../../../../../../../../../../../../etc/passwd") fd=-1 errno=2 + open_close("/nonexistent") fd=-1 errno=2 + status=0 exit=0 +test(test_wpaths): pledge=("stdio rpath",{"/",NULL}) + open_close("/etc/passwd") fd=3 errno=0 + open_close("generic") fd=3 errno=0 + open_close("../../../../../../../../../../../../../../../etc/passwd") fd=3 errno=0 + open_close("/nonexistent") fd=-1 errno=2 + status=0 exit=0 +test(test_wpaths): pledge=("stdio rpath",{"/etc",NULL}) + open_close("/etc/passwd") fd=3 errno=0 + open_close("generic") fd=-1 errno=2 + open_close("../../../../../../../../../../../../../../../etc/passwd") fd=3 errno=0 + open_close("/nonexistent") fd=-1 errno=2 + status=0 exit=0 +test(test_wpaths): pledge=("stdio rpath",{"/etc/",NULL}) + open_close("/etc/passwd") fd=3 errno=0 + open_close("generic") fd=-1 errno=2 + open_close("../../../../../../../../../../../../../../../etc/passwd") fd=3 errno=0 + open_close("/nonexistent") fd=-1 errno=2 + status=0 exit=0 +test(test_wpaths): pledge=("stdio rpath",{"/etc/passwd",NULL}) + open_close("/etc/passwd") fd=3 errno=0 + open_close("generic") fd=-1 errno=2 + open_close("../../../../../../../../../../../../../../../etc/passwd") fd=3 errno=0 + open_close("/nonexistent") fd=-1 errno=2 + status=0 exit=0 +test(test_wpaths): pledge=("stdio rpath",{"/bin",NULL}) + open_close("/etc/passwd") fd=-1 errno=2 + open_close("generic") fd=-1 errno=2 + open_close("../../../../../../../../../../../../../../../etc/passwd") fd=-1 errno=2 + open_close("/nonexistent") fd=-1 errno=2 + status=0 exit=0 +test(test_wpaths): pledge=("stdio rpath",{"generic",NULL}) + open_close("/etc/passwd") fd=-1 errno=2 + open_close("generic") fd=3 errno=0 + open_close("../../../../../../../../../../../../../../../etc/passwd") fd=-1 errno=2 + open_close("/nonexistent") fd=-1 errno=2 + status=0 exit=0 +test(test_wpaths): pledge=("stdio rpath",{"",NULL}) + open_close("/etc/passwd") fd=-1 errno=2 + open_close("generic") fd=3 errno=0 + open_close("../../../../../../../../../../../../../../../etc/passwd") fd=-1 errno=2 + open_close("/nonexistent") fd=-1 errno=2 + status=0 exit=0 +test(test_wpaths): pledge=("stdio rpath",{".",NULL}) + open_close("/etc/passwd") fd=-1 errno=2 + open_close("generic") fd=3 errno=0 + open_close("../../../../../../../../../../../../../../../etc/passwd") fd=-1 errno=2 + open_close("/nonexistent") fd=-1 errno=2 + status=0 exit=0 +test(test_pledge): pledge=("stdio rpath",NULL) status=0 exit=0 +test(test_pledge): pledge=("malloc rw rpath",NULL) status=0 exit=0 +test(test_pledge): pledge=("stdio rpath wpath",NULL) status=0 exit=0 +test(test_pledge): pledge=("stdio rpath wpath",{"/sbin",NULL}) status=256 exit=1 (errno: "Operation not permitted") +test(test_pledge): pledge=("stdio rpath wpath",{"/",NULL}) status=256 exit=1 (errno: "Operation not permitted") +test(test_pledge): pledge=("stdio",NULL) status=256 exit=1 (errno: "Operation not permitted") +test(test_pledge): pledge=("unix",NULL) status=256 exit=1 (errno: "Operation not permitted") +test(test_stat): pledge=("stdio rpath",{"/usr/share/man",NULL}) + stat("/usr/share/man/man8/afterboot.8"): realpath=failed(2) uid=0 gid=7 mode=100444 + stat("/usr/share/man/man8/"): realpath=failed(2) uid=0 gid=0 mode=40755 + stat("/usr/share/man"): realpath=failed(2) uid=0 gid=0 mode=40755 + stat("/usr/share"): realpath=failed(2) errno=2 + stat("/usr"): realpath="/usr" errno=2 + stat("/"): realpath="/" errno=2 + stat("/usr/bin/gzip"): realpath=failed(2) errno=2 + status=0 exit=0 +test(test_mmap): pledge=("rpath malloc prot_exec",{"/dev/zero",NULL}) status=0 exit=0 +test(test_mmap): pledge=("rpath malloc",{"/dev/zero",NULL}) status=9 signal=9 pledged_syscall=197 diff --git a/regress/sys/kern/pledge/sigabrt/Makefile b/regress/sys/kern/pledge/sigabrt/Makefile new file mode 100644 index 00000000000..43fde4ca8a4 --- /dev/null +++ b/regress/sys/kern/pledge/sigabrt/Makefile @@ -0,0 +1,11 @@ +# $OpenBSD: Makefile,v 1.1 2015/10/09 06:44:13 semarie Exp $ +PROG= sigabrt +NOMAN= yes + +run-regress-${PROG}: ${PROG} + rm -f ./${PROG}.core + if ./${PROG}; then false; else true; fi + if [ ! -e ./${PROG}.core ]; then echo "No coredump"; false; fi + ./${PROG} | diff -I OpenBSD -u ${.CURDIR}/${PROG}.out - + +.include diff --git a/regress/sys/kern/pledge/sigabrt/sigabrt.c b/regress/sys/kern/pledge/sigabrt/sigabrt.c new file mode 100644 index 00000000000..ef7dc1db9a7 --- /dev/null +++ b/regress/sys/kern/pledge/sigabrt/sigabrt.c @@ -0,0 +1,49 @@ +/* $OpenBSD: sigabrt.c,v 1.1 2015/10/09 06:44:13 semarie Exp $ */ +/* + * Copyright (c) 2015 Sebastien Marie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +void +handler(int sigraised) +{ + /* this handler shouldn't not be called */ + printf("forbidden STDIO in SIGABRT handler\n"); +} + +int +main(int argc, char *argv[]) +{ + /* install SIGABRT handler */ + signal(SIGABRT, &handler); + + printf("permitted STDIO\n"); + fflush(stdout); + + if (pledge("abort", NULL) == -1) + err(EXIT_FAILURE, "pledge"); + + /* this will triggered pledge_fail() */ + printf("forbidden STDIO 1\n"); + + /* shouldn't continue */ + printf("forbidden STDIO 2\n"); + return (EXIT_SUCCESS); +} diff --git a/regress/sys/kern/pledge/sigabrt/sigabrt.out b/regress/sys/kern/pledge/sigabrt/sigabrt.out new file mode 100644 index 00000000000..b0261dd76ae --- /dev/null +++ b/regress/sys/kern/pledge/sigabrt/sigabrt.out @@ -0,0 +1,2 @@ +$OpenBSD: sigabrt.out,v 1.1 2015/10/09 06:44:13 semarie Exp $ +permitted STDIO diff --git a/regress/sys/kern/pledge/sigkill/Makefile b/regress/sys/kern/pledge/sigkill/Makefile new file mode 100644 index 00000000000..3aeca2487cf --- /dev/null +++ b/regress/sys/kern/pledge/sigkill/Makefile @@ -0,0 +1,11 @@ +# $OpenBSD: Makefile,v 1.1 2015/10/09 06:44:13 semarie Exp $ +PROG= sigkill +NOMAN= yes + +run-regress-${PROG}: ${PROG} + rm -f ./${PROG}.core + if ./${PROG}; then false; else true; fi + if [ -e ./${PROG}.core ]; then echo "Unexpected coredump"; false; fi + ./${PROG} | diff -I OpenBSD -u ${.CURDIR}/${PROG}.out - + +.include diff --git a/regress/sys/kern/pledge/sigkill/sigkill.c b/regress/sys/kern/pledge/sigkill/sigkill.c new file mode 100644 index 00000000000..fcabcd0b1cb --- /dev/null +++ b/regress/sys/kern/pledge/sigkill/sigkill.c @@ -0,0 +1,50 @@ +/* $OpenBSD: sigkill.c,v 1.1 2015/10/09 06:44:13 semarie Exp $ */ +/* + * Copyright (c) 2015 Sebastien Marie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +void +handler(int sigraised) +{ + /* the handler shouldn't not be called */ + printf("forbidden STDIO in %d handler\n", sigraised); +} + +int +main(int argc, char *argv[]) +{ + /* install some handlers */ + signal(SIGHUP, &handler); + signal(SIGABRT, &handler); + + printf("permitted STDIO\n"); + fflush(stdout); + + if (pledge("", NULL) == -1) + err(EXIT_FAILURE, "pledge"); + + /* this will triggered pledge_fail() */ + printf("forbidden STDIO 1\n"); + + /* shouldn't continue */ + printf("forbidden STDIO 2\n"); + return (EXIT_SUCCESS); +} diff --git a/regress/sys/kern/pledge/sigkill/sigkill.out b/regress/sys/kern/pledge/sigkill/sigkill.out new file mode 100644 index 00000000000..936362eab98 --- /dev/null +++ b/regress/sys/kern/pledge/sigkill/sigkill.out @@ -0,0 +1,2 @@ +$OpenBSD: sigkill.out,v 1.1 2015/10/09 06:44:13 semarie Exp $ +permitted STDIO diff --git a/regress/sys/kern/tame/Makefile b/regress/sys/kern/tame/Makefile deleted file mode 100644 index 77679562375..00000000000 --- a/regress/sys/kern/tame/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $OpenBSD: Makefile,v 1.2 2015/09/10 11:18:34 semarie Exp $ - -SUBDIR += sigabrt -SUBDIR += sigkill -SUBDIR += generic - -.include diff --git a/regress/sys/kern/tame/generic/Makefile b/regress/sys/kern/tame/generic/Makefile deleted file mode 100644 index 65815a42431..00000000000 --- a/regress/sys/kern/tame/generic/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# $OpenBSD: Makefile,v 1.3 2015/09/24 06:25:54 semarie Exp $ -PROG= generic -SRCS+= main.c manager.c -NOMAN= yes - -CFLAGS+= -Wall -Werror - -REGRESS_TARGETS+= test_normal test_systrace -REGRESS_SKIP_TARGETS+= test_systrace - -test_normal: ${PROG} - ./${PROG} | diff -I OpenBSD -u ${.CURDIR}/tests.out - - -test_systrace: ${PROG} - systrace -A ./${PROG} | diff -I OpenBSD -u ${.CURDIR}/tests.out - - -regenerate: ${PROG} - echo '# $$OpenBSD: Makefile,v 1.3 2015/09/24 06:25:54 semarie Exp $$' > ${.CURDIR}/tests.out - ./${PROG} | tee -a ${.CURDIR}/tests.out - -.include diff --git a/regress/sys/kern/tame/generic/main.c b/regress/sys/kern/tame/generic/main.c deleted file mode 100644 index a916177957c..00000000000 --- a/regress/sys/kern/tame/generic/main.c +++ /dev/null @@ -1,338 +0,0 @@ -/* $OpenBSD: main.c,v 1.10 2015/10/06 15:45:31 semarie Exp $ */ -/* - * Copyright (c) 2015 Sebastien Marie - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "manager.h" - -static void -test_nop() -{ - /* nop */ -} - -static void -test_inet() -{ - int fd = socket(AF_INET, SOCK_STREAM, 0); - int saved_errno = errno; - close(fd); - errno = saved_errno ? saved_errno : errno; -} - -static void -test_kill() -{ - kill(0, SIGINT); -} - -static void -test_allowed_syscalls() -{ - clock_getres(CLOCK_MONOTONIC, NULL); - clock_gettime(CLOCK_MONOTONIC, NULL); - /* fchdir(); */ - getdtablecount(); - getegid(); - geteuid(); - getgid(); - getgroups(0, NULL); - getitimer(ITIMER_REAL, NULL); - getlogin(); - getpgid(0); - getpgrp(); - getpid(); - getppid(); - /* getresgid(); */ - /* getresuid(); */ - { struct rlimit rl; getrlimit(RLIMIT_CORE, &rl); } - getsid(0); - getthrid(); - { struct timeval tp; gettimeofday(&tp, NULL); } - getuid(); - geteuid(); - issetugid(); - /* nanosleep(); */ - /* sigreturn(); */ - umask(0000); - /* wait4(); */ -} - - -static void -open_close(const char *filename) -{ - int fd; - int saved_errno; - - errno = 0; - printf("\n open_close(\"%s\")", filename); - fd = open(filename, O_RDONLY); - saved_errno = errno; - printf(" fd=%d errno=%d", fd, errno); - if (fd != -1) - close(fd); - errno = saved_errno; -} - -static void -test_wpaths() -{ - /* absolute file */ - open_close("/etc/passwd"); - - /* relative */ - open_close("generic"); - - /* relative */ - open_close("../../../../../../../../../../../../../../../etc/passwd"); - - /* ENOENT */ - open_close("/nonexistent"); - - /* calling exit to flush stdout */ - printf("\n"); - exit(EXIT_SUCCESS); -} - -static void -test_tame() -{ - const char *wpaths[] = { "/sbin", NULL }; - - if (tame("stdio rpath", wpaths) != 0) - _exit(errno); -} - -static void -do_stat(const char *path) -{ - char resolved[PATH_MAX]; - struct stat sb; - - printf("\n stat(\"%s\"):", path); - - /* call realpath(3) */ - errno = 0; - if (realpath(path, resolved) != NULL) - printf(" realpath=\"%s\"", resolved); - else - printf(" realpath=failed(%d)", errno); - - /* call stat(2) */ - errno = 0; - if (stat(path, &sb) == 0) - printf(" uid=%d gid=%d mode=%04o", sb.st_uid, sb.st_gid, - sb.st_mode); - else - printf(" errno=%d", errno); -} - -static void -test_stat() -{ - /* in whitelisted path */ - do_stat("/usr/share/man/man8/afterboot.8"); - do_stat("/usr/share/man/man8/"); - do_stat("/usr/share/man"); - - /* parent of whitelisted path */ - do_stat("/usr/share"); - do_stat("/usr"); - do_stat("/"); - - /* outside whitelisted path */ - do_stat("/usr/bin/gzip"); - - /* calling exit to flush stdout */ - printf("\n"); - exit(EXIT_SUCCESS); -} - -static void -test_mmap() -{ - int fd; - void * data; - - if ((fd = open("/dev/zero", O_RDONLY, 0)) == -1) - _exit(errno); - - data = mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_FILE|MAP_SHARED, fd, 0); - - if (data == MAP_FAILED) - _exit(errno); - - munmap(data, 4096); - close(fd); -} - -static void -test_rpath() -{ - int fd; - char data[512]; - - if ((fd = open("/dev/zero", O_RDONLY, 0)) == -1) - _exit(errno); - - if (read(fd, data, sizeof(data)) == -1) - _exit(errno); - - close(fd); -} - -static void -test_wpath() -{ - int fd; - char data[] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; - - if ((fd = open("/dev/null", O_WRONLY, 0)) == -1) - _exit(errno); - - if (write(fd, data, sizeof(data)) == -1) - _exit(errno); - - close(fd); -} - -static void -test_cpath() -{ - const char filename[] = "/tmp/generic-test-cpath"; - - if (mkdir(filename, S_IRWXU) == -1) - _exit(errno); - - if (rmdir(filename) == -1) - _exit(errno); -} - -int -main(int argc, char *argv[]) -{ - int ret = EXIT_SUCCESS; - - if (argc != 1) - errx(1, "usage: %s", argv[0]); - - /* - * testsuite - */ - - /* _exit is always allowed, and nothing else under flags=0 */ - start_test(&ret, "", NULL, test_nop); - start_test(&ret, "", NULL, test_inet); - - /* test coredump */ - start_test(&ret, "abort", NULL, test_inet); - - /* inet under inet is ok */ - start_test(&ret, "inet", NULL, test_inet); - - /* kill under inet is forbidden */ - start_test(&ret, "inet", NULL, test_kill); - - /* kill under proc is allowed */ - start_test(&ret, "proc", NULL, test_kill); - - /* tests TAME_SELF for permitted syscalls */ - start_test(&ret, "malloc", NULL, test_allowed_syscalls); - start_test(&ret, "rw", NULL, test_allowed_syscalls); - start_test(&ret, "stdio", NULL, test_allowed_syscalls); - start_test(&ret, "rpath", NULL, test_allowed_syscalls); - start_test(&ret, "wpath", NULL, test_allowed_syscalls); - start_test(&ret, "tmppath", NULL, test_allowed_syscalls); - start_test(&ret, "inet", NULL, test_allowed_syscalls); - start_test(&ret, "unix", NULL, test_allowed_syscalls); - start_test(&ret, "dns", NULL, test_allowed_syscalls); - start_test(&ret, "getpw", NULL, test_allowed_syscalls); - - /* tests req without TAME_SELF for "permitted syscalls" */ - // XXX it is a documentation bug - start_test(&ret, "cmsg", NULL, test_allowed_syscalls); - start_test(&ret, "ioctl", NULL, test_allowed_syscalls); - start_test(&ret, "proc", NULL, test_allowed_syscalls); - start_test(&ret, "cpath", NULL, test_allowed_syscalls); - start_test(&ret, "abort", NULL, test_allowed_syscalls); - start_test(&ret, "fattr", NULL, test_allowed_syscalls); - - start_test(&ret, "rpath", NULL, test_rpath); - start_test(&ret, "wpath", NULL, test_wpath); - start_test(&ret, "cpath", NULL, test_cpath); - - /* - * test whitelist path - */ - start_test(&ret, "stdio rpath", NULL, test_wpaths); - start_test1(&ret, "stdio rpath", NULL, test_wpaths); - start_test1(&ret, "stdio rpath", "/", test_wpaths); - start_test1(&ret, "stdio rpath", "/etc", test_wpaths); - start_test1(&ret, "stdio rpath", "/etc/", test_wpaths); - start_test1(&ret, "stdio rpath", "/etc/passwd", test_wpaths); - // XXX start_test1(&ret, "stdio rpath", "/etc/passwd/", test_wpaths); - start_test1(&ret, "stdio rpath", "/bin", test_wpaths); - start_test1(&ret, "stdio rpath", "generic", test_wpaths); - start_test1(&ret, "stdio rpath", "", test_wpaths); - start_test1(&ret, "stdio rpath", ".", test_wpaths); - - /* - * test tame(2) arguments - */ - /* same request */ - start_test(&ret, "stdio rpath", NULL, test_tame); - /* same request (stdio = malloc rw) */ - start_test(&ret, "malloc rw rpath", NULL, test_tame); - /* reduce request */ - start_test(&ret, "stdio rpath wpath", NULL, test_tame); - /* reduce request (with same/other wpaths) */ - start_test1(&ret, "stdio rpath wpath", "/sbin", test_tame); - start_test1(&ret, "stdio rpath wpath", "/", test_tame); - /* add request */ - start_test(&ret, "stdio", NULL, test_tame); - /* change request */ - start_test(&ret, "unix", NULL, test_tame); - - /* test stat(2) */ - start_test1(&ret, "stdio rpath", "/usr/share/man", test_stat); - - /* mmap */ - start_test1(&ret, "rpath malloc prot_exec", "/dev/zero", test_mmap); - start_test1(&ret, "rpath malloc", "/dev/zero", test_mmap); - - return (ret); -} diff --git a/regress/sys/kern/tame/generic/manager.c b/regress/sys/kern/tame/generic/manager.c deleted file mode 100644 index c3d0abbc042..00000000000 --- a/regress/sys/kern/tame/generic/manager.c +++ /dev/null @@ -1,334 +0,0 @@ -/* $OpenBSD: manager.c,v 1.5 2015/10/08 10:09:09 semarie Exp $ */ -/* - * Copyright (c) 2015 Sebastien Marie - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern char *__progname; - -static const char * -coredump_name() -{ - static char coredump[PATH_MAX] = ""; - - if (*coredump) - return (coredump); - - if (strlcpy(coredump, __progname, sizeof(coredump)) >= sizeof(coredump)) - errx(1, "coredump: strlcpy"); - - if (strlcat(coredump, ".core", sizeof(coredump)) >= sizeof(coredump)) - errx(1, "coredump: strlcat"); - - return (coredump); -} - - -static int -check_coredump() -{ - const char *coredump = coredump_name(); - int fd; - - if ((fd = open(coredump, O_RDONLY)) == -1) { - if (errno == ENOENT) - return (1); /* coredump not found */ - else - return (-1); /* error */ - } - - (void)close(fd); - return (0); /* coredump found */ -} - - -static int -clear_coredump(int *ret, const char *test_name) -{ - int saved_errno = errno; - int u; - - if (((u = unlink(coredump_name())) != 0) && (errno != ENOENT)) { - warn("test(%s): clear_coredump", test_name); - *ret = EXIT_FAILURE; - return (-1); - } - errno = saved_errno; - - return (0); -} - - -static int -grab_syscall(pid_t pid) -{ - int ret = -1; - char *search = NULL; - int searchlen; - FILE *fd; - char line[1024]; - char *end; - - /* build searched string */ - if ((searchlen = asprintf(&search, "%s(%d): syscall ", __progname, pid)) - <= 0) - goto out; - - /* call dmesg */ - if ((fd = popen("/sbin/dmesg", "r")) == NULL) - goto out; - - /* search the string */ - while (1) { - /* read a line */ - fgets(line, sizeof(line), fd); - - /* error checking */ - if (ferror(fd)) { - ret = -1; - goto out; - } - - /* quit */ - if (feof(fd)) - break; - - /* strip trailing '\n' */ - end = strchr(line, '\n'); - if (*end == '\n') - *end = '\0'; - - /* check if found */ - if (strncmp(search, line, searchlen) == 0) { - const char *errstr = NULL; - /* found */ - ret = strtonum(line + searchlen, 0, 255, &errstr); - if (errstr) { - warn("strtonum: line=%s err=%s", line, errstr); - return (-1); - } - } - } - - /* cleanup */ - if (pclose(fd) == -1) - goto out; - - /* not found */ - if (ret == -1) - ret = 0; - -out: - free(search); - return (ret); -} - -/* mainly stolen from src/bin/cat/cat.c */ -static int -drainfd(int rfd, int wfd) -{ - char buf[1024]; - ssize_t nr, nw, off; - - while ((nr = read(rfd, buf, sizeof(buf))) != -1 && nr != 0) - for (off = 0; nr; nr -= nw, off += nw) - if ((nw = write(wfd, buf + off, (size_t)nr)) == 0 || - nw == -1) - return (-1); - if (nr < 0) - return (-1); - - return (0); -} - -void -_start_test(int *ret, const char *test_name, const char *request, - const char *paths[], void (*test_func)(void)) -{ - int fildes[2]; - pid_t pid; - int status; - int i; - - /* early print testname */ - printf("test(%s): tame=", test_name); - if (request) { - printf("(\"%s\",", request); - if (paths) { - printf("{"); - for (i = 0; paths[i] != NULL; i++) - printf("\"%s\",", paths[i]); - printf("NULL})"); - } else - printf("NULL)"); - } else - printf("not-called"); - - /* unlink previous coredump (if exists) */ - if (clear_coredump(ret, test_name) == -1) - return; - - /* flush outputs (for STDOUT_FILENO manipulation) */ - if (fflush(NULL) != 0) { - warn("test(%s) fflush", test_name); - *ret = EXIT_FAILURE; - return; - } - - /* make pipe to grab output */ - if (pipe(fildes) != 0) { - warn("test(%s) pipe", test_name); - *ret = EXIT_FAILURE; - return; - } - - /* fork and launch the test */ - switch (pid = fork()) { - case -1: - (void)close(fildes[0]); - (void)close(fildes[1]); - - warn("test(%s) fork", test_name); - *ret = EXIT_FAILURE; - return; - - case 0: - /* output to pipe */ - (void)close(fildes[0]); - while (dup2(fildes[1], STDOUT_FILENO) == -1) - if (errno != EINTR) - err(errno, "dup2"); - - /* create a new session (for kill) */ - setsid(); - - /* set tame policy */ - if (request && tame(request, paths) != 0) - err(errno, "tame"); - - /* reset errno and launch test */ - errno = 0; - test_func(); - - if (errno != 0) - _exit(errno); - - _exit(EXIT_SUCCESS); - /* NOTREACHED */ - } - - /* copy pipe to output */ - (void)close(fildes[1]); - if (drainfd(fildes[0], STDOUT_FILENO) != 0) { - warn("test(%s): drainfd", test_name); - *ret = EXIT_FAILURE; - return; - } - if (close(fildes[0]) != 0) { - warn("test(%s): close", test_name); - *ret = EXIT_FAILURE; - return; - } - - /* wait for test to terminate */ - while (waitpid(pid, &status, 0) < 0) { - if (errno == EAGAIN) - continue; - warn("test(%s): waitpid", test_name); - *ret = EXIT_FAILURE; - return; - } - - /* show status and details */ - printf(" status=%d", status); - - if (WIFCONTINUED(status)) - printf(" continued"); - - if (WIFEXITED(status)) { - int e = WEXITSTATUS(status); - printf(" exit=%d", e); - if (e > 0 && e <= ELAST) - printf(" (errno: \"%s\")", strerror(e)); - } - - if (WIFSIGNALED(status)) { - int signal = WTERMSIG(status); - printf(" signal=%d", signal); - - /* check if core file is really here ? */ - if (WCOREDUMP(status)) { - int coredump = check_coredump(); - - switch(coredump) { - case -1: /* error */ - warn("test(%s): check_coredump", test_name); - *ret = EXIT_FAILURE; - return; - - case 0: /* found */ - printf(" coredump=present"); - break; - - case 1: /* not found */ - printf(" coredump=absent"); - break; - - default: - warnx("test(%s): unknown coredump code %d", - test_name, coredump); - *ret = EXIT_FAILURE; - return; - } - - } - - /* grab tamed syscall from dmesg */ - if ((signal == SIGKILL) || (signal = SIGABRT)) { - int syscall = grab_syscall(pid); - switch (syscall) { - case -1: /* error */ - warn("test(%s): grab_syscall pid=%d", test_name, - pid); - *ret = EXIT_FAILURE; - return; - - case 0: /* not found */ - printf(" tamed_syscall=not_found"); - break; - - default: - printf(" tamed_syscall=%d", syscall); - } - } - } - - if (WIFSTOPPED(status)) - printf(" stop=%d", WSTOPSIG(status)); - - printf("\n"); -} diff --git a/regress/sys/kern/tame/generic/manager.h b/regress/sys/kern/tame/generic/manager.h deleted file mode 100644 index 0960e366d5a..00000000000 --- a/regress/sys/kern/tame/generic/manager.h +++ /dev/null @@ -1,32 +0,0 @@ -/* $OpenBSD: manager.h,v 1.1 2015/09/24 06:25:54 semarie Exp $ */ -/* - * Copyright (c) 2015 Sebastien Marie - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef _MANAGER_H_ -#define _MANAGER_H_ - -void _start_test(int *ret, const char *test_name, const char *request, - const char *paths[], void (*test_func)(void)); - -#define start_test(ret,req,paths,func) \ - _start_test(ret,#func,req,paths,func) - -#define start_test1(ret,req,path,func) \ - do { \ - const char *_paths[] = {path, NULL}; \ - start_test(ret,req,_paths,func); \ - } while (0) - -#endif /* _MANAGER_H_ */ diff --git a/regress/sys/kern/tame/generic/tests.out b/regress/sys/kern/tame/generic/tests.out deleted file mode 100644 index 69e1118ad20..00000000000 --- a/regress/sys/kern/tame/generic/tests.out +++ /dev/null @@ -1,104 +0,0 @@ -# $OpenBSD: tests.out,v 1.9 2015/10/06 15:45:31 semarie Exp $ -test(test_nop): tame=("",NULL) status=0 exit=0 -test(test_inet): tame=("",NULL) status=9 signal=9 tamed_syscall=97 -test(test_inet): tame=("abort",NULL) status=134 signal=6 coredump=present tamed_syscall=97 -test(test_inet): tame=("inet",NULL) status=0 exit=0 -test(test_kill): tame=("inet",NULL) status=9 signal=9 tamed_syscall=37 -test(test_kill): tame=("proc",NULL) status=2 signal=2 tamed_syscall=not_found -test(test_allowed_syscalls): tame=("malloc",NULL) status=0 exit=0 -test(test_allowed_syscalls): tame=("rw",NULL) status=0 exit=0 -test(test_allowed_syscalls): tame=("stdio",NULL) status=0 exit=0 -test(test_allowed_syscalls): tame=("rpath",NULL) status=0 exit=0 -test(test_allowed_syscalls): tame=("wpath",NULL) status=0 exit=0 -test(test_allowed_syscalls): tame=("tmppath",NULL) status=0 exit=0 -test(test_allowed_syscalls): tame=("inet",NULL) status=0 exit=0 -test(test_allowed_syscalls): tame=("unix",NULL) status=0 exit=0 -test(test_allowed_syscalls): tame=("dns",NULL) status=0 exit=0 -test(test_allowed_syscalls): tame=("getpw",NULL) status=0 exit=0 -test(test_allowed_syscalls): tame=("cmsg",NULL) status=9 signal=9 tamed_syscall=89 -test(test_allowed_syscalls): tame=("ioctl",NULL) status=9 signal=9 tamed_syscall=89 -test(test_allowed_syscalls): tame=("proc",NULL) status=9 signal=9 tamed_syscall=89 -test(test_allowed_syscalls): tame=("cpath",NULL) status=9 signal=9 tamed_syscall=89 -test(test_allowed_syscalls): tame=("abort",NULL) status=134 signal=6 coredump=present tamed_syscall=89 -test(test_allowed_syscalls): tame=("fattr",NULL) status=9 signal=9 tamed_syscall=89 -test(test_rpath): tame=("rpath",NULL) status=0 exit=0 -test(test_wpath): tame=("wpath",NULL) status=0 exit=0 -test(test_cpath): tame=("cpath",NULL) status=0 exit=0 -test(test_wpaths): tame=("stdio rpath",NULL) - open_close("/etc/passwd") fd=3 errno=0 - open_close("generic") fd=3 errno=0 - open_close("../../../../../../../../../../../../../../../etc/passwd") fd=3 errno=0 - open_close("/nonexistent") fd=-1 errno=2 - status=0 exit=0 -test(test_wpaths): tame=("stdio rpath",{NULL}) - open_close("/etc/passwd") fd=-1 errno=2 - open_close("generic") fd=-1 errno=2 - open_close("../../../../../../../../../../../../../../../etc/passwd") fd=-1 errno=2 - open_close("/nonexistent") fd=-1 errno=2 - status=0 exit=0 -test(test_wpaths): tame=("stdio rpath",{"/",NULL}) - open_close("/etc/passwd") fd=3 errno=0 - open_close("generic") fd=3 errno=0 - open_close("../../../../../../../../../../../../../../../etc/passwd") fd=3 errno=0 - open_close("/nonexistent") fd=-1 errno=2 - status=0 exit=0 -test(test_wpaths): tame=("stdio rpath",{"/etc",NULL}) - open_close("/etc/passwd") fd=3 errno=0 - open_close("generic") fd=-1 errno=2 - open_close("../../../../../../../../../../../../../../../etc/passwd") fd=3 errno=0 - open_close("/nonexistent") fd=-1 errno=2 - status=0 exit=0 -test(test_wpaths): tame=("stdio rpath",{"/etc/",NULL}) - open_close("/etc/passwd") fd=3 errno=0 - open_close("generic") fd=-1 errno=2 - open_close("../../../../../../../../../../../../../../../etc/passwd") fd=3 errno=0 - open_close("/nonexistent") fd=-1 errno=2 - status=0 exit=0 -test(test_wpaths): tame=("stdio rpath",{"/etc/passwd",NULL}) - open_close("/etc/passwd") fd=3 errno=0 - open_close("generic") fd=-1 errno=2 - open_close("../../../../../../../../../../../../../../../etc/passwd") fd=3 errno=0 - open_close("/nonexistent") fd=-1 errno=2 - status=0 exit=0 -test(test_wpaths): tame=("stdio rpath",{"/bin",NULL}) - open_close("/etc/passwd") fd=-1 errno=2 - open_close("generic") fd=-1 errno=2 - open_close("../../../../../../../../../../../../../../../etc/passwd") fd=-1 errno=2 - open_close("/nonexistent") fd=-1 errno=2 - status=0 exit=0 -test(test_wpaths): tame=("stdio rpath",{"generic",NULL}) - open_close("/etc/passwd") fd=-1 errno=2 - open_close("generic") fd=3 errno=0 - open_close("../../../../../../../../../../../../../../../etc/passwd") fd=-1 errno=2 - open_close("/nonexistent") fd=-1 errno=2 - status=0 exit=0 -test(test_wpaths): tame=("stdio rpath",{"",NULL}) - open_close("/etc/passwd") fd=-1 errno=2 - open_close("generic") fd=3 errno=0 - open_close("../../../../../../../../../../../../../../../etc/passwd") fd=-1 errno=2 - open_close("/nonexistent") fd=-1 errno=2 - status=0 exit=0 -test(test_wpaths): tame=("stdio rpath",{".",NULL}) - open_close("/etc/passwd") fd=-1 errno=2 - open_close("generic") fd=3 errno=0 - open_close("../../../../../../../../../../../../../../../etc/passwd") fd=-1 errno=2 - open_close("/nonexistent") fd=-1 errno=2 - status=0 exit=0 -test(test_tame): tame=("stdio rpath",NULL) status=0 exit=0 -test(test_tame): tame=("malloc rw rpath",NULL) status=0 exit=0 -test(test_tame): tame=("stdio rpath wpath",NULL) status=0 exit=0 -test(test_tame): tame=("stdio rpath wpath",{"/sbin",NULL}) status=256 exit=1 (errno: "Operation not permitted") -test(test_tame): tame=("stdio rpath wpath",{"/",NULL}) status=256 exit=1 (errno: "Operation not permitted") -test(test_tame): tame=("stdio",NULL) status=256 exit=1 (errno: "Operation not permitted") -test(test_tame): tame=("unix",NULL) status=256 exit=1 (errno: "Operation not permitted") -test(test_stat): tame=("stdio rpath",{"/usr/share/man",NULL}) - stat("/usr/share/man/man8/afterboot.8"): realpath=failed(2) uid=0 gid=7 mode=100444 - stat("/usr/share/man/man8/"): realpath=failed(2) uid=0 gid=0 mode=40755 - stat("/usr/share/man"): realpath=failed(2) uid=0 gid=0 mode=40755 - stat("/usr/share"): realpath=failed(2) errno=2 - stat("/usr"): realpath="/usr" errno=2 - stat("/"): realpath="/" errno=2 - stat("/usr/bin/gzip"): realpath=failed(2) errno=2 - status=0 exit=0 -test(test_mmap): tame=("rpath malloc prot_exec",{"/dev/zero",NULL}) status=0 exit=0 -test(test_mmap): tame=("rpath malloc",{"/dev/zero",NULL}) status=9 signal=9 tamed_syscall=197 diff --git a/regress/sys/kern/tame/sigabrt/Makefile b/regress/sys/kern/tame/sigabrt/Makefile deleted file mode 100644 index cba94fef7f3..00000000000 --- a/regress/sys/kern/tame/sigabrt/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $OpenBSD: Makefile,v 1.1 2015/07/27 18:03:36 semarie Exp $ -PROG= sigabrt -NOMAN= yes - -run-regress-${PROG}: ${PROG} - rm -f ./${PROG}.core - if ./${PROG}; then false; else true; fi - if [ ! -e ./${PROG}.core ]; then echo "No coredump"; false; fi - ./${PROG} | diff -I OpenBSD -u ${.CURDIR}/${PROG}.out - - -.include diff --git a/regress/sys/kern/tame/sigabrt/sigabrt.c b/regress/sys/kern/tame/sigabrt/sigabrt.c deleted file mode 100644 index 890f862acd2..00000000000 --- a/regress/sys/kern/tame/sigabrt/sigabrt.c +++ /dev/null @@ -1,47 +0,0 @@ -/* $OpenBSD: sigabrt.c,v 1.3 2015/09/10 11:16:08 semarie Exp $ */ -/* - * Copyright (c) 2015 Sebastien Marie - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include - -void -handler(int sigraised) -{ - /* this handler shouldn't not be called */ - printf("forbidden STDIO in SIGABRT handler\n"); -} - -int -main(int argc, char *argv[]) -{ - /* install SIGABRT handler */ - signal(SIGABRT, &handler); - - printf("permitted STDIO\n"); - fflush(stdout); - - tame("abort", NULL); - - /* this will triggered tame_fail() */ - printf("forbidden STDIO 1\n"); - - /* shouldn't continue */ - printf("forbidden STDIO 2\n"); - return (EXIT_SUCCESS); -} diff --git a/regress/sys/kern/tame/sigabrt/sigabrt.out b/regress/sys/kern/tame/sigabrt/sigabrt.out deleted file mode 100644 index 7c93c1299f3..00000000000 --- a/regress/sys/kern/tame/sigabrt/sigabrt.out +++ /dev/null @@ -1,2 +0,0 @@ -$OpenBSD: sigabrt.out,v 1.1 2015/07/27 18:03:36 semarie Exp $ -permitted STDIO diff --git a/regress/sys/kern/tame/sigkill/Makefile b/regress/sys/kern/tame/sigkill/Makefile deleted file mode 100644 index 86910e48f01..00000000000 --- a/regress/sys/kern/tame/sigkill/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $OpenBSD: Makefile,v 1.1 2015/07/27 18:03:36 semarie Exp $ -PROG= sigkill -NOMAN= yes - -run-regress-${PROG}: ${PROG} - rm -f ./${PROG}.core - if ./${PROG}; then false; else true; fi - if [ -e ./${PROG}.core ]; then echo "Unexpected coredump"; false; fi - ./${PROG} | diff -I OpenBSD -u ${.CURDIR}/${PROG}.out - - -.include diff --git a/regress/sys/kern/tame/sigkill/sigkill.c b/regress/sys/kern/tame/sigkill/sigkill.c deleted file mode 100644 index cdc6e3be159..00000000000 --- a/regress/sys/kern/tame/sigkill/sigkill.c +++ /dev/null @@ -1,48 +0,0 @@ -/* $OpenBSD: sigkill.c,v 1.3 2015/09/10 11:16:08 semarie Exp $ */ -/* - * Copyright (c) 2015 Sebastien Marie - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include - -void -handler(int sigraised) -{ - /* the handler shouldn't not be called */ - printf("forbidden STDIO in %d handler\n", sigraised); -} - -int -main(int argc, char *argv[]) -{ - /* install some handlers */ - signal(SIGHUP, &handler); - signal(SIGABRT, &handler); - - printf("permitted STDIO\n"); - fflush(stdout); - - tame("", NULL); - - /* this will triggered tame_fail() */ - printf("forbidden STDIO 1\n"); - - /* shouldn't continue */ - printf("forbidden STDIO 2\n"); - return (EXIT_SUCCESS); -} diff --git a/regress/sys/kern/tame/sigkill/sigkill.out b/regress/sys/kern/tame/sigkill/sigkill.out deleted file mode 100644 index d593f6ee318..00000000000 --- a/regress/sys/kern/tame/sigkill/sigkill.out +++ /dev/null @@ -1,2 +0,0 @@ -$OpenBSD: sigkill.out,v 1.1 2015/07/27 18:03:36 semarie Exp $ -permitted STDIO