Prevent use-after-free on destroying unmapped views

Prior to this commit view->workspace was set on view creation. If
the output containing this view was subsequently destroyed,
the workspace was freed leading to a use-after-free when the
view was destroyed.
This commit is contained in:
project-repo 2020-10-09 13:13:31 +02:00
commit edceb0218d
5 changed files with 33 additions and 29 deletions

2
seat.c
View file

@ -53,7 +53,7 @@ static bool
view_at(const struct cg_view *view, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
struct wlr_box *output_layout_box = wlr_output_layout_get_box(
view->workspace->output->server->output_layout,
view->server->output_layout,
view->workspace->output->wlr_output);
double view_sx = lx - view->ox - output_layout_box->x;

33
view.c
View file

@ -281,6 +281,10 @@ view_for_each_popup(struct cg_view *view, wlr_surface_iterator_func_t iterator,
void
view_unmap(struct cg_view *view) {
/* If the view is not mapped, do nothing */
if(view->wlr_surface == NULL) {
return;
}
#if CG_HAS_XWAYLAND
if((view->type != CG_XWAYLAND_VIEW || xwayland_view_should_manage(view)))
#endif
@ -290,14 +294,14 @@ view_unmap(struct cg_view *view) {
struct cg_view *prev = view_get_prev_view(view);
wlr_output_damage_add_box(view_tile->workspace->output->damage,
&view_tile->tile);
if(view == view->workspace->server->seat->focused_view) {
seat_set_focus(view->workspace->server->seat, prev);
} else if(view->workspace->server->seat->seat->keyboard_state
if(view == view->server->seat->focused_view) {
seat_set_focus(view->server->seat, prev);
} else if(view->server->seat->seat->keyboard_state
.focused_surface == view->wlr_surface) {
wlr_seat_keyboard_clear_focus(
view->workspace->server->seat->seat);
seat_set_focus(view->workspace->server->seat,
view->workspace->server->seat->focused_view);
view->server->seat->seat);
seat_set_focus(view->server->seat,
view->server->seat->focused_view);
} else {
view_tile->view = prev;
if(prev != NULL) {
@ -309,12 +313,12 @@ view_unmap(struct cg_view *view) {
#if CG_HAS_XWAYLAND
else {
view_damage_whole(view);
if(view->workspace->server->seat->seat->keyboard_state
if(view->server->seat->seat->keyboard_state
.focused_surface == NULL ||
view->workspace->server->seat->seat->keyboard_state
view->server->seat->seat->keyboard_state
.focused_surface == view->wlr_surface) {
seat_set_focus(view->workspace->server->seat,
view->workspace->server->seat->focused_view);
seat_set_focus(view->server->seat,
view->server->seat->focused_view);
}
}
#endif
@ -363,7 +367,7 @@ view_map(struct cg_view *view, struct wlr_surface *surface,
void
view_destroy(struct cg_view *view) {
struct cg_output *curr_output = view->workspace->server->curr_output;
struct cg_output *curr_output = view->server->curr_output;
if(view->wlr_surface != NULL) {
view_unmap(view);
}
@ -375,9 +379,10 @@ view_destroy(struct cg_view *view) {
}
void
view_init(struct cg_view *view, struct cg_workspace *ws, enum cg_view_type type,
const struct cg_view_impl *impl) {
view->workspace = ws;
view_init(struct cg_view *view, enum cg_view_type type,
const struct cg_view_impl *impl,struct cg_server *server) {
view->workspace = NULL;
view->server=server;
view->type = type;
view->impl = impl;

5
view.h
View file

@ -19,6 +19,7 @@ enum cg_view_type {
struct cg_view {
struct cg_workspace *workspace;
struct cg_server *server;
struct wl_list link; // server::views
struct wl_list children; // cg_view_child::link
struct wlr_surface *wlr_surface;
@ -106,8 +107,8 @@ view_map(struct cg_view *view, struct wlr_surface *surface,
void
view_destroy(struct cg_view *view);
void
view_init(struct cg_view *view, struct cg_workspace *ws, enum cg_view_type type,
const struct cg_view_impl *impl);
view_init(struct cg_view *view, enum cg_view_type type,
const struct cg_view_impl *impl, struct cg_server *server);
struct wlr_surface *
view_wlr_surface_at(const struct cg_view *view, double sx, double sy,

View file

@ -103,7 +103,7 @@ popup_unconstrain(struct cg_xdg_popup *popup) {
struct wlr_box *popup_box = &popup->wlr_popup->geometry;
struct wlr_output_layout *output_layout =
view->workspace->output->server->output_layout;
view->server->output_layout;
struct wlr_box *view_output_box = wlr_output_layout_get_box(
output_layout, view->workspace->output->wlr_output);
struct wlr_output *wlr_output = wlr_output_layout_output_at(
@ -297,11 +297,13 @@ handle_xdg_shell_surface_map(struct wl_listener *listener, void *_data) {
xdg_shell_view->commit.notify = handle_xdg_shell_surface_commit;
wl_signal_add(&xdg_shell_view->xdg_surface->surface->events.commit,
&xdg_shell_view->commit);
xdg_shell_view->new_popup.notify = handle_new_xdg_popup;
wl_signal_add(&xdg_shell_view->xdg_surface->events.new_popup, &xdg_shell_view->new_popup);
view_map(
view, xdg_shell_view->xdg_surface->surface,
view->workspace->server->curr_output
->workspaces[view->workspace->server->curr_output->curr_workspace]);
view->server->curr_output
->workspaces[view->server->curr_output->curr_workspace]);
view_damage_whole(view);
}
@ -352,8 +354,7 @@ handle_xdg_shell_surface_new(struct wl_listener *listener, void *data) {
}
view_init(
&xdg_shell_view->view,
server->curr_output->workspaces[server->curr_output->curr_workspace],
CG_XDG_SHELL_VIEW, &xdg_shell_view_impl);
CG_XDG_SHELL_VIEW, &xdg_shell_view_impl,server);
xdg_shell_view->xdg_surface = xdg_surface;
@ -367,8 +368,6 @@ handle_xdg_shell_surface_new(struct wl_listener *listener, void *data) {
handle_xdg_shell_surface_request_fullscreen;
wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen,
&xdg_shell_view->request_fullscreen);
xdg_shell_view->new_popup.notify = handle_new_xdg_popup;
wl_signal_add(&xdg_surface->events.new_popup, &xdg_shell_view->new_popup);
}
void

View file

@ -83,7 +83,7 @@ maximize(struct cg_view *view, int width, int height) {
struct cg_output *output = view->workspace->output;
struct wlr_box *box =
wlr_output_layout_get_box(view->workspace->server->output_layout,
wlr_output_layout_get_box(view->server->output_layout,
view->workspace->output->wlr_output);
struct wlr_xwayland_surface_size_hints *hints =
xwayland_view->xwayland_surface->size_hints;
@ -190,8 +190,8 @@ handle_xwayland_surface_map(struct wl_listener *listener, void *_data) {
view_map(
view, xwayland_view->xwayland_surface->surface,
view->workspace->server->curr_output
->workspaces[view->workspace->server->curr_output->curr_workspace]);
view->server->curr_output
->workspaces[view->server->curr_output->curr_workspace]);
view_damage_whole(view);
}
@ -240,8 +240,7 @@ handle_xwayland_surface_new(struct wl_listener *listener, void *data) {
view_init(
&xwayland_view->view,
server->curr_output->workspaces[server->curr_output->curr_workspace],
CG_XWAYLAND_VIEW, &xwayland_view_impl);
CG_XWAYLAND_VIEW, &xwayland_view_impl,server);
xwayland_view->xwayland_surface = xwayland_surface;
xwayland_view->map.notify = handle_xwayland_surface_map;