diff options
author | Stefan Metzmacher <metze@samba.org> | 2013-02-21 14:41:24 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2013-03-01 11:59:28 -0800 |
commit | 8e3ef659f876573bd7abb7d0e707369157232125 (patch) | |
tree | d8d3365bc4d4b38f44bef402b8ac15b2c3ed71d9 /lib/tevent | |
parent | d5b341d873bc326843d80dd15d3cd3ef465234ae (diff) | |
download | samba-8e3ef659f876573bd7abb7d0e707369157232125.tar.gz samba-8e3ef659f876573bd7abb7d0e707369157232125.tar.bz2 samba-8e3ef659f876573bd7abb7d0e707369157232125.zip |
tevent: make sure we cleanup the array passed to poll() after deleting an event
If we don't cleanup the array passed to poll after an
event was deleted, we may pass a bad file descriptor to poll().
This was found by the following test failure in Samba's
autobuild, while removing the epoll support from
the "standard" backend.
[48/1555 in 4m37s] samba3.smbtorture_s3.plain(s3dc).LOCK4
UNEXPECTED(failure): samba3.smbtorture_s3.plain(s3dc).LOCK4.smbtorture(s3dc)
REASON: _StringException: _StringException: using seed 1361530718
host=127.0.0.2 share=tmp user=metze myname=sn-devel-104
Running LOCK4
starting locktest4
Failed to create file: NT_STATUS_INVALID_HANDLE
finished locktest4
TEST LOCK4 FAILED!
LOCK4 took 190.492 secs
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib/tevent')
-rw-r--r-- | lib/tevent/tevent_poll.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c index 68885e94c0..0928cbd6cb 100644 --- a/lib/tevent/tevent_poll.c +++ b/lib/tevent/tevent_poll.c @@ -38,6 +38,7 @@ struct poll_event_context { * picked up yet by poll_event_loop_once */ struct tevent_fd *fresh; + bool deleted; /* * These two arrays are maintained together. @@ -219,6 +220,7 @@ static int poll_event_fd_destructor(struct tevent_fd *fde) ev->additional_data, struct poll_event_context); poll_ev->fdes[del_idx] = NULL; + poll_ev->deleted = true; poll_event_wake_pollthread(poll_ev); done: return tevent_common_fd_destructor(fde); @@ -363,6 +365,34 @@ static bool poll_event_setup_fresh(struct tevent_context *ev, struct tevent_fd *fde, *next; unsigned num_fresh, num_fds; + if (poll_ev->deleted) { + unsigned first_fd = (poll_ev->signal_fd != -1) ? 1 : 0; + unsigned i; + + for (i=first_fd; i < poll_ev->num_fds;) { + fde = poll_ev->fdes[i]; + if (fde != NULL) { + i++; + continue; + } + + /* + * This fde was talloc_free()'ed. Delete it + * from the arrays + */ + poll_ev->num_fds -= 1; + if (poll_ev->num_fds == i) { + break; + } + poll_ev->fds[i] = poll_ev->fds[poll_ev->num_fds]; + poll_ev->fdes[i] = poll_ev->fdes[poll_ev->num_fds]; + if (poll_ev->fdes[i] != NULL) { + poll_ev->fdes[i]->additional_flags = i; + } + } + } + poll_ev->deleted = false; + if (poll_ev->fresh == NULL) { return true; } |