Sebastian Lackner : server: Avoid sending unexpected wakeup with uninitialized cookie value.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Jul 15 09:51:23 CDT 2015


Module: wine
Branch: master
Commit: 3db6d1acafab6fbb22b5bcefee99099779653b5b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3db6d1acafab6fbb22b5bcefee99099779653b5b

Author: Sebastian Lackner <sebastian at 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 );




More information about the wine-cvs mailing list