cap_test.h revision 224651
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 * $FreeBSD: head/tools/regression/security/cap_test/cap_test.h 224651 2011-08-04 14:20:13Z jonathan $
28 */
29
30#ifndef CAP_TEST_H
31#define	CAP_TEST_H
32
33#include <err.h>
34
35/*
36 * Define a file required by a test. The test can't complete without the file,
37 * so if we don't have it, just die.
38 */
39#define	REQUIRE(fd)	do {						\
40	if ((fd) < 0)							\
41		err(-1, "%s:%d: Missing required file '%s'",		\
42			__FILE__, __LINE__, #fd);			\
43} while (0)
44
45/* Whether a test passed or failed. */
46#define	PASSED	0
47#define	FAILED	1
48
49/* A test has failed; print a message and clear the 'success' flag. */
50#define	FAIL(...)	do {						\
51	warn(__VA_ARGS__);						\
52	success = FAILED;						\
53} while (0)
54
55/* As above, but do not print the errno message. */
56#define	FAILX(...)	do {						\
57	warnx(__VA_ARGS__);						\
58	success = FAILED;						\
59} while (0)
60
61/* Like an assertion, but don't kill the test, just fail and keep going. */
62#define	CHECK(condition) do {						\
63	if (!(condition))						\
64		FAILX("%s:%d: Assertion '%s' failed",			\
65		    __func__, __LINE__, #condition);			\
66} while (0)
67
68/* Make sure that a system call's return value is >= 0. */
69#define	CHECK_SYSCALL_SUCCEEDS(syscall, ...) do {			\
70	if (syscall(__VA_ARGS__) < 0)					\
71		FAIL("%s() at line %d: %s failed",			\
72		    __func__, __LINE__, #syscall);			\
73} while (0)
74
75/* Make sure that a system call fails with the correct errno. */
76#define	CHECK_SYSCALL_FAILS(expected_errno, syscall, ...)	do {	\
77	if (syscall(__VA_ARGS__) < 0) {					\
78		if (errno != expected_errno)				\
79			FAIL("%s() at line %d: %s",			\
80			    __func__, __LINE__, #syscall);		\
81	} else {							\
82		FAILX("%s() at line %d: %s succeeded; it should've failed", \
83		    __func__, __LINE__, #syscall);			\
84	}								\
85} while (0)
86
87/* Make sure that a system call fails, but not with a particular errno. */
88#define	CHECK_SYSCALL_FAILS_BUT_NOT_WITH(bad_errno, syscall, ...)	do { \
89	if (syscall(__VA_ARGS__) < 0) {					\
90		if (errno == bad_errno)					\
91			FAIL("%s() at line %d: %s",			\
92			    __func__, __LINE__, #syscall);		\
93	} else {							\
94		FAILX("%s() at line %d: %s succeeded; it should've failed", \
95		    __func__, __LINE__, #syscall);			\
96	}								\
97} while (0)
98
99/* A system call should fail with ECAPMODE. */
100#define	CHECK_CAPMODE(...) \
101	CHECK_SYSCALL_FAILS(ECAPMODE, __VA_ARGS__)
102
103/* A system call should fail, but not with ECAPMODE. */
104#define	CHECK_NOT_CAPMODE(...) \
105	CHECK_SYSCALL_FAILS_BUT_NOT_WITH(ECAPMODE, __VA_ARGS__)
106
107/* A system call should fail with ENOTCAPABLE. */
108#define	CHECK_NOTCAPABLE(...) \
109	CHECK_SYSCALL_FAILS(ENOTCAPABLE, __VA_ARGS__)
110
111/* Ensure that 'rights' are a subset of 'max'. */
112#define	CHECK_RIGHTS(rights, max)	do {				\
113	if ((success == PASSED) && (rights != max))			\
114		FAILX("Rights of opened file (%jx) > maximum (%jx)",	\
115		    (cap_rights_t) rights, (cap_rights_t) max);		\
116} while (0)
117
118/* Create a capability from a file descriptor, make sure it succeeds. */
119#define	MAKE_CAPABILITY(to, from, rights)	do {			\
120	cap_rights_t _rights;						\
121	REQUIRE(to = cap_new(from, rights));				\
122	CHECK_SYSCALL_SUCCEEDS(cap_getrights, to, &_rights);		\
123	if ((success == PASSED) && (_rights != (rights)))		\
124		FAILX("New capability's rights (%jx) != %jx",		\
125		    _rights, (cap_rights_t) (rights));			\
126} while (0)
127
128/*
129 * A top-level test should take no arguments and return an integer value,
130 * either PASSED or FAILED.
131 *
132 * Errors such as SIGSEGV will be caught and interpreted as FAILED.
133 */
134typedef int	(*test_function)(void);
135
136/* Information about a test. */
137struct test {
138	char		*t_name;
139	test_function	 t_run;
140	int		 t_result;
141};
142
143/*
144 * Run a test in a child process so that cap_enter(2) doesn't mess up
145 * subsequent tests.
146 */
147int	execute(int id, struct test*);
148
149int	test_capmode(void);
150int	test_capabilities(void);
151int	test_syscalls(void);
152int	test_sysctl(void);
153int	test_fcntl(void);
154
155#endif /* CAP_TEST_H */
156