Ensure that process descriptors work as expected. We should be able to: - pdfork(), like regular fork(), but producing a process descriptor - pdgetpid() to convert a PD into a PID - pdkill() to send signals to a process identified by a PD Approved by: re (kib), mentor (rwatson) Sponsored by: Google Inc
159 lines
5.1 KiB
C
159 lines
5.1 KiB
C
/*-
|
|
* Copyright (c) 2008-2011 Robert N. M. Watson
|
|
* Copyright (c) 2011 Jonathan Anderson
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
#ifndef CAP_TEST_H
|
|
#define CAP_TEST_H
|
|
|
|
#include <err.h>
|
|
|
|
/*
|
|
* Define a file required by a test. The test can't complete without the file,
|
|
* so if we don't have it, just die.
|
|
*/
|
|
#define REQUIRE(fd) do { \
|
|
if ((fd) < 0) \
|
|
err(-1, "%s:%d: Missing required file '%s'", \
|
|
__FILE__, __LINE__, #fd); \
|
|
} while (0)
|
|
|
|
/* Whether a test passed or failed. */
|
|
#define PASSED 0
|
|
#define FAILED 1
|
|
|
|
/* A test has failed; print a message and clear the 'success' flag. */
|
|
#define FAIL(...) do { \
|
|
warn(__VA_ARGS__); \
|
|
success = FAILED; \
|
|
} while (0)
|
|
|
|
/* As above, but do not print the errno message. */
|
|
#define FAILX(...) do { \
|
|
warnx(__VA_ARGS__); \
|
|
success = FAILED; \
|
|
} while (0)
|
|
|
|
/* Like an assertion, but don't kill the test, just fail and keep going. */
|
|
#define CHECK(condition) do { \
|
|
if (!(condition)) \
|
|
FAILX("%s:%d: Assertion '%s' failed", \
|
|
__func__, __LINE__, #condition); \
|
|
} while (0)
|
|
|
|
/* Make sure that a system call's return value is >= 0. */
|
|
#define CHECK_SYSCALL_SUCCEEDS(syscall, ...) do { \
|
|
if (syscall(__VA_ARGS__) < 0) \
|
|
FAIL("%s() at line %d: %s failed", \
|
|
__func__, __LINE__, #syscall); \
|
|
} while (0)
|
|
|
|
/* Make sure that a system call fails with the correct errno. */
|
|
#define CHECK_SYSCALL_FAILS(expected_errno, syscall, ...) do { \
|
|
if (syscall(__VA_ARGS__) < 0) { \
|
|
if (errno != expected_errno) \
|
|
FAIL("%s() at line %d: %s", \
|
|
__func__, __LINE__, #syscall); \
|
|
} else { \
|
|
FAILX("%s() at line %d: %s succeeded; it should've failed", \
|
|
__func__, __LINE__, #syscall); \
|
|
} \
|
|
} while (0)
|
|
|
|
/* Make sure that a system call fails, but not with a particular errno. */
|
|
#define CHECK_SYSCALL_FAILS_BUT_NOT_WITH(bad_errno, syscall, ...) do { \
|
|
if (syscall(__VA_ARGS__) < 0) { \
|
|
if (errno == bad_errno) \
|
|
FAIL("%s() at line %d: %s", \
|
|
__func__, __LINE__, #syscall); \
|
|
} else { \
|
|
FAILX("%s() at line %d: %s succeeded; it should've failed", \
|
|
__func__, __LINE__, #syscall); \
|
|
} \
|
|
} while (0)
|
|
|
|
/* A system call should fail with ECAPMODE. */
|
|
#define CHECK_CAPMODE(...) \
|
|
CHECK_SYSCALL_FAILS(ECAPMODE, __VA_ARGS__)
|
|
|
|
/* A system call should fail, but not with ECAPMODE. */
|
|
#define CHECK_NOT_CAPMODE(...) \
|
|
CHECK_SYSCALL_FAILS_BUT_NOT_WITH(ECAPMODE, __VA_ARGS__)
|
|
|
|
/* A system call should fail with ENOTCAPABLE. */
|
|
#define CHECK_NOTCAPABLE(...) \
|
|
CHECK_SYSCALL_FAILS(ENOTCAPABLE, __VA_ARGS__)
|
|
|
|
/* Ensure that 'rights' are a subset of 'max'. */
|
|
#define CHECK_RIGHTS(rights, max) do { \
|
|
if ((success == PASSED) && (rights != max)) \
|
|
FAILX("Rights of opened file (%jx) > maximum (%jx)", \
|
|
(cap_rights_t) rights, (cap_rights_t) max); \
|
|
} while (0)
|
|
|
|
/* Create a capability from a file descriptor, make sure it succeeds. */
|
|
#define MAKE_CAPABILITY(to, from, rights) do { \
|
|
cap_rights_t _rights; \
|
|
REQUIRE(to = cap_new(from, rights)); \
|
|
CHECK_SYSCALL_SUCCEEDS(cap_getrights, to, &_rights); \
|
|
if ((success == PASSED) && (_rights != (rights))) \
|
|
FAILX("New capability's rights (%jx) != %jx", \
|
|
_rights, (cap_rights_t) (rights)); \
|
|
} while (0)
|
|
|
|
/*
|
|
* A top-level test should take no arguments and return an integer value,
|
|
* either PASSED or FAILED.
|
|
*
|
|
* Errors such as SIGSEGV will be caught and interpreted as FAILED.
|
|
*/
|
|
typedef int (*test_function)(void);
|
|
|
|
/* Information about a test. */
|
|
struct test {
|
|
char *t_name;
|
|
test_function t_run;
|
|
int t_result;
|
|
};
|
|
|
|
/*
|
|
* Run a test in a child process so that cap_enter(2) doesn't mess up
|
|
* subsequent tests.
|
|
*/
|
|
int execute(int id, struct test*);
|
|
|
|
int test_capmode(void);
|
|
int test_capabilities(void);
|
|
int test_fcntl(void);
|
|
int test_pdfork(void);
|
|
int test_pdkill(void);
|
|
int test_pdwait(void);
|
|
int test_relative(void);
|
|
int test_sysctl(void);
|
|
|
|
#endif /* CAP_TEST_H */
|