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 // And again with pselect 77 struct timespec ts; 78 ts.tv_sec = 0; 79 ts.tv_nsec = 100000; 80 maxfd = InitFDSet(&rset, cap_fd, kCapCount); 81 maxfd = AddFDToSet(&rset, fd, maxfd); 82 InitFDSet(&wset, cap_fd, kCapCount); 83 AddFDToSet(&rset, fd, 0); 84 ret = pselect(maxfd+1, &rset, &wset, NULL, &ts, NULL); 85 EXPECT_OK(ret); 86 87 InitFDSet(&rset, cap_fd, kCapCount); 88 AddFDToSet(&rset, fd, maxfd); 89 maxfd = AddFDToSet(&rset, cap_rw, maxfd); 90 InitFDSet(&wset, cap_fd, kCapCount); 91 AddFDToSet(&wset, fd, maxfd); 92 AddFDToSet(&wset, cap_rw, maxfd); 93 ret = pselect(maxfd+1, &rset, &wset, NULL, &ts, NULL); 94 EXPECT_NOTCAPABLE(ret); 95 } 96 97 FORK_TEST_ON(Poll, LotsOFileDescriptors, TmpFile("cap_poll")) { 98 int fd = open(TmpFile("cap_poll"), O_RDWR | O_CREAT, 0644); 99 EXPECT_OK(fd); 100 if (fd < 0) return; 101 102 // Create many POLL_EVENT capabilities. 103 const int kCapCount = 64; 104 struct pollfd cap_fd[kCapCount + 2]; 105 cap_rights_t r_poll; 106 cap_rights_init(&r_poll, CAP_EVENT); 107 for (int ii = 0; ii < kCapCount; ii++) { 108 cap_fd[ii].fd = dup(fd); 109 EXPECT_OK(cap_fd[ii].fd); 110 EXPECT_OK(cap_rights_limit(cap_fd[ii].fd, &r_poll)); 111 cap_fd[ii].events = POLLIN|POLLOUT; 112 } 113 cap_fd[kCapCount].fd = fd; 114 cap_fd[kCapCount].events = POLLIN|POLLOUT; 115 cap_rights_t r_rw; 116 cap_rights_init(&r_rw, CAP_READ, CAP_WRITE, CAP_SEEK); 117 int cap_rw = dup(fd); 118 EXPECT_OK(cap_rw); 119 EXPECT_OK(cap_rights_limit(cap_rw, &r_rw)); 120 cap_fd[kCapCount + 1].fd = cap_rw; 121 cap_fd[kCapCount + 1].events = POLLIN|POLLOUT; 122 123 EXPECT_OK(cap_enter()); // Enter capability mode 124 125 EXPECT_OK(poll(cap_fd, kCapCount + 1, 10)); 126 // Now also include the capability with no CAP_EVENT. 127 EXPECT_OK(poll(cap_fd, kCapCount + 2, 10)); 128 EXPECT_NE(0, (cap_fd[kCapCount + 1].revents & POLLNVAL)); 129 130 // And again with ppoll 131 struct timespec ts; 132 ts.tv_sec = 0; 133 ts.tv_nsec = 100000; 134 EXPECT_OK(ppoll(cap_fd, kCapCount + 1, &ts, NULL)); 135 // Now also include the capability with no CAP_EVENT. 136 EXPECT_OK(ppoll(cap_fd, kCapCount + 2, &ts, NULL)); 137 EXPECT_NE(0, (cap_fd[kCapCount + 1].revents & POLLNVAL)); 138 } 139