1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/file.h>
4 #include <sys/types.h>
5 #include <sys/wait.h>
6 #include <sys/stat.h>
7 #include <sys/mman.h>
8 #include <sys/select.h>
9 #include <sys/socket.h>
10 #include <sys/time.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <poll.h>
14 #include <stdint.h>
15
16 #include "capsicum.h"
17 #include "syscalls.h"
18 #include "capsicum-test.h"
19
20 /* Utilities for printing rights information */
21 /* Written in C style to allow for: */
22 /* TODO(drysdale): migrate these to somewhere in libcaprights/ */
23 #define RIGHTS_INFO(RR) { (RR), #RR}
24 typedef struct {
25 uint64_t right;
26 const char* name;
27 } right_info;
28 static right_info known_rights[] = {
29 /* Rights that are common to all versions of Capsicum */
30 RIGHTS_INFO(CAP_READ),
31 RIGHTS_INFO(CAP_WRITE),
32 RIGHTS_INFO(CAP_SEEK_TELL),
33 RIGHTS_INFO(CAP_SEEK),
34 RIGHTS_INFO(CAP_PREAD),
35 RIGHTS_INFO(CAP_PWRITE),
36 RIGHTS_INFO(CAP_MMAP),
37 RIGHTS_INFO(CAP_MMAP_R),
38 RIGHTS_INFO(CAP_MMAP_W),
39 RIGHTS_INFO(CAP_MMAP_X),
40 RIGHTS_INFO(CAP_MMAP_RW),
41 RIGHTS_INFO(CAP_MMAP_RX),
42 RIGHTS_INFO(CAP_MMAP_WX),
43 RIGHTS_INFO(CAP_MMAP_RWX),
44 RIGHTS_INFO(CAP_CREATE),
45 RIGHTS_INFO(CAP_FEXECVE),
46 RIGHTS_INFO(CAP_FSYNC),
47 RIGHTS_INFO(CAP_FTRUNCATE),
48 RIGHTS_INFO(CAP_LOOKUP),
49 RIGHTS_INFO(CAP_FCHDIR),
50 RIGHTS_INFO(CAP_FCHFLAGS),
51 RIGHTS_INFO(CAP_CHFLAGSAT),
52 RIGHTS_INFO(CAP_FCHMOD),
53 RIGHTS_INFO(CAP_FCHMODAT),
54 RIGHTS_INFO(CAP_FCHOWN),
55 RIGHTS_INFO(CAP_FCHOWNAT),
56 RIGHTS_INFO(CAP_FCNTL),
57 RIGHTS_INFO(CAP_FLOCK),
58 RIGHTS_INFO(CAP_FPATHCONF),
59 RIGHTS_INFO(CAP_FSCK),
60 RIGHTS_INFO(CAP_FSTAT),
61 RIGHTS_INFO(CAP_FSTATAT),
62 RIGHTS_INFO(CAP_FSTATFS),
63 RIGHTS_INFO(CAP_FUTIMES),
64 RIGHTS_INFO(CAP_FUTIMESAT),
65 RIGHTS_INFO(CAP_MKDIRAT),
66 RIGHTS_INFO(CAP_MKFIFOAT),
67 RIGHTS_INFO(CAP_MKNODAT),
68 RIGHTS_INFO(CAP_RENAMEAT_SOURCE),
69 RIGHTS_INFO(CAP_SYMLINKAT),
70 RIGHTS_INFO(CAP_UNLINKAT),
71 RIGHTS_INFO(CAP_ACCEPT),
72 RIGHTS_INFO(CAP_BIND),
73 RIGHTS_INFO(CAP_CONNECT),
74 RIGHTS_INFO(CAP_GETPEERNAME),
75 RIGHTS_INFO(CAP_GETSOCKNAME),
76 RIGHTS_INFO(CAP_GETSOCKOPT),
77 RIGHTS_INFO(CAP_LISTEN),
78 RIGHTS_INFO(CAP_PEELOFF),
79 RIGHTS_INFO(CAP_RECV),
80 RIGHTS_INFO(CAP_SEND),
81 RIGHTS_INFO(CAP_SETSOCKOPT),
82 RIGHTS_INFO(CAP_SHUTDOWN),
83 RIGHTS_INFO(CAP_BINDAT),
84 RIGHTS_INFO(CAP_CONNECTAT),
85 RIGHTS_INFO(CAP_LINKAT_SOURCE),
86 RIGHTS_INFO(CAP_RENAMEAT_TARGET),
87 RIGHTS_INFO(CAP_SOCK_CLIENT),
88 RIGHTS_INFO(CAP_SOCK_SERVER),
89 RIGHTS_INFO(CAP_MAC_GET),
90 RIGHTS_INFO(CAP_MAC_SET),
91 RIGHTS_INFO(CAP_SEM_GETVALUE),
92 RIGHTS_INFO(CAP_SEM_POST),
93 RIGHTS_INFO(CAP_SEM_WAIT),
94 RIGHTS_INFO(CAP_EVENT),
95 RIGHTS_INFO(CAP_KQUEUE_EVENT),
96 RIGHTS_INFO(CAP_IOCTL),
97 RIGHTS_INFO(CAP_TTYHOOK),
98 RIGHTS_INFO(CAP_PDWAIT),
99 RIGHTS_INFO(CAP_PDGETPID),
100 RIGHTS_INFO(CAP_PDKILL),
101 RIGHTS_INFO(CAP_EXTATTR_DELETE),
102 RIGHTS_INFO(CAP_EXTATTR_GET),
103 RIGHTS_INFO(CAP_EXTATTR_LIST),
104 RIGHTS_INFO(CAP_EXTATTR_SET),
105 RIGHTS_INFO(CAP_ACL_CHECK),
106 RIGHTS_INFO(CAP_ACL_DELETE),
107 RIGHTS_INFO(CAP_ACL_GET),
108 RIGHTS_INFO(CAP_ACL_SET),
109 RIGHTS_INFO(CAP_KQUEUE_CHANGE),
110 RIGHTS_INFO(CAP_KQUEUE),
111 /* Rights that are only present in some version or some OS, and so are #ifdef'ed */
112 /* LINKAT got split */
113 #ifdef CAP_LINKAT
114 RIGHTS_INFO(CAP_LINKAT),
115 #endif
116 #ifdef CAP_LINKAT_SOURCE
117 RIGHTS_INFO(CAP_LINKAT_SOURCE),
118 #endif
119 #ifdef CAP_LINKAT_TARGET
120 RIGHTS_INFO(CAP_LINKAT_TARGET),
121 #endif
122 /* Linux aliased some FD operations for pdgetpid/pdkill */
123 #ifdef CAP_PDGETPID_FREEBSD
124 RIGHTS_INFO(CAP_PDGETPID_FREEBSD),
125 #endif
126 #ifdef CAP_PDKILL_FREEBSD
127 RIGHTS_INFO(CAP_PDKILL_FREEBSD),
128 #endif
129 /* Linux-specific rights */
130 #ifdef CAP_FSIGNAL
131 RIGHTS_INFO(CAP_FSIGNAL),
132 #endif
133 #ifdef CAP_EPOLL_CTL
134 RIGHTS_INFO(CAP_EPOLL_CTL),
135 #endif
136 #ifdef CAP_NOTIFY
137 RIGHTS_INFO(CAP_NOTIFY),
138 #endif
139 #ifdef CAP_SETNS
140 RIGHTS_INFO(CAP_SETNS),
141 #endif
142 #ifdef CAP_PERFMON
143 RIGHTS_INFO(CAP_PERFMON),
144 #endif
145 #ifdef CAP_BPF
146 RIGHTS_INFO(CAP_BPF),
147 #endif
148 /* Rights in later versions of FreeBSD (>10.0) */
149 };
150
ShowCapRights(FILE * out,int fd)151 void ShowCapRights(FILE *out, int fd) {
152 size_t ii;
153 bool first = true;
154 cap_rights_t rights;
155 CAP_SET_NONE(&rights);
156 if (cap_rights_get(fd, &rights) < 0) {
157 fprintf(out, "Failed to get rights for fd %d: errno %d\n", fd, errno);
158 return;
159 }
160
161 /* First print out all known rights */
162 size_t num_known = (sizeof(known_rights)/sizeof(known_rights[0]));
163 for (ii = 0; ii < num_known; ii++) {
164 if (cap_rights_is_set(&rights, known_rights[ii].right)) {
165 if (!first) fprintf(out, ",");
166 first = false;
167 fprintf(out, "%s", known_rights[ii].name);
168 }
169 }
170 /* Now repeat the loop, clearing rights we know of; this needs to be
171 * a separate loop because some named rights overlap.
172 */
173 for (ii = 0; ii < num_known; ii++) {
174 cap_rights_clear(&rights, known_rights[ii].right);
175 }
176 /* The following relies on the internal structure of cap_rights_t to
177 * try to show rights we don't know about. */
178 for (ii = 0; ii < (size_t)CAPARSIZE(&rights); ii++) {
179 uint64_t bits = (rights.cr_rights[0] & 0x01ffffffffffffffULL);
180 if (bits != 0) {
181 uint64_t which = 1;
182 for (which = 1; which < 0x0200000000000000 ; which <<= 1) {
183 if (bits & which) {
184 if (!first) fprintf(out, ",");
185 fprintf(out, "CAP_RIGHT(%d, 0x%016llxULL)", (int)ii, (long long unsigned)which);
186 }
187 }
188 }
189 }
190 fprintf(out, "\n");
191 }
192
ShowAllCapRights(FILE * out)193 void ShowAllCapRights(FILE *out) {
194 int fd;
195 struct rlimit limits;
196 if (getrlimit(RLIMIT_NOFILE, &limits) != 0) {
197 fprintf(out, "Failed to getrlimit for max FDs: errno %d\n", errno);
198 return;
199 }
200 for (fd = 0; fd < (int)limits.rlim_cur; fd++) {
201 if (fcntl(fd, F_GETFD, 0) != 0) {
202 continue;
203 }
204 fprintf(out, "fd %d: ", fd);
205 ShowCapRights(out, fd);
206 }
207 }
208
FORK_TEST(Capability,CapNew)209 FORK_TEST(Capability, CapNew) {
210 cap_rights_t r_rws;
211 cap_rights_init(&r_rws, CAP_READ, CAP_WRITE, CAP_SEEK);
212 cap_rights_t r_all;
213 CAP_SET_ALL(&r_all);
214
215 int cap_fd = dup(STDOUT_FILENO);
216 cap_rights_t rights;
217 CAP_SET_NONE(&rights);
218 EXPECT_OK(cap_rights_get(cap_fd, &rights));
219 EXPECT_RIGHTS_EQ(&r_all, &rights);
220
221 EXPECT_OK(cap_fd);
222 EXPECT_OK(cap_rights_limit(cap_fd, &r_rws));
223 if (cap_fd < 0) return;
224 int rc = write(cap_fd, "OK!\n", 4);
225 EXPECT_OK(rc);
226 EXPECT_EQ(4, rc);
227 EXPECT_OK(cap_rights_get(cap_fd, &rights));
228 EXPECT_RIGHTS_EQ(&r_rws, &rights);
229
230 // dup/dup2 should preserve rights.
231 int cap_dup = dup(cap_fd);
232 EXPECT_OK(cap_dup);
233 EXPECT_OK(cap_rights_get(cap_dup, &rights));
234 EXPECT_RIGHTS_EQ(&r_rws, &rights);
235 close(cap_dup);
236 EXPECT_OK(dup2(cap_fd, cap_dup));
237 EXPECT_OK(cap_rights_get(cap_dup, &rights));
238 EXPECT_RIGHTS_EQ(&r_rws, &rights);
239 close(cap_dup);
240 #ifdef HAVE_DUP3
241 EXPECT_OK(dup3(cap_fd, cap_dup, 0));
242 EXPECT_OK(cap_rights_get(cap_dup, &rights));
243 EXPECT_RIGHTS_EQ(&r_rws, &rights);
244 close(cap_dup);
245 #endif
246
247 // Try to get a disjoint set of rights in a sub-capability.
248 cap_rights_t r_rs;
249 cap_rights_init(&r_rs, CAP_READ, CAP_SEEK);
250 cap_rights_t r_rsmapchmod;
251 cap_rights_init(&r_rsmapchmod, CAP_READ, CAP_SEEK, CAP_MMAP, CAP_FCHMOD);
252 int cap_cap_fd = dup(cap_fd);
253 EXPECT_OK(cap_cap_fd);
254 EXPECT_NOTCAPABLE(cap_rights_limit(cap_cap_fd, &r_rsmapchmod));
255
256 // Dump rights info to stderr (mostly to ensure that Show[All]CapRights()
257 // is working.
258 ShowAllCapRights(stderr);
259
260 EXPECT_OK(close(cap_fd));
261 }
262
FORK_TEST(Capability,CapEnter)263 FORK_TEST(Capability, CapEnter) {
264 EXPECT_EQ(0, cap_enter());
265 }
266
FORK_TEST(Capability,BasicInterception)267 FORK_TEST(Capability, BasicInterception) {
268 cap_rights_t r_0;
269 cap_rights_init(&r_0, 0);
270 int cap_fd = dup(1);
271 EXPECT_OK(cap_fd);
272 EXPECT_OK(cap_rights_limit(cap_fd, &r_0));
273
274 EXPECT_NOTCAPABLE(write(cap_fd, "", 0));
275
276 EXPECT_OK(cap_enter()); // Enter capability mode
277
278 EXPECT_NOTCAPABLE(write(cap_fd, "", 0));
279
280 // Create a new capability which does have write permission
281 cap_rights_t r_ws;
282 cap_rights_init(&r_ws, CAP_WRITE, CAP_SEEK);
283 int cap_fd2 = dup(1);
284 EXPECT_OK(cap_fd2);
285 EXPECT_OK(cap_rights_limit(cap_fd2, &r_ws));
286 EXPECT_OK(write(cap_fd2, "", 0));
287
288 // Tidy up.
289 if (cap_fd >= 0) close(cap_fd);
290 if (cap_fd2 >= 0) close(cap_fd2);
291 }
292
293 FORK_TEST_ON(Capability, OpenAtDirectoryTraversal, TmpFile("cap_openat_testfile")) {
294 int dir = open(tmpdir.c_str(), O_RDONLY);
295 EXPECT_OK(dir);
296
297 cap_enter();
298
299 int file = openat(dir, "cap_openat_testfile", O_RDONLY|O_CREAT, 0644);
300 EXPECT_OK(file);
301
302 // Test that we are confined to /tmp, and cannot
303 // escape using absolute paths or ../.
304 int new_file = openat(dir, "../dev/null", O_RDONLY);
305 EXPECT_EQ(-1, new_file);
306
307 new_file = openat(dir, "..", O_RDONLY);
308 EXPECT_EQ(-1, new_file);
309
310 new_file = openat(dir, "/dev/null", O_RDONLY);
311 EXPECT_EQ(-1, new_file);
312
313 new_file = openat(dir, "/", O_RDONLY);
314 EXPECT_EQ(-1, new_file);
315
316 // Tidy up.
317 close(file);
318 close(dir);
319 }
320
321 FORK_TEST_ON(Capability, FileInSync, TmpFile("cap_file_sync")) {
322 int fd = open(TmpFile("cap_file_sync"), O_RDWR|O_CREAT, 0644);
323 EXPECT_OK(fd);
324 const char* message = "Hello capability world";
325 EXPECT_OK(write(fd, message, strlen(message)));
326
327 cap_rights_t r_rsstat;
328 cap_rights_init(&r_rsstat, CAP_READ, CAP_SEEK, CAP_FSTAT);
329
330 int cap_fd = dup(fd);
331 EXPECT_OK(cap_fd);
332 EXPECT_OK(cap_rights_limit(cap_fd, &r_rsstat));
333 int cap_cap_fd = dup(cap_fd);
334 EXPECT_OK(cap_cap_fd);
335 EXPECT_OK(cap_rights_limit(cap_cap_fd, &r_rsstat));
336
337 EXPECT_OK(cap_enter()); // Enter capability mode.
338
339 // Changes to one file descriptor affect the others.
340 EXPECT_EQ(1, lseek(fd, 1, SEEK_SET));
341 EXPECT_EQ(1, lseek(fd, 0, SEEK_CUR));
342 EXPECT_EQ(1, lseek(cap_fd, 0, SEEK_CUR));
343 EXPECT_EQ(1, lseek(cap_cap_fd, 0, SEEK_CUR));
344 EXPECT_EQ(3, lseek(cap_fd, 3, SEEK_SET));
345 EXPECT_EQ(3, lseek(fd, 0, SEEK_CUR));
346 EXPECT_EQ(3, lseek(cap_fd, 0, SEEK_CUR));
347 EXPECT_EQ(3, lseek(cap_cap_fd, 0, SEEK_CUR));
348 EXPECT_EQ(5, lseek(cap_cap_fd, 5, SEEK_SET));
349 EXPECT_EQ(5, lseek(fd, 0, SEEK_CUR));
350 EXPECT_EQ(5, lseek(cap_fd, 0, SEEK_CUR));
351 EXPECT_EQ(5, lseek(cap_cap_fd, 0, SEEK_CUR));
352
353 close(cap_cap_fd);
354 close(cap_fd);
355 close(fd);
356 }
357
358 // Create a capability on /tmp that does not allow CAP_WRITE,
359 // and check that this restriction is inherited through openat().
360 FORK_TEST_ON(Capability, Inheritance, TmpFile("cap_openat_write_testfile")) {
361 int dir = open(tmpdir.c_str(), O_RDONLY);
362 EXPECT_OK(dir);
363
364 cap_rights_t r_rl;
365 cap_rights_init(&r_rl, CAP_READ, CAP_LOOKUP);
366
367 int cap_dir = dup(dir);
368 EXPECT_OK(cap_dir);
369 EXPECT_OK(cap_rights_limit(cap_dir, &r_rl));
370
371 const char *filename = "cap_openat_write_testfile";
372 int file = openat(dir, filename, O_WRONLY|O_CREAT, 0644);
373 EXPECT_OK(file);
374 EXPECT_EQ(5, write(file, "TEST\n", 5));
375 if (file >= 0) close(file);
376
377 EXPECT_OK(cap_enter());
378 file = openat(cap_dir, filename, O_RDONLY);
379 EXPECT_OK(file);
380
381 cap_rights_t rights;
382 cap_rights_init(&rights, 0);
383 EXPECT_OK(cap_rights_get(file, &rights));
384 EXPECT_RIGHTS_EQ(&r_rl, &rights);
385 if (file >= 0) close(file);
386
387 file = openat(cap_dir, filename, O_WRONLY|O_APPEND);
388 EXPECT_NOTCAPABLE(file);
389 if (file > 0) close(file);
390
391 if (dir > 0) close(dir);
392 if (cap_dir > 0) close(cap_dir);
393 }
394
395
396 // Ensure that, if the capability had enough rights for the system call to
397 // pass, then it did. Otherwise, ensure that the errno is ENOTCAPABLE;
398 // capability restrictions should kick in before any other error logic.
399 #define CHECK_RIGHT_RESULT(result, rights, ...) do { \
400 cap_rights_t rights_needed; \
401 cap_rights_init(&rights_needed, __VA_ARGS__); \
402 if (cap_rights_contains(&rights, &rights_needed)) { \
403 EXPECT_OK(result) << std::endl \
404 << " need: " << rights_needed \
405 << std::endl \
406 << " got: " << rights; \
407 } else { \
408 EXPECT_EQ(-1, result) << " need: " << rights_needed \
409 << std::endl \
410 << " got: "<< rights; \
411 EXPECT_EQ(ENOTCAPABLE, errno); \
412 } \
413 } while (0)
414
415 #define EXPECT_MMAP_NOTCAPABLE(result) do { \
416 void *rv = result; \
417 EXPECT_EQ(MAP_FAILED, rv); \
418 EXPECT_EQ(ENOTCAPABLE, errno); \
419 if (rv != MAP_FAILED) munmap(rv, getpagesize()); \
420 } while (0)
421
422 #define EXPECT_MMAP_OK(result) do { \
423 void *rv = result; \
424 EXPECT_NE(MAP_FAILED, rv) << " with errno " << errno; \
425 if (rv != MAP_FAILED) munmap(rv, getpagesize()); \
426 } while (0)
427
428
429 // As above, but for the special mmap() case: unmap after successful mmap().
430 #define CHECK_RIGHT_MMAP_RESULT(result, rights, ...) do { \
431 cap_rights_t rights_needed; \
432 cap_rights_init(&rights_needed, __VA_ARGS__); \
433 if (cap_rights_contains(&rights, &rights_needed)) { \
434 EXPECT_MMAP_OK(result); \
435 } else { \
436 EXPECT_MMAP_NOTCAPABLE(result); \
437 } \
438 } while (0)
439
440 FORK_TEST_ON(Capability, Mmap, TmpFile("cap_mmap_operations")) {
441 int fd = open(TmpFile("cap_mmap_operations"), O_RDWR | O_CREAT, 0644);
442 EXPECT_OK(fd);
443 if (fd < 0) return;
444
445 cap_rights_t r_0;
446 cap_rights_init(&r_0, 0);
447 cap_rights_t r_mmap;
448 cap_rights_init(&r_mmap, CAP_MMAP);
449 cap_rights_t r_r;
450 cap_rights_init(&r_r, CAP_PREAD);
451 cap_rights_t r_rmmap;
452 cap_rights_init(&r_rmmap, CAP_PREAD, CAP_MMAP);
453
454 // If we're missing a capability, it will fail.
455 int cap_none = dup(fd);
456 EXPECT_OK(cap_none);
457 EXPECT_OK(cap_rights_limit(cap_none, &r_0));
458 int cap_mmap = dup(fd);
459 EXPECT_OK(cap_mmap);
460 EXPECT_OK(cap_rights_limit(cap_mmap, &r_mmap));
461 int cap_read = dup(fd);
462 EXPECT_OK(cap_read);
463 EXPECT_OK(cap_rights_limit(cap_read, &r_r));
464 int cap_both = dup(fd);
465 EXPECT_OK(cap_both);
466 EXPECT_OK(cap_rights_limit(cap_both, &r_rmmap));
467
468 EXPECT_OK(cap_enter()); // Enter capability mode.
469
470 EXPECT_MMAP_NOTCAPABLE(mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE, cap_none, 0));
471 EXPECT_MMAP_NOTCAPABLE(mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE, cap_mmap, 0));
472 EXPECT_MMAP_NOTCAPABLE(mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE, cap_read, 0));
473
474 EXPECT_MMAP_OK(mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE, cap_both, 0));
475
476 // A call with MAP_ANONYMOUS should succeed without any capability requirements.
477 EXPECT_MMAP_OK(mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0));
478
479 EXPECT_OK(close(cap_both));
480 EXPECT_OK(close(cap_read));
481 EXPECT_OK(close(cap_mmap));
482 EXPECT_OK(close(cap_none));
483 EXPECT_OK(close(fd));
484 }
485
486 // Given a file descriptor, create a capability with specific rights and
487 // make sure only those rights work.
488 #define TRY_FILE_OPS(fd, ...) do { \
489 SCOPED_TRACE(#__VA_ARGS__); \
490 cap_rights_t rights; \
491 cap_rights_init(&rights, __VA_ARGS__); \
492 TryFileOps((fd), rights); \
493 } while (0)
494
TryFileOps(int fd,cap_rights_t rights)495 static void TryFileOps(int fd, cap_rights_t rights) {
496 int cap_fd = dup(fd);
497 EXPECT_OK(cap_fd);
498 EXPECT_OK(cap_rights_limit(cap_fd, &rights));
499 if (cap_fd < 0) return;
500 cap_rights_t erights;
501 EXPECT_OK(cap_rights_get(cap_fd, &erights));
502 EXPECT_RIGHTS_EQ(&rights, &erights);
503
504 // Check creation of a capability from a capability.
505 int cap_cap_fd = dup(cap_fd);
506 EXPECT_OK(cap_cap_fd);
507 EXPECT_OK(cap_rights_limit(cap_cap_fd, &rights));
508 EXPECT_NE(cap_fd, cap_cap_fd);
509 EXPECT_OK(cap_rights_get(cap_cap_fd, &erights));
510 EXPECT_RIGHTS_EQ(&rights, &erights);
511 close(cap_cap_fd);
512
513 char ch;
514 CHECK_RIGHT_RESULT(read(cap_fd, &ch, sizeof(ch)), rights, CAP_READ, CAP_SEEK_ASWAS);
515
516 ssize_t len1 = pread(cap_fd, &ch, sizeof(ch), 0);
517 CHECK_RIGHT_RESULT(len1, rights, CAP_PREAD);
518 ssize_t len2 = pread(cap_fd, &ch, sizeof(ch), 0);
519 CHECK_RIGHT_RESULT(len2, rights, CAP_PREAD);
520 EXPECT_EQ(len1, len2);
521
522 CHECK_RIGHT_RESULT(write(cap_fd, &ch, sizeof(ch)), rights, CAP_WRITE, CAP_SEEK_ASWAS);
523 CHECK_RIGHT_RESULT(pwrite(cap_fd, &ch, sizeof(ch), 0), rights, CAP_PWRITE);
524 CHECK_RIGHT_RESULT(lseek(cap_fd, 0, SEEK_SET), rights, CAP_SEEK);
525
526 #ifdef HAVE_CHFLAGS
527 // Note: this is not expected to work over NFS.
528 struct statfs sf;
529 EXPECT_OK(fstatfs(fd, &sf));
530 bool is_nfs = (strncmp("nfs", sf.f_fstypename, sizeof(sf.f_fstypename)) == 0);
531 if (!is_nfs) {
532 CHECK_RIGHT_RESULT(fchflags(cap_fd, UF_NODUMP), rights, CAP_FCHFLAGS);
533 }
534 #endif
535
536 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_NONE, MAP_SHARED, cap_fd, 0),
537 rights, CAP_MMAP);
538 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, cap_fd, 0),
539 rights, CAP_MMAP_R);
540 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, cap_fd, 0),
541 rights, CAP_MMAP_W);
542 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, cap_fd, 0),
543 rights, CAP_MMAP_X);
544 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, cap_fd, 0),
545 rights, CAP_MMAP_RW);
546 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED, cap_fd, 0),
547 rights, CAP_MMAP_RX);
548 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED, cap_fd, 0),
549 rights, CAP_MMAP_WX);
550 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, cap_fd, 0),
551 rights, CAP_MMAP_RWX);
552
553 CHECK_RIGHT_RESULT(fsync(cap_fd), rights, CAP_FSYNC);
554 #ifdef HAVE_SYNC_FILE_RANGE
555 CHECK_RIGHT_RESULT(sync_file_range(cap_fd, 0, 1, 0), rights, CAP_FSYNC, CAP_SEEK);
556 #endif
557
558 int rc = fcntl(cap_fd, F_GETFL);
559 CHECK_RIGHT_RESULT(rc, rights, CAP_FCNTL);
560 rc = fcntl(cap_fd, F_SETFL, rc);
561 CHECK_RIGHT_RESULT(rc, rights, CAP_FCNTL);
562
563 CHECK_RIGHT_RESULT(fchown(cap_fd, -1, -1), rights, CAP_FCHOWN);
564
565 CHECK_RIGHT_RESULT(fchmod(cap_fd, 0644), rights, CAP_FCHMOD);
566
567 CHECK_RIGHT_RESULT(flock(cap_fd, LOCK_SH), rights, CAP_FLOCK);
568 CHECK_RIGHT_RESULT(flock(cap_fd, LOCK_UN), rights, CAP_FLOCK);
569
570 CHECK_RIGHT_RESULT(ftruncate(cap_fd, 0), rights, CAP_FTRUNCATE);
571
572 struct stat sb;
573 CHECK_RIGHT_RESULT(fstat(cap_fd, &sb), rights, CAP_FSTAT);
574
575 struct statfs cap_sf;
576 CHECK_RIGHT_RESULT(fstatfs(cap_fd, &cap_sf), rights, CAP_FSTATFS);
577
578 #ifdef HAVE_FPATHCONF
579 CHECK_RIGHT_RESULT(fpathconf(cap_fd, _PC_NAME_MAX), rights, CAP_FPATHCONF);
580 #endif
581
582 CHECK_RIGHT_RESULT(futimes(cap_fd, NULL), rights, CAP_FUTIMES);
583
584 struct pollfd pollfd;
585 pollfd.fd = cap_fd;
586 pollfd.events = POLLIN | POLLERR | POLLHUP;
587 pollfd.revents = 0;
588 int ret = poll(&pollfd, 1, 0);
589 if (cap_rights_is_set(&rights, CAP_EVENT)) {
590 EXPECT_OK(ret);
591 } else {
592 EXPECT_NE(0, (pollfd.revents & POLLNVAL));
593 }
594
595 struct timeval tv;
596 tv.tv_sec = 0;
597 tv.tv_usec = 100;
598 fd_set rset;
599 FD_ZERO(&rset);
600 FD_SET(cap_fd, &rset);
601 fd_set wset;
602 FD_ZERO(&wset);
603 FD_SET(cap_fd, &wset);
604 ret = select(cap_fd+1, &rset, &wset, NULL, &tv);
605 if (cap_rights_is_set(&rights, CAP_EVENT)) {
606 EXPECT_OK(ret);
607 } else {
608 EXPECT_NOTCAPABLE(ret);
609 }
610
611 // TODO(FreeBSD): kqueue
612
613 EXPECT_OK(close(cap_fd));
614 }
615
616 FORK_TEST_ON(Capability, Operations, TmpFile("cap_fd_operations")) {
617 int fd = open(TmpFile("cap_fd_operations"), O_RDWR | O_CREAT, 0644);
618 EXPECT_OK(fd);
619 if (fd < 0) return;
620
621 EXPECT_OK(cap_enter()); // Enter capability mode.
622
623 // Try a variety of different combinations of rights - a full
624 // enumeration is too large (2^N with N~30+) to perform.
625 TRY_FILE_OPS(fd, CAP_READ);
626 TRY_FILE_OPS(fd, CAP_PREAD);
627 TRY_FILE_OPS(fd, CAP_WRITE);
628 TRY_FILE_OPS(fd, CAP_PWRITE);
629 TRY_FILE_OPS(fd, CAP_READ, CAP_WRITE);
630 TRY_FILE_OPS(fd, CAP_PREAD, CAP_PWRITE);
631 TRY_FILE_OPS(fd, CAP_SEEK);
632 TRY_FILE_OPS(fd, CAP_FCHFLAGS);
633 TRY_FILE_OPS(fd, CAP_IOCTL);
634 TRY_FILE_OPS(fd, CAP_FSTAT);
635 TRY_FILE_OPS(fd, CAP_MMAP);
636 TRY_FILE_OPS(fd, CAP_MMAP_R);
637 TRY_FILE_OPS(fd, CAP_MMAP_W);
638 TRY_FILE_OPS(fd, CAP_MMAP_X);
639 TRY_FILE_OPS(fd, CAP_MMAP_RW);
640 TRY_FILE_OPS(fd, CAP_MMAP_RX);
641 TRY_FILE_OPS(fd, CAP_MMAP_WX);
642 TRY_FILE_OPS(fd, CAP_MMAP_RWX);
643 TRY_FILE_OPS(fd, CAP_FCNTL);
644 TRY_FILE_OPS(fd, CAP_EVENT);
645 TRY_FILE_OPS(fd, CAP_FSYNC);
646 TRY_FILE_OPS(fd, CAP_FCHOWN);
647 TRY_FILE_OPS(fd, CAP_FCHMOD);
648 TRY_FILE_OPS(fd, CAP_FTRUNCATE);
649 TRY_FILE_OPS(fd, CAP_FLOCK);
650 TRY_FILE_OPS(fd, CAP_FSTATFS);
651 TRY_FILE_OPS(fd, CAP_FPATHCONF);
652 TRY_FILE_OPS(fd, CAP_FUTIMES);
653 TRY_FILE_OPS(fd, CAP_ACL_GET);
654 TRY_FILE_OPS(fd, CAP_ACL_SET);
655 TRY_FILE_OPS(fd, CAP_ACL_DELETE);
656 TRY_FILE_OPS(fd, CAP_ACL_CHECK);
657 TRY_FILE_OPS(fd, CAP_EXTATTR_GET);
658 TRY_FILE_OPS(fd, CAP_EXTATTR_SET);
659 TRY_FILE_OPS(fd, CAP_EXTATTR_DELETE);
660 TRY_FILE_OPS(fd, CAP_EXTATTR_LIST);
661 TRY_FILE_OPS(fd, CAP_MAC_GET);
662 TRY_FILE_OPS(fd, CAP_MAC_SET);
663
664 // Socket-specific.
665 TRY_FILE_OPS(fd, CAP_GETPEERNAME);
666 TRY_FILE_OPS(fd, CAP_GETSOCKNAME);
667 TRY_FILE_OPS(fd, CAP_ACCEPT);
668
669 close(fd);
670 }
671
672 #define TRY_DIR_OPS(dfd, ...) do { \
673 cap_rights_t rights; \
674 cap_rights_init(&rights, __VA_ARGS__); \
675 TryDirOps((dfd), rights); \
676 } while (0)
677
TryDirOps(int dirfd,cap_rights_t rights)678 static void TryDirOps(int dirfd, cap_rights_t rights) {
679 cap_rights_t erights;
680 int dfd_cap = dup(dirfd);
681 EXPECT_OK(dfd_cap);
682 EXPECT_OK(cap_rights_limit(dfd_cap, &rights));
683 EXPECT_OK(cap_rights_get(dfd_cap, &erights));
684 EXPECT_RIGHTS_EQ(&rights, &erights);
685
686 int rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDONLY, 0600);
687 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_LOOKUP);
688 if (rc >= 0) {
689 EXPECT_OK(close(rc));
690 EXPECT_OK(unlinkat(dirfd, "cap_create", 0));
691 }
692 rc = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY | O_APPEND, 0600);
693 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_WRITE, CAP_LOOKUP);
694 if (rc >= 0) {
695 EXPECT_OK(close(rc));
696 EXPECT_OK(unlinkat(dirfd, "cap_create", 0));
697 }
698 rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR | O_APPEND, 0600);
699 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_LOOKUP);
700 if (rc >= 0) {
701 EXPECT_OK(close(rc));
702 EXPECT_OK(unlinkat(dirfd, "cap_create", 0));
703 }
704
705 rc = openat(dirfd, "cap_faccess", O_CREAT, 0600);
706 EXPECT_OK(rc);
707 EXPECT_OK(close(rc));
708 rc = faccessat(dfd_cap, "cap_faccess", F_OK, 0);
709 CHECK_RIGHT_RESULT(rc, rights, CAP_FSTAT, CAP_LOOKUP);
710 EXPECT_OK(unlinkat(dirfd, "cap_faccess", 0));
711
712 rc = openat(dirfd, "cap_fsync", O_CREAT, 0600);
713 EXPECT_OK(rc);
714 EXPECT_OK(close(rc));
715 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDONLY);
716 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_LOOKUP);
717 if (rc >= 0) {
718 EXPECT_OK(close(rc));
719 }
720 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY | O_APPEND);
721 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP);
722 if (rc >= 0) {
723 EXPECT_OK(close(rc));
724 }
725 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR | O_APPEND);
726 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP);
727 if (rc >= 0) {
728 EXPECT_OK(close(rc));
729 }
730 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDONLY);
731 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_LOOKUP);
732 if (rc >= 0) {
733 EXPECT_OK(close(rc));
734 }
735 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY | O_APPEND);
736 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP);
737 if (rc >= 0) {
738 EXPECT_OK(close(rc));
739 }
740 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR | O_APPEND);
741 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP);
742 if (rc >= 0) {
743 EXPECT_OK(close(rc));
744 }
745 EXPECT_OK(unlinkat(dirfd, "cap_fsync", 0));
746
747 rc = openat(dirfd, "cap_ftruncate", O_CREAT, 0600);
748 EXPECT_OK(rc);
749 EXPECT_OK(close(rc));
750 rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDONLY);
751 CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_READ, CAP_LOOKUP);
752 if (rc >= 0) {
753 EXPECT_OK(close(rc));
754 }
755 rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_WRONLY);
756 CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_WRITE, CAP_LOOKUP);
757 if (rc >= 0) {
758 EXPECT_OK(close(rc));
759 }
760 rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDWR);
761 CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_READ, CAP_WRITE, CAP_LOOKUP);
762 if (rc >= 0) {
763 EXPECT_OK(close(rc));
764 }
765 EXPECT_OK(unlinkat(dirfd, "cap_ftruncate", 0));
766
767 rc = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY, 0600);
768 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
769 if (rc >= 0) {
770 EXPECT_OK(close(rc));
771 EXPECT_OK(unlinkat(dirfd, "cap_create", 0));
772 }
773 rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR, 0600);
774 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
775 if (rc >= 0) {
776 EXPECT_OK(close(rc));
777 EXPECT_OK(unlinkat(dirfd, "cap_create", 0));
778 }
779
780 rc = openat(dirfd, "cap_fsync", O_CREAT, 0600);
781 EXPECT_OK(rc);
782 EXPECT_OK(close(rc));
783 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY);
784 CHECK_RIGHT_RESULT(rc,
785 rights, CAP_FSYNC, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
786 if (rc >= 0) {
787 EXPECT_OK(close(rc));
788 }
789 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR);
790 CHECK_RIGHT_RESULT(rc,
791 rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
792 if (rc >= 0) {
793 EXPECT_OK(close(rc));
794 }
795 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY);
796 CHECK_RIGHT_RESULT(rc,
797 rights, CAP_FSYNC, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
798 if (rc >= 0) {
799 EXPECT_OK(close(rc));
800 }
801 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR);
802 CHECK_RIGHT_RESULT(rc,
803 rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
804 if (rc >= 0) {
805 EXPECT_OK(close(rc));
806 }
807 EXPECT_OK(unlinkat(dirfd, "cap_fsync", 0));
808
809 #ifdef HAVE_CHFLAGSAT
810 rc = openat(dirfd, "cap_chflagsat", O_CREAT, 0600);
811 EXPECT_OK(rc);
812 EXPECT_OK(close(rc));
813 rc = chflagsat(dfd_cap, "cap_chflagsat", UF_NODUMP, 0);
814 CHECK_RIGHT_RESULT(rc, rights, CAP_CHFLAGSAT, CAP_LOOKUP);
815 EXPECT_OK(unlinkat(dirfd, "cap_chflagsat", 0));
816 #endif
817
818 rc = openat(dirfd, "cap_fchownat", O_CREAT, 0600);
819 EXPECT_OK(rc);
820 EXPECT_OK(close(rc));
821 rc = fchownat(dfd_cap, "cap_fchownat", -1, -1, 0);
822 CHECK_RIGHT_RESULT(rc, rights, CAP_FCHOWN, CAP_LOOKUP);
823 EXPECT_OK(unlinkat(dirfd, "cap_fchownat", 0));
824
825 rc = openat(dirfd, "cap_fchmodat", O_CREAT, 0600);
826 EXPECT_OK(rc);
827 EXPECT_OK(close(rc));
828 rc = fchmodat(dfd_cap, "cap_fchmodat", 0600, 0);
829 CHECK_RIGHT_RESULT(rc, rights, CAP_FCHMOD, CAP_LOOKUP);
830 EXPECT_OK(unlinkat(dirfd, "cap_fchmodat", 0));
831
832 rc = openat(dirfd, "cap_fstatat", O_CREAT, 0600);
833 EXPECT_OK(rc);
834 EXPECT_OK(close(rc));
835 struct stat sb;
836 rc = fstatat(dfd_cap, "cap_fstatat", &sb, 0);
837 CHECK_RIGHT_RESULT(rc, rights, CAP_FSTAT, CAP_LOOKUP);
838 EXPECT_OK(unlinkat(dirfd, "cap_fstatat", 0));
839
840 rc = openat(dirfd, "cap_futimesat", O_CREAT, 0600);
841 EXPECT_OK(rc);
842 EXPECT_OK(close(rc));
843 rc = futimesat(dfd_cap, "cap_futimesat", NULL);
844 CHECK_RIGHT_RESULT(rc, rights, CAP_FUTIMES, CAP_LOOKUP);
845 EXPECT_OK(unlinkat(dirfd, "cap_futimesat", 0));
846
847 // For linkat(2), need:
848 // - CAP_LINKAT_SOURCE on source
849 // - CAP_LINKAT_TARGET on destination.
850 rc = openat(dirfd, "cap_linkat_src", O_CREAT, 0600);
851 EXPECT_OK(rc);
852 EXPECT_OK(close(rc));
853
854 rc = linkat(dirfd, "cap_linkat_src", dfd_cap, "cap_linkat_dst", 0);
855 CHECK_RIGHT_RESULT(rc, rights, CAP_LINKAT_TARGET);
856 if (rc >= 0) {
857 EXPECT_OK(unlinkat(dirfd, "cap_linkat_dst", 0));
858 }
859
860 rc = linkat(dfd_cap, "cap_linkat_src", dirfd, "cap_linkat_dst", 0);
861 CHECK_RIGHT_RESULT(rc, rights, CAP_LINKAT_SOURCE);
862 if (rc >= 0) {
863 EXPECT_OK(unlinkat(dirfd, "cap_linkat_dst", 0));
864 }
865
866 EXPECT_OK(unlinkat(dirfd, "cap_linkat_src", 0));
867
868 rc = mkdirat(dfd_cap, "cap_mkdirat", 0700);
869 CHECK_RIGHT_RESULT(rc, rights, CAP_MKDIRAT, CAP_LOOKUP);
870 if (rc >= 0) {
871 EXPECT_OK(unlinkat(dirfd, "cap_mkdirat", AT_REMOVEDIR));
872 }
873
874 #ifdef HAVE_MKFIFOAT
875 rc = mkfifoat(dfd_cap, "cap_mkfifoat", 0600);
876 CHECK_RIGHT_RESULT(rc, rights, CAP_MKFIFOAT, CAP_LOOKUP);
877 if (rc >= 0) {
878 EXPECT_OK(unlinkat(dirfd, "cap_mkfifoat", 0));
879 }
880 #endif
881
882 if (getuid() == 0) {
883 rc = mknodat(dfd_cap, "cap_mknodat", S_IFCHR | 0600, 0);
884 CHECK_RIGHT_RESULT(rc, rights, CAP_MKNODAT, CAP_LOOKUP);
885 if (rc >= 0) {
886 EXPECT_OK(unlinkat(dirfd, "cap_mknodat", 0));
887 }
888 }
889
890 // For renameat(2), need:
891 // - CAP_RENAMEAT_SOURCE on source
892 // - CAP_RENAMEAT_TARGET on destination.
893 rc = openat(dirfd, "cap_renameat_src", O_CREAT, 0600);
894 EXPECT_OK(rc);
895 EXPECT_OK(close(rc));
896
897 rc = renameat(dirfd, "cap_renameat_src", dfd_cap, "cap_renameat_dst");
898 CHECK_RIGHT_RESULT(rc, rights, CAP_RENAMEAT_TARGET);
899 if (rc >= 0) {
900 EXPECT_OK(unlinkat(dirfd, "cap_renameat_dst", 0));
901 } else {
902 EXPECT_OK(unlinkat(dirfd, "cap_renameat_src", 0));
903 }
904
905 rc = openat(dirfd, "cap_renameat_src", O_CREAT, 0600);
906 EXPECT_OK(rc);
907 EXPECT_OK(close(rc));
908
909 rc = renameat(dfd_cap, "cap_renameat_src", dirfd, "cap_renameat_dst");
910 CHECK_RIGHT_RESULT(rc, rights, CAP_RENAMEAT_SOURCE);
911
912 if (rc >= 0) {
913 EXPECT_OK(unlinkat(dirfd, "cap_renameat_dst", 0));
914 } else {
915 EXPECT_OK(unlinkat(dirfd, "cap_renameat_src", 0));
916 }
917
918 rc = symlinkat("test", dfd_cap, "cap_symlinkat");
919 CHECK_RIGHT_RESULT(rc, rights, CAP_SYMLINKAT, CAP_LOOKUP);
920 if (rc >= 0) {
921 EXPECT_OK(unlinkat(dirfd, "cap_symlinkat", 0));
922 }
923
924 rc = openat(dirfd, "cap_unlinkat", O_CREAT, 0600);
925 EXPECT_OK(rc);
926 EXPECT_OK(close(rc));
927 rc = unlinkat(dfd_cap, "cap_unlinkat", 0);
928 CHECK_RIGHT_RESULT(rc, rights, CAP_UNLINKAT, CAP_LOOKUP);
929 unlinkat(dirfd, "cap_unlinkat", 0);
930 EXPECT_OK(mkdirat(dirfd, "cap_unlinkat", 0700));
931 rc = unlinkat(dfd_cap, "cap_unlinkat", AT_REMOVEDIR);
932 CHECK_RIGHT_RESULT(rc, rights, CAP_UNLINKAT, CAP_LOOKUP);
933 unlinkat(dirfd, "cap_unlinkat", AT_REMOVEDIR);
934
935 EXPECT_OK(close(dfd_cap));
936 }
937
DirOperationsTest(int extra)938 void DirOperationsTest(int extra) {
939 int rc = mkdir(TmpFile("cap_dirops"), 0755);
940 EXPECT_OK(rc);
941 if (rc < 0 && errno != EEXIST) return;
942 int dfd = open(TmpFile("cap_dirops"), O_RDONLY | O_DIRECTORY | extra);
943 EXPECT_OK(dfd);
944 int tmpfd = open(tmpdir.c_str(), O_RDONLY | O_DIRECTORY);
945 EXPECT_OK(tmpfd);
946
947 EXPECT_OK(cap_enter()); // Enter capability mode.
948
949 TRY_DIR_OPS(dfd, CAP_LINKAT_SOURCE);
950 TRY_DIR_OPS(dfd, CAP_LINKAT_TARGET);
951 TRY_DIR_OPS(dfd, CAP_CREATE, CAP_READ, CAP_LOOKUP);
952 TRY_DIR_OPS(dfd, CAP_CREATE, CAP_WRITE, CAP_LOOKUP);
953 TRY_DIR_OPS(dfd, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_LOOKUP);
954 TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_READ, CAP_LOOKUP);
955 TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP);
956 TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP);
957 TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_READ, CAP_LOOKUP);
958 TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_WRITE, CAP_LOOKUP);
959 TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_READ, CAP_WRITE, CAP_LOOKUP);
960 TRY_DIR_OPS(dfd, CAP_FCHOWN, CAP_LOOKUP);
961 TRY_DIR_OPS(dfd, CAP_FCHMOD, CAP_LOOKUP);
962 TRY_DIR_OPS(dfd, CAP_FSTAT, CAP_LOOKUP);
963 TRY_DIR_OPS(dfd, CAP_FUTIMES, CAP_LOOKUP);
964 TRY_DIR_OPS(dfd, CAP_MKDIRAT, CAP_LOOKUP);
965 TRY_DIR_OPS(dfd, CAP_MKFIFOAT, CAP_LOOKUP);
966 TRY_DIR_OPS(dfd, CAP_MKNODAT, CAP_LOOKUP);
967 TRY_DIR_OPS(dfd, CAP_SYMLINKAT, CAP_LOOKUP);
968 TRY_DIR_OPS(dfd, CAP_UNLINKAT, CAP_LOOKUP);
969 // Rename needs CAP_RENAMEAT_SOURCE on source directory and
970 // CAP_RENAMEAT_TARGET on destination directory.
971 TRY_DIR_OPS(dfd, CAP_RENAMEAT_SOURCE, CAP_UNLINKAT, CAP_LOOKUP);
972 TRY_DIR_OPS(dfd, CAP_RENAMEAT_TARGET, CAP_UNLINKAT, CAP_LOOKUP);
973
974 EXPECT_OK(unlinkat(tmpfd, "cap_dirops", AT_REMOVEDIR));
975 EXPECT_OK(close(tmpfd));
976 EXPECT_OK(close(dfd));
977 }
978
FORK_TEST(Capability,DirOperations)979 FORK_TEST(Capability, DirOperations) {
980 DirOperationsTest(0);
981 }
982
983 #ifdef O_PATH
FORK_TEST(Capability,PathDirOperations)984 FORK_TEST(Capability, PathDirOperations) {
985 // Make the dfd in the test a path-only file descriptor.
986 DirOperationsTest(O_PATH);
987 }
988 #endif
989
TryReadWrite(int cap_fd)990 static void TryReadWrite(int cap_fd) {
991 char buffer[64];
992 EXPECT_OK(read(cap_fd, buffer, sizeof(buffer)));
993 int rc = write(cap_fd, "", 0);
994 EXPECT_EQ(-1, rc);
995 EXPECT_EQ(ENOTCAPABLE, errno);
996 }
997
998 FORK_TEST_ON(Capability, SocketTransfer, TmpFile("cap_fd_transfer")) {
999 int sock_fds[2];
1000 EXPECT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds));
1001
1002 struct msghdr mh;
1003 mh.msg_name = NULL; // No address needed
1004 mh.msg_namelen = 0;
1005 char buffer1[1024];
1006 struct iovec iov[1];
1007 iov[0].iov_base = buffer1;
1008 iov[0].iov_len = sizeof(buffer1);
1009 mh.msg_iov = iov;
1010 mh.msg_iovlen = 1;
1011 char buffer2[1024];
1012 mh.msg_control = buffer2;
1013 mh.msg_controllen = sizeof(buffer2);
1014 struct cmsghdr *cmptr;
1015
1016 cap_rights_t r_rs;
1017 cap_rights_init(&r_rs, CAP_READ, CAP_SEEK);
1018
1019 pid_t child = fork();
1020 if (child == 0) {
1021 // Child: enter cap mode
1022 EXPECT_OK(cap_enter());
1023 // Child: send startup notification
1024 SEND_INT_MESSAGE(sock_fds[0], MSG_CHILD_STARTED);
1025
1026 // Child: wait to receive FD over socket
1027 int rc = recvmsg(sock_fds[0], &mh, 0);
1028 EXPECT_OK(rc);
1029 EXPECT_LE(CMSG_LEN(sizeof(int)), mh.msg_controllen);
1030 cmptr = CMSG_FIRSTHDR(&mh);
1031 int cap_fd = *(int*)CMSG_DATA(cmptr);
1032 EXPECT_EQ(CMSG_LEN(sizeof(int)), cmptr->cmsg_len);
1033 cmptr = CMSG_NXTHDR(&mh, cmptr);
1034 EXPECT_TRUE(cmptr == NULL);
1035
1036 // Child: confirm we can do the right operations on the capability
1037 cap_rights_t rights;
1038 EXPECT_OK(cap_rights_get(cap_fd, &rights));
1039 EXPECT_RIGHTS_EQ(&r_rs, &rights);
1040 TryReadWrite(cap_fd);
1041
1042 // Child: acknowledge that we have received and tested the file descriptor
1043 SEND_INT_MESSAGE(sock_fds[0], MSG_CHILD_FD_RECEIVED);
1044
1045 // Child: wait for a normal read
1046 AWAIT_INT_MESSAGE(sock_fds[0], MSG_PARENT_REQUEST_CHILD_EXIT);
1047 exit(testing::Test::HasFailure());
1048 }
1049
1050 int fd = open(TmpFile("cap_fd_transfer"), O_RDWR | O_CREAT, 0644);
1051 EXPECT_OK(fd);
1052 if (fd < 0) return;
1053 int cap_fd = dup(fd);
1054 EXPECT_OK(cap_fd);
1055 EXPECT_OK(cap_rights_limit(cap_fd, &r_rs));
1056
1057 EXPECT_OK(cap_enter()); // Enter capability mode.
1058
1059 // Confirm we can do the right operations on the capability
1060 TryReadWrite(cap_fd);
1061
1062 // Wait for child to start up:
1063 AWAIT_INT_MESSAGE(sock_fds[1], MSG_CHILD_STARTED);
1064
1065 // Send the file descriptor over the pipe to the sub-process
1066 mh.msg_controllen = CMSG_LEN(sizeof(int));
1067 cmptr = CMSG_FIRSTHDR(&mh);
1068 cmptr->cmsg_level = SOL_SOCKET;
1069 cmptr->cmsg_type = SCM_RIGHTS;
1070 cmptr->cmsg_len = CMSG_LEN(sizeof(int));
1071 *(int *)CMSG_DATA(cmptr) = cap_fd;
1072 buffer1[0] = 0;
1073 iov[0].iov_len = 1;
1074 int rc = sendmsg(sock_fds[1], &mh, 0);
1075 EXPECT_OK(rc);
1076
1077 // Check that the child received the message
1078 AWAIT_INT_MESSAGE(sock_fds[1], MSG_CHILD_FD_RECEIVED);
1079
1080 // Tell the child to exit
1081 SEND_INT_MESSAGE(sock_fds[1], MSG_PARENT_REQUEST_CHILD_EXIT);
1082 }
1083
TEST(Capability,SyscallAt)1084 TEST(Capability, SyscallAt) {
1085 int rc = mkdir(TmpFile("cap_at_topdir"), 0755);
1086 EXPECT_OK(rc);
1087 if (rc < 0 && errno != EEXIST) return;
1088
1089 cap_rights_t r_all;
1090 cap_rights_init(&r_all, CAP_READ, CAP_LOOKUP, CAP_MKNODAT, CAP_UNLINKAT, CAP_MKDIRAT, CAP_MKFIFOAT);
1091 cap_rights_t r_no_unlink;
1092 cap_rights_init(&r_no_unlink, CAP_READ, CAP_LOOKUP, CAP_MKDIRAT, CAP_MKFIFOAT);
1093 cap_rights_t r_no_mkdir;
1094 cap_rights_init(&r_no_mkdir, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKFIFOAT);
1095 cap_rights_t r_no_mkfifo;
1096 cap_rights_init(&r_no_mkfifo, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKDIRAT);
1097 cap_rights_t r_create;
1098 cap_rights_init(&r_create, CAP_READ, CAP_LOOKUP, CAP_CREATE);
1099 cap_rights_t r_bind;
1100 cap_rights_init(&r_bind, CAP_READ, CAP_LOOKUP, CAP_BIND);
1101
1102 int dfd = open(TmpFile("cap_at_topdir"), O_RDONLY);
1103 EXPECT_OK(dfd);
1104 int cap_dfd_all = dup(dfd);
1105 EXPECT_OK(cap_dfd_all);
1106 EXPECT_OK(cap_rights_limit(cap_dfd_all, &r_all));
1107 int cap_dfd_no_unlink = dup(dfd);
1108 EXPECT_OK(cap_dfd_no_unlink);
1109 EXPECT_OK(cap_rights_limit(cap_dfd_no_unlink, &r_no_unlink));
1110 int cap_dfd_no_mkdir = dup(dfd);
1111 EXPECT_OK(cap_dfd_no_mkdir);
1112 EXPECT_OK(cap_rights_limit(cap_dfd_no_mkdir, &r_no_mkdir));
1113 int cap_dfd_no_mkfifo = dup(dfd);
1114 EXPECT_OK(cap_dfd_no_mkfifo);
1115 EXPECT_OK(cap_rights_limit(cap_dfd_no_mkfifo, &r_no_mkfifo));
1116 int cap_dfd_create = dup(dfd);
1117 EXPECT_OK(cap_dfd_create);
1118 EXPECT_OK(cap_rights_limit(cap_dfd_create, &r_create));
1119 int cap_dfd_bind = dup(dfd);
1120 EXPECT_OK(cap_dfd_bind);
1121 EXPECT_OK(cap_rights_limit(cap_dfd_bind, &r_bind));
1122
1123 // Need CAP_MKDIRAT to mkdirat(2).
1124 EXPECT_NOTCAPABLE(mkdirat(cap_dfd_no_mkdir, "cap_subdir", 0755));
1125 rmdir(TmpFile("cap_at_topdir/cap_subdir"));
1126 EXPECT_OK(mkdirat(cap_dfd_all, "cap_subdir", 0755));
1127
1128 // Need CAP_UNLINKAT to unlinkat(dfd, name, AT_REMOVEDIR).
1129 EXPECT_NOTCAPABLE(unlinkat(cap_dfd_no_unlink, "cap_subdir", AT_REMOVEDIR));
1130 EXPECT_OK(unlinkat(cap_dfd_all, "cap_subdir", AT_REMOVEDIR));
1131 rmdir(TmpFile("cap_at_topdir/cap_subdir"));
1132
1133 // Need CAP_MKFIFOAT to mkfifoat(2).
1134 EXPECT_NOTCAPABLE(mkfifoat(cap_dfd_no_mkfifo, "cap_fifo", 0755));
1135 unlink(TmpFile("cap_at_topdir/cap_fifo"));
1136 EXPECT_OK(mkfifoat(cap_dfd_all, "cap_fifo", 0755));
1137 unlink(TmpFile("cap_at_topdir/cap_fifo"));
1138
1139 #ifdef HAVE_MKNOD_REG
1140 // Need CAP_CREATE to create a regular file with mknodat(2).
1141 EXPECT_NOTCAPABLE(mknodat(cap_dfd_all, "cap_regular", S_IFREG|0755, 0));
1142 unlink(TmpFile("cap_at_topdir/cap_regular"));
1143 EXPECT_OK(mknodat(cap_dfd_create, "cap_regular", S_IFREG|0755, 0));
1144 unlink(TmpFile("cap_at_topdir/cap_regular"));
1145 #endif
1146
1147 #ifdef HAVE_MKNOD_SOCKET
1148 // Need CAP_BIND to create a UNIX domain socket with mknodat(2).
1149 EXPECT_NOTCAPABLE(mknodat(cap_dfd_all, "cap_socket", S_IFSOCK|0755, 0));
1150 unlink(TmpFile("cap_at_topdir/cap_socket"));
1151 EXPECT_OK(mknodat(cap_dfd_bind, "cap_socket", S_IFSOCK|0755, 0));
1152 unlink(TmpFile("cap_at_topdir/cap_socket"));
1153 #endif
1154
1155 close(cap_dfd_all);
1156 close(cap_dfd_no_mkfifo);
1157 close(cap_dfd_no_mkdir);
1158 close(cap_dfd_no_unlink);
1159 close(cap_dfd_create);
1160 close(cap_dfd_bind);
1161 close(dfd);
1162
1163 // Tidy up.
1164 rmdir(TmpFile("cap_at_topdir"));
1165 }
1166
TEST(Capability,SyscallAtIfRoot)1167 TEST(Capability, SyscallAtIfRoot) {
1168 GTEST_SKIP_IF_NOT_ROOT();
1169 int rc = mkdir(TmpFile("cap_at_topdir"), 0755);
1170 EXPECT_OK(rc);
1171 if (rc < 0 && errno != EEXIST) return;
1172
1173 cap_rights_t r_all;
1174 cap_rights_init(&r_all, CAP_READ, CAP_LOOKUP, CAP_MKNODAT, CAP_UNLINKAT, CAP_MKDIRAT, CAP_MKFIFOAT);
1175 cap_rights_t r_no_mkfifo;
1176 cap_rights_init(&r_no_mkfifo, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKDIRAT);
1177 cap_rights_t r_no_mknod;
1178 cap_rights_init(&r_no_mknod, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKDIRAT);
1179
1180 int dfd = open(TmpFile("cap_at_topdir"), O_RDONLY);
1181 EXPECT_OK(dfd);
1182 int cap_dfd_all = dup(dfd);
1183 EXPECT_OK(cap_dfd_all);
1184 EXPECT_OK(cap_rights_limit(cap_dfd_all, &r_all));
1185 int cap_dfd_no_mkfifo = dup(dfd);
1186 EXPECT_OK(cap_dfd_no_mkfifo);
1187 EXPECT_OK(cap_rights_limit(cap_dfd_no_mkfifo, &r_no_mkfifo));
1188 int cap_dfd_no_mknod = dup(dfd);
1189 EXPECT_OK(cap_dfd_no_mknod);
1190 EXPECT_OK(cap_rights_limit(cap_dfd_no_mknod, &r_no_mknod));
1191
1192 // Need CAP_MKNODAT to mknodat(2) a device
1193 EXPECT_NOTCAPABLE(mknodat(cap_dfd_no_mknod, "cap_device", S_IFCHR|0755, makedev(99, 123)));
1194 unlink(TmpFile("cap_at_topdir/cap_device"));
1195 EXPECT_OK(mknodat(cap_dfd_all, "cap_device", S_IFCHR|0755, makedev(99, 123)));
1196 unlink(TmpFile("cap_at_topdir/cap_device"));
1197
1198 // Need CAP_MKFIFOAT to mknodat(2) for a FIFO.
1199 EXPECT_NOTCAPABLE(mknodat(cap_dfd_no_mkfifo, "cap_fifo", S_IFIFO|0755, 0));
1200 unlink(TmpFile("cap_at_topdir/cap_fifo"));
1201 EXPECT_OK(mknodat(cap_dfd_all, "cap_fifo", S_IFIFO|0755, 0));
1202 unlink(TmpFile("cap_at_topdir/cap_fifo"));
1203
1204 close(cap_dfd_all);
1205 close(cap_dfd_no_mknod);
1206 close(cap_dfd_no_mkfifo);
1207 close(dfd);
1208
1209 // Tidy up.
1210 rmdir(TmpFile("cap_at_topdir"));
1211 }
1212
1213 FORK_TEST_ON(Capability, ExtendedAttributesIfAvailable, TmpFile("cap_extattr")) {
1214 int fd = open(TmpFile("cap_extattr"), O_RDONLY|O_CREAT, 0644);
1215 EXPECT_OK(fd);
1216
1217 char buffer[1024];
1218 int rc = fgetxattr_(fd, "user.capsicumtest", buffer, sizeof(buffer));
1219 if (rc < 0 && errno == ENOTSUP) {
1220 // Need user_xattr mount option for non-root users on Linux
1221 close(fd);
1222 GTEST_SKIP() << "/tmp doesn't support extended attributes";
1223 }
1224
1225 cap_rights_t r_rws;
1226 cap_rights_init(&r_rws, CAP_READ, CAP_WRITE, CAP_SEEK);
1227 cap_rights_t r_xlist;
1228 cap_rights_init(&r_xlist, CAP_EXTATTR_LIST);
1229 cap_rights_t r_xget;
1230 cap_rights_init(&r_xget, CAP_EXTATTR_GET);
1231 cap_rights_t r_xset;
1232 cap_rights_init(&r_xset, CAP_EXTATTR_SET);
1233 cap_rights_t r_xdel;
1234 cap_rights_init(&r_xdel, CAP_EXTATTR_DELETE);
1235
1236 int cap = dup(fd);
1237 EXPECT_OK(cap);
1238 EXPECT_OK(cap_rights_limit(cap, &r_rws));
1239 int cap_xlist = dup(fd);
1240 EXPECT_OK(cap_xlist);
1241 EXPECT_OK(cap_rights_limit(cap_xlist, &r_xlist));
1242 int cap_xget = dup(fd);
1243 EXPECT_OK(cap_xget);
1244 EXPECT_OK(cap_rights_limit(cap_xget, &r_xget));
1245 int cap_xset = dup(fd);
1246 EXPECT_OK(cap_xset);
1247 EXPECT_OK(cap_rights_limit(cap_xset, &r_xset));
1248 int cap_xdel = dup(fd);
1249 EXPECT_OK(cap_xdel);
1250 EXPECT_OK(cap_rights_limit(cap_xdel, &r_xdel));
1251
1252 const char* value = "capsicum";
1253 int len = strlen(value) + 1;
1254 EXPECT_NOTCAPABLE(fsetxattr_(cap, "user.capsicumtest", value, len, 0));
1255 EXPECT_NOTCAPABLE(fsetxattr_(cap_xlist, "user.capsicumtest", value, len, 0));
1256 EXPECT_NOTCAPABLE(fsetxattr_(cap_xget, "user.capsicumtest", value, len, 0));
1257 EXPECT_NOTCAPABLE(fsetxattr_(cap_xdel, "user.capsicumtest", value, len, 0));
1258 EXPECT_OK(fsetxattr_(cap_xset, "user.capsicumtest", value, len, 0));
1259
1260 EXPECT_NOTCAPABLE(flistxattr_(cap, buffer, sizeof(buffer)));
1261 EXPECT_NOTCAPABLE(flistxattr_(cap_xget, buffer, sizeof(buffer)));
1262 EXPECT_NOTCAPABLE(flistxattr_(cap_xset, buffer, sizeof(buffer)));
1263 EXPECT_NOTCAPABLE(flistxattr_(cap_xdel, buffer, sizeof(buffer)));
1264 EXPECT_OK(flistxattr_(cap_xlist, buffer, sizeof(buffer)));
1265
1266 EXPECT_NOTCAPABLE(fgetxattr_(cap, "user.capsicumtest", buffer, sizeof(buffer)));
1267 EXPECT_NOTCAPABLE(fgetxattr_(cap_xlist, "user.capsicumtest", buffer, sizeof(buffer)));
1268 EXPECT_NOTCAPABLE(fgetxattr_(cap_xset, "user.capsicumtest", buffer, sizeof(buffer)));
1269 EXPECT_NOTCAPABLE(fgetxattr_(cap_xdel, "user.capsicumtest", buffer, sizeof(buffer)));
1270 EXPECT_OK(fgetxattr_(cap_xget, "user.capsicumtest", buffer, sizeof(buffer)));
1271
1272 EXPECT_NOTCAPABLE(fremovexattr_(cap, "user.capsicumtest"));
1273 EXPECT_NOTCAPABLE(fremovexattr_(cap_xlist, "user.capsicumtest"));
1274 EXPECT_NOTCAPABLE(fremovexattr_(cap_xget, "user.capsicumtest"));
1275 EXPECT_NOTCAPABLE(fremovexattr_(cap_xset, "user.capsicumtest"));
1276 EXPECT_OK(fremovexattr_(cap_xdel, "user.capsicumtest"));
1277
1278 close(cap_xdel);
1279 close(cap_xset);
1280 close(cap_xget);
1281 close(cap_xlist);
1282 close(cap);
1283 close(fd);
1284 }
1285
TEST(Capability,PipeUnseekable)1286 TEST(Capability, PipeUnseekable) {
1287 int fds[2];
1288 EXPECT_OK(pipe(fds));
1289
1290 // Some programs detect pipes by calling seek() and getting ESPIPE.
1291 EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET));
1292 EXPECT_EQ(ESPIPE, errno);
1293
1294 cap_rights_t rights;
1295 cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_SEEK);
1296 EXPECT_OK(cap_rights_limit(fds[0], &rights));
1297
1298 EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET));
1299 EXPECT_EQ(ESPIPE, errno);
1300
1301 // Remove CAP_SEEK and see if ENOTCAPABLE trumps ESPIPE.
1302 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
1303 EXPECT_OK(cap_rights_limit(fds[0], &rights));
1304 EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET));
1305 EXPECT_EQ(ENOTCAPABLE, errno);
1306 // TODO(drysdale): in practical terms it might be nice if ESPIPE trumped ENOTCAPABLE.
1307 // EXPECT_EQ(ESPIPE, errno);
1308
1309 close(fds[0]);
1310 close(fds[1]);
1311 }
1312
TEST(Capability,NoBypassDACIfRoot)1313 TEST(Capability, NoBypassDACIfRoot) {
1314 GTEST_SKIP_IF_NOT_ROOT();
1315 int fd = open(TmpFile("cap_root_owned"), O_RDONLY|O_CREAT, 0644);
1316 EXPECT_OK(fd);
1317 cap_rights_t rights;
1318 cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FCHMOD, CAP_FSTAT);
1319 EXPECT_OK(cap_rights_limit(fd, &rights));
1320
1321 pid_t child = fork();
1322 if (child == 0) {
1323 // Child: change uid to a lesser being
1324 ASSERT_NE(0u, other_uid) << "other_uid not initialized correctly, "
1325 "please pass the -u <uid> flag.";
1326 EXPECT_EQ(0, setuid(other_uid));
1327 EXPECT_EQ(other_uid, getuid());
1328 // Attempt to fchmod the file, and fail.
1329 // Having CAP_FCHMOD doesn't bypass the need to comply with DAC policy.
1330 int rc = fchmod(fd, 0666);
1331 EXPECT_EQ(-1, rc);
1332 EXPECT_EQ(EPERM, errno);
1333 exit(HasFailure());
1334 }
1335 int status;
1336 EXPECT_EQ(child, waitpid(child, &status, 0));
1337 EXPECT_TRUE(WIFEXITED(status)) << "0x" << std::hex << status;
1338 EXPECT_EQ(0, WEXITSTATUS(status));
1339 struct stat info;
1340 EXPECT_OK(fstat(fd, &info));
1341 EXPECT_EQ((mode_t)(S_IFREG|0644), info.st_mode);
1342 close(fd);
1343 unlink(TmpFile("cap_root_owned"));
1344 }
1345
TEST(Capability,CheckIsEmpty)1346 TEST(Capability, CheckIsEmpty) {
1347 cap_rights_t rights;
1348
1349 cap_rights_init(&rights);
1350 EXPECT_TRUE(cap_rights_is_empty(&rights));
1351
1352 size_t num_known = (sizeof(known_rights)/sizeof(known_rights[0]));
1353 for (size_t ii = 0; ii < num_known; ii++) {
1354 cap_rights_init(&rights, known_rights[ii].right);
1355 EXPECT_FALSE(cap_rights_is_empty(&rights));
1356 cap_rights_clear(&rights, known_rights[ii].right);
1357 EXPECT_TRUE(cap_rights_is_empty(&rights));
1358 }
1359 }
1360