xref: /freebsd/tests/sys/capsicum/capsicum-test.h (revision 670b568ec1c36464c6d55e400382c290b0391ccf)
1*670b568eSEd Maste /* -*- C++ -*- */
2*670b568eSEd Maste #ifndef CAPSICUM_TEST_H
3*670b568eSEd Maste #define CAPSICUM_TEST_H
4*670b568eSEd Maste 
5*670b568eSEd Maste #include <errno.h>
6*670b568eSEd Maste #include <sys/types.h>
7*670b568eSEd Maste #include <sys/wait.h>
8*670b568eSEd Maste #include <sys/resource.h>
9*670b568eSEd Maste #include <signal.h>
10*670b568eSEd Maste 
11*670b568eSEd Maste #include <ios>
12*670b568eSEd Maste #include <ostream>
13*670b568eSEd Maste #include <string>
14*670b568eSEd Maste 
15*670b568eSEd Maste #include "gtest/gtest.h"
16*670b568eSEd Maste 
17*670b568eSEd Maste extern bool verbose;
18*670b568eSEd Maste extern std::string tmpdir;
19*670b568eSEd Maste extern bool tmpdir_on_tmpfs;
20*670b568eSEd Maste extern bool force_mt;
21*670b568eSEd Maste extern bool force_nofork;
22*670b568eSEd Maste extern uid_t other_uid;
23*670b568eSEd Maste 
WaitingThreadFn(void *)24*670b568eSEd Maste static inline void *WaitingThreadFn(void *) {
25*670b568eSEd Maste   // Loop until cancelled
26*670b568eSEd Maste   while (true) {
27*670b568eSEd Maste     usleep(10000);
28*670b568eSEd Maste     pthread_testcancel();
29*670b568eSEd Maste   }
30*670b568eSEd Maste   return NULL;
31*670b568eSEd Maste }
32*670b568eSEd Maste 
33*670b568eSEd Maste // If force_mt is set, run another thread in parallel with the test.  This forces
34*670b568eSEd Maste // the kernel into multi-threaded mode.
35*670b568eSEd Maste template <typename T, typename Function>
MaybeRunWithThread(T * self,Function fn)36*670b568eSEd Maste void MaybeRunWithThread(T *self, Function fn) {
37*670b568eSEd Maste   pthread_t subthread;
38*670b568eSEd Maste   if (force_mt) {
39*670b568eSEd Maste     pthread_create(&subthread, NULL, WaitingThreadFn, NULL);
40*670b568eSEd Maste   }
41*670b568eSEd Maste   (self->*fn)();
42*670b568eSEd Maste   if (force_mt) {
43*670b568eSEd Maste     pthread_cancel(subthread);
44*670b568eSEd Maste     pthread_join(subthread, NULL);
45*670b568eSEd Maste   }
46*670b568eSEd Maste }
47*670b568eSEd Maste template <typename Function>
MaybeRunWithThread(Function fn)48*670b568eSEd Maste void MaybeRunWithThread(Function fn) {
49*670b568eSEd Maste   pthread_t subthread;
50*670b568eSEd Maste   if (force_mt) {
51*670b568eSEd Maste     pthread_create(&subthread, NULL, WaitingThreadFn, NULL);
52*670b568eSEd Maste   }
53*670b568eSEd Maste   (fn)();
54*670b568eSEd Maste   if (force_mt) {
55*670b568eSEd Maste     pthread_cancel(subthread);
56*670b568eSEd Maste     pthread_join(subthread, NULL);
57*670b568eSEd Maste   }
58*670b568eSEd Maste }
59*670b568eSEd Maste 
60*670b568eSEd Maste // Return the absolute path of a filename in the temp directory, `tmpdir`,
61*670b568eSEd Maste // with the given pathname, e.g., "/tmp/<pathname>", if `tmpdir` was set to
62*670b568eSEd Maste // "/tmp".
63*670b568eSEd Maste const char *TmpFile(const char *pathname);
64*670b568eSEd Maste 
65*670b568eSEd Maste // Run the given test function in a forked process, so that trapdoor
66*670b568eSEd Maste // entry doesn't affect other tests, and watch out for hung processes.
67*670b568eSEd Maste // Implemented as a macro to allow access to the test case instance's
68*670b568eSEd Maste // HasFailure() method, which is reported as the forked process's
69*670b568eSEd Maste // exit status.
70*670b568eSEd Maste #define _RUN_FORKED(INNERCODE, TESTCASENAME, TESTNAME)         \
71*670b568eSEd Maste     pid_t pid = force_nofork ? 0 : fork();                     \
72*670b568eSEd Maste     if (pid == 0) {                                            \
73*670b568eSEd Maste       INNERCODE;                                               \
74*670b568eSEd Maste       if (!force_nofork) {                                     \
75*670b568eSEd Maste         exit(HasFailure());                                    \
76*670b568eSEd Maste       }                                                        \
77*670b568eSEd Maste     } else if (pid > 0) {                                      \
78*670b568eSEd Maste       int rc, status;                                          \
79*670b568eSEd Maste       int remaining_us = 30000000;                             \
80*670b568eSEd Maste       while (remaining_us > 0) {                               \
81*670b568eSEd Maste         status = 0;                                            \
82*670b568eSEd Maste         rc = waitpid(pid, &status, WNOHANG);                   \
83*670b568eSEd Maste         if (rc != 0) break;                                    \
84*670b568eSEd Maste         remaining_us -= 10000;                                 \
85*670b568eSEd Maste         usleep(10000);                                         \
86*670b568eSEd Maste       }                                                        \
87*670b568eSEd Maste       if (remaining_us <= 0) {                                 \
88*670b568eSEd Maste         fprintf(stderr, "Warning: killing unresponsive test "  \
89*670b568eSEd Maste                         "%s.%s (pid %d)\n",                    \
90*670b568eSEd Maste                         TESTCASENAME, TESTNAME, pid);          \
91*670b568eSEd Maste         kill(pid, SIGKILL);                                    \
92*670b568eSEd Maste         ADD_FAILURE() << "Test hung";                          \
93*670b568eSEd Maste       } else if (rc < 0) {                                     \
94*670b568eSEd Maste         fprintf(stderr, "Warning: waitpid error %s (%d)\n",    \
95*670b568eSEd Maste                         strerror(errno), errno);               \
96*670b568eSEd Maste         ADD_FAILURE() << "Failed to wait for child";           \
97*670b568eSEd Maste       } else {                                                 \
98*670b568eSEd Maste         int rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1; \
99*670b568eSEd Maste         EXPECT_EQ(0, rc);                                      \
100*670b568eSEd Maste       }                                                        \
101*670b568eSEd Maste     }
102*670b568eSEd Maste #define _RUN_FORKED_MEM(THIS, TESTFN, TESTCASENAME, TESTNAME)  \
103*670b568eSEd Maste   _RUN_FORKED(MaybeRunWithThread(THIS, &TESTFN), TESTCASENAME, TESTNAME);
104*670b568eSEd Maste #define _RUN_FORKED_FN(TESTFN, TESTCASENAME, TESTNAME)   \
105*670b568eSEd Maste   _RUN_FORKED(MaybeRunWithThread(&TESTFN), TESTCASENAME, TESTNAME);
106*670b568eSEd Maste 
107*670b568eSEd Maste // Run a test case in a forked process, possibly cleaning up a
108*670b568eSEd Maste // test file after completion
109*670b568eSEd Maste #define FORK_TEST_ON(test_case_name, test_name, test_file)     \
110*670b568eSEd Maste     static void test_case_name##_##test_name##_ForkTest();     \
111*670b568eSEd Maste     TEST(test_case_name, test_name ## Forked) {                \
112*670b568eSEd Maste       _RUN_FORKED_FN(test_case_name##_##test_name##_ForkTest,  \
113*670b568eSEd Maste                      #test_case_name, #test_name);             \
114*670b568eSEd Maste       const char *filename = test_file;                        \
115*670b568eSEd Maste       if (filename) unlink(filename);                          \
116*670b568eSEd Maste     }                                                          \
117*670b568eSEd Maste     static void test_case_name##_##test_name##_ForkTest()
118*670b568eSEd Maste 
119*670b568eSEd Maste #define FORK_TEST(test_case_name, test_name) FORK_TEST_ON(test_case_name, test_name, NULL)
120*670b568eSEd Maste 
121*670b568eSEd Maste // Run a test case fixture in a forked process, so that trapdoors don't
122*670b568eSEd Maste // affect other tests.
123*670b568eSEd Maste #define ICLASS_NAME(test_case_name, test_name) Forked##test_case_name##_##test_name
124*670b568eSEd Maste #define FORK_TEST_F(test_case_name, test_name)                \
125*670b568eSEd Maste   class ICLASS_NAME(test_case_name, test_name) : public test_case_name { \
126*670b568eSEd Maste     public:                                                    \
127*670b568eSEd Maste       ICLASS_NAME(test_case_name, test_name)() {}              \
128*670b568eSEd Maste       void InnerTestBody();                                    \
129*670b568eSEd Maste     };                                                         \
130*670b568eSEd Maste     TEST_F(ICLASS_NAME(test_case_name, test_name), _) {        \
131*670b568eSEd Maste       _RUN_FORKED_MEM(this,                                    \
132*670b568eSEd Maste                       ICLASS_NAME(test_case_name, test_name)::InnerTestBody,  \
133*670b568eSEd Maste                       #test_case_name, #test_name);            \
134*670b568eSEd Maste     }                                                          \
135*670b568eSEd Maste     void ICLASS_NAME(test_case_name, test_name)::InnerTestBody()
136*670b568eSEd Maste 
137*670b568eSEd Maste // Emit errno information on failure
138*670b568eSEd Maste #define EXPECT_OK(v) EXPECT_LE(0, v) << "   errno " << errno << " " << strerror(errno)
139*670b568eSEd Maste 
140*670b568eSEd Maste // Expect a syscall to fail with the given error.
141*670b568eSEd Maste #define EXPECT_SYSCALL_FAIL(E, C) \
142*670b568eSEd Maste     do { \
143*670b568eSEd Maste       SCOPED_TRACE(#C); \
144*670b568eSEd Maste       EXPECT_GT(0, C); \
145*670b568eSEd Maste       EXPECT_EQ(E, errno) << "expected '" << strerror(E) \
146*670b568eSEd Maste                           << "' but got '" << strerror(errno) << "'"; \
147*670b568eSEd Maste     } while (0)
148*670b568eSEd Maste 
149*670b568eSEd Maste // Expect a syscall to fail with anything other than the given error.
150*670b568eSEd Maste #define EXPECT_SYSCALL_FAIL_NOT(E, C) \
151*670b568eSEd Maste     do { \
152*670b568eSEd Maste       EXPECT_GT(0, C); \
153*670b568eSEd Maste       EXPECT_NE(E, errno) << strerror(E); \
154*670b568eSEd Maste     } while (0)
155*670b568eSEd Maste 
156*670b568eSEd Maste // Expect a void syscall to fail with anything other than the given error.
157*670b568eSEd Maste #define EXPECT_VOID_SYSCALL_FAIL_NOT(E, C)   \
158*670b568eSEd Maste     do { \
159*670b568eSEd Maste       errno = 0; \
160*670b568eSEd Maste       C; \
161*670b568eSEd Maste       EXPECT_NE(E, errno) << #C << " failed with ECAPMODE"; \
162*670b568eSEd Maste     } while (0)
163*670b568eSEd Maste 
164*670b568eSEd Maste // Expect a system call to fail due to path traversal; exact error
165*670b568eSEd Maste // code is OS-specific.
166*670b568eSEd Maste #ifdef O_BENEATH
167*670b568eSEd Maste #define EXPECT_OPENAT_FAIL_TRAVERSAL(fd, path, flags) \
168*670b568eSEd Maste     do {                                              \
169*670b568eSEd Maste       SCOPED_TRACE(GTEST_STRINGIFY_(openat((fd), (path), (flags)))); \
170*670b568eSEd Maste       const int result = openat((fd), (path), (flags)); \
171*670b568eSEd Maste       if (((flags) & O_BENEATH) == O_BENEATH) { \
172*670b568eSEd Maste         EXPECT_SYSCALL_FAIL(E_NO_TRAVERSE_O_BENEATH, result); \
173*670b568eSEd Maste       } else { \
174*670b568eSEd Maste         EXPECT_SYSCALL_FAIL(E_NO_TRAVERSE_CAPABILITY, result); \
175*670b568eSEd Maste       } \
176*670b568eSEd Maste       if (result >= 0) { close(result); } \
177*670b568eSEd Maste     } while (0)
178*670b568eSEd Maste #else
179*670b568eSEd Maste #define EXPECT_OPENAT_FAIL_TRAVERSAL(fd, path, flags) \
180*670b568eSEd Maste     do { \
181*670b568eSEd Maste       SCOPED_TRACE(GTEST_STRINGIFY_(openat((fd), (path), (flags)))); \
182*670b568eSEd Maste       const int result = openat((fd), (path), (flags)); \
183*670b568eSEd Maste       EXPECT_SYSCALL_FAIL(E_NO_TRAVERSE_CAPABILITY, result); \
184*670b568eSEd Maste       if (result >= 0) { close(result); } \
185*670b568eSEd Maste     } while (0)
186*670b568eSEd Maste #endif
187*670b568eSEd Maste 
188*670b568eSEd Maste // Expect a system call to fail with ECAPMODE.
189*670b568eSEd Maste #define EXPECT_CAPMODE(C) EXPECT_SYSCALL_FAIL(ECAPMODE, C)
190*670b568eSEd Maste 
191*670b568eSEd Maste // Expect a system call to fail, but not with ECAPMODE.
192*670b568eSEd Maste #define EXPECT_FAIL_NOT_CAPMODE(C) EXPECT_SYSCALL_FAIL_NOT(ECAPMODE, C)
193*670b568eSEd Maste #define EXPECT_FAIL_VOID_NOT_CAPMODE(C) EXPECT_VOID_SYSCALL_FAIL_NOT(ECAPMODE, C)
194*670b568eSEd Maste 
195*670b568eSEd Maste // Expect a system call to fail with ENOTCAPABLE.
196*670b568eSEd Maste #define EXPECT_NOTCAPABLE(C) EXPECT_SYSCALL_FAIL(ENOTCAPABLE, C)
197*670b568eSEd Maste 
198*670b568eSEd Maste // Expect a system call to fail, but not with ENOTCAPABLE.
199*670b568eSEd Maste #define EXPECT_FAIL_NOT_NOTCAPABLE(C) EXPECT_SYSCALL_FAIL_NOT(ENOTCAPABLE, C)
200*670b568eSEd Maste 
201*670b568eSEd Maste // Expect a system call to fail with either ENOTCAPABLE or ECAPMODE.
202*670b568eSEd Maste #define EXPECT_CAPFAIL(C) \
203*670b568eSEd Maste     do { \
204*670b568eSEd Maste       int rc = C; \
205*670b568eSEd Maste       EXPECT_GT(0, rc); \
206*670b568eSEd Maste       EXPECT_TRUE(errno == ECAPMODE || errno == ENOTCAPABLE) \
207*670b568eSEd Maste         << #C << " did not fail with ECAPMODE/ENOTCAPABLE but " << errno \
208*670b568eSEd Maste         << "(" << strerror(errno) << ")"; \
209*670b568eSEd Maste     } while (0)
210*670b568eSEd Maste 
211*670b568eSEd Maste // Ensure that 'rights' are a subset of 'max'.
212*670b568eSEd Maste #define EXPECT_RIGHTS_IN(rights, max) \
213*670b568eSEd Maste     EXPECT_TRUE(cap_rights_contains((max), (rights)))  \
214*670b568eSEd Maste     << "rights " << std::hex << *(rights) \
215*670b568eSEd Maste     << " not a subset of " << std::hex << *(max)
216*670b568eSEd Maste 
217*670b568eSEd Maste // Ensure rights are identical
218*670b568eSEd Maste #define EXPECT_RIGHTS_EQ(a, b) \
219*670b568eSEd Maste   do { \
220*670b568eSEd Maste     EXPECT_RIGHTS_IN((a), (b)); \
221*670b568eSEd Maste     EXPECT_RIGHTS_IN((b), (a)); \
222*670b568eSEd Maste   } while (0)
223*670b568eSEd Maste 
224*670b568eSEd Maste // Get the state of a process as a single character.
225*670b568eSEd Maste //  - 'D': disk wait
226*670b568eSEd Maste //  - 'R': runnable
227*670b568eSEd Maste //  - 'S': sleeping/idle
228*670b568eSEd Maste //  - 'T': stopped
229*670b568eSEd Maste //  - 'Z': zombie
230*670b568eSEd Maste // On error, return either '?' or '\0'.
231*670b568eSEd Maste char ProcessState(int pid);
232*670b568eSEd Maste 
233*670b568eSEd Maste // Check process state reaches a particular expected state (or two).
234*670b568eSEd Maste // Retries a few times to allow for timing issues.
235*670b568eSEd Maste #define EXPECT_PID_REACHES_STATES(pid, expected1, expected2) { \
236*670b568eSEd Maste   int counter = 5; \
237*670b568eSEd Maste   char state; \
238*670b568eSEd Maste   do { \
239*670b568eSEd Maste     state = ProcessState(pid); \
240*670b568eSEd Maste     if (state == expected1 || state == expected2) break; \
241*670b568eSEd Maste     usleep(100000); \
242*670b568eSEd Maste   } while (--counter > 0); \
243*670b568eSEd Maste   EXPECT_TRUE(state == expected1 || state == expected2) \
244*670b568eSEd Maste       << " pid " << pid << " in state " << state; \
245*670b568eSEd Maste }
246*670b568eSEd Maste 
247*670b568eSEd Maste #define EXPECT_PID_ALIVE(pid)   EXPECT_PID_REACHES_STATES(pid, 'R', 'S')
248*670b568eSEd Maste #define EXPECT_PID_DEAD(pid)    EXPECT_PID_REACHES_STATES(pid, 'Z', '\0')
249*670b568eSEd Maste #define EXPECT_PID_ZOMBIE(pid)  EXPECT_PID_REACHES_STATES(pid, 'Z', 'Z');
250*670b568eSEd Maste #define EXPECT_PID_GONE(pid)    EXPECT_PID_REACHES_STATES(pid, '\0', '\0');
251*670b568eSEd Maste 
252*670b568eSEd Maste enum {
253*670b568eSEd Maste   // Magic numbers for messages sent by child processes.
254*670b568eSEd Maste   MSG_CHILD_STARTED = 1234,
255*670b568eSEd Maste   MSG_CHILD_FD_RECEIVED = 4321,
256*670b568eSEd Maste   // Magic numbers for messages sent by parent processes.
257*670b568eSEd Maste   MSG_PARENT_REQUEST_CHILD_EXIT = 9999,
258*670b568eSEd Maste   MSG_PARENT_CLOSED_FD = 10000,
259*670b568eSEd Maste   MSG_PARENT_CHILD_SHOULD_RUN = 10001,
260*670b568eSEd Maste };
261*670b568eSEd Maste 
262*670b568eSEd Maste #define SEND_INT_MESSAGE(fd, message) \
263*670b568eSEd Maste   do { \
264*670b568eSEd Maste     int _msg = message; \
265*670b568eSEd Maste     EXPECT_EQ(sizeof(_msg), (size_t)write(fd, &_msg, sizeof(_msg))); \
266*670b568eSEd Maste   } while (0)
267*670b568eSEd Maste 
268*670b568eSEd Maste #define AWAIT_INT_MESSAGE(fd, expected) \
269*670b568eSEd Maste   do {                                  \
270*670b568eSEd Maste     int _msg = 0; \
271*670b568eSEd Maste     EXPECT_EQ(sizeof(_msg), (size_t)read(fd, &_msg, sizeof(_msg))); \
272*670b568eSEd Maste     EXPECT_EQ(expected, _msg); \
273*670b568eSEd Maste   } while (0)
274*670b568eSEd Maste 
275*670b568eSEd Maste // Mark a test that can only be run as root.
276*670b568eSEd Maste #define GTEST_SKIP_IF_NOT_ROOT() \
277*670b568eSEd Maste   if (getuid() != 0) { GTEST_SKIP() << "requires root"; }
278*670b568eSEd Maste 
279*670b568eSEd Maste extern std::string capsicum_test_bindir;
280*670b568eSEd Maste 
281*670b568eSEd Maste #endif  // CAPSICUM_TEST_H
282