1 #include <sys/select.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <poll.h> 6 7 #include "capsicum.h" 8 #include "syscalls.h" 9 #include "capsicum-test.h" 10 11 namespace { 12 13 int AddFDToSet(fd_set* fset, int fd, int maxfd) { 14 FD_SET(fd, fset); 15 if (fd > maxfd) maxfd = fd; 16 return maxfd; 17 } 18 19 int InitFDSet(fd_set* fset, int *fds, int fdcount) { 20 FD_ZERO(fset); 21 int maxfd = -1; 22 for (int ii = 0; ii < fdcount; ii++) { 23 maxfd = AddFDToSet(fset, fds[ii], maxfd); 24 } 25 return maxfd; 26 } 27 28 } // namespace 29 30 FORK_TEST_ON(Select, LotsOFileDescriptors, TmpFile("cap_select")) { 31 int fd = open(TmpFile("cap_select"), O_RDWR | O_CREAT, 0644); 32 EXPECT_OK(fd); 33 if (fd < 0) return; 34 35 // Create many POLL_EVENT capabilities. 36 const int kCapCount = 64; 37 int cap_fd[kCapCount]; 38 cap_rights_t r_poll; 39 cap_rights_init(&r_poll, CAP_EVENT); 40 for (int ii = 0; ii < kCapCount; ii++) { 41 cap_fd[ii] = dup(fd); 42 EXPECT_OK(cap_fd[ii]); 43 EXPECT_OK(cap_rights_limit(cap_fd[ii], &r_poll)); 44 } 45 cap_rights_t r_rw; 46 cap_rights_init(&r_rw, CAP_READ, CAP_WRITE, CAP_SEEK); 47 int cap_rw = dup(fd); 48 EXPECT_OK(cap_rw); 49 EXPECT_OK(cap_rights_limit(cap_rw, &r_rw)); 50 51 EXPECT_OK(cap_enter()); // Enter capability mode 52 53 struct timeval tv; 54 tv.tv_sec = 0; 55 tv.tv_usec = 100; 56 // Add normal file descriptor and all CAP_EVENT capabilities 57 fd_set rset; 58 fd_set wset; 59 int maxfd = InitFDSet(&rset, cap_fd, kCapCount); 60 maxfd = AddFDToSet(&rset, fd, maxfd); 61 InitFDSet(&wset, cap_fd, kCapCount); 62 AddFDToSet(&rset, fd, 0); 63 int ret = select(maxfd+1, &rset, &wset, NULL, &tv); 64 EXPECT_OK(ret); 65 66 // Now also include the capability with no CAP_EVENT. 67 InitFDSet(&rset, cap_fd, kCapCount); 68 AddFDToSet(&rset, fd, maxfd); 69 maxfd = AddFDToSet(&rset, cap_rw, maxfd); 70 InitFDSet(&wset, cap_fd, kCapCount); 71 AddFDToSet(&wset, fd, maxfd); 72 AddFDToSet(&wset, cap_rw, maxfd); 73 ret = select(maxfd+1, &rset, &wset, NULL, &tv); 74 EXPECT_NOTCAPABLE(ret); 75 76 #ifdef HAVE_PSELECT 77 // And again with pselect 78 struct timespec ts; 79 ts.tv_sec = 0; 80 ts.tv_nsec = 100000; 81 maxfd = InitFDSet(&rset, cap_fd, kCapCount); 82 maxfd = AddFDToSet(&rset, fd, maxfd); 83 InitFDSet(&wset, cap_fd, kCapCount); 84 AddFDToSet(&rset, fd, 0); 85 ret = pselect(maxfd+1, &rset, &wset, NULL, &ts, NULL); 86 EXPECT_OK(ret); 87 88 InitFDSet(&rset, cap_fd, kCapCount); 89 AddFDToSet(&rset, fd, maxfd); 90 maxfd = AddFDToSet(&rset, cap_rw, maxfd); 91 InitFDSet(&wset, cap_fd, kCapCount); 92 AddFDToSet(&wset, fd, maxfd); 93 AddFDToSet(&wset, cap_rw, maxfd); 94 ret = pselect(maxfd+1, &rset, &wset, NULL, &ts, NULL); 95 EXPECT_NOTCAPABLE(ret); 96 #endif 97 } 98 99 FORK_TEST_ON(Poll, LotsOFileDescriptors, TmpFile("cap_poll")) { 100 int fd = open(TmpFile("cap_poll"), O_RDWR | O_CREAT, 0644); 101 EXPECT_OK(fd); 102 if (fd < 0) return; 103 104 // Create many POLL_EVENT capabilities. 105 const int kCapCount = 64; 106 struct pollfd cap_fd[kCapCount + 2]; 107 cap_rights_t r_poll; 108 cap_rights_init(&r_poll, CAP_EVENT); 109 for (int ii = 0; ii < kCapCount; ii++) { 110 cap_fd[ii].fd = dup(fd); 111 EXPECT_OK(cap_fd[ii].fd); 112 EXPECT_OK(cap_rights_limit(cap_fd[ii].fd, &r_poll)); 113 cap_fd[ii].events = POLLIN|POLLOUT; 114 } 115 cap_fd[kCapCount].fd = fd; 116 cap_fd[kCapCount].events = POLLIN|POLLOUT; 117 cap_rights_t r_rw; 118 cap_rights_init(&r_rw, CAP_READ, CAP_WRITE, CAP_SEEK); 119 int cap_rw = dup(fd); 120 EXPECT_OK(cap_rw); 121 EXPECT_OK(cap_rights_limit(cap_rw, &r_rw)); 122 cap_fd[kCapCount + 1].fd = cap_rw; 123 cap_fd[kCapCount + 1].events = POLLIN|POLLOUT; 124 125 EXPECT_OK(cap_enter()); // Enter capability mode 126 127 EXPECT_OK(poll(cap_fd, kCapCount + 1, 10)); 128 // Now also include the capability with no CAP_EVENT. 129 EXPECT_OK(poll(cap_fd, kCapCount + 2, 10)); 130 EXPECT_NE(0, (cap_fd[kCapCount + 1].revents & POLLNVAL)); 131 132 #ifdef HAVE_PPOLL 133 // And again with ppoll 134 struct timespec ts; 135 ts.tv_sec = 0; 136 ts.tv_nsec = 100000; 137 EXPECT_OK(ppoll(cap_fd, kCapCount + 1, &ts, NULL)); 138 // Now also include the capability with no CAP_EVENT. 139 EXPECT_OK(ppoll(cap_fd, kCapCount + 2, &ts, NULL)); 140 EXPECT_NE(0, (cap_fd[kCapCount + 1].revents & POLLNVAL)); 141 #endif 142 } 143