[PATCH 1/3 v3] wayland-server: Add API to control globals visibility

Giulio Camuffo giuliocamuffo at gmail.com
Mon Aug 8 08:53:13 UTC 2016


Hi,

this looks like a nice way to implement restricted interfaces... i
just wonder, would we need to revoke allowed interfaces? How would
this approach allow that?
Also, this still doesn't prevent a client from binding an interface if
it knows the name and id. Do we care?

2016-08-08 10:10 GMT+02:00 Olivier Fourdan <ofourdan at redhat.com>:
> Add a new API to let compositor decide whether or not a wl_global
> should be advertised to the clients via wl_registry_bind() or
> display_get_registry()
>
> By using its own filter, the compositor can decide which wl_global would
> be listed to clients.
>
> Compositors can use this mechanism to hide their own private interfaces
> that regular clients should not use.
>
> Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
> ---
>  v2: Follow-up on Jonas' comments on v1:
>      Add global's data as user data in callback filter function
>      Pass wl_global instead of wl_interface in callback filter function
>      Add wl_global_get_interface() to retrieve the wl_interface from the
>      given wl_global
>      Post an error if a client tries to bind a global which is filtered
>      out.
>  v3: Follow-up on Jonas' comments on v2:
>      Separate from the other wl_global and test additions
>      Add its own user data to the global filter
>      Rephrase the API doc
>      Other few small changes
>
>  src/wayland-server-core.h | 10 ++++++++
>  src/wayland-server.c      | 62 +++++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 67 insertions(+), 5 deletions(-)
>
> diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h
> index ad1292f..b70d85f 100644
> --- a/src/wayland-server-core.h
> +++ b/src/wayland-server-core.h
> @@ -28,6 +28,7 @@
>
>  #include <sys/types.h>
>  #include <stdint.h>
> +#include <stdbool.h>
>  #include "wayland-util.h"
>  #include "wayland-version.h"
>
> @@ -164,6 +165,15 @@ wl_global_create(struct wl_display *display,
>  void
>  wl_global_destroy(struct wl_global *global);
>
> +typedef bool (*wl_display_filter_global_func_t)(const struct wl_client *client,
> +                                               const struct wl_global *global,
> +                                               void *data);
> +
> +void
> +wl_display_set_filter_global(struct wl_display *display,
> +                            wl_display_filter_global_func_t filter,
> +                            void *data);
> +
>  struct wl_client *
>  wl_client_create(struct wl_display *display, int fd);
>
> diff --git a/src/wayland-server.c b/src/wayland-server.c
> index 19aa2e8..480af23 100644
> --- a/src/wayland-server.c
> +++ b/src/wayland-server.c
> @@ -98,6 +98,9 @@ struct wl_display {
>         struct wl_signal destroy_signal;
>
>         struct wl_array additional_shm_formats;
> +
> +       wl_display_filter_global_func_t global_filter;
> +       void *global_filter_data;
>  };
>
>  struct wl_global {
> @@ -714,6 +717,16 @@ wl_client_destroy(struct wl_client *client)
>         free(client);
>  }
>
> +static bool
> +filter_global(const struct wl_client *client,
> +             const struct wl_global *global)
> +{
> +       struct wl_display *display = client->display;
> +
> +       return (display->global_filter == NULL ||
> +               display->global_filter(client, global, display->global_filter_data));
> +}
> +
>  static void
>  registry_bind(struct wl_client *client,
>               struct wl_resource *resource, uint32_t name,
> @@ -740,6 +753,10 @@ registry_bind(struct wl_client *client,
>                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
>                                        "invalid version for global %s (%d): have %d, wanted %d",
>                                        interface, name, global->version, version);
> +       else if (!filter_global(client, global))
> +               wl_resource_post_error(resource,
> +                                      WL_DISPLAY_ERROR_INVALID_OBJECT,
> +                                      "invalid global %s (%d)", interface, name);
>         else
>                 global->bind(client, global->data, version, id);
>  }
> @@ -795,11 +812,12 @@ display_get_registry(struct wl_client *client,
>                        &registry_resource->link);
>
>         wl_list_for_each(global, &display->global_list, link)
> -               wl_resource_post_event(registry_resource,
> -                                      WL_REGISTRY_GLOBAL,
> -                                      global->name,
> -                                      global->interface->name,
> -                                      global->version);
> +               if (filter_global(client, global))
> +                       wl_resource_post_event(registry_resource,
> +                                              WL_REGISTRY_GLOBAL,
> +                                              global->name,
> +                                              global->interface->name,
> +                                              global->version);
>  }
>
>  static const struct wl_display_interface display_interface = {
> @@ -868,6 +886,9 @@ wl_display_create(void)
>         display->id = 1;
>         display->serial = 0;
>
> +       display->global_filter = NULL;
> +       display->global_filter_data = NULL;
> +
>         wl_array_init(&display->additional_shm_formats);
>
>         return display;
> @@ -940,6 +961,37 @@ wl_display_destroy(struct wl_display *display)
>         free(display);
>  }
>
> +/** Set a filter function for global objects
> + *
> + * \param display The Wayland display object.
> + * \param filter  The global filter funtion.
> + * \param data User data to be associated with the global filter.
> + * \return None.
> + *
> + * Set a filter for the wl_display to advertise or hide global objects
> + * to clients.
> + * The set filter will be used during wl_global advertisment to
> + * determine whether a global object should be advertised to a
> + * given client, and during wl_global binding to determine whether
> + * a given client should be allowed to bind to a global.
> + *
> + * Clients that try to bind to a global that was filtered out will
> + * have an error raised.
> + *
> + * Setting the filter NULL will result in all globals being
> + * advertised to all clients. The default is no filter.
> + *
> + * \memberof wl_display
> + */
> +WL_EXPORT void
> +wl_display_set_filter_global(struct wl_display *display,
> +                            wl_display_filter_global_func_t filter,
> +                            void *data)
> +{
> +       display->global_filter = filter;
> +       display->global_filter_data = data;
> +}
> +
>  WL_EXPORT struct wl_global *
>  wl_global_create(struct wl_display *display,
>                  const struct wl_interface *interface, int version,
> --
> 2.7.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list