Blame SOURCES/0001-Fix-poll_for_response-race-condition.patch

4b168a
From 77f8517710a724fa1f29de8ad806692782f962bd Mon Sep 17 00:00:00 2001
4b168a
From: Frediano Ziglio <fziglio@redhat.com>
4b168a
Date: Wed, 29 Jan 2020 09:06:54 +0000
4b168a
Subject: [PATCH libX11] Fix poll_for_response race condition
4b168a
4b168a
In poll_for_response is it possible that event replies are skipped
4b168a
and a more up to date message reply is returned.
4b168a
This will cause next poll_for_event call to fail aborting the program.
4b168a
4b168a
This was proved using some slow ssh tunnel or using some program
4b168a
to slow down server replies (I used a combination of xtrace and strace).
4b168a
4b168a
How the race happens:
4b168a
- program enters into poll_for_response;
4b168a
- poll_for_event is called but the server didn't still send the reply;
4b168a
- pending_requests is not NULL because we send a request (see call
4b168a
  to  append_pending_request in _XSend);
4b168a
- xcb_poll_for_reply64 is called from poll_for_response;
4b168a
- xcb_poll_for_reply64 will read from server, at this point
4b168a
  server reply with an event (say sequence N) and the reply to our
4b168a
  last request (say sequence N+1);
4b168a
- xcb_poll_for_reply64 returns the reply for the request we asked;
4b168a
- last_request_read is set to N+1 sequence in poll_for_response;
4b168a
- poll_for_response returns the response to the request;
4b168a
- poll_for_event is called (for instance from another poll_for_response);
4b168a
- event with sequence N is retrieved;
4b168a
- the N sequence is widen, however, as the "new" number computed from
4b168a
  last_request_read is less than N the number is widened to N + 2^32
4b168a
  (assuming last_request_read is still contained in 32 bit);
4b168a
- poll_for_event enters the nested if statement as req is NULL;
4b168a
- we compare the widen N (which now does not fit into 32 bit) with
4b168a
  request (which fits into 32 bit) hitting the throw_thread_fail_assert.
4b168a
4b168a
I propose to change the widen to not go too far from the wide number
4b168a
instead of supposing the result is always bigger than the wide number
4b168a
passed.
4b168a
4b168a
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
4b168a
---
4b168a
 src/xcb_io.c | 4 +---
4b168a
 1 file changed, 1 insertion(+), 3 deletions(-)
4b168a
4b168a
diff --git a/src/xcb_io.c b/src/xcb_io.c
4b168a
index 6a12d150..2aacbda3 100644
4b168a
--- a/src/xcb_io.c
4b168a
+++ b/src/xcb_io.c
4b168a
@@ -201,12 +201,10 @@ static int handle_error(Display *dpy, xError *err, Bool in_XReply)
4b168a
 }
4b168a
 
4b168a
 /* Widen a 32-bit sequence number into a 64bit (uint64_t) sequence number.
4b168a
- * Treating the comparison as a 1 and shifting it avoids a conditional branch.
4b168a
  */
4b168a
 static void widen(uint64_t *wide, unsigned int narrow)
4b168a
 {
4b168a
-	uint64_t new = (*wide & ~((uint64_t)0xFFFFFFFFUL)) | narrow;
4b168a
-	*wide = new + (((uint64_t)(new < *wide)) << 32);
4b168a
+	*wide += (int32_t) (narrow - *wide);
4b168a
 }
4b168a
 
4b168a
 /* Thread-safety rules:
4b168a
-- 
4b168a
2.23.0
4b168a