diff options
author | jonathan <jonathan@FreeBSD.org> | 2011-08-16 14:14:56 +0000 |
---|---|---|
committer | jonathan <jonathan@FreeBSD.org> | 2011-08-16 14:14:56 +0000 |
commit | a76ca2eae754746b1de94206ff7de76a42bc6bab (patch) | |
tree | e1ac53093570fbc2a88500f2e87efee7faf0f821 | |
parent | 82e7e2a2904eb45b64f219faf9a9e96f6673e433 (diff) | |
download | FreeBSD-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.c | 11 | ||||
-rw-r--r-- | tools/regression/security/cap_test/cap_test_capabilities.c | 18 |
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"); |