<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Dec 31, 2013 at 3:37 AM, Pekka Paalanen <span dir="ltr"><<a href="mailto:ppaalanen@gmail.com" target="_blank">ppaalanen@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Wed, 25 Dec 2013 17:02:09 +0100<br>
Mariusz Ceier <<a href="mailto:mceier%2Bwayland@gmail.com">mceier+wayland@gmail.com</a>> wrote:<br>
<br>
> Some structures containing resources list are freed before<br>
> resources on that list are destroyed, and that triggers invalid<br>
> read/write in compositor.c:3103 indirectly called from<br>
> text-backend.c:938 when running weston under valgrind.<br>
><br>
> This patch destroys resources on these lists before such<br>
> structures are freed.<br>
><br>
> That fixes at least x11 and freerds backend.<br>
><br>
> Signed-off-by: Mariusz Ceier <<a href="mailto:mceier%2Bwayland@gmail.com">mceier+wayland@gmail.com</a>><br>
> ---<br>
>  src/compositor.c |  4 ++++<br>
>  src/input.c      | 15 ++++++++++++---<br>
>  2 files changed, 16 insertions(+), 3 deletions(-)<br>
><br>
> diff --git a/src/compositor.c b/src/compositor.c<br>
> index ff0f3ab..a4077e8 100644<br>
> --- a/src/compositor.c<br>
> +++ b/src/compositor.c<br>
> @@ -3183,6 +3183,7 @@ weston_compositor_verify_pointers(struct<br>
> weston_compositor *ec) WL_EXPORT void<br>
>  weston_output_destroy(struct weston_output *output)<br>
>  {<br>
> +     struct wl_resource *resource, *next_resource;<br>
>       output->destroying = 1;<br>
><br>
>       weston_compositor_remove_output(output->compositor,<br>
> output); @@ -3192,6 +3193,9 @@ weston_output_destroy(struct<br>
> weston_output *output)<br>
>       wl_signal_emit(&output->destroy_signal, output);<br>
><br>
> +     wl_resource_for_each_safe(resource, next_resource,<br>
> &output->resource_list)<br>
> +             wl_resource_destroy(resource);<br>
> +<br>
<br>
</div></div>Hi,<br>
<br>
I didn't check the other cases, but this case seems suspicious at<br>
first. There is the following fundamental principle with Wayland<br>
protocol objects as I understand it.<br>
<br>
You cannot just go and destroy wl_resources, because there are<br>
clients using them - that is why the wl_resources exist in the<br>
first place. Clients use all protocol objects they have, and if the<br>
protocol does not say an object is destroyed, then it must be legal<br>
to use it, regardless of what happens in the server.<br>
<br>
If you can guarantee, that clients know the protocol object has<br>
gone away without any races, then the clients have already<br>
destroyed the protocol objects themselves, which means that you<br>
have no wl_resources to destroy in the list.<br>
<br>
If you cannot guarantee that, then the protocol objects<br>
(wl_resources) must continue to exist in such a way, that clients<br>
do not get a fatal protocol error when using them. The objects just<br>
do nothing. This state is called "inert".<br>
<br>
If this principle is broken, it usually leads to races between the<br>
server and the client, which sometimes leads to a fatal protocol<br>
error and causes disconnection of the client. This happens, when the<br>
server destroys a wl_resource, and then receives a request from the<br>
client for that destroyed resource. The client may have sent the<br>
request even before the wl_resource was destroyed in the server, at<br>
which point it was a legal request from the client's perspective<br>
(this is the essence of the race).<br>
<br>
However, since wl_output interface contains no requests, your patch<br>
might be right. A client cannot send a wl_output request after the<br>
wl_resource has been destroyed in the server, because the interface<br>
has no requests.<br>
<br>
The wl_output could still be used as an argument to other requests<br>
in other interfaces, though. Whether that is fatal, or just<br>
silently gets turned into NULL argument in libwayland-server, I do<br>
not remember off-hand. Would be best to verify what happens in that<br>
case, since it must not be fatal to the client.<br></blockquote><div><br></div><div>Yes, I just looked it up.  If a client sends a request with the output as an argument after the output gets destroyed, the client will get an INVALID_OBJECT protocol error and disconnect.  This is a problem.<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
If this patch leads to a race with possibly a protocol error as the<br>
result (think about output hot-unplug), then I think you would need<br>
to turn the wl_resource into an inert object instead of destroying<br>
it directly.<br></blockquote><div><br></div><div>The way to do this would be to set dummy handler and call wl_resource_set_destructor(resource, NULL);  This leaves the resource inert and allows us to destroy the underlying object.  The resources will get cleaned up when the client quits.  The reason for the invalid read/write is because the resource destructor calls wl_list_remove on the resource's internal wl_list link.  Because we deleted the underlying weston_output object, this results in an invalid read/write.<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
The same idea applies to the hunks below, too.<br>
<br>
<br>
Thanks,<br>
pq<br>
<div class="HOEnZb"><div class="h5"><br>
>       free(output->name);<br>
>       pixman_region32_fini(&output->region);<br>
>       pixman_region32_fini(&output->previous_damage);<br>
> diff --git a/src/input.c b/src/input.c<br>
> index 07e9d6c..062a2cb 100644<br>
> --- a/src/input.c<br>
> +++ b/src/input.c<br>
> @@ -471,10 +471,13 @@ weston_pointer_create(struct weston_seat<br>
> *seat) WL_EXPORT void<br>
>  weston_pointer_destroy(struct weston_pointer *pointer)<br>
>  {<br>
> +     struct wl_resource *resource, *next_resource;<br>
> +<br>
>       if (pointer->sprite)<br>
>               pointer_unmap_sprite(pointer);<br>
><br>
> -     /* XXX: What about pointer->resource_list? */<br>
> +     wl_resource_for_each_safe(resource, next_resource,<br>
> &pointer->resource_list)<br>
> +             wl_resource_destroy(resource);<br>
><br>
>       wl_list_remove(&pointer->focus_resource_listener.link);<br>
>       wl_list_remove(&pointer->focus_view_listener.link);<br>
> @@ -520,7 +523,7 @@ weston_xkb_info_destroy(struct<br>
> weston_xkb_info *xkb_info); WL_EXPORT void<br>
>  weston_keyboard_destroy(struct weston_keyboard *keyboard)<br>
>  {<br>
> -     /* XXX: What about keyboard->resource_list? */<br>
> +     struct wl_resource *resource, *next_resource;<br>
><br>
>  #ifdef ENABLE_XKBCOMMON<br>
>       if (keyboard->seat->compositor->use_xkbcommon) {<br>
> @@ -533,6 +536,9 @@ weston_keyboard_destroy(struct<br>
> weston_keyboard *keyboard) }<br>
>  #endif<br>
><br>
> +     wl_resource_for_each_safe(resource, next_resource,<br>
> &keyboard->resource_list)<br>
> +             wl_resource_destroy(resource);<br>
> +<br>
>       wl_array_release(&keyboard->keys);<br>
>       wl_list_remove(&keyboard->focus_resource_listener.link);<br>
>       free(keyboard);<br>
> @@ -570,7 +576,10 @@ weston_touch_create(void)<br>
>  WL_EXPORT void<br>
>  weston_touch_destroy(struct weston_touch *touch)<br>
>  {<br>
> -     /* XXX: What about touch->resource_list? */<br>
> +     struct wl_resource *resource, *next_resource;<br>
> +<br>
> +     wl_resource_for_each_safe(resource, next_resource,<br>
> &touch->resource_list)<br>
> +             wl_resource_destroy(resource);<br>
><br>
>       wl_list_remove(&touch->focus_view_listener.link);<br>
>       wl_list_remove(&touch->focus_resource_listener.link);<br>
> --<br>
> 1.8.5.2<br>
><br>
> _______________________________________________<br>
> wayland-devel mailing list<br>
> <a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/wayland-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/wayland-devel</a><br>
_______________________________________________<br>
wayland-devel mailing list<br>
<a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/wayland-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/wayland-devel</a><br>
</div></div></blockquote></div><br></div></div>