[PATCH weston] xwm: fix use after free

Bryce Harrington bryce at osg.samsung.com
Tue Jan 27 19:29:28 PST 2015


On Fri, Dec 26, 2014 at 06:10:35PM +0200, Giulio Camuffo wrote:
> Calling wl_event_source_remove() will free the event source later, so
> reset the pointer to avoid calling it two times on the same pointer.
> Fix a compositor crash when copying some text from weston terminal,
> pasting it in the same terminal and hitting ctrl-u, while a X client
> is running.
> ---
>  xwayland/selection.c | 7 +++++++
>  1 file changed, 7 insertions(+)

Looking at wl_event_source_remove(), I definitely see what you mean
about it delaying the free's.

Verifying the pointer does eventually get freed is a bit tricky but I
think I understand it: wl_event_source_remove() adds source->link to the
loop->destroy_list, then later on this list is processed by a C macro:

        wl_list_for_each_safe(source, next, &loop->destroy_list, link)
                free(source);

This uses wl_container_of() on the link stored in destroy_list to find
its parent container, source, and then frees it.

So, presuming my understanding of the logic is correct:

Reviewed-by: Bryce Harrington <bryce at osg.samsung.com>

> diff --git a/xwayland/selection.c b/xwayland/selection.c
> index b694477..24bd56d 100644
> --- a/xwayland/selection.c
> +++ b/xwayland/selection.c
> @@ -46,6 +46,7 @@ writable_callback(int fd, uint32_t mask, void *data)
>  		wm->property_reply = NULL;
>  		if (wm->property_source)
>  			wl_event_source_remove(wm->property_source);
> +		wm->property_source = NULL;
>  		close(fd);
>  		weston_log("write error to target fd: %m\n");
>  		return 1;
> @@ -61,6 +62,7 @@ writable_callback(int fd, uint32_t mask, void *data)
>  		wm->property_reply = NULL;
>  		if (wm->property_source)
>  			wl_event_source_remove(wm->property_source);

If we need to check wm->property_source before calling
wl_event_source_remove(), shouldn't this also be done for the subsequent
calls as well?

> +		wm->property_source = NULL;
>  
>  		if (wm->incr) {
>  			xcb_delete_property(wm->conn,
> @@ -352,6 +354,7 @@ weston_wm_read_data_source(int fd, uint32_t mask, void *data)
>  		weston_log("read error from data source: %m\n");
>  		weston_wm_send_selection_notify(wm, XCB_ATOM_NONE);
>  		wl_event_source_remove(wm->property_source);
> +		wm->property_source = NULL;
>  		close(fd);
>  		wl_array_release(&wm->source_data);
>  	}
> @@ -375,6 +378,7 @@ weston_wm_read_data_source(int fd, uint32_t mask, void *data)
>  			wm->selection_property_set = 1;
>  			wm->flush_property_on_delete = 1;
>  			wl_event_source_remove(wm->property_source);
> +			wm->property_source = NULL;
>  			weston_wm_send_selection_notify(wm, wm->selection_request.property);
>  		} else if (wm->selection_property_set) {
>  			weston_log("got %zu bytes, waiting for "
> @@ -382,6 +386,7 @@ weston_wm_read_data_source(int fd, uint32_t mask, void *data)
>  
>  			wm->flush_property_on_delete = 1;
>  			wl_event_source_remove(wm->property_source);
> +			wm->property_source = NULL;
>  		} else {
>  			weston_log("got %zu bytes, "
>  				"property deleted, seting new property\n",
> @@ -395,6 +400,7 @@ weston_wm_read_data_source(int fd, uint32_t mask, void *data)
>  		weston_wm_send_selection_notify(wm, wm->selection_request.property);
>  		xcb_flush(wm->conn);
>  		wl_event_source_remove(wm->property_source);
> +		wm->property_source = NULL;
>  		close(fd);
>  		wl_array_release(&wm->source_data);
>  		wm->selection_request.requestor = XCB_NONE;
> @@ -413,6 +419,7 @@ weston_wm_read_data_source(int fd, uint32_t mask, void *data)
>  		}
>  		xcb_flush(wm->conn);
>  		wl_event_source_remove(wm->property_source);
> +		wm->property_source = NULL;
>  		close(wm->data_source_fd);
>  		wm->data_source_fd = -1;
>  		close(fd);
> -- 
> 2.2.1
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list