xwayland: Fix some memory leaks on compositor shutdown path

While exiting, on the shutdown compositor path, for instance if we don't have
permission access to create a lock file we will end up reporting some memory
leaks/use-after-free.

This patch addresses of all them:

- api->listen returns NULL and we do not property free wet_xwayland
  struct
- we don't remove the signal handler causing a use-after-free (signal
  handler gets called by the main object has been freed)
- we don't remove/destroy the debug scope causing a mem-leak
- on the same path check for valid event source to avoid deref invalid
  pointers.

Add a simple wrapper which we can call in other call sites.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
This commit is contained in:
Marius Vlad 2025-12-09 16:12:52 +02:00 committed by Pekka Paalanen
parent 119ce40714
commit 582ae5385b
2 changed files with 21 additions and 11 deletions

View file

@ -260,8 +260,10 @@ wet_load_xwayland(struct weston_compositor *comp)
wxw->compositor = comp; wxw->compositor = comp;
wxw->api = api; wxw->api = api;
wxw->xwayland = xwayland; wxw->xwayland = xwayland;
if (api->listen(xwayland, wxw, spawn_xserver) < 0) if (api->listen(xwayland, wxw, spawn_xserver) < 0) {
free(wxw);
return NULL; return NULL;
}
return wxw; return wxw;
} }

View file

@ -86,8 +86,10 @@ weston_xserver_shutdown(struct weston_xserver *wxs)
wl_client_destroy(wxs->client); wl_client_destroy(wxs->client);
wxs->client = NULL; wxs->client = NULL;
} else { } else {
wl_event_source_remove(wxs->abstract_source); if (wxs->abstract_source)
wl_event_source_remove(wxs->unix_source); wl_event_source_remove(wxs->abstract_source);
if (wxs->unix_source)
wl_event_source_remove(wxs->unix_source);
} }
close(wxs->abstract_fd); close(wxs->abstract_fd);
close(wxs->unix_fd); close(wxs->unix_fd);
@ -233,11 +235,8 @@ create_lockfile(int display, char *lockfile, size_t lsize)
} }
static void static void
weston_xserver_destroy(struct wl_listener *l, void *data) weston_xserver_destroy(struct weston_xserver *wxs)
{ {
struct weston_xserver *wxs =
container_of(l, struct weston_xserver, compositor_destroy_listener);
wl_list_remove(&wxs->compositor_destroy_listener.link); wl_list_remove(&wxs->compositor_destroy_listener.link);
if (wxs->loop) if (wxs->loop)
@ -248,6 +247,15 @@ weston_xserver_destroy(struct wl_listener *l, void *data)
free(wxs); free(wxs);
} }
static void
weston_xserver_destroy_handler(struct wl_listener *l, void *data)
{
struct weston_xserver *wxs =
container_of(l, struct weston_xserver, compositor_destroy_listener);
weston_xserver_destroy(wxs);
}
static struct weston_xwayland * static struct weston_xwayland *
weston_xwayland_get(struct weston_compositor *compositor) weston_xwayland_get(struct weston_compositor *compositor)
{ {
@ -255,7 +263,7 @@ weston_xwayland_get(struct weston_compositor *compositor)
struct weston_xserver *wxs; struct weston_xserver *wxs;
listener = wl_signal_get(&compositor->destroy_signal, listener = wl_signal_get(&compositor->destroy_signal,
weston_xserver_destroy); weston_xserver_destroy_handler);
if (!listener) if (!listener)
return NULL; return NULL;
@ -281,7 +289,7 @@ retry:
wxs->display++; wxs->display++;
goto retry; goto retry;
} else { } else {
free(wxs); weston_xserver_destroy(wxs);
return -1; return -1;
} }
} }
@ -297,7 +305,7 @@ retry:
if (wxs->unix_fd < 0) { if (wxs->unix_fd < 0) {
unlink(lockfile); unlink(lockfile);
close(wxs->abstract_fd); close(wxs->abstract_fd);
free(wxs); weston_xserver_destroy(wxs);
return -1; return -1;
} }
@ -380,7 +388,7 @@ weston_module_init(struct weston_compositor *compositor)
if (!weston_compositor_add_destroy_listener_once(compositor, if (!weston_compositor_add_destroy_listener_once(compositor,
&wxs->compositor_destroy_listener, &wxs->compositor_destroy_listener,
weston_xserver_destroy)) { weston_xserver_destroy_handler)) {
free(wxs); free(wxs);
return 0; return 0;
} }