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