[PATCH] remove listener from wl_data_source destroy_signal listener list

Dmitry Guryanov dmitry.guryanov at gmail.com
Tue Jul 17 07:56:03 PDT 2012


I've found a bug during wayland exploration - if you make two
drag'n'drops in weston client example, dnd - weston crashes with
segfault. I've tried to investigate it and found a problem.

In function drag_grab_button we first call data_device_end_drag_grab,
which sets seat->drag_data_source to NULL. Then we remove
listener from list only if drag_data_source is not NULL.

So if client will not free wl_data_source and start another drag'n'drop,
after the first one. Then two wl_data_source structures will be
free'd on client exit (let's name them s1 and s2).

next and prev pointer of
wl_data_source.resource.destroy_signal.listener_list in both
wl_data_source structures will be seat->drag_data_source_listener,
but next and prev in seat->drag_data_source_listener.link point
to listener_list in s2.

So if you try to iterate over listener_list in s1
then you get drag_data_source_listener as first item and
(struct wl_listener *)(&s2.resource.destroy_signal.listener_list)

Iteration over that list occurs in
wl_resource_destroy->destroy_resource->wl_signal_emit->wl_signal_emit
and try to call function at address of wl_resource->client, so
weston segfaults there.
---
 src/data-device.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/data-device.c b/src/data-device.c
index 67ae41f..82020af 100644
--- a/src/data-device.c
+++ b/src/data-device.c
@@ -265,9 +265,9 @@ drag_grab_button(struct wl_pointer_grab *grab,
 
 	if (seat->pointer->button_count == 0 &&
 	    state == WL_POINTER_BUTTON_STATE_RELEASED) {
-		data_device_end_drag_grab(seat);
 		if (seat->drag_data_source)
 			wl_list_remove(&seat->drag_data_source_listener.link);
+		data_device_end_drag_grab(seat);
 	}
 }
 
-- 
1.7.10.4



More information about the wayland-devel mailing list