Blame SOURCES/0098-sbus-allow-freeing-msg-through-dbus-api-when-using-t.patch

b2d430
From efb18a2688546db9c6fe7ba75b595a2fc54dff41 Mon Sep 17 00:00:00 2001
b2d430
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
b2d430
Date: Fri, 15 Jul 2016 14:50:41 +0200
b2d430
Subject: [PATCH 098/102] sbus: allow freeing msg through dbus api when using
b2d430
 talloc
b2d430
MIME-Version: 1.0
b2d430
Content-Type: text/plain; charset=UTF-8
b2d430
Content-Transfer-Encoding: 8bit
b2d430
b2d430
When a talloc-bound message was freed by removing all references
b2d430
to it with dbus_message_unref we failed to free the talloc context
b2d430
and thus leaking memory or unreferencing invalid message when
b2d430
the parent context is freed.
b2d430
b2d430
This patch allows to bound dbus message to talloc in the way that
b2d430
allows us to free the message by both talloc and dbus api.
b2d430
b2d430
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
b2d430
(cherry picked from commit 5d556f70f00c43864d8495d7caacfadf962799df)
b2d430
---
b2d430
 src/sbus/sssd_dbus_utils.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
b2d430
 1 file changed, 51 insertions(+)
b2d430
b2d430
diff --git a/src/sbus/sssd_dbus_utils.c b/src/sbus/sssd_dbus_utils.c
b2d430
index 4c33f9fd75cac2d4a56a5638982f8ecb73da8e2e..b0150e2fe7f829013677e0a4a894d1468e5b9128 100644
b2d430
--- a/src/sbus/sssd_dbus_utils.c
b2d430
+++ b/src/sbus/sssd_dbus_utils.c
b2d430
@@ -25,22 +25,52 @@
b2d430
 
b2d430
 struct sbus_talloc_msg {
b2d430
     DBusMessage *msg;
b2d430
+    dbus_int32_t data_slot;
b2d430
+    bool in_talloc_destructor;
b2d430
 };
b2d430
 
b2d430
 static int sbus_talloc_msg_destructor(struct sbus_talloc_msg *talloc_msg)
b2d430
 {
b2d430
+    talloc_msg->in_talloc_destructor = true;
b2d430
+
b2d430
     if (talloc_msg->msg == NULL) {
b2d430
         return 0;
b2d430
     }
b2d430
 
b2d430
+    /* There may exist more references to this message but this talloc
b2d430
+     * context is no longer valid. We remove dbus message data to invoke
b2d430
+     * dbus destructor now. */
b2d430
+    dbus_message_set_data(talloc_msg->msg, talloc_msg->data_slot, NULL, NULL);
b2d430
     dbus_message_unref(talloc_msg->msg);
b2d430
     return 0;
b2d430
 }
b2d430
 
b2d430
+static void sbus_msg_data_destructor(void *ctx)
b2d430
+{
b2d430
+    struct sbus_talloc_msg *talloc_msg;
b2d430
+
b2d430
+    talloc_msg = talloc_get_type(ctx, struct sbus_talloc_msg);
b2d430
+
b2d430
+    dbus_message_free_data_slot(&talloc_msg->data_slot);
b2d430
+
b2d430
+    if (!talloc_msg->in_talloc_destructor) {
b2d430
+        /* References to this message dropped to zero but through
b2d430
+         * dbus_message_unref(), not by calling talloc_free(). We need to free
b2d430
+         * the talloc context and avoid running talloc desctuctor. */
b2d430
+        talloc_set_destructor(talloc_msg, NULL);
b2d430
+        talloc_free(talloc_msg);
b2d430
+    }
b2d430
+}
b2d430
+
b2d430
 errno_t sbus_talloc_bound_message(TALLOC_CTX *mem_ctx, DBusMessage *msg)
b2d430
 {
b2d430
     struct sbus_talloc_msg *talloc_msg;
b2d430
+    dbus_int32_t data_slot = -1;
b2d430
+    DBusFreeFunction free_fn;
b2d430
+    dbus_bool_t bret;
b2d430
 
b2d430
+    /* Create a talloc context that will unreference this message when
b2d430
+     * the parent context is freed. */
b2d430
     talloc_msg = talloc(mem_ctx, struct sbus_talloc_msg);
b2d430
     if (talloc_msg == NULL) {
b2d430
         DEBUG(SSSDBG_CRIT_FAILURE,
b2d430
@@ -48,7 +78,28 @@ errno_t sbus_talloc_bound_message(TALLOC_CTX *mem_ctx, DBusMessage *msg)
b2d430
         return ENOMEM;
b2d430
     }
b2d430
 
b2d430
+    /* Allocate a dbus message data slot that will contain point to the
b2d430
+     * talloc context so we can pick up cases when the dbus message is
b2d430
+     * freed through dbus api. */
b2d430
+    bret = dbus_message_allocate_data_slot(&data_slot);
b2d430
+    if (!bret) {
b2d430
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate data slot!\n");
b2d430
+        talloc_free(talloc_msg);
b2d430
+        return ENOMEM;
b2d430
+    }
b2d430
+
b2d430
+    free_fn = sbus_msg_data_destructor;
b2d430
+    bret = dbus_message_set_data(msg, data_slot, talloc_msg, free_fn);
b2d430
+    if (!bret) {
b2d430
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set message data!\n");
b2d430
+        talloc_free(talloc_msg);
b2d430
+        dbus_message_free_data_slot(&data_slot);
b2d430
+        return ENOMEM;
b2d430
+    }
b2d430
+
b2d430
     talloc_msg->msg = msg;
b2d430
+    talloc_msg->data_slot = data_slot;
b2d430
+    talloc_msg->in_talloc_destructor = false;
b2d430
 
b2d430
     talloc_set_destructor(talloc_msg, sbus_talloc_msg_destructor);
b2d430
 
b2d430
-- 
b2d430
2.4.11
b2d430