1 /*- 2 * Copyright (c) 2008-2011 Robert N. M. Watson 3 * Copyright (c) 2011 Jonathan Anderson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #ifndef CAP_TEST_H 29 #define CAP_TEST_H 30 31 #include <err.h> 32 33 /* 34 * Define a file required by a test. The test can't complete without the file, 35 * so if we don't have it, just die. 36 */ 37 #define REQUIRE(fd) do { \ 38 if ((fd) < 0) \ 39 err(-1, "%s:%d: Missing required file '%s'", \ 40 __FILE__, __LINE__, #fd); \ 41 } while (0) 42 43 /* Whether a test passed or failed. */ 44 #define PASSED 0 45 #define FAILED 1 46 47 /* A test has failed; print a message and clear the 'success' flag. */ 48 #define FAIL(...) do { \ 49 warn(__VA_ARGS__); \ 50 success = FAILED; \ 51 } while (0) 52 53 /* As above, but do not print the errno message. */ 54 #define FAILX(...) do { \ 55 warnx(__VA_ARGS__); \ 56 success = FAILED; \ 57 } while (0) 58 59 /* Like an assertion, but don't kill the test, just fail and keep going. */ 60 #define CHECK(condition) do { \ 61 if (!(condition)) \ 62 FAILX("%s:%d: Assertion '%s' failed", \ 63 __func__, __LINE__, #condition); \ 64 } while (0) 65 66 /* Make sure that a system call's return value is >= 0. */ 67 #define CHECK_SYSCALL_SUCCEEDS(syscall, ...) do { \ 68 if (syscall(__VA_ARGS__) < 0) \ 69 FAIL("%s() at line %d: %s failed", \ 70 __func__, __LINE__, #syscall); \ 71 } while (0) 72 73 /* Make sure that a system call fails with the correct errno. */ 74 #define CHECK_SYSCALL_FAILS(expected_errno, syscall, ...) do { \ 75 if (syscall(__VA_ARGS__) < 0) { \ 76 if (errno != expected_errno) \ 77 FAIL("%s() at line %d: %s", \ 78 __func__, __LINE__, #syscall); \ 79 } else { \ 80 FAILX("%s() at line %d: %s succeeded; it should've failed", \ 81 __func__, __LINE__, #syscall); \ 82 } \ 83 } while (0) 84 85 /* Make sure that a system call fails, but not with a particular errno. */ 86 #define CHECK_SYSCALL_FAILS_BUT_NOT_WITH(bad_errno, syscall, ...) do { \ 87 if (syscall(__VA_ARGS__) < 0) { \ 88 if (errno == bad_errno) \ 89 FAIL("%s() at line %d: %s", \ 90 __func__, __LINE__, #syscall); \ 91 } else { \ 92 FAILX("%s() at line %d: %s succeeded; it should've failed", \ 93 __func__, __LINE__, #syscall); \ 94 } \ 95 } while (0) 96 97 /* A system call should fail with ECAPMODE. */ 98 #define CHECK_CAPMODE(...) \ 99 CHECK_SYSCALL_FAILS(ECAPMODE, __VA_ARGS__) 100 101 /* A system call should fail, but not with ECAPMODE. */ 102 #define CHECK_NOT_CAPMODE(...) \ 103 CHECK_SYSCALL_FAILS_BUT_NOT_WITH(ECAPMODE, __VA_ARGS__) 104 105 /* A system call should fail with ENOTCAPABLE. */ 106 #define CHECK_NOTCAPABLE(...) \ 107 CHECK_SYSCALL_FAILS(ENOTCAPABLE, __VA_ARGS__) 108 109 /* Ensure that 'rights' are a subset of 'max'. */ 110 #define CHECK_RIGHTS(rights, max) do { \ 111 if ((success == PASSED) && (rights != max)) \ 112 FAILX("Rights of opened file (%jx) > maximum (%jx)", \ 113 (cap_rights_t) rights, (cap_rights_t) max); \ 114 } while (0) 115 116 /* Create a capability from a file descriptor, make sure it succeeds. */ 117 #define MAKE_CAPABILITY(to, from, rights) do { \ 118 cap_rights_t _rights; \ 119 REQUIRE(to = cap_new(from, rights)); \ 120 CHECK_SYSCALL_SUCCEEDS(cap_getrights, to, &_rights); \ 121 if ((success == PASSED) && (_rights != (rights))) \ 122 FAILX("New capability's rights (%jx) != %jx", \ 123 _rights, (cap_rights_t) (rights)); \ 124 } while (0) 125 126 /* 127 * A top-level test should take no arguments and return an integer value, 128 * either PASSED or FAILED. 129 * 130 * Errors such as SIGSEGV will be caught and interpreted as FAILED. 131 */ 132 typedef int (*test_function)(void); 133 134 /* Information about a test. */ 135 struct test { 136 char *t_name; 137 test_function t_run; 138 int t_result; 139 }; 140 141 /* 142 * Run a test in a child process so that cap_enter(2) doesn't mess up 143 * subsequent tests. 144 */ 145 int execute(int id, struct test*); 146 147 int test_capmode(void); 148 int test_capabilities(void); 149 int test_fcntl(void); 150 int test_pdfork(void); 151 int test_pdkill(void); 152 int test_pdwait(void); 153 int test_relative(void); 154 int test_sysctl(void); 155 156 #endif /* CAP_TEST_H */ 157