From 56c036debc03cc47a24fe9c036a5ba86eb73ab54 Mon Sep 17 00:00:00 2001 From: Ryan Neph Date: Fri, 16 Feb 2024 15:38:58 -0800 Subject: [PATCH] vm_tools: sommelier: validate client global bind requests Match the default server validations of wl_registry binds provided by libwayland. BUG=b:325125144 TEST=(linux vm; Xwayland wsi) steam client, hollow knight TEST=(linux vm; Wayland wsi) vkcube, glxgears, blender 4.0 TEST=(linux vm; Xwayland wsi) vkcube, glxgears, blender 4.0, gimp 2.10 TEST=(linux vm; Wayland wsi) custom wayland client trying to bind invalid global versions -> getting fatal error as expected Change-Id: Icb0bbe2ebb2554e0f69b2c9a5428f2ce59137daa Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/5304345 Tested-by: Ryan Neph Commit-Queue: Ryan Neph Reviewed-by: Chloe Pelling Reviewed-by: Max Lee --- sommelier-display.cc | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/sommelier-display.cc b/sommelier-display.cc index 54c308c..819b536 100644 --- a/sommelier-display.cc +++ b/sommelier-display.cc @@ -26,12 +26,36 @@ static void sl_registry_bind(struct wl_client* client, break; } - assert(sl_client_supports_interface(host->ctx, client, global->interface)); - assert(&global->link != &host->ctx->globals); - assert(version != 0); - assert(global->version >= version); + // matches the behavior of libwayland's `registry_bind()` + if (!sl_client_supports_interface(host->ctx, client, global->interface)) { + wl_resource_post_error(resource, WL_DISPLAY_ERROR_IMPLEMENTATION, + "client doesn't support interface %s", interface); + } else if (&global->link == &host->ctx->globals) { + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "invalid global %s (%d)", interface, name); + } else if (strcmp(global->interface->name, interface) != 0) { + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "invalid interface for global %u: " + "have %s, wanted %s", + name, interface, global->interface->name); + } else if (version == 0) { + wl_resource_post_error( + resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "invalid version for global %s (%d): 0 is not a valid version", + interface, name); + } else if (global->version < version) { + wl_resource_post_error( + resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "invalid version for global %s (%d): have %d, wanted %d", interface, + name, global->version, version); + } else { + global->bind(client, global->data, version, id); + return; + } - global->bind(client, global->data, version, id); + // flush immediately on error before tearing down the session, otherwise + // client may never receive the descriptive error event. + wl_client_flush(client); } static const struct wl_registry_interface sl_registry_implementation = {