xref: /freebsd/tools/regression/security/cap_test/cap_test.h (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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