aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Ongyerth <ongy@ongy.net>2017-09-08 16:02:26 +0200
committerMarkus Ongyerth <ongy@ongy.net>2017-09-08 16:02:26 +0200
commit935b6d871e8e384c52c1c0077def06bd767d4361 (patch)
tree5369476aa44d1c8048213ef895edc9be4b83a746
parentc59ccbde518ac173fffe8aba16ad9c5b703f7e2a (diff)
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
-rw-r--r--types/wlr_input_device.c3
-rw-r--r--types/wlr_keyboard.c1
-rw-r--r--types/wlr_pointer.c4
3 files changed, 7 insertions, 1 deletions
diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c
index 002c2b54..7015dcba 100644
--- a/types/wlr_input_device.c
+++ b/types/wlr_input_device.c
@@ -30,7 +30,7 @@ void wlr_input_device_destroy(struct wlr_input_device *dev) {
}
wl_signal_emit(&dev->events.destroy, dev);
-
+
if (dev->_device) {
switch (dev->type) {
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) {
dev->impl->destroy(dev);
} else {
+ wl_list_remove(&dev->events.destroy.listener_list);
free(dev);
}
}
diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c
index 02b3842d..f20d2a73 100644
--- a/types/wlr_keyboard.c
+++ b/types/wlr_keyboard.c
@@ -14,6 +14,7 @@ void wlr_keyboard_destroy(struct wlr_keyboard *kb) {
if (kb && kb->impl && kb->impl->destroy) {
kb->impl->destroy(kb);
} else {
+ wl_list_remove(&kb->events.key.listener_list);
free(kb);
}
}
diff --git a/types/wlr_pointer.c b/types/wlr_pointer.c
index 74856762..04100e56 100644
--- a/types/wlr_pointer.c
+++ b/types/wlr_pointer.c
@@ -17,6 +17,10 @@ void wlr_pointer_destroy(struct wlr_pointer *pointer) {
if (pointer && pointer->impl && pointer->impl->destroy) {
pointer->impl->destroy(pointer);
} 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);
}
}