Module: wine Branch: master Commit: 3db6d1acafab6fbb22b5bcefee99099779653b5b URL: http://source.winehq.org/git/wine.git/?a=commit;h=3db6d1acafab6fbb22b5bcefee...
Author: Sebastian Lackner sebastian@fds-team.de Date: Wed Jul 15 06:19:54 2015 +0200
server: Avoid sending unexpected wakeup with uninitialized cookie value.
The code for SELECT_SIGNAL_AND_WAIT in select_on() calls signal_object(). This might wake up the same thread which is currently in the wineserver call. The value for current->wait->cookie is initialized at the end of the function, and not defined yet at this point.
---
server/thread.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/server/thread.c b/server/thread.c index 6c5d12d..8471651 100644 --- a/server/thread.c +++ b/server/thread.c @@ -601,6 +601,7 @@ static int wait_on( const select_op_t *select_op, unsigned int count, struct obj wait->count = count; wait->flags = flags; wait->select = select_op->op; + wait->cookie = 0; wait->user = NULL; wait->timeout = timeout; wait->abandoned = 0; @@ -719,7 +720,7 @@ int wake_thread( struct thread *thread ) cookie = thread->wait->cookie; if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled ); end_wait( thread ); - if (send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */ + if (cookie && send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */ { if (!count) count = -1; break; @@ -749,7 +750,7 @@ int wake_thread_queue_entry( struct wait_queue_entry *entry ) if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled ); end_wait( thread );
- if (send_thread_wakeup( thread, cookie, signaled ) != -1) + if (!cookie || send_thread_wakeup( thread, cookie, signaled ) != -1) wake_thread( thread ); /* check other waits too */
return 1; @@ -768,6 +769,8 @@ static void thread_timeout( void *ptr )
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=TIMEOUT\n", thread->id ); end_wait( thread ); + + assert( cookie ); if (send_thread_wakeup( thread, cookie, STATUS_TIMEOUT ) == -1) return; /* check if other objects have become signaled in the meantime */ wake_thread( thread ); @@ -1429,6 +1432,12 @@ DECL_HANDLER(select) set_error( STATUS_INVALID_PARAMETER ); return; } + if (!req->cookie) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + op_size = min( get_req_data_size() - sizeof(*result), sizeof(select_op) ); memset( &select_op, 0, sizeof(select_op) ); memcpy( &select_op, result + 1, op_size );