|
|
f35488 |
From f845355e32127c5e8f2bf700cdaa5b8721804232 Mon Sep 17 00:00:00 2001
|
|
|
f35488 |
From: Alexey Tikhonov <atikhono@redhat.com>
|
|
|
f35488 |
Date: Fri, 8 Nov 2019 20:01:50 +0100
|
|
|
f35488 |
Subject: [PATCH] SBUS: defer deallocation of sbus_watch_ctx
|
|
|
f35488 |
MIME-Version: 1.0
|
|
|
f35488 |
Content-Type: text/plain; charset=UTF-8
|
|
|
f35488 |
Content-Transfer-Encoding: 8bit
|
|
|
f35488 |
|
|
|
f35488 |
The following flow was causing use-after-free error:
|
|
|
f35488 |
tevent_common_invoke_fd_handler(RW) -> sbus_watch_handler(RW) ->
|
|
|
f35488 |
dbus_watch_handle(R) -> ...libdbus detects connection is closed... ->
|
|
|
f35488 |
sbus_remove_watch() -> talloc_free(watch) ->
|
|
|
f35488 |
... get back to libdbus and back to sbus_watch_handler() ->
|
|
|
f35488 |
"if (watch->dbus_write_watch) dbus_watch_handle(W)" => use-after-free
|
|
|
f35488 |
|
|
|
f35488 |
To resolve an issue schedule deallocation of watch as immediate event.
|
|
|
f35488 |
|
|
|
f35488 |
Resolves: https://pagure.io/SSSD/sssd/issue/2660
|
|
|
f35488 |
|
|
|
f35488 |
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
|
|
f35488 |
---
|
|
|
f35488 |
src/sbus/sssd_dbus_common.c | 24 +++++++++++++++++++++++-
|
|
|
f35488 |
src/sbus/sssd_dbus_private.h | 1 +
|
|
|
f35488 |
2 files changed, 24 insertions(+), 1 deletion(-)
|
|
|
f35488 |
|
|
|
f35488 |
diff --git a/src/sbus/sssd_dbus_common.c b/src/sbus/sssd_dbus_common.c
|
|
|
f35488 |
index 50100320a..dbdcae9ec 100644
|
|
|
f35488 |
--- a/src/sbus/sssd_dbus_common.c
|
|
|
f35488 |
+++ b/src/sbus/sssd_dbus_common.c
|
|
|
f35488 |
@@ -133,6 +133,12 @@ dbus_bool_t sbus_add_watch(DBusWatch *dbus_watch, void *data)
|
|
|
f35488 |
DEBUG(SSSDBG_FATAL_FAILURE, "Out of Memory!\n");
|
|
|
f35488 |
return FALSE;
|
|
|
f35488 |
}
|
|
|
f35488 |
+ watch->im_event = tevent_create_immediate(watch);
|
|
|
f35488 |
+ if (watch->im_event == NULL) {
|
|
|
f35488 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of Memory!\n");
|
|
|
f35488 |
+ talloc_free(watch);
|
|
|
f35488 |
+ return FALSE;
|
|
|
f35488 |
+ }
|
|
|
f35488 |
watch->conn = conn;
|
|
|
f35488 |
watch->fd = fd;
|
|
|
f35488 |
}
|
|
|
f35488 |
@@ -243,6 +249,13 @@ void sbus_toggle_watch(DBusWatch *dbus_watch, void *data)
|
|
|
f35488 |
enabled?"enabled":"disabled");
|
|
|
f35488 |
}
|
|
|
f35488 |
|
|
|
f35488 |
+static void free_sbus_watch(struct tevent_context *ev,
|
|
|
f35488 |
+ struct tevent_immediate *im,
|
|
|
f35488 |
+ void *data)
|
|
|
f35488 |
+{
|
|
|
f35488 |
+ struct sbus_watch_ctx *w = talloc_get_type(data, struct sbus_watch_ctx);
|
|
|
f35488 |
+ talloc_free(w); /* this will free attached 'im' as well */
|
|
|
f35488 |
+}
|
|
|
f35488 |
/*
|
|
|
f35488 |
* sbus_remove_watch
|
|
|
f35488 |
* Hook for D-BUS to remove file descriptor-based events
|
|
|
f35488 |
@@ -274,7 +287,16 @@ void sbus_remove_watch(DBusWatch *dbus_watch, void *data)
|
|
|
f35488 |
watch->dbus_write_watch = NULL;
|
|
|
f35488 |
}
|
|
|
f35488 |
if (!watch->dbus_read_watch && !watch->dbus_write_watch) {
|
|
|
f35488 |
- talloc_free(watch);
|
|
|
f35488 |
+ /* libdus doesn't need this watch{fd} anymore, so associated
|
|
|
f35488 |
+ * tevent_fd should be removed from monitoring at the spot.
|
|
|
f35488 |
+ */
|
|
|
f35488 |
+ talloc_zfree(watch->fde);
|
|
|
f35488 |
+ /* watch itself can't be freed yet as it still may be referenced
|
|
|
f35488 |
+ * in the current context (for example in sbus_watch_handler())
|
|
|
f35488 |
+ * so instead schedule immediate event to delete it.
|
|
|
f35488 |
+ */
|
|
|
f35488 |
+ tevent_schedule_immediate(watch->im_event, watch->conn->ev,
|
|
|
f35488 |
+ free_sbus_watch, watch);
|
|
|
f35488 |
}
|
|
|
f35488 |
}
|
|
|
f35488 |
|
|
|
f35488 |
diff --git a/src/sbus/sssd_dbus_private.h b/src/sbus/sssd_dbus_private.h
|
|
|
f35488 |
index a3d4bae16..92649f113 100644
|
|
|
f35488 |
--- a/src/sbus/sssd_dbus_private.h
|
|
|
f35488 |
+++ b/src/sbus/sssd_dbus_private.h
|
|
|
f35488 |
@@ -88,6 +88,7 @@ struct sbus_watch_ctx {
|
|
|
f35488 |
|
|
|
f35488 |
struct tevent_fd *fde;
|
|
|
f35488 |
int fd;
|
|
|
f35488 |
+ struct tevent_immediate *im_event;
|
|
|
f35488 |
|
|
|
f35488 |
DBusWatch *dbus_read_watch;
|
|
|
f35488 |
DBusWatch *dbus_write_watch;
|
|
|
f35488 |
--
|
|
|
f35488 |
2.21.1
|
|
|
f35488 |
|