]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/regression/security/cap_test/cap_test.h
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / tools / regression / security / cap_test / cap_test.h
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$
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  */
134 typedef int     (*test_function)(void);
135
136 /* Information about a test. */
137 struct 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  */
147 int     execute(int id, struct test*);
148
149 int     test_capmode(void);
150 int     test_capabilities(void);
151 int     test_fcntl(void);
152 int     test_pdfork(void);
153 int     test_pdkill(void);
154 int     test_pdwait(void);
155 int     test_relative(void);
156 int     test_sysctl(void);
157
158 #endif /* CAP_TEST_H */