kern/130924: poll() system call overwrites complete pollfd struct instead of just revents

Kurt Miller kurt at intricatesoftware.com
Fri Jan 23 16:50:02 PST 2009


>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 at 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:


More information about the freebsd-bugs mailing list