Date: Sat, 24 Jan 2009 00:49:15 GMT From: Kurt Miller <kurt@intricatesoftware.com> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/130924: poll() system call overwrites complete pollfd struct instead of just revents Message-ID: <200901240049.n0O0nFZx050036@www.freebsd.org> Resent-Message-ID: <200901240050.n0O0o1wg061366@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 130924 >Category: kern >Synopsis: poll() system call overwrites complete pollfd struct instead of just revents >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sat Jan 24 00:50:01 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Kurt Miller >Release: 7.0-release >Organization: Intricate Software >Environment: FreeBSD fbsd-i386-70.intricatesoftware.com 7.0-RELEASE FreeBSD 7.0-RELEASE #0: Sun Feb 24 19:59:52 UTC 2008 root@logan.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386 >Description: poll() system call overwrites complete pollfd struct instead of just revents. This can cause threaded programs to 'loose' new events set while another thread is blocked and waiting in poll(). For example the JDK allows one thread to change the pollfd events field while a second thread is blocked in poll(). After waking up the blocked thread and returning to poll, the new event is lost by the poll system call overwriting the complete pollfd struct instead of just revents. >How-To-Repeat: #include <err.h> #include <poll.h> #include <pthread.h> #include <stdio.h> #include <unistd.h> struct pollfd fds[2]; int pipefds[2]; static void * thread(void *arg) { sleep(1); fds[1].events = POLLIN | POLLOUT; write(pipefds[0], "", 1); return NULL; } int main(int argc, char *argv[]) { pthread_t tid; if (pipe(pipefds) != 0) err(1, "pipe failed"); fds[0].fd = pipefds[0]; fds[0].events = POLLIN; fds[1].fd = pipefds[1]; fds[1].events = POLLIN; if (pthread_create(&tid, NULL, thread, NULL) != 0) err(1, "pthread_create failed"); poll(fds, 2, -1); if (fds[1].events != (POLLIN | POLLOUT)) { printf("events overwritten by kernel!\n"); return 1; } return 0; } >Fix: change the poll system call to copyout just the revents value instead of the full pollfd struct. >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901240049.n0O0nFZx050036>