mirror of
https://github.com/swaywm/sway.git
synced 2026-04-16 08:21:30 -04:00
guard seat_get_focus() NULL dereferences
seat_get_focus() can return NULL when the focus stack is empty. a few call sites don't check for this and just dereference the result, which crashes sway. this happens when a client disconnects abruptly, leaving the seat with a stale has_focus flag or empty focus stack. whatever touches focus next dereferences NULL. the two confirmed crash sites were seat_set_workspace_focus and seat_set_focus_surface (coredumps below). seat_unfocus_unless_client has the same pattern so a check was added there too for safety. cannot remember how this one was triggered: ``` seat_send_unfocus () seat_set_workspace_focus () seat_set_focus () wl_signal_emit_mutable () container_begin_destroy () view_unmap () handle_unmap () wl_signal_emit_mutable () wlr_surface_unmap () destroy_xdg_toplevel () destroy_xdg_surface_role_object () destroy_xdg_surface () xdg_client_handle_resource_destroy () wl_client_destroy () ``` mouse click on empty container (clicked wallpaper, likely just after a wallpaper engine crash): ``` seat_send_unfocus () seat_set_workspace_focus () seat_set_focus () handle_button () wl_signal_emit_mutable () handle_pointer_button () handle_libinput_readable () wl_event_loop_dispatch () ``` IPC workspace switch (with noctalia workspace widget): ``` seat_send_unfocus () seat_set_workspace_focus () seat_set_focus () workspace_switch () cmd_workspace () execute_command () ipc_client_handle_command () ipc_client_handle_readable () wl_event_loop_dispatch () ``` layer surface teardown (restarted noctalia shell): ``` seat_send_unfocus () seat_set_focus_surface () seat_set_focus_layer () handle_node_destroy () wl_signal_emit_mutable () sway_scene_node_destroy () layer_surface_destroy () surface_handle_role_resource_destroy () ```
This commit is contained in:
parent
c57daaf0d1
commit
7ef26f9a92
1 changed files with 9 additions and 5 deletions
|
|
@ -1136,10 +1136,12 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n
|
|||
|
||||
if (node == NULL) {
|
||||
// Close any popups on the old focus
|
||||
if (node_is_view(last_focus)) {
|
||||
view_close_popups(last_focus->sway_container->view);
|
||||
if (last_focus) {
|
||||
if (node_is_view(last_focus)) {
|
||||
view_close_popups(last_focus->sway_container->view);
|
||||
}
|
||||
seat_send_unfocus(last_focus, seat);
|
||||
}
|
||||
seat_send_unfocus(last_focus, seat);
|
||||
sway_input_method_relay_set_focus(&seat->im_relay, NULL);
|
||||
seat->has_focus = false;
|
||||
return;
|
||||
|
|
@ -1291,7 +1293,9 @@ void seat_set_focus_surface(struct sway_seat *seat,
|
|||
struct wlr_surface *surface, bool unfocus) {
|
||||
if (seat->has_focus && unfocus) {
|
||||
struct sway_node *focus = seat_get_focus(seat);
|
||||
seat_send_unfocus(focus, seat);
|
||||
if (focus) {
|
||||
seat_send_unfocus(focus, seat);
|
||||
}
|
||||
seat->has_focus = false;
|
||||
}
|
||||
|
||||
|
|
@ -1340,7 +1344,7 @@ void seat_unfocus_unless_client(struct sway_seat *seat, struct wl_client *client
|
|||
}
|
||||
if (seat->has_focus) {
|
||||
struct sway_node *focus = seat_get_focus(seat);
|
||||
if (node_is_view(focus) && wl_resource_get_client(
|
||||
if (focus && node_is_view(focus) && wl_resource_get_client(
|
||||
focus->sway_container->view->surface->resource) != client) {
|
||||
seat_set_focus(seat, NULL);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue