From c7f8b28d8d48a9857659ad73935a3b513e588d4c Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Mon, 26 Mar 2018 10:48:30 +0200 Subject: [PATCH] Fix use-after-free in x11 backend during shutdown The xcb_connection_t instance that is used here comes from XGetXCBConnection(), is created by XOpenDisplay(), and is owned by the returned Display*. Calling xcb_disconnect() directly on it leads to various use-after-frees during shutdown, as reported by valgrind. The first one of the about 30 errors is: Invalid read of size 4 at 0x71F2051: xcb_take_socket (in /usr/lib64/libxcb.so.1.1.0) by 0x78551DD: ??? (in /usr/lib64/libX11.so.6.3.0) by 0x7855A14: _XFlush (in /usr/lib64/libX11.so.6.3.0) by 0x7858504: _XGetRequest (in /usr/lib64/libX11.so.6.3.0) by 0x7838966: XFreeGC (in /usr/lib64/libX11.so.6.3.0) by 0x783238B: XCloseDisplay (in /usr/lib64/libX11.so.6.3.0) by 0x4E680C2: wlr_x11_backend_destroy (backend.c:333) by 0x4E57E94: wlr_backend_destroy (backend.c:39) by 0x4E629FB: multi_backend_destroy (backend.c:47) by 0x4E62B5A: handle_display_destroy (backend.c:90) by 0x50B7E9F: ??? (in /usr/lib64/libwayland-server.so.0.1.0) by 0x50B8476: wl_display_destroy (in /usr/lib64/libwayland-server.so.0.1.0) Address 0xc14dda0 is 0 bytes inside a block of size 21,152 free'd at 0x4C2DD18: free (vg_replace_malloc.c:530) by 0x4E680A5: wlr_x11_backend_destroy (backend.c:330) by 0x4E57E94: wlr_backend_destroy (backend.c:39) by 0x4E629FB: multi_backend_destroy (backend.c:47) by 0x4E62B5A: handle_display_destroy (backend.c:90) by 0x50B7E9F: ??? (in /usr/lib64/libwayland-server.so.0.1.0) by 0x50B8476: wl_display_destroy (in /usr/lib64/libwayland-server.so.0.1.0) by 0x40C54E: main (main.c:84) Block was alloc'd at at 0x4C2EA1E: calloc (vg_replace_malloc.c:711) by 0x71F0C60: xcb_connect_to_fd (in /usr/lib64/libxcb.so.1.1.0) by 0x71F4BD4: xcb_connect_to_display_with_auth_info (in /usr/lib64/libxcb.so.1.1.0) by 0x7854AA1: _XConnectXCB (in /usr/lib64/libX11.so.6.3.0) by 0x7845481: XOpenDisplay (in /usr/lib64/libX11.so.6.3.0) by 0x4E681B6: wlr_x11_backend_create (backend.c:376) by 0x4E580EE: wlr_backend_autocreate (backend.c:99) by 0x40C27D: main (main.c:35) Normally, one would expect this to crash during XCloseDisplay() when xcb_disconnect() is called again and frees the same data again (glibc would detect a double free). However, XCloseDisplay() tries to clean up some internal caches first for which it has to send requests to the X11 server (e.g. the XFreeGC() above). This fails since the file descriptor was already closed, which causes an IO error. Xlib's _XDefaultIOError() handles this by printing an error message and calling exit(1). Thus, the only symptom of this problem was compositors exiting mid-shutdown and printing an error message: XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0" after 6 requests (6 known processed) with 0 events remaining. Fixes: https://github.com/swaywm/wlroots/issues/745 Signed-off-by: Uli Schlachter --- backend/x11/backend.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/x11/backend.c b/backend/x11/backend.c index dd2c0a6e..36d72d9e 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -326,9 +326,6 @@ static void wlr_x11_backend_destroy(struct wlr_backend *backend) { wl_event_source_remove(x11->frame_timer); wlr_egl_finish(&x11->egl); - if (x11->xcb_conn) { - xcb_disconnect(x11->xcb_conn); - } if (x11->xlib_conn) { XCloseDisplay(x11->xlib_conn); } @@ -428,7 +425,6 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, error_event: wl_event_source_remove(x11->event_source); error_x11: - xcb_disconnect(x11->xcb_conn); XCloseDisplay(x11->xlib_conn); free(x11); return NULL;