xref: /freebsd/contrib/capsicum-test/capability-fd.cc (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
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 
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 
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 
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 
263 FORK_TEST(Capability, CapEnter) {
264   EXPECT_EQ(0, cap_enter());
265 }
266 
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 
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 
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 
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 
979 FORK_TEST(Capability, DirOperations) {
980   DirOperationsTest(0);
981 }
982 
983 #ifdef O_PATH
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 
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 
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 
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 
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 
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 
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