fixes use after free caused by signal lists

A structs throughout the code use implementation specific free
functions.
When those functions are not used, they simply call free() on their
data, but this leaves around wl_signals linked into listeners.
When those listeners try to remove themself from the list, they write
into the now free memory.

This commit adds calls to remove the signals from those lists, so the
listeners can safely call wl_list_remove
This commit is contained in:
Markus Ongyerth 2017-09-08 16:02:26 +02:00
parent c59ccbde51
commit 935b6d871e
3 changed files with 7 additions and 1 deletions

View file

@ -30,7 +30,7 @@ void wlr_input_device_destroy(struct wlr_input_device *dev) {
} }
wl_signal_emit(&dev->events.destroy, dev); wl_signal_emit(&dev->events.destroy, dev);
if (dev->_device) { if (dev->_device) {
switch (dev->type) { switch (dev->type) {
case WLR_INPUT_DEVICE_KEYBOARD: case WLR_INPUT_DEVICE_KEYBOARD:
@ -58,6 +58,7 @@ void wlr_input_device_destroy(struct wlr_input_device *dev) {
if (dev->impl && dev->impl->destroy) { if (dev->impl && dev->impl->destroy) {
dev->impl->destroy(dev); dev->impl->destroy(dev);
} else { } else {
wl_list_remove(&dev->events.destroy.listener_list);
free(dev); free(dev);
} }
} }

View file

@ -14,6 +14,7 @@ void wlr_keyboard_destroy(struct wlr_keyboard *kb) {
if (kb && kb->impl && kb->impl->destroy) { if (kb && kb->impl && kb->impl->destroy) {
kb->impl->destroy(kb); kb->impl->destroy(kb);
} else { } else {
wl_list_remove(&kb->events.key.listener_list);
free(kb); free(kb);
} }
} }

View file

@ -17,6 +17,10 @@ void wlr_pointer_destroy(struct wlr_pointer *pointer) {
if (pointer && pointer->impl && pointer->impl->destroy) { if (pointer && pointer->impl && pointer->impl->destroy) {
pointer->impl->destroy(pointer); pointer->impl->destroy(pointer);
} else { } else {
wl_list_remove(&pointer->events.motion.listener_list);
wl_list_remove(&pointer->events.motion_absolute.listener_list);
wl_list_remove(&pointer->events.button.listener_list);
wl_list_remove(&pointer->events.axis.listener_list);
free(pointer); free(pointer);
} }
} }