freebsd-skq/select.cc
Enji Cooper e5a5dd6cc4 Import capsicum-test into ^/vendor/google/capsicum-test/dist
The following change imports google/capsicum-test@9333154 from GitHub, omitting
the embedded version of googletest, as well as the incomplete libcasper.

This test suite helps verify capsicum(3) support via functional tests
written in the GoogleTest test framework.

Kernel support for capsicum(4) is tested by side-effect of testing
capsicum(3).

NB: as discussed in a previous [closed] PR [1], the casper(3) tests are
incomplete/buggy and will not pass on FreeBSD. Thus, I have no intention of
integrating them into the build/test on FreeBSD as-is.

The import command used was:
```
curl -L https://github.com/google/capsicum-test/tarball/9333154 | tar --strip-components=1 -xvzf - -C dist/
rm -Rf dist/*/
```

1. https://github.com/google/capsicum-test/pull/26

Reviewed by:	emaste (mentor)
Differential Revision:	https://reviews.freebsd.org/D19261
2019-03-12 01:43:01 +00:00

143 lines
4.0 KiB
C++

#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
}