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