Path: blob/main/tools/regression/security/cap_test/cap_test.h
48266 views
/*-1* Copyright (c) 2008-2011 Robert N. M. Watson2* Copyright (c) 2011 Jonathan Anderson3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#ifndef CAP_TEST_H28#define CAP_TEST_H2930#include <err.h>3132/*33* Define a file required by a test. The test can't complete without the file,34* so if we don't have it, just die.35*/36#define REQUIRE(fd) do { \37if ((fd) < 0) \38err(-1, "%s:%d: Missing required file '%s'", \39__FILE__, __LINE__, #fd); \40} while (0)4142/* Whether a test passed or failed. */43#define PASSED 044#define FAILED 14546/* A test has failed; print a message and clear the 'success' flag. */47#define FAIL(...) do { \48warn(__VA_ARGS__); \49success = FAILED; \50} while (0)5152/* As above, but do not print the errno message. */53#define FAILX(...) do { \54warnx(__VA_ARGS__); \55success = FAILED; \56} while (0)5758/* Like an assertion, but don't kill the test, just fail and keep going. */59#define CHECK(condition) do { \60if (!(condition)) \61FAILX("%s:%d: Assertion '%s' failed", \62__func__, __LINE__, #condition); \63} while (0)6465/* Make sure that a system call's return value is >= 0. */66#define CHECK_SYSCALL_SUCCEEDS(syscall, ...) do { \67if (syscall(__VA_ARGS__) < 0) \68FAIL("%s() at line %d: %s failed", \69__func__, __LINE__, #syscall); \70} while (0)7172/* Make sure that a system call fails with the correct errno. */73#define CHECK_SYSCALL_FAILS(expected_errno, syscall, ...) do { \74if (syscall(__VA_ARGS__) < 0) { \75if (errno != expected_errno) \76FAIL("%s() at line %d: %s", \77__func__, __LINE__, #syscall); \78} else { \79FAILX("%s() at line %d: %s succeeded; it should've failed", \80__func__, __LINE__, #syscall); \81} \82} while (0)8384/* Make sure that a system call fails, but not with a particular errno. */85#define CHECK_SYSCALL_FAILS_BUT_NOT_WITH(bad_errno, syscall, ...) do { \86if (syscall(__VA_ARGS__) < 0) { \87if (errno == bad_errno) \88FAIL("%s() at line %d: %s", \89__func__, __LINE__, #syscall); \90} else { \91FAILX("%s() at line %d: %s succeeded; it should've failed", \92__func__, __LINE__, #syscall); \93} \94} while (0)9596/* A system call should fail with ECAPMODE. */97#define CHECK_CAPMODE(...) \98CHECK_SYSCALL_FAILS(ECAPMODE, __VA_ARGS__)99100/* A system call should fail, but not with ECAPMODE. */101#define CHECK_NOT_CAPMODE(...) \102CHECK_SYSCALL_FAILS_BUT_NOT_WITH(ECAPMODE, __VA_ARGS__)103104/* A system call should fail with ENOTCAPABLE. */105#define CHECK_NOTCAPABLE(...) \106CHECK_SYSCALL_FAILS(ENOTCAPABLE, __VA_ARGS__)107108/* Ensure that 'rights' are a subset of 'max'. */109#define CHECK_RIGHTS(rights, max) do { \110if ((success == PASSED) && (rights != max)) \111FAILX("Rights of opened file (%jx) > maximum (%jx)", \112(cap_rights_t) rights, (cap_rights_t) max); \113} while (0)114115/* Create a capability from a file descriptor, make sure it succeeds. */116#define MAKE_CAPABILITY(to, from, rights) do { \117cap_rights_t _rights; \118REQUIRE(to = cap_new(from, rights)); \119CHECK_SYSCALL_SUCCEEDS(cap_getrights, to, &_rights); \120if ((success == PASSED) && (_rights != (rights))) \121FAILX("New capability's rights (%jx) != %jx", \122_rights, (cap_rights_t) (rights)); \123} while (0)124125/*126* A top-level test should take no arguments and return an integer value,127* either PASSED or FAILED.128*129* Errors such as SIGSEGV will be caught and interpreted as FAILED.130*/131typedef int (*test_function)(void);132133/* Information about a test. */134struct test {135char *t_name;136test_function t_run;137int t_result;138};139140/*141* Run a test in a child process so that cap_enter(2) doesn't mess up142* subsequent tests.143*/144int execute(int id, struct test*);145146int test_capmode(void);147int test_capabilities(void);148int test_fcntl(void);149int test_pdfork(void);150int test_pdkill(void);151int test_pdwait(void);152int test_relative(void);153int test_sysctl(void);154155#endif /* CAP_TEST_H */156157158