Realized this issue while discussing rust-windowing/raw-window-handle#182
ObjectId is effectively a weak pointer to an underlying wl_proxy. However, it's unique in that any existing ObjectId can destroy the underlying wl_proxy, invalidating it for any other object ID. For example:
use winit_wayland::Window;
let window: Window = /* ... */;
// We can arbitrarily destroy the surface.
window.surface().destroy();
window.set_fullscreen(None); /* Will panic with `InvalidId` */
Internally, this is kept safe by the fact that an ObjectId cannot actually be used to send requests if the underlying object is invalid; it keeps track of whether destroy() has been called and, if it has, returns an error when a request attempts to be marshalled.
However, for the underlying proxy, we need to pass the pointer to other APIs that do not know of wayland-backend, like EGL. If the proxy is destroyed while the EGL object still exists, it will cause a use-after-free.
let window: Arc<Window> = Arc::new(/* ... */);
let egl: glutin::api::egl::Surface = Surface::new(window.clone()); /* Simplified. */
window.surface().destroy();
egl.swap_buffers(); /* EGL doesn't know the pointer is invalid, use-after-free occurs here! */
It seems to me that in this case it is on the onus of the graphics API to ensure that the WlSurface is valid before continuing to do anything with it. If this is true, then both glutin and wgpu are implementing the Wayland window incorrectly, and all windowing calls need to be guarded before being called.
Realized this issue while discussing rust-windowing/raw-window-handle#182
ObjectIdis effectively a weak pointer to an underlyingwl_proxy. However, it's unique in that any existingObjectIdcan destroy the underlyingwl_proxy, invalidating it for any other object ID. For example:Internally, this is kept safe by the fact that an
ObjectIdcannot actually be used to send requests if the underlying object is invalid; it keeps track of whetherdestroy()has been called and, if it has, returns an error when a request attempts to be marshalled.However, for the underlying proxy, we need to pass the pointer to other APIs that do not know of
wayland-backend, like EGL. If the proxy is destroyed while the EGL object still exists, it will cause a use-after-free.It seems to me that in this case it is on the onus of the graphics API to ensure that the
WlSurfaceis valid before continuing to do anything with it. If this is true, then bothglutinandwgpuare implementing the Wayland window incorrectly, and all windowing calls need to be guarded before being called.