mirror of
https://github.com/swaywm/sway.git
synced 2025-10-29 05:40:18 -04:00
server: recreate renderer in idle callback to avoid UAF
Destroying the wlr_renderer in a callback to its own renderer_lost event is unsafe due to wl_signal_emit*() still accessing it after it was destroyed. Delegate recreation of renderer to an idle callback and ensure that only one such idle callback is scheduled at a time by storing the returned event source.
This commit is contained in:
parent
ab2e1f5817
commit
240a69ad63
2 changed files with 16 additions and 3 deletions
|
|
@ -46,6 +46,7 @@ struct sway_server {
|
|||
|
||||
struct wl_listener new_output;
|
||||
struct wl_listener renderer_lost;
|
||||
struct wl_event_source *recreating_renderer;
|
||||
|
||||
struct wlr_idle_notifier_v1 *idle_notifier_v1;
|
||||
struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;
|
||||
|
|
|
|||
|
|
@ -182,11 +182,11 @@ static void detect_proprietary(struct wlr_backend *backend, void *data) {
|
|||
drmFreeVersion(version);
|
||||
}
|
||||
|
||||
static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
||||
struct sway_server *server = wl_container_of(listener, server, renderer_lost);
|
||||
static void do_renderer_recreate(void *data) {
|
||||
struct sway_server *server = data;
|
||||
server->recreating_renderer = NULL;
|
||||
|
||||
sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
|
||||
|
||||
struct wlr_renderer *renderer = wlr_renderer_autocreate(server->backend);
|
||||
if (renderer == NULL) {
|
||||
sway_log(SWAY_ERROR, "Unable to create renderer");
|
||||
|
|
@ -221,6 +221,18 @@ static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
|||
wlr_renderer_destroy(old_renderer);
|
||||
}
|
||||
|
||||
static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
||||
struct sway_server *server = wl_container_of(listener, server, renderer_lost);
|
||||
|
||||
if (server->recreating_renderer != NULL) {
|
||||
sway_log(SWAY_DEBUG, "Re-creation of renderer already scheduled");
|
||||
return;
|
||||
}
|
||||
|
||||
sway_log(SWAY_INFO, "Scheduling re-creation of renderer after GPU reset");
|
||||
server->recreating_renderer = wl_event_loop_add_idle(server->wl_event_loop, do_renderer_recreate, server);
|
||||
}
|
||||
|
||||
bool server_init(struct sway_server *server) {
|
||||
sway_log(SWAY_DEBUG, "Initializing Wayland server");
|
||||
server->wl_display = wl_display_create();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue