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