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