summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjonathan <jonathan@FreeBSD.org>2011-08-16 14:14:56 +0000
committerjonathan <jonathan@FreeBSD.org>2011-08-16 14:14:56 +0000
commita76ca2eae754746b1de94206ff7de76a42bc6bab (patch)
treee1ac53093570fbc2a88500f2e87efee7faf0f821
parent82e7e2a2904eb45b64f219faf9a9e96f6673e433 (diff)
downloadFreeBSD-src-a76ca2eae754746b1de94206ff7de76a42bc6bab.zip
FreeBSD-src-a76ca2eae754746b1de94206ff7de76a42bc6bab.tar.gz
poll(2) implementation for capabilities.
When calling poll(2) on a capability, unwrap first and then poll the underlying object. Approved by: re (kib), mentor (rwatson) Sponsored by: Google Inc
-rw-r--r--sys/kern/sys_generic.c11
-rw-r--r--tools/regression/security/cap_test/cap_test_capabilities.c18
2 files changed, 27 insertions, 2 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index 7dc69a6e..6edd4fb 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -1279,11 +1279,17 @@ pollrescan(struct thread *td)
if (si != NULL)
continue;
fp = fdp->fd_ofiles[fd->fd];
+#ifdef CAPABILITIES
+ if ((fp == NULL)
+ || (cap_funwrap(fp, CAP_POLL_EVENT, &fp) != 0)) {
+#else
if (fp == NULL) {
+#endif
fd->revents = POLLNVAL;
n++;
continue;
}
+
/*
* Note: backend also returns POLLHUP and
* POLLERR if appropriate.
@@ -1344,7 +1350,12 @@ pollscan(td, fds, nfd)
fds->revents = 0;
} else {
fp = fdp->fd_ofiles[fds->fd];
+#ifdef CAPABILITIES
+ if ((fp == NULL)
+ || (cap_funwrap(fp, CAP_POLL_EVENT, &fp) != 0)) {
+#else
if (fp == NULL) {
+#endif
fds->revents = POLLNVAL;
n++;
} else {
diff --git a/tools/regression/security/cap_test/cap_test_capabilities.c b/tools/regression/security/cap_test/cap_test_capabilities.c
index ab1c58f..450ad88 100644
--- a/tools/regression/security/cap_test/cap_test_capabilities.c
+++ b/tools/regression/security/cap_test/cap_test_capabilities.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <fcntl.h>
+#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -68,6 +69,7 @@ __FBSDID("$FreeBSD$");
else if (errno != ENOTCAPABLE) \
SYSCALL_FAIL(syscall, "errno != ENOTCAPABLE"); \
} \
+ errno = 0; \
} while (0)
/*
@@ -87,6 +89,7 @@ __FBSDID("$FreeBSD$");
} else if (errno != ENOTCAPABLE) \
SYSCALL_FAIL(syscall, "errno != ENOTCAPABLE"); \
} \
+ errno = 0; \
} while (0)
/*
@@ -104,6 +107,7 @@ try_file_ops(int fd, cap_rights_t rights)
void *p;
char ch;
int ret, is_nfs;
+ struct pollfd pollfd;
int success = PASSED;
REQUIRE(fstatfs(fd, &sf));
@@ -114,6 +118,10 @@ try_file_ops(int fd, cap_rights_t rights)
REQUIRE(fd_capcap = cap_new(fd_cap, rights));
CHECK(fd_capcap != fd_cap);
+ pollfd.fd = fd_cap;
+ pollfd.events = POLLIN | POLLERR | POLLHUP;
+ pollfd.revents = 0;
+
ssize = read(fd_cap, &ch, sizeof(ch));
CHECK_RESULT(read, CAP_READ | CAP_SEEK, ssize >= 0);
@@ -189,7 +197,13 @@ try_file_ops(int fd, cap_rights_t rights)
ret = futimes(fd_cap, NULL);
CHECK_RESULT(futimes, CAP_FUTIMES, ret == 0);
- /* XXX select / poll / kqueue */
+ ret = poll(&pollfd, 1, 0);
+ if (rights & CAP_POLL_EVENT)
+ CHECK((pollfd.revents & POLLNVAL) == 0);
+ else
+ CHECK((pollfd.revents & POLLNVAL) != 0);
+
+ /* XXX: select, kqueue */
close (fd_cap);
return (success);
@@ -210,7 +224,7 @@ test_capabilities(void)
int fd;
int success = PASSED;
- fd = open("/tmp/cap_test", O_RDWR | O_CREAT, 0644);
+ fd = open("/tmp/cap_test_capabilities", O_RDWR | O_CREAT, 0644);
if (fd < 0)
err(-1, "open");
OpenPOWER on IntegriCloud