]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/capsicum-test/capability-fd.cc
ident(1): Normalizing date format
[FreeBSD/FreeBSD.git] / contrib / capsicum-test / capability-fd.cc
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   cap_rights_t rights;                   \
490   cap_rights_init(&rights, __VA_ARGS__); \
491   TryFileOps((fd), rights);              \
492 } while (0)
493
494 static void TryFileOps(int fd, cap_rights_t rights) {
495   int cap_fd = dup(fd);
496   EXPECT_OK(cap_fd);
497   EXPECT_OK(cap_rights_limit(cap_fd, &rights));
498   if (cap_fd < 0) return;
499   cap_rights_t erights;
500   EXPECT_OK(cap_rights_get(cap_fd, &erights));
501   EXPECT_RIGHTS_EQ(&rights, &erights);
502
503   // Check creation of a capability from a capability.
504   int cap_cap_fd = dup(cap_fd);
505   EXPECT_OK(cap_cap_fd);
506   EXPECT_OK(cap_rights_limit(cap_cap_fd, &rights));
507   EXPECT_NE(cap_fd, cap_cap_fd);
508   EXPECT_OK(cap_rights_get(cap_cap_fd, &erights));
509   EXPECT_RIGHTS_EQ(&rights, &erights);
510   close(cap_cap_fd);
511
512   char ch;
513   CHECK_RIGHT_RESULT(read(cap_fd, &ch, sizeof(ch)), rights, CAP_READ, CAP_SEEK_ASWAS);
514
515   ssize_t len1 = pread(cap_fd, &ch, sizeof(ch), 0);
516   CHECK_RIGHT_RESULT(len1, rights, CAP_PREAD);
517   ssize_t len2 = pread(cap_fd, &ch, sizeof(ch), 0);
518   CHECK_RIGHT_RESULT(len2, rights, CAP_PREAD);
519   EXPECT_EQ(len1, len2);
520
521   CHECK_RIGHT_RESULT(write(cap_fd, &ch, sizeof(ch)), rights, CAP_WRITE, CAP_SEEK_ASWAS);
522   CHECK_RIGHT_RESULT(pwrite(cap_fd, &ch, sizeof(ch), 0), rights, CAP_PWRITE);
523   CHECK_RIGHT_RESULT(lseek(cap_fd, 0, SEEK_SET), rights, CAP_SEEK);
524
525 #ifdef HAVE_CHFLAGS
526   // Note: this is not expected to work over NFS.
527   struct statfs sf;
528   EXPECT_OK(fstatfs(fd, &sf));
529   bool is_nfs = (strncmp("nfs", sf.f_fstypename, sizeof(sf.f_fstypename)) == 0);
530   if (!is_nfs) {
531     CHECK_RIGHT_RESULT(fchflags(cap_fd, UF_NODUMP), rights, CAP_FCHFLAGS);
532   }
533 #endif
534
535   CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_NONE, MAP_SHARED, cap_fd, 0),
536                           rights, CAP_MMAP);
537   CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, cap_fd, 0),
538                           rights, CAP_MMAP_R);
539   CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, cap_fd, 0),
540                           rights, CAP_MMAP_W);
541   CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, cap_fd, 0),
542                           rights, CAP_MMAP_X);
543   CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, cap_fd, 0),
544                           rights, CAP_MMAP_RW);
545   CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED, cap_fd, 0),
546                           rights, CAP_MMAP_RX);
547   CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED, cap_fd, 0),
548                           rights, CAP_MMAP_WX);
549   CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, cap_fd, 0),
550                           rights, CAP_MMAP_RWX);
551
552   CHECK_RIGHT_RESULT(fsync(cap_fd), rights, CAP_FSYNC);
553 #ifdef HAVE_SYNC_FILE_RANGE
554   CHECK_RIGHT_RESULT(sync_file_range(cap_fd, 0, 1, 0), rights, CAP_FSYNC, CAP_SEEK);
555 #endif
556
557   int rc = fcntl(cap_fd, F_GETFL);
558   CHECK_RIGHT_RESULT(rc, rights, CAP_FCNTL);
559   rc = fcntl(cap_fd, F_SETFL, rc);
560   CHECK_RIGHT_RESULT(rc, rights, CAP_FCNTL);
561
562   CHECK_RIGHT_RESULT(fchown(cap_fd, -1, -1), rights, CAP_FCHOWN);
563
564   CHECK_RIGHT_RESULT(fchmod(cap_fd, 0644), rights, CAP_FCHMOD);
565
566   CHECK_RIGHT_RESULT(flock(cap_fd, LOCK_SH), rights, CAP_FLOCK);
567   CHECK_RIGHT_RESULT(flock(cap_fd, LOCK_UN), rights, CAP_FLOCK);
568
569   CHECK_RIGHT_RESULT(ftruncate(cap_fd, 0), rights, CAP_FTRUNCATE);
570
571   struct stat sb;
572   CHECK_RIGHT_RESULT(fstat(cap_fd, &sb), rights, CAP_FSTAT);
573
574   struct statfs cap_sf;
575   CHECK_RIGHT_RESULT(fstatfs(cap_fd, &cap_sf), rights, CAP_FSTATFS);
576
577 #ifdef HAVE_FPATHCONF
578   CHECK_RIGHT_RESULT(fpathconf(cap_fd, _PC_NAME_MAX), rights, CAP_FPATHCONF);
579 #endif
580
581   CHECK_RIGHT_RESULT(futimes(cap_fd, NULL), rights, CAP_FUTIMES);
582
583   struct pollfd pollfd;
584   pollfd.fd = cap_fd;
585   pollfd.events = POLLIN | POLLERR | POLLHUP;
586   pollfd.revents = 0;
587   int ret = poll(&pollfd, 1, 0);
588   if (cap_rights_is_set(&rights, CAP_EVENT)) {
589     EXPECT_OK(ret);
590   } else {
591     EXPECT_NE(0, (pollfd.revents & POLLNVAL));
592   }
593
594   struct timeval tv;
595   tv.tv_sec = 0;
596   tv.tv_usec = 100;
597   fd_set rset;
598   FD_ZERO(&rset);
599   FD_SET(cap_fd, &rset);
600   fd_set wset;
601   FD_ZERO(&wset);
602   FD_SET(cap_fd, &wset);
603   ret = select(cap_fd+1, &rset, &wset, NULL, &tv);
604   if (cap_rights_is_set(&rights, CAP_EVENT)) {
605     EXPECT_OK(ret);
606   } else {
607     EXPECT_NOTCAPABLE(ret);
608   }
609
610   // TODO(FreeBSD): kqueue
611
612   EXPECT_OK(close(cap_fd));
613 }
614
615 FORK_TEST_ON(Capability, Operations, TmpFile("cap_fd_operations")) {
616   int fd = open(TmpFile("cap_fd_operations"), O_RDWR | O_CREAT, 0644);
617   EXPECT_OK(fd);
618   if (fd < 0) return;
619
620   EXPECT_OK(cap_enter());  // Enter capability mode.
621
622   // Try a variety of different combinations of rights - a full
623   // enumeration is too large (2^N with N~30+) to perform.
624   TRY_FILE_OPS(fd, CAP_READ);
625   TRY_FILE_OPS(fd, CAP_PREAD);
626   TRY_FILE_OPS(fd, CAP_WRITE);
627   TRY_FILE_OPS(fd, CAP_PWRITE);
628   TRY_FILE_OPS(fd, CAP_READ, CAP_WRITE);
629   TRY_FILE_OPS(fd, CAP_PREAD, CAP_PWRITE);
630   TRY_FILE_OPS(fd, CAP_SEEK);
631   TRY_FILE_OPS(fd, CAP_FCHFLAGS);
632   TRY_FILE_OPS(fd, CAP_IOCTL);
633   TRY_FILE_OPS(fd, CAP_FSTAT);
634   TRY_FILE_OPS(fd, CAP_MMAP);
635   TRY_FILE_OPS(fd, CAP_MMAP_R);
636   TRY_FILE_OPS(fd, CAP_MMAP_W);
637   TRY_FILE_OPS(fd, CAP_MMAP_X);
638   TRY_FILE_OPS(fd, CAP_MMAP_RW);
639   TRY_FILE_OPS(fd, CAP_MMAP_RX);
640   TRY_FILE_OPS(fd, CAP_MMAP_WX);
641   TRY_FILE_OPS(fd, CAP_MMAP_RWX);
642   TRY_FILE_OPS(fd, CAP_FCNTL);
643   TRY_FILE_OPS(fd, CAP_EVENT);
644   TRY_FILE_OPS(fd, CAP_FSYNC);
645   TRY_FILE_OPS(fd, CAP_FCHOWN);
646   TRY_FILE_OPS(fd, CAP_FCHMOD);
647   TRY_FILE_OPS(fd, CAP_FTRUNCATE);
648   TRY_FILE_OPS(fd, CAP_FLOCK);
649   TRY_FILE_OPS(fd, CAP_FSTATFS);
650   TRY_FILE_OPS(fd, CAP_FPATHCONF);
651   TRY_FILE_OPS(fd, CAP_FUTIMES);
652   TRY_FILE_OPS(fd, CAP_ACL_GET);
653   TRY_FILE_OPS(fd, CAP_ACL_SET);
654   TRY_FILE_OPS(fd, CAP_ACL_DELETE);
655   TRY_FILE_OPS(fd, CAP_ACL_CHECK);
656   TRY_FILE_OPS(fd, CAP_EXTATTR_GET);
657   TRY_FILE_OPS(fd, CAP_EXTATTR_SET);
658   TRY_FILE_OPS(fd, CAP_EXTATTR_DELETE);
659   TRY_FILE_OPS(fd, CAP_EXTATTR_LIST);
660   TRY_FILE_OPS(fd, CAP_MAC_GET);
661   TRY_FILE_OPS(fd, CAP_MAC_SET);
662
663   // Socket-specific.
664   TRY_FILE_OPS(fd, CAP_GETPEERNAME);
665   TRY_FILE_OPS(fd, CAP_GETSOCKNAME);
666   TRY_FILE_OPS(fd, CAP_ACCEPT);
667
668   close(fd);
669 }
670
671 #define TRY_DIR_OPS(dfd, ...) do {       \
672   cap_rights_t rights;                   \
673   cap_rights_init(&rights, __VA_ARGS__); \
674   TryDirOps((dfd), rights);              \
675 } while (0)
676
677 static void TryDirOps(int dirfd, cap_rights_t rights) {
678   cap_rights_t erights;
679   int dfd_cap = dup(dirfd);
680   EXPECT_OK(dfd_cap);
681   EXPECT_OK(cap_rights_limit(dfd_cap, &rights));
682   EXPECT_OK(cap_rights_get(dfd_cap, &erights));
683   EXPECT_RIGHTS_EQ(&rights, &erights);
684
685   int rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDONLY, 0600);
686   CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_LOOKUP);
687   if (rc >= 0) {
688     EXPECT_OK(close(rc));
689     EXPECT_OK(unlinkat(dirfd, "cap_create", 0));
690   }
691   rc = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY | O_APPEND, 0600);
692   CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_WRITE, CAP_LOOKUP);
693   if (rc >= 0) {
694     EXPECT_OK(close(rc));
695     EXPECT_OK(unlinkat(dirfd, "cap_create", 0));
696   }
697   rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR | O_APPEND, 0600);
698   CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_LOOKUP);
699   if (rc >= 0) {
700     EXPECT_OK(close(rc));
701     EXPECT_OK(unlinkat(dirfd, "cap_create", 0));
702   }
703
704   rc = openat(dirfd, "cap_faccess", O_CREAT, 0600);
705   EXPECT_OK(rc);
706   EXPECT_OK(close(rc));
707   rc = faccessat(dfd_cap, "cap_faccess", F_OK, 0);
708   CHECK_RIGHT_RESULT(rc, rights, CAP_FSTAT, CAP_LOOKUP);
709   EXPECT_OK(unlinkat(dirfd, "cap_faccess", 0));
710
711   rc = openat(dirfd, "cap_fsync", O_CREAT, 0600);
712   EXPECT_OK(rc);
713   EXPECT_OK(close(rc));
714   rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDONLY);
715   CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_LOOKUP);
716   if (rc >= 0) {
717     EXPECT_OK(close(rc));
718   }
719   rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY | O_APPEND);
720   CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP);
721   if (rc >= 0) {
722     EXPECT_OK(close(rc));
723   }
724   rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR | O_APPEND);
725   CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP);
726   if (rc >= 0) {
727     EXPECT_OK(close(rc));
728   }
729   rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDONLY);
730   CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_LOOKUP);
731   if (rc >= 0) {
732     EXPECT_OK(close(rc));
733   }
734   rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY | O_APPEND);
735   CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP);
736   if (rc >= 0) {
737     EXPECT_OK(close(rc));
738   }
739   rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR | O_APPEND);
740   CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP);
741   if (rc >= 0) {
742     EXPECT_OK(close(rc));
743   }
744   EXPECT_OK(unlinkat(dirfd, "cap_fsync", 0));
745
746   rc = openat(dirfd, "cap_ftruncate", O_CREAT, 0600);
747   EXPECT_OK(rc);
748   EXPECT_OK(close(rc));
749   rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDONLY);
750   CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_READ, CAP_LOOKUP);
751   if (rc >= 0) {
752     EXPECT_OK(close(rc));
753   }
754   rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_WRONLY);
755   CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_WRITE, CAP_LOOKUP);
756   if (rc >= 0) {
757     EXPECT_OK(close(rc));
758   }
759   rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDWR);
760   CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_READ, CAP_WRITE, CAP_LOOKUP);
761   if (rc >= 0) {
762     EXPECT_OK(close(rc));
763   }
764   EXPECT_OK(unlinkat(dirfd, "cap_ftruncate", 0));
765
766   rc = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY, 0600);
767   CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
768   if (rc >= 0) {
769     EXPECT_OK(close(rc));
770     EXPECT_OK(unlinkat(dirfd, "cap_create", 0));
771   }
772   rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR, 0600);
773   CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
774   if (rc >= 0) {
775     EXPECT_OK(close(rc));
776     EXPECT_OK(unlinkat(dirfd, "cap_create", 0));
777   }
778
779   rc = openat(dirfd, "cap_fsync", O_CREAT, 0600);
780   EXPECT_OK(rc);
781   EXPECT_OK(close(rc));
782   rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY);
783   CHECK_RIGHT_RESULT(rc,
784                rights, CAP_FSYNC, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
785   if (rc >= 0) {
786     EXPECT_OK(close(rc));
787   }
788   rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR);
789   CHECK_RIGHT_RESULT(rc,
790                rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
791   if (rc >= 0) {
792     EXPECT_OK(close(rc));
793   }
794   rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY);
795   CHECK_RIGHT_RESULT(rc,
796                rights, CAP_FSYNC, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
797   if (rc >= 0) {
798     EXPECT_OK(close(rc));
799   }
800   rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR);
801   CHECK_RIGHT_RESULT(rc,
802                rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP);
803   if (rc >= 0) {
804     EXPECT_OK(close(rc));
805   }
806   EXPECT_OK(unlinkat(dirfd, "cap_fsync", 0));
807
808 #ifdef HAVE_CHFLAGSAT
809   rc = openat(dirfd, "cap_chflagsat", O_CREAT, 0600);
810   EXPECT_OK(rc);
811   EXPECT_OK(close(rc));
812   rc = chflagsat(dfd_cap, "cap_chflagsat", UF_NODUMP, 0);
813   CHECK_RIGHT_RESULT(rc, rights, CAP_CHFLAGSAT, CAP_LOOKUP);
814   EXPECT_OK(unlinkat(dirfd, "cap_chflagsat", 0));
815 #endif
816
817   rc = openat(dirfd, "cap_fchownat", O_CREAT, 0600);
818   EXPECT_OK(rc);
819   EXPECT_OK(close(rc));
820   rc = fchownat(dfd_cap, "cap_fchownat", -1, -1, 0);
821   CHECK_RIGHT_RESULT(rc, rights, CAP_FCHOWN, CAP_LOOKUP);
822   EXPECT_OK(unlinkat(dirfd, "cap_fchownat", 0));
823
824   rc = openat(dirfd, "cap_fchmodat", O_CREAT, 0600);
825   EXPECT_OK(rc);
826   EXPECT_OK(close(rc));
827   rc = fchmodat(dfd_cap, "cap_fchmodat", 0600, 0);
828   CHECK_RIGHT_RESULT(rc, rights, CAP_FCHMOD, CAP_LOOKUP);
829   EXPECT_OK(unlinkat(dirfd, "cap_fchmodat", 0));
830
831   rc = openat(dirfd, "cap_fstatat", O_CREAT, 0600);
832   EXPECT_OK(rc);
833   EXPECT_OK(close(rc));
834   struct stat sb;
835   rc = fstatat(dfd_cap, "cap_fstatat", &sb, 0);
836   CHECK_RIGHT_RESULT(rc, rights, CAP_FSTAT, CAP_LOOKUP);
837   EXPECT_OK(unlinkat(dirfd, "cap_fstatat", 0));
838
839   rc = openat(dirfd, "cap_futimesat", O_CREAT, 0600);
840   EXPECT_OK(rc);
841   EXPECT_OK(close(rc));
842   rc = futimesat(dfd_cap, "cap_futimesat", NULL);
843   CHECK_RIGHT_RESULT(rc, rights, CAP_FUTIMES, CAP_LOOKUP);
844   EXPECT_OK(unlinkat(dirfd, "cap_futimesat", 0));
845
846   // For linkat(2), need:
847   //  - CAP_LINKAT_SOURCE on source
848   //  - CAP_LINKAT_TARGET on destination.
849   rc = openat(dirfd, "cap_linkat_src", O_CREAT, 0600);
850   EXPECT_OK(rc);
851   EXPECT_OK(close(rc));
852
853   rc = linkat(dirfd, "cap_linkat_src", dfd_cap, "cap_linkat_dst", 0);
854   CHECK_RIGHT_RESULT(rc, rights, CAP_LINKAT_TARGET);
855   if (rc >= 0) {
856     EXPECT_OK(unlinkat(dirfd, "cap_linkat_dst", 0));
857   }
858
859   rc = linkat(dfd_cap, "cap_linkat_src", dirfd, "cap_linkat_dst", 0);
860   CHECK_RIGHT_RESULT(rc, rights, CAP_LINKAT_SOURCE);
861   if (rc >= 0) {
862     EXPECT_OK(unlinkat(dirfd, "cap_linkat_dst", 0));
863   }
864
865   EXPECT_OK(unlinkat(dirfd, "cap_linkat_src", 0));
866
867   rc = mkdirat(dfd_cap, "cap_mkdirat", 0700);
868   CHECK_RIGHT_RESULT(rc, rights, CAP_MKDIRAT, CAP_LOOKUP);
869   if (rc >= 0) {
870     EXPECT_OK(unlinkat(dirfd, "cap_mkdirat", AT_REMOVEDIR));
871   }
872
873 #ifdef HAVE_MKFIFOAT
874   rc = mkfifoat(dfd_cap, "cap_mkfifoat", 0600);
875   CHECK_RIGHT_RESULT(rc, rights, CAP_MKFIFOAT, CAP_LOOKUP);
876   if (rc >= 0) {
877     EXPECT_OK(unlinkat(dirfd, "cap_mkfifoat", 0));
878   }
879 #endif
880
881   if (getuid() == 0) {
882     rc = mknodat(dfd_cap, "cap_mknodat", S_IFCHR | 0600, 0);
883     CHECK_RIGHT_RESULT(rc, rights, CAP_MKNODAT, CAP_LOOKUP);
884     if (rc >= 0) {
885       EXPECT_OK(unlinkat(dirfd, "cap_mknodat", 0));
886     }
887   }
888
889   // For renameat(2), need:
890   //  - CAP_RENAMEAT_SOURCE on source
891   //  - CAP_RENAMEAT_TARGET on destination.
892   rc = openat(dirfd, "cap_renameat_src", O_CREAT, 0600);
893   EXPECT_OK(rc);
894   EXPECT_OK(close(rc));
895
896   rc = renameat(dirfd, "cap_renameat_src", dfd_cap, "cap_renameat_dst");
897   CHECK_RIGHT_RESULT(rc, rights, CAP_RENAMEAT_TARGET);
898   if (rc >= 0) {
899     EXPECT_OK(unlinkat(dirfd, "cap_renameat_dst", 0));
900   } else {
901     EXPECT_OK(unlinkat(dirfd, "cap_renameat_src", 0));
902   }
903
904   rc = openat(dirfd, "cap_renameat_src", O_CREAT, 0600);
905   EXPECT_OK(rc);
906   EXPECT_OK(close(rc));
907
908   rc = renameat(dfd_cap, "cap_renameat_src", dirfd, "cap_renameat_dst");
909   CHECK_RIGHT_RESULT(rc, rights, CAP_RENAMEAT_SOURCE);
910
911   if (rc >= 0) {
912     EXPECT_OK(unlinkat(dirfd, "cap_renameat_dst", 0));
913   } else {
914     EXPECT_OK(unlinkat(dirfd, "cap_renameat_src", 0));
915   }
916
917   rc = symlinkat("test", dfd_cap, "cap_symlinkat");
918   CHECK_RIGHT_RESULT(rc, rights, CAP_SYMLINKAT, CAP_LOOKUP);
919   if (rc >= 0) {
920     EXPECT_OK(unlinkat(dirfd, "cap_symlinkat", 0));
921   }
922
923   rc = openat(dirfd, "cap_unlinkat", O_CREAT, 0600);
924   EXPECT_OK(rc);
925   EXPECT_OK(close(rc));
926   rc = unlinkat(dfd_cap, "cap_unlinkat", 0);
927   CHECK_RIGHT_RESULT(rc, rights, CAP_UNLINKAT, CAP_LOOKUP);
928   unlinkat(dirfd, "cap_unlinkat", 0);
929   EXPECT_OK(mkdirat(dirfd, "cap_unlinkat", 0700));
930   rc = unlinkat(dfd_cap, "cap_unlinkat", AT_REMOVEDIR);
931   CHECK_RIGHT_RESULT(rc, rights, CAP_UNLINKAT, CAP_LOOKUP);
932   unlinkat(dirfd, "cap_unlinkat", AT_REMOVEDIR);
933
934   EXPECT_OK(close(dfd_cap));
935 }
936
937 void DirOperationsTest(int extra) {
938   int rc = mkdir(TmpFile("cap_dirops"), 0755);
939   EXPECT_OK(rc);
940   if (rc < 0 && errno != EEXIST) return;
941   int dfd = open(TmpFile("cap_dirops"), O_RDONLY | O_DIRECTORY | extra);
942   EXPECT_OK(dfd);
943   int tmpfd = open(tmpdir.c_str(), O_RDONLY | O_DIRECTORY);
944   EXPECT_OK(tmpfd);
945
946   EXPECT_OK(cap_enter());  // Enter capability mode.
947
948   TRY_DIR_OPS(dfd, CAP_LINKAT_SOURCE);
949   TRY_DIR_OPS(dfd, CAP_LINKAT_TARGET);
950   TRY_DIR_OPS(dfd, CAP_CREATE, CAP_READ, CAP_LOOKUP);
951   TRY_DIR_OPS(dfd, CAP_CREATE, CAP_WRITE, CAP_LOOKUP);
952   TRY_DIR_OPS(dfd, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_LOOKUP);
953   TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_READ, CAP_LOOKUP);
954   TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP);
955   TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP);
956   TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_READ, CAP_LOOKUP);
957   TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_WRITE, CAP_LOOKUP);
958   TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_READ, CAP_WRITE, CAP_LOOKUP);
959   TRY_DIR_OPS(dfd, CAP_FCHOWN, CAP_LOOKUP);
960   TRY_DIR_OPS(dfd, CAP_FCHMOD, CAP_LOOKUP);
961   TRY_DIR_OPS(dfd, CAP_FSTAT, CAP_LOOKUP);
962   TRY_DIR_OPS(dfd, CAP_FUTIMES, CAP_LOOKUP);
963   TRY_DIR_OPS(dfd, CAP_MKDIRAT, CAP_LOOKUP);
964   TRY_DIR_OPS(dfd, CAP_MKFIFOAT, CAP_LOOKUP);
965   TRY_DIR_OPS(dfd, CAP_MKNODAT, CAP_LOOKUP);
966   TRY_DIR_OPS(dfd, CAP_SYMLINKAT, CAP_LOOKUP);
967   TRY_DIR_OPS(dfd, CAP_UNLINKAT, CAP_LOOKUP);
968   // Rename needs CAP_RENAMEAT_SOURCE on source directory and
969   // CAP_RENAMEAT_TARGET on destination directory.
970   TRY_DIR_OPS(dfd, CAP_RENAMEAT_SOURCE, CAP_UNLINKAT, CAP_LOOKUP);
971   TRY_DIR_OPS(dfd, CAP_RENAMEAT_TARGET, CAP_UNLINKAT, CAP_LOOKUP);
972
973   EXPECT_OK(unlinkat(tmpfd, "cap_dirops", AT_REMOVEDIR));
974   EXPECT_OK(close(tmpfd));
975   EXPECT_OK(close(dfd));
976 }
977
978 FORK_TEST(Capability, DirOperations) {
979   DirOperationsTest(0);
980 }
981
982 #ifdef O_PATH
983 FORK_TEST(Capability, PathDirOperations) {
984   // Make the dfd in the test a path-only file descriptor.
985   DirOperationsTest(O_PATH);
986 }
987 #endif
988
989 static void TryReadWrite(int cap_fd) {
990   char buffer[64];
991   EXPECT_OK(read(cap_fd, buffer, sizeof(buffer)));
992   int rc = write(cap_fd, "", 0);
993   EXPECT_EQ(-1, rc);
994   EXPECT_EQ(ENOTCAPABLE, errno);
995 }
996
997 FORK_TEST_ON(Capability, SocketTransfer, TmpFile("cap_fd_transfer")) {
998   int sock_fds[2];
999   EXPECT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds));
1000
1001   struct msghdr mh;
1002   mh.msg_name = NULL;  // No address needed
1003   mh.msg_namelen = 0;
1004   char buffer1[1024];
1005   struct iovec iov[1];
1006   iov[0].iov_base = buffer1;
1007   iov[0].iov_len = sizeof(buffer1);
1008   mh.msg_iov = iov;
1009   mh.msg_iovlen = 1;
1010   char buffer2[1024];
1011   mh.msg_control = buffer2;
1012   mh.msg_controllen = sizeof(buffer2);
1013   struct cmsghdr *cmptr;
1014
1015   cap_rights_t r_rs;
1016   cap_rights_init(&r_rs, CAP_READ, CAP_SEEK);
1017
1018   pid_t child = fork();
1019   if (child == 0) {
1020     // Child: enter cap mode
1021     EXPECT_OK(cap_enter());
1022
1023     // Child: wait to receive FD over socket
1024     int rc = recvmsg(sock_fds[0], &mh, 0);
1025     EXPECT_OK(rc);
1026     EXPECT_LE(CMSG_LEN(sizeof(int)), mh.msg_controllen);
1027     cmptr = CMSG_FIRSTHDR(&mh);
1028     int cap_fd = *(int*)CMSG_DATA(cmptr);
1029     EXPECT_EQ(CMSG_LEN(sizeof(int)), cmptr->cmsg_len);
1030     cmptr = CMSG_NXTHDR(&mh, cmptr);
1031     EXPECT_TRUE(cmptr == NULL);
1032
1033     // Child: confirm we can do the right operations on the capability
1034     cap_rights_t rights;
1035     EXPECT_OK(cap_rights_get(cap_fd, &rights));
1036     EXPECT_RIGHTS_EQ(&r_rs, &rights);
1037     TryReadWrite(cap_fd);
1038
1039     // Child: wait for a normal read
1040     int val;
1041     read(sock_fds[0], &val, sizeof(val));
1042     exit(0);
1043   }
1044
1045   int fd = open(TmpFile("cap_fd_transfer"), O_RDWR | O_CREAT, 0644);
1046   EXPECT_OK(fd);
1047   if (fd < 0) return;
1048   int cap_fd = dup(fd);
1049   EXPECT_OK(cap_fd);
1050   EXPECT_OK(cap_rights_limit(cap_fd, &r_rs));
1051
1052   EXPECT_OK(cap_enter());  // Enter capability mode.
1053
1054   // Confirm we can do the right operations on the capability
1055   TryReadWrite(cap_fd);
1056
1057   // Send the file descriptor over the pipe to the sub-process
1058   mh.msg_controllen = CMSG_LEN(sizeof(int));
1059   cmptr = CMSG_FIRSTHDR(&mh);
1060   cmptr->cmsg_level = SOL_SOCKET;
1061   cmptr->cmsg_type = SCM_RIGHTS;
1062   cmptr->cmsg_len = CMSG_LEN(sizeof(int));
1063   *(int *)CMSG_DATA(cmptr) = cap_fd;
1064   buffer1[0] = 0;
1065   iov[0].iov_len = 1;
1066   sleep(3);
1067   int rc = sendmsg(sock_fds[1], &mh, 0);
1068   EXPECT_OK(rc);
1069
1070   sleep(1);  // Ensure subprocess runs
1071   int zero = 0;
1072   write(sock_fds[1], &zero, sizeof(zero));
1073 }
1074
1075 TEST(Capability, SyscallAt) {
1076   int rc = mkdir(TmpFile("cap_at_topdir"), 0755);
1077   EXPECT_OK(rc);
1078   if (rc < 0 && errno != EEXIST) return;
1079
1080   cap_rights_t r_all;
1081   cap_rights_init(&r_all, CAP_READ, CAP_LOOKUP, CAP_MKNODAT, CAP_UNLINKAT, CAP_MKDIRAT, CAP_MKFIFOAT);
1082   cap_rights_t r_no_unlink;
1083   cap_rights_init(&r_no_unlink, CAP_READ, CAP_LOOKUP, CAP_MKDIRAT, CAP_MKFIFOAT);
1084   cap_rights_t r_no_mkdir;
1085   cap_rights_init(&r_no_mkdir, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKFIFOAT);
1086   cap_rights_t r_no_mkfifo;
1087   cap_rights_init(&r_no_mkfifo, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKDIRAT);
1088   cap_rights_t r_no_mknod;
1089   cap_rights_init(&r_no_mknod, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKDIRAT);
1090   cap_rights_t r_create;
1091   cap_rights_init(&r_create, CAP_READ, CAP_LOOKUP, CAP_CREATE);
1092   cap_rights_t r_bind;
1093   cap_rights_init(&r_bind, CAP_READ, CAP_LOOKUP, CAP_BIND);
1094
1095   int dfd = open(TmpFile("cap_at_topdir"), O_RDONLY);
1096   EXPECT_OK(dfd);
1097   int cap_dfd_all = dup(dfd);
1098   EXPECT_OK(cap_dfd_all);
1099   EXPECT_OK(cap_rights_limit(cap_dfd_all, &r_all));
1100   int cap_dfd_no_unlink = dup(dfd);
1101   EXPECT_OK(cap_dfd_no_unlink);
1102   EXPECT_OK(cap_rights_limit(cap_dfd_no_unlink, &r_no_unlink));
1103   int cap_dfd_no_mkdir = dup(dfd);
1104   EXPECT_OK(cap_dfd_no_mkdir);
1105   EXPECT_OK(cap_rights_limit(cap_dfd_no_mkdir, &r_no_mkdir));
1106   int cap_dfd_no_mkfifo = dup(dfd);
1107   EXPECT_OK(cap_dfd_no_mkfifo);
1108   EXPECT_OK(cap_rights_limit(cap_dfd_no_mkfifo, &r_no_mkfifo));
1109   int cap_dfd_no_mknod = dup(dfd);
1110   EXPECT_OK(cap_dfd_no_mknod);
1111   EXPECT_OK(cap_rights_limit(cap_dfd_no_mknod, &r_no_mknod));
1112   int cap_dfd_create = dup(dfd);
1113   EXPECT_OK(cap_dfd_create);
1114   EXPECT_OK(cap_rights_limit(cap_dfd_create, &r_create));
1115   int cap_dfd_bind = dup(dfd);
1116   EXPECT_OK(cap_dfd_bind);
1117   EXPECT_OK(cap_rights_limit(cap_dfd_bind, &r_bind));
1118
1119   // Need CAP_MKDIRAT to mkdirat(2).
1120   EXPECT_NOTCAPABLE(mkdirat(cap_dfd_no_mkdir, "cap_subdir", 0755));
1121   rmdir(TmpFile("cap_at_topdir/cap_subdir"));
1122   EXPECT_OK(mkdirat(cap_dfd_all, "cap_subdir", 0755));
1123
1124   // Need CAP_UNLINKAT to unlinkat(dfd, name, AT_REMOVEDIR).
1125   EXPECT_NOTCAPABLE(unlinkat(cap_dfd_no_unlink, "cap_subdir", AT_REMOVEDIR));
1126   EXPECT_OK(unlinkat(cap_dfd_all, "cap_subdir", AT_REMOVEDIR));
1127   rmdir(TmpFile("cap_at_topdir/cap_subdir"));
1128
1129   // Need CAP_MKFIFOAT to mkfifoat(2).
1130   EXPECT_NOTCAPABLE(mkfifoat(cap_dfd_no_mkfifo, "cap_fifo", 0755));
1131   unlink(TmpFile("cap_at_topdir/cap_fifo"));
1132   EXPECT_OK(mkfifoat(cap_dfd_all, "cap_fifo", 0755));
1133   unlink(TmpFile("cap_at_topdir/cap_fifo"));
1134
1135 #ifdef HAVE_MKNOD_REG
1136   // Need CAP_CREATE to create a regular file with mknodat(2).
1137   EXPECT_NOTCAPABLE(mknodat(cap_dfd_all, "cap_regular", S_IFREG|0755, 0));
1138   unlink(TmpFile("cap_at_topdir/cap_regular"));
1139   EXPECT_OK(mknodat(cap_dfd_create, "cap_regular", S_IFREG|0755, 0));
1140   unlink(TmpFile("cap_at_topdir/cap_regular"));
1141 #endif
1142
1143 #ifdef HAVE_MKNOD_SOCKET
1144   // Need CAP_BIND to create a UNIX domain socket with mknodat(2).
1145   EXPECT_NOTCAPABLE(mknodat(cap_dfd_all, "cap_socket", S_IFSOCK|0755, 0));
1146   unlink(TmpFile("cap_at_topdir/cap_socket"));
1147   EXPECT_OK(mknodat(cap_dfd_bind, "cap_socket", S_IFSOCK|0755, 0));
1148   unlink(TmpFile("cap_at_topdir/cap_socket"));
1149 #endif
1150
1151   if (getuid() == 0) {
1152     // Need CAP_MKNODAT to mknodat(2) a device
1153     EXPECT_NOTCAPABLE(mknodat(cap_dfd_no_mknod, "cap_device", S_IFCHR|0755, makedev(99, 123)));
1154     unlink(TmpFile("cap_at_topdir/cap_device"));
1155     EXPECT_OK(mknodat(cap_dfd_all, "cap_device", S_IFCHR|0755, makedev(99, 123)));
1156     unlink(TmpFile("cap_at_topdir/cap_device"));
1157
1158     // Need CAP_MKFIFOAT to mknodat(2) for a FIFO.
1159     EXPECT_NOTCAPABLE(mknodat(cap_dfd_no_mkfifo, "cap_fifo", S_IFIFO|0755, 0));
1160     unlink(TmpFile("cap_at_topdir/cap_fifo"));
1161     EXPECT_OK(mknodat(cap_dfd_all, "cap_fifo", S_IFIFO|0755, 0));
1162     unlink(TmpFile("cap_at_topdir/cap_fifo"));
1163   } else {
1164     TEST_SKIPPED("requires root (partial)");
1165   }
1166
1167   close(cap_dfd_all);
1168   close(cap_dfd_no_mknod);
1169   close(cap_dfd_no_mkfifo);
1170   close(cap_dfd_no_mkdir);
1171   close(cap_dfd_no_unlink);
1172   close(cap_dfd_create);
1173   close(cap_dfd_bind);
1174   close(dfd);
1175
1176   // Tidy up.
1177   rmdir(TmpFile("cap_at_topdir"));
1178 }
1179
1180 FORK_TEST_ON(Capability, ExtendedAttributes, TmpFile("cap_extattr")) {
1181   int fd = open(TmpFile("cap_extattr"), O_RDONLY|O_CREAT, 0644);
1182   EXPECT_OK(fd);
1183
1184   char buffer[1024];
1185   int rc = fgetxattr_(fd, "user.capsicumtest", buffer, sizeof(buffer));
1186   if (rc < 0 && errno == ENOTSUP) {
1187     // Need user_xattr mount option for non-root users on Linux
1188     TEST_SKIPPED("/tmp doesn't support extended attributes");
1189     close(fd);
1190     return;
1191   }
1192
1193   cap_rights_t r_rws;
1194   cap_rights_init(&r_rws, CAP_READ, CAP_WRITE, CAP_SEEK);
1195   cap_rights_t r_xlist;
1196   cap_rights_init(&r_xlist, CAP_EXTATTR_LIST);
1197   cap_rights_t r_xget;
1198   cap_rights_init(&r_xget, CAP_EXTATTR_GET);
1199   cap_rights_t r_xset;
1200   cap_rights_init(&r_xset, CAP_EXTATTR_SET);
1201   cap_rights_t r_xdel;
1202   cap_rights_init(&r_xdel, CAP_EXTATTR_DELETE);
1203
1204   int cap = dup(fd);
1205   EXPECT_OK(cap);
1206   EXPECT_OK(cap_rights_limit(cap, &r_rws));
1207   int cap_xlist = dup(fd);
1208   EXPECT_OK(cap_xlist);
1209   EXPECT_OK(cap_rights_limit(cap_xlist, &r_xlist));
1210   int cap_xget = dup(fd);
1211   EXPECT_OK(cap_xget);
1212   EXPECT_OK(cap_rights_limit(cap_xget, &r_xget));
1213   int cap_xset = dup(fd);
1214   EXPECT_OK(cap_xset);
1215   EXPECT_OK(cap_rights_limit(cap_xset, &r_xset));
1216   int cap_xdel = dup(fd);
1217   EXPECT_OK(cap_xdel);
1218   EXPECT_OK(cap_rights_limit(cap_xdel, &r_xdel));
1219
1220   const char* value = "capsicum";
1221   int len = strlen(value) + 1;
1222   EXPECT_NOTCAPABLE(fsetxattr_(cap, "user.capsicumtest", value, len, 0));
1223   EXPECT_NOTCAPABLE(fsetxattr_(cap_xlist, "user.capsicumtest", value, len, 0));
1224   EXPECT_NOTCAPABLE(fsetxattr_(cap_xget, "user.capsicumtest", value, len, 0));
1225   EXPECT_NOTCAPABLE(fsetxattr_(cap_xdel, "user.capsicumtest", value, len, 0));
1226   EXPECT_OK(fsetxattr_(cap_xset, "user.capsicumtest", value, len, 0));
1227
1228   EXPECT_NOTCAPABLE(flistxattr_(cap, buffer, sizeof(buffer)));
1229   EXPECT_NOTCAPABLE(flistxattr_(cap_xget, buffer, sizeof(buffer)));
1230   EXPECT_NOTCAPABLE(flistxattr_(cap_xset, buffer, sizeof(buffer)));
1231   EXPECT_NOTCAPABLE(flistxattr_(cap_xdel, buffer, sizeof(buffer)));
1232   EXPECT_OK(flistxattr_(cap_xlist, buffer, sizeof(buffer)));
1233
1234   EXPECT_NOTCAPABLE(fgetxattr_(cap, "user.capsicumtest", buffer, sizeof(buffer)));
1235   EXPECT_NOTCAPABLE(fgetxattr_(cap_xlist, "user.capsicumtest", buffer, sizeof(buffer)));
1236   EXPECT_NOTCAPABLE(fgetxattr_(cap_xset, "user.capsicumtest", buffer, sizeof(buffer)));
1237   EXPECT_NOTCAPABLE(fgetxattr_(cap_xdel, "user.capsicumtest", buffer, sizeof(buffer)));
1238   EXPECT_OK(fgetxattr_(cap_xget, "user.capsicumtest", buffer, sizeof(buffer)));
1239
1240   EXPECT_NOTCAPABLE(fremovexattr_(cap, "user.capsicumtest"));
1241   EXPECT_NOTCAPABLE(fremovexattr_(cap_xlist, "user.capsicumtest"));
1242   EXPECT_NOTCAPABLE(fremovexattr_(cap_xget, "user.capsicumtest"));
1243   EXPECT_NOTCAPABLE(fremovexattr_(cap_xset, "user.capsicumtest"));
1244   EXPECT_OK(fremovexattr_(cap_xdel, "user.capsicumtest"));
1245
1246   close(cap_xdel);
1247   close(cap_xset);
1248   close(cap_xget);
1249   close(cap_xlist);
1250   close(cap);
1251   close(fd);
1252 }
1253
1254 TEST(Capability, PipeUnseekable) {
1255   int fds[2];
1256   EXPECT_OK(pipe(fds));
1257
1258   // Some programs detect pipes by calling seek() and getting ESPIPE.
1259   EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET));
1260   EXPECT_EQ(ESPIPE, errno);
1261
1262   cap_rights_t rights;
1263   cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_SEEK);
1264   EXPECT_OK(cap_rights_limit(fds[0], &rights));
1265
1266   EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET));
1267   EXPECT_EQ(ESPIPE, errno);
1268
1269   // Remove CAP_SEEK and see if ENOTCAPABLE trumps ESPIPE.
1270   cap_rights_init(&rights, CAP_READ, CAP_WRITE);
1271   EXPECT_OK(cap_rights_limit(fds[0], &rights));
1272   EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET));
1273   EXPECT_EQ(ENOTCAPABLE, errno);
1274   // TODO(drysdale): in practical terms it might be nice if ESPIPE trumped ENOTCAPABLE.
1275   // EXPECT_EQ(ESPIPE, errno);
1276
1277   close(fds[0]);
1278   close(fds[1]);
1279 }
1280
1281 TEST(Capability, NoBypassDAC) {
1282   REQUIRE_ROOT();
1283   int fd = open(TmpFile("cap_root_owned"), O_RDONLY|O_CREAT, 0644);
1284   EXPECT_OK(fd);
1285   cap_rights_t rights;
1286   cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FCHMOD, CAP_FSTAT);
1287   EXPECT_OK(cap_rights_limit(fd, &rights));
1288
1289   pid_t child = fork();
1290   if (child == 0) {
1291     // Child: change uid to a lesser being
1292     setuid(other_uid);
1293     // Attempt to fchmod the file, and fail.
1294     // Having CAP_FCHMOD doesn't bypass the need to comply with DAC policy.
1295     int rc = fchmod(fd, 0666);
1296     EXPECT_EQ(-1, rc);
1297     EXPECT_EQ(EPERM, errno);
1298     exit(HasFailure());
1299   }
1300   int status;
1301   EXPECT_EQ(child, waitpid(child, &status, 0));
1302   EXPECT_TRUE(WIFEXITED(status)) << "0x" << std::hex << status;
1303   EXPECT_EQ(0, WEXITSTATUS(status));
1304   struct stat info;
1305   EXPECT_OK(fstat(fd, &info));
1306   EXPECT_EQ((mode_t)(S_IFREG|0644), info.st_mode);
1307   close(fd);
1308   unlink(TmpFile("cap_root_owned"));
1309 }