[PATCH wayland 3/3] Add a version field to wl_resource and verify request versions before calling them
Jason Ekstrand
jason at jlekstrand.net
Thu Jun 27 17:30:20 PDT 2013
DISCARD THIS PATCH. NEW SERIES COMING
This patch breaks ABI too badly. Specifically Mesa (and probably other EGL
implementations) use wl_client_add_object internally.
--Jason Ekstrand
On Wed, Jun 26, 2013 at 10:18 PM, Jason Ekstrand <jason at jlekstrand.net>wrote:
> This commit provides a layer of protection for the compositor in the form
> of message version checking. Version information is provided to libwayland
> as an aditional argument to wl_client_add_object and wl_client_new_object.
> libwayland then uses this version information to verify that a request
> exists in that protocol version before invoking it. This way libwayland
> won't accidentally invoke a request that does not exist and thereby cause
> the compositor to crash.
>
> Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
> ---
> src/wayland-server.c | 38 ++++++++++++++++++++++++++++++--------
> src/wayland-server.h | 6 ++++--
> src/wayland-shm.c | 8 ++++----
> 3 files changed, 38 insertions(+), 14 deletions(-)
>
> diff --git a/src/wayland-server.c b/src/wayland-server.c
> index 0c3fbc9..565392b 100644
> --- a/src/wayland-server.c
> +++ b/src/wayland-server.c
> @@ -109,6 +109,7 @@ struct wl_resource {
> struct wl_signal destroy_signal;
> struct wl_client *client;
> void *data;
> + int version;
> };
>
> static int wl_debug = 0;
> @@ -210,6 +211,7 @@ wl_client_connection_data(int fd, uint32_t mask, void
> *data)
> struct wl_closure *closure;
> const struct wl_message *message;
> uint32_t p[2];
> + uint32_t resource_flags;
> int opcode, size;
> int len;
>
> @@ -246,6 +248,7 @@ wl_client_connection_data(int fd, uint32_t mask, void
> *data)
> break;
>
> resource = wl_map_lookup(&client->objects, p[0]);
> + resource_flags = wl_map_lookup_flags(&client->objects,
> p[0]);
> if (resource == NULL) {
> wl_resource_post_error(client->display_resource,
>
> WL_DISPLAY_ERROR_INVALID_OBJECT,
> @@ -265,6 +268,18 @@ wl_client_connection_data(int fd, uint32_t mask, void
> *data)
> }
>
> message = &object->interface->methods[opcode];
> + if (!(resource_flags & WL_MAP_ENTRY_LEGACY) &&
> + resource->version < wl_message_get_since(message)) {
> + wl_resource_post_error(client->display_resource,
> +
> WL_DISPLAY_ERROR_INVALID_METHOD,
> + "invalid method %d, object
> %s@%u",
> + opcode,
> + object->interface->name,
> + object->id);
> + break;
> + }
> +
> +
> closure = wl_connection_demarshal(client->connection, size,
> &client->objects,
> message);
> len -= size;
> @@ -510,6 +525,12 @@ wl_resource_get_user_data(struct wl_resource
> *resource)
> return resource->data;
> }
>
> +WL_EXPORT int
> +wl_resource_get_version(struct wl_resource *resource)
> +{
> + return resource->version;
> +}
> +
> WL_EXPORT void
> wl_resource_set_destructor(struct wl_resource *resource,
> wl_resource_destroy_func_t destroy)
> @@ -603,8 +624,8 @@ display_sync(struct wl_client *client,
> struct wl_resource *callback;
> uint32_t serial;
>
> - callback = wl_client_add_object(client,
> - &wl_callback_interface, NULL, id,
> NULL);
> + callback = wl_client_add_object(client, &wl_callback_interface, 1,
> + NULL, id, NULL);
> serial = wl_display_get_serial(client->display);
> wl_callback_send_done(callback, serial);
> wl_resource_destroy(callback);
> @@ -626,7 +647,7 @@ display_get_registry(struct wl_client *client,
> struct wl_global *global;
>
> registry_resource =
> - wl_client_add_object(client, &wl_registry_interface,
> + wl_client_add_object(client, &wl_registry_interface, 1,
> ®istry_interface, id, display);
> registry_resource->destroy = unbind_resource;
>
> @@ -660,7 +681,7 @@ bind_display(struct wl_client *client,
> struct wl_display *display = data;
>
> client->display_resource =
> - wl_client_add_object(client, &wl_display_interface,
> + wl_client_add_object(client, &wl_display_interface, 1,
> &display_interface, id, display);
>
> if(client->display_resource)
> @@ -997,7 +1018,7 @@ wl_display_get_destroy_listener(struct wl_display
> *display,
>
> WL_EXPORT struct wl_resource *
> wl_client_add_object(struct wl_client *client,
> - const struct wl_interface *interface,
> + const struct wl_interface *interface, int version,
> const void *implementation,
> uint32_t id, void *data)
> {
> @@ -1018,6 +1039,7 @@ wl_client_add_object(struct wl_client *client,
> resource->destroy = NULL;
> resource->client = client;
> resource->data = data;
> + resource->version = version;
>
> if (wl_map_insert_at(&client->objects, 0, resource->object.id,
> resource) < 0) {
> wl_resource_post_error(client->display_resource,
> @@ -1033,14 +1055,14 @@ wl_client_add_object(struct wl_client *client,
>
> WL_EXPORT struct wl_resource *
> wl_client_new_object(struct wl_client *client,
> - const struct wl_interface *interface,
> + const struct wl_interface *interface, int version,
> const void *implementation, void *data)
> {
> uint32_t id;
>
> id = wl_map_insert_new(&client->objects, 0, NULL);
> - return wl_client_add_object(client,
> - interface, implementation, id, data);
> + return wl_client_add_object(client, interface, version,
> + implementation, id, data);
>
> }
>
> diff --git a/src/wayland-server.h b/src/wayland-server.h
> index 7c53cfc..8a72d40 100644
> --- a/src/wayland-server.h
> +++ b/src/wayland-server.h
> @@ -128,11 +128,11 @@ struct wl_listener
> *wl_client_get_destroy_listener(struct wl_client *client,
>
> struct wl_resource *
> wl_client_add_object(struct wl_client *client,
> - const struct wl_interface *interface,
> + const struct wl_interface *interface, int version,
> const void *implementation, uint32_t id, void *data);
> struct wl_resource *
> wl_client_new_object(struct wl_client *client,
> - const struct wl_interface *interface,
> + const struct wl_interface *interface, int version,
> const void *implementation, void *data);
> struct wl_resource *
> wl_client_get_object(struct wl_client *client, uint32_t id);
> @@ -258,6 +258,8 @@ void
> wl_resource_set_user_data(struct wl_resource *resource, void *data);
> void *
> wl_resource_get_user_data(struct wl_resource *resource);
> +int
> +wl_resource_get_version(struct wl_resource *resource);
> void
> wl_resource_set_destructor(struct wl_resource *resource,
> wl_resource_destroy_func_t destroy);
> diff --git a/src/wayland-shm.c b/src/wayland-shm.c
> index 8a10253..c53a884 100644
> --- a/src/wayland-shm.c
> +++ b/src/wayland-shm.c
> @@ -127,7 +127,7 @@ shm_pool_create_buffer(struct wl_client *client,
> struct wl_resource *resource,
> buffer->pool = pool;
> pool->refcount++;
>
> - buffer->resource = wl_client_add_object(client,
> &wl_buffer_interface,
> + buffer->resource = wl_client_add_object(client,
> &wl_buffer_interface, 1,
> &shm_buffer_interface,
> id, buffer);
> wl_resource_set_destructor(buffer->resource, destroy_buffer);
> @@ -204,7 +204,7 @@ shm_create_pool(struct wl_client *client, struct
> wl_resource *resource,
> }
> close(fd);
>
> - pool->resource = wl_client_add_object(client,
> &wl_shm_pool_interface,
> + pool->resource = wl_client_add_object(client,
> &wl_shm_pool_interface, 1,
> &shm_pool_interface, id,
> pool);
> if (!pool->resource)
> goto err_free;
> @@ -229,7 +229,7 @@ bind_shm(struct wl_client *client,
> {
> struct wl_resource *resource;
>
> - resource = wl_client_add_object(client, &wl_shm_interface,
> + resource = wl_client_add_object(client, &wl_shm_interface, 1,
> &shm_interface, id, data);
>
> wl_shm_send_format(resource, WL_SHM_FORMAT_ARGB8888);
> @@ -272,7 +272,7 @@ wl_shm_buffer_create(struct wl_client *client,
> buffer->pool = NULL;
>
>
> - buffer->resource = wl_client_add_object(client,
> &wl_buffer_interface,
> + buffer->resource = wl_client_add_object(client,
> &wl_buffer_interface, 1,
> &shm_buffer_interface,
> id, buffer);
> wl_resource_set_destructor(buffer->resource, destroy_buffer);
> --
> 1.8.2.1
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20130627/d3332a32/attachment-0001.html>
More information about the wayland-devel
mailing list