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}
24typedef struct {
25  uint64_t right;
26  const char* name;
27} right_info;
28static 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
151void 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
193void 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
209FORK_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
263FORK_TEST(Capability, CapEnter) {
264  EXPECT_EQ(0, cap_enter());
265}
266
267FORK_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
293FORK_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
321FORK_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().
360FORK_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
440FORK_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
495static 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
616FORK_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
678static 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
938void 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
979FORK_TEST(Capability, DirOperations) {
980  DirOperationsTest(0);
981}
982
983#ifdef O_PATH
984FORK_TEST(Capability, PathDirOperations) {
985  // Make the dfd in the test a path-only file descriptor.
986  DirOperationsTest(O_PATH);
987}
988#endif
989
990static 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
998FORK_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
1084TEST(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
1167TEST(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
1213FORK_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
1286TEST(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
1313TEST(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
1346TEST(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