Skip to content

Current implementation of wayland-backend makes it difficult to use Wayland surfaces safely #870

@notgull

Description

@notgull

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions