Prepare master for new framework integration
[AGL/meta-agl.git] / meta-app-framework / recipes-core / dbus-cynagora / dbus-cynagora / 0003-Handle-unavailability-of-policy-results-for-broadcas.patch
diff --git a/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0003-Handle-unavailability-of-policy-results-for-broadcas.patch b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0003-Handle-unavailability-of-policy-results-for-broadcas.patch
deleted file mode 100644 (file)
index 7d89a74..0000000
+++ /dev/null
@@ -1,1095 +0,0 @@
-From 9d39aa9dd55680529d721a0389ce9ef579bb669a Mon Sep 17 00:00:00 2001
-From: Jacek Bukarewicz <j.bukarewicz@samsung.com>
-Date: Fri, 28 Nov 2014 12:39:33 +0100
-Subject: [PATCH 3/8] Handle unavailability of policy results for broadcasts
- and receive rules
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When message is sent to the addressed recipient and receive rule
-result is unavailable we don't want to block the sender
-as it most likely will be the privileged service, so instead we queue
-it at the recipient. Any further messages sent to it will be queued to
-maintain message order. Once the answer from Cynara arrives messages are
-dispatched from the recipient queue. In such case full dispatch is
-performed - messages are sent to addressed recipient and other
-interested connections.
-Messages sent to non-addressed recipients (eavesdroppers or broadcast
-message recipients) are handled in a similar way. The difference is
-that it is not full dispatch meaning message is sent to a single recipient.
-
-Cherry picked from 1e231194610892dd4360224998d91336097b05a1 by Jose Bollo
-
-Updated for dbus 1.10.20 by Scott Murray and José Bollo
-
-Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-Signed-off-by: Scott Murray <scott.murray@konsulko.com>
----
- bus/activation.c |   4 +-
- bus/bus.c        |  50 ++++++--
- bus/bus.h        |  19 +++
- bus/check.c      | 307 +++++++++++++++++++++++++++++++++++++++++++++++
- bus/check.h      |  25 ++++
- bus/connection.c | 168 ++++++++++++++++++++++++--
- bus/connection.h |  19 ++-
- bus/dispatch.c   | 115 +++++++++++++++---
- bus/dispatch.h   |  11 +-
- bus/driver.c     |   2 +-
- bus/policy.c     |   6 +
- 11 files changed, 683 insertions(+), 43 deletions(-)
-
-diff --git a/bus/activation.c b/bus/activation.c
-index 8301b59..d4b597c 100644
---- a/bus/activation.c
-+++ b/bus/activation.c
-@@ -1259,7 +1259,7 @@ bus_activation_send_pending_auto_activation_messages (BusActivation  *activation
-           res = bus_dispatch_matches (transaction,
-                                       entry->connection,
-                                       addressed_recipient,
--                                      entry->activation_message, &error);
-+                                      entry->activation_message, NULL, &error);
-           if (res == BUS_RESULT_FALSE)
-             {
-               /* If permission is denied, we just want to return the error
-@@ -2140,7 +2140,7 @@ bus_activation_activate_service (BusActivation  *activation,
-                                bus_connection_get_loginfo (connection));
-               /* Wonderful, systemd is connected, let's just send the msg */
-               res = bus_dispatch_matches (activation_transaction, NULL,
--                                             systemd, message, error);
-+                                             systemd, message, NULL, error);
-               if (res == BUS_RESULT_TRUE)
-                 retval = TRUE;
-diff --git a/bus/bus.c b/bus/bus.c
-index 6fc45d0..0aa700b 100644
---- a/bus/bus.c
-+++ b/bus/bus.c
-@@ -1800,17 +1800,9 @@ bus_context_check_security_policy (BusContext     *context,
-     }
-   /* See if limits on size have been exceeded */
--  if (proposed_recipient &&
--      ((dbus_connection_get_outgoing_size (proposed_recipient) > context->limits.max_outgoing_bytes) ||
--       (dbus_connection_get_outgoing_unix_fds (proposed_recipient) > context->limits.max_outgoing_unix_fds)))
--    {
--      complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED,
--          "Rejected: destination has a full message queue",
--          0, message, sender, proposed_recipient, requested_reply, TRUE, NULL,
--          error);
--      _dbus_verbose ("security policy disallowing message due to full message queue\n");
-+  if (!bus_context_check_recipient_message_limits(context, proposed_recipient, sender, message,
-+      requested_reply, error))
-       return BUS_RESULT_FALSE;
--    }
-   /* Record that we will allow a reply here in the future (don't
-    * bother if the recipient is the bus or this is an eavesdropping
-@@ -1869,3 +1861,41 @@ bus_context_check_all_watches (BusContext *context)
-       _dbus_server_toggle_all_watches (server, enabled);
-     }
- }
-+
-+void
-+bus_context_complain_about_message (BusContext     *context,
-+                                    const char     *error_name,
-+                                    const char     *complaint,
-+                                    int             matched_rules,
-+                                    DBusMessage    *message,
-+                                    DBusConnection *sender,
-+                                    DBusConnection *proposed_recipient,
-+                                    dbus_bool_t     requested_reply,
-+                                    dbus_bool_t     log,
-+                                    const char     *privilege,
-+                                    DBusError      *error)
-+{
-+  complain_about_message(context, error_name, complaint, matched_rules, message, sender,
-+      proposed_recipient, requested_reply, log, privilege, error);
-+}
-+
-+dbus_bool_t bus_context_check_recipient_message_limits (BusContext *context,
-+                                                        DBusConnection *recipient,
-+                                                        DBusConnection *sender,
-+                                                        DBusMessage *message,
-+                                                        dbus_bool_t requested_reply,
-+                                                        DBusError *error)
-+{
-+  if (recipient &&
-+       ((dbus_connection_get_outgoing_size (recipient) > context->limits.max_outgoing_bytes) ||
-+        (dbus_connection_get_outgoing_unix_fds (recipient) > context->limits.max_outgoing_unix_fds)))
-+     {
-+       complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED,
-+           "Rejected: destination has a full message queue",
-+           0, message, sender, recipient, requested_reply, TRUE, NULL,
-+           error);
-+       _dbus_verbose ("security policy disallowing message due to full message queue\n");
-+       return FALSE;
-+     }
-+  return TRUE;
-+}
-diff --git a/bus/bus.h b/bus/bus.h
-index 82c32c8..1b08f7c 100644
---- a/bus/bus.h
-+++ b/bus/bus.h
-@@ -164,4 +164,23 @@ BusResult         bus_context_check_security_policy              (BusContext
-                                                                   BusDeferredMessage **deferred_message);
- void              bus_context_check_all_watches                  (BusContext       *context);
-+dbus_bool_t       bus_context_check_recipient_message_limits     (BusContext *context,
-+                                                                  DBusConnection *recipient,
-+                                                                  DBusConnection *sender,
-+                                                                  DBusMessage *message,
-+                                                                  dbus_bool_t requested_reply,
-+                                                                  DBusError *error);
-+void              bus_context_complain_about_message             (BusContext     *context,
-+                                                                  const char     *error_name,
-+                                                                  const char     *complaint,
-+                                                                  int             matched_rules,
-+                                                                  DBusMessage    *message,
-+                                                                  DBusConnection *sender,
-+                                                                  DBusConnection *proposed_recipient,
-+                                                                  dbus_bool_t     requested_reply,
-+                                                                  dbus_bool_t     log,
-+                                                                  const char     *privilege,
-+                                                                  DBusError      *error);
-+
-+
- #endif /* BUS_BUS_H */
-diff --git a/bus/check.c b/bus/check.c
-index 4b8a699..f3d283f 100644
---- a/bus/check.c
-+++ b/bus/check.c
-@@ -49,6 +49,9 @@ typedef struct BusDeferredMessage
-   DBusConnection *sender;
-   DBusConnection *proposed_recipient;
-   DBusConnection *addressed_recipient;
-+  dbus_bool_t requested_reply;
-+  int matched_rules;
-+  const char *privilege;
-   dbus_bool_t full_dispatch;
-   BusDeferredMessageStatus status;
-   BusResult response;
-@@ -135,6 +138,89 @@ bus_check_enable_dispatch_callback (BusDeferredMessage *deferred_message,
-   _dbus_connection_enable_dispatch(deferred_message->sender);
- }
-+static void
-+bus_check_queued_message_reply_callback (BusDeferredMessage *deferred_message,
-+                                         BusResult result)
-+{
-+  int status;
-+
-+  _dbus_verbose("bus_check_queued_message_reply_callback called message=%p\n", deferred_message);
-+
-+  if (!bus_connection_is_active(deferred_message->proposed_recipient))
-+    return;
-+
-+  status = deferred_message->status;
-+
-+  deferred_message->status = 0; /* mark message as not waiting for response */
-+  deferred_message->response = result;
-+
-+  /*
-+   * If send rule allows us to send message we still need to check receive rules.
-+   */
-+  if ((status & BUS_DEFERRED_MESSAGE_CHECK_SEND) && (result == BUS_RESULT_TRUE))
-+    {
-+      int toggles;
-+      BusContext *context;
-+      BusRegistry *registry;
-+      BusClientPolicy *recipient_policy;
-+      BusDeferredMessage *deferred_message_receive;
-+
-+      context = bus_connection_get_context(deferred_message->proposed_recipient);
-+      registry = bus_context_get_registry(context);
-+      recipient_policy = bus_connection_get_policy(deferred_message->proposed_recipient);
-+
-+      deferred_message->response = bus_client_policy_check_can_receive(recipient_policy, registry,
-+          deferred_message->requested_reply, deferred_message->sender,
-+          deferred_message->addressed_recipient, deferred_message->proposed_recipient, deferred_message->message,
-+          &toggles, NULL, &deferred_message_receive);
-+      if (deferred_message->response == BUS_RESULT_LATER)
-+        {
-+          /* replace deferred message associated with send check with the one associated with
-+           * receive check */
-+          if (!bus_deferred_message_replace(deferred_message, deferred_message_receive))
-+            {
-+              /* failed to replace deferred message (due to oom). Set it to rejected */
-+              deferred_message->response = BUS_RESULT_FALSE;
-+            }
-+        }
-+    }
-+
-+  bus_connection_dispatch_deferred(deferred_message->proposed_recipient);
-+}
-+
-+static void
-+queue_deferred_message_cancel_transaction_hook (void *data)
-+{
-+  BusDeferredMessage *deferred_message = (BusDeferredMessage *)data;
-+  bus_connection_remove_deferred_message(deferred_message->proposed_recipient, deferred_message);
-+}
-+
-+
-+dbus_bool_t
-+bus_deferred_message_queue_at_recipient (BusDeferredMessage *deferred_message,
-+                                         BusTransaction *transaction,
-+                                         dbus_bool_t full_dispatch,
-+                                         dbus_bool_t prepend)
-+{
-+  _dbus_assert(deferred_message != NULL);
-+  _dbus_assert(deferred_message->proposed_recipient != NULL);
-+
-+  if (!bus_connection_queue_deferred_message(deferred_message->proposed_recipient,
-+         deferred_message, prepend))
-+    return FALSE;
-+
-+  if (!bus_transaction_add_cancel_hook(transaction, queue_deferred_message_cancel_transaction_hook,
-+      deferred_message, NULL))
-+    {
-+      bus_connection_remove_deferred_message(deferred_message->proposed_recipient, deferred_message);
-+      return FALSE;
-+    }
-+  deferred_message->response_callback = bus_check_queued_message_reply_callback;
-+  deferred_message->full_dispatch = full_dispatch;
-+
-+  return TRUE;
-+}
-+
- static void
- deferred_message_free_function(void *data)
- {
-@@ -159,6 +245,20 @@ bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message)
-   deferred_message->response_callback = bus_check_enable_dispatch_callback;
- }
-+void
-+bus_deferred_message_set_policy_check_info (BusDeferredMessage *deferred_message,
-+                                            dbus_bool_t requested_reply,
-+                                            int matched_rules,
-+                                            const char *privilege)
-+{
-+  _dbus_assert(deferred_message != NULL);
-+
-+  deferred_message->requested_reply = requested_reply;
-+  deferred_message->matched_rules = matched_rules;
-+  deferred_message->privilege = privilege;
-+}
-+
-+
- #ifdef DBUS_ENABLE_EMBEDDED_TESTS
- BusResult (*bus_check_test_override) (DBusConnection *connection,
-                                         const char *privilege);
-@@ -259,6 +359,9 @@ BusDeferredMessage *bus_deferred_message_new (DBusMessage *message,
-   deferred_message->addressed_recipient = addressed_recipient != NULL ? dbus_connection_ref(addressed_recipient) : NULL;
-   deferred_message->proposed_recipient = proposed_recipient != NULL ? dbus_connection_ref(proposed_recipient) : NULL;
-   deferred_message->message = dbus_message_ref(message);
-+  deferred_message->requested_reply = FALSE;
-+  deferred_message->matched_rules = 0;
-+  deferred_message->privilege = NULL;
-   deferred_message->response = response;
-   deferred_message->status = 0;
-   deferred_message->full_dispatch = FALSE;
-@@ -295,12 +398,215 @@ bus_deferred_message_unref (BusDeferredMessage *deferred_message)
-      }
- }
-+dbus_bool_t
-+bus_deferred_message_check_message_limits (BusDeferredMessage *deferred_message, DBusError *error)
-+{
-+  BusContext *context = bus_connection_get_context(deferred_message->proposed_recipient);
-+
-+  return bus_context_check_recipient_message_limits(context, deferred_message->proposed_recipient,
-+      deferred_message->sender, deferred_message->message, deferred_message->requested_reply,
-+      error);
-+}
-+
-+dbus_bool_t
-+bus_deferred_message_expect_method_reply(BusDeferredMessage *deferred_message, BusTransaction *transaction, DBusError *error)
-+{
-+  int type = dbus_message_get_type(deferred_message->message);
-+  if (type == DBUS_MESSAGE_TYPE_METHOD_CALL &&
-+        deferred_message->sender &&
-+        deferred_message->addressed_recipient &&
-+        deferred_message->addressed_recipient == deferred_message->proposed_recipient && /* not eavesdropping */
-+        !bus_connections_expect_reply (bus_connection_get_connections (deferred_message->sender),
-+                                       transaction,
-+                                       deferred_message->sender, deferred_message->addressed_recipient,
-+                                       deferred_message->message, error))
-+    {
-+      _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
-+      return FALSE;
-+    }
-+  return TRUE;
-+}
-+
-+void
-+bus_deferred_message_create_error(BusDeferredMessage *deferred_message,
-+    const char *error_message, DBusError *error)
-+{
-+  BusContext *context;
-+  _dbus_assert (deferred_message->status == 0 && deferred_message->response == BUS_RESULT_FALSE);
-+
-+  if (deferred_message->sender == NULL)
-+    return; /* error won't be sent to bus driver anyway */
-+
-+  context = bus_connection_get_context(deferred_message->sender);
-+  bus_context_complain_about_message(context, DBUS_ERROR_ACCESS_DENIED, "Rejected message",
-+      deferred_message->matched_rules, deferred_message->message, deferred_message->sender,
-+      deferred_message->proposed_recipient, deferred_message->requested_reply, FALSE,
-+      deferred_message->privilege, error);
-+}
-+
-+BusResult
-+bus_deferred_message_dispatch (BusDeferredMessage *deferred_message)
-+{
-+  BusContext *context = bus_connection_get_context (deferred_message->proposed_recipient);
-+  BusTransaction *transaction = bus_transaction_new (context);
-+  BusResult result = BUS_RESULT_TRUE;
-+  DBusError error;
-+
-+  if (transaction == NULL)
-+    {
-+      return BUS_RESULT_FALSE;
-+    }
-+
-+  dbus_error_init(&error);
-+
-+  if (!deferred_message->full_dispatch)
-+    {
-+      result = deferred_message->response;
-+      if (result == BUS_RESULT_TRUE)
-+        {
-+          if (!bus_context_check_recipient_message_limits(context, deferred_message->proposed_recipient,
-+               deferred_message->sender, deferred_message->message, deferred_message->requested_reply, &error))
-+              result = BUS_RESULT_FALSE;
-+        }
-+      else if (result == BUS_RESULT_LATER)
-+        {
-+          BusDeferredMessage *deferred_message2;
-+          result = bus_context_check_security_policy (context, transaction,
-+                                                      deferred_message->sender,
-+                                                      deferred_message->addressed_recipient,
-+                                                      deferred_message->proposed_recipient,
-+                                                      deferred_message->message, NULL, NULL,
-+                                                      &deferred_message2);
-+
-+          if (result == BUS_RESULT_LATER)
-+            {
-+              /* prepend at recipient */
-+              if (!bus_deferred_message_queue_at_recipient(deferred_message2, transaction,
-+                  FALSE, TRUE))
-+                result = BUS_RESULT_FALSE;
-+            }
-+        }
-+
-+      /* silently drop messages on access denial */
-+      if (result == BUS_RESULT_TRUE)
-+        {
-+          if (!bus_transaction_send (transaction, deferred_message->proposed_recipient, deferred_message->message, TRUE))
-+            result = BUS_RESULT_FALSE;
-+        }
-+
-+      bus_transaction_execute_and_free(transaction);
-+
-+      goto out;
-+    }
-+
-+  /* do not attempt to send message if sender has disconnected */
-+  if (deferred_message->sender != NULL && !bus_connection_is_active(deferred_message->sender))
-+    {
-+      bus_transaction_cancel_and_free(transaction);
-+      result = BUS_RESULT_FALSE;
-+      goto out;
-+    }
-+
-+  result = bus_dispatch_matches(transaction, deferred_message->sender,
-+      deferred_message->addressed_recipient, deferred_message->message, deferred_message, &error);
-+
-+  if (result == BUS_RESULT_LATER)
-+    {
-+      /* Message deferring was already done in bus_dispatch_matches */
-+      bus_transaction_cancel_and_free(transaction);
-+      goto out;
-+    }
-+
-+  /* this part is a copy & paste from bus_dispatch function. Probably can be moved to a function */
-+  if (dbus_error_is_set (&error))
-+    {
-+      if (!dbus_connection_get_is_connected (deferred_message->sender))
-+        {
-+          /* If we disconnected it, we won't bother to send it any error
-+           * messages.
-+           */
-+          _dbus_verbose ("Not sending error to connection we disconnected\n");
-+        }
-+      else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
-+        {
-+          bus_connection_send_oom_error (deferred_message->sender, deferred_message->message);
-+
-+          /* cancel transaction due to OOM */
-+          if (transaction != NULL)
-+            {
-+              bus_transaction_cancel_and_free (transaction);
-+              transaction = NULL;
-+            }
-+        }
-+      else
-+        {
-+          /* Try to send the real error, if no mem to do that, send
-+           * the OOM error
-+           */
-+          _dbus_assert (transaction != NULL);
-+          if (!bus_transaction_send_error_reply (transaction, deferred_message->sender,
-+                                                 &error, deferred_message->message))
-+            {
-+              bus_connection_send_oom_error (deferred_message->sender, deferred_message->message);
-+
-+              /* cancel transaction due to OOM */
-+              if (transaction != NULL)
-+                {
-+                  bus_transaction_cancel_and_free (transaction);
-+                  transaction = NULL;
-+                }
-+            }
-+        }
-+    }
-+
-+  if (transaction != NULL)
-+    {
-+      bus_transaction_execute_and_free (transaction);
-+    }
-+
-+out:
-+  dbus_error_free(&error);
-+
-+  return result;
-+}
-+
-+dbus_bool_t
-+bus_deferred_message_replace (BusDeferredMessage *old_message, BusDeferredMessage *new_message)
-+{
-+  if (bus_connection_replace_deferred_message(old_message->proposed_recipient,
-+        old_message, new_message))
-+    {
-+      new_message->response_callback = old_message->response_callback;
-+      new_message->full_dispatch = old_message->full_dispatch;
-+      return TRUE;
-+    }
-+  return FALSE;
-+}
-+
-+dbus_bool_t
-+bus_deferred_message_waits_for_check(BusDeferredMessage *deferred_message)
-+{
-+  return deferred_message->status != 0;
-+}
-+
-+DBusConnection *
-+bus_deferred_message_get_recipient(BusDeferredMessage *deferred_message)
-+{
-+  return deferred_message->proposed_recipient;
-+}
-+
- BusDeferredMessageStatus
- bus_deferred_message_get_status (BusDeferredMessage *deferred_message)
- {
-   return deferred_message->status;
- }
-+BusResult
-+bus_deferred_message_get_response (BusDeferredMessage *deferred_message)
-+{
-+  return deferred_message->response;
-+}
-+
- void
- bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
-                                         BusResult result)
-@@ -310,3 +616,4 @@ bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
-       deferred_message->response_callback(deferred_message, result);
-     }
- }
-+
-diff --git a/bus/check.h b/bus/check.h
-index d177549..9c13c18 100644
---- a/bus/check.h
-+++ b/bus/check.h
-@@ -64,12 +64,37 @@ BusDeferredMessage *bus_deferred_message_new                (DBusMessage *messag
- BusDeferredMessage *bus_deferred_message_ref                (BusDeferredMessage *deferred_message);
- void                bus_deferred_message_unref              (BusDeferredMessage *deferred_message);
-+BusResult           bus_deferred_message_dispatch           (BusDeferredMessage *deferred_message);
-+dbus_bool_t         bus_deferred_message_waits_for_check    (BusDeferredMessage *deferred_message);
-+DBusConnection     *bus_deferred_message_get_recipient      (BusDeferredMessage *deferred_message);
- void                bus_deferred_message_response_received  (BusDeferredMessage *deferred_message,
-                                                              BusResult result);
-+dbus_bool_t         bus_deferred_message_queue_at_recipient (BusDeferredMessage *deferred_message,
-+                                                             BusTransaction *transaction,
-+                                                             dbus_bool_t full_dispatch,
-+                                                             dbus_bool_t prepend);
-+dbus_bool_t         bus_deferred_message_replace            (BusDeferredMessage *old_message,
-+                                                             BusDeferredMessage *new_message);
- void                bus_deferred_message_disable_sender     (BusDeferredMessage *deferred_message);
-+BusResult           bus_deferred_message_get_response       (BusDeferredMessage *deferred_message);
- BusDeferredMessageStatus  bus_deferred_message_get_status   (BusDeferredMessage *deferred_message);
-+
-+dbus_bool_t         bus_deferred_message_expect_method_reply (BusDeferredMessage *deferred_message,
-+                                                              BusTransaction *transaction,
-+                                                              DBusError *error);
-+void                bus_deferred_message_create_error        (BusDeferredMessage *deferred_message,
-+                                                              const char *error_message,
-+                                                              DBusError *error);
-+void                bus_deferred_message_set_policy_check_info (BusDeferredMessage *deferred_message,
-+                                                                dbus_bool_t requested_reply,
-+                                                                int matched_rules,
-+                                                                const char *privilege);
-+dbus_bool_t         bus_deferred_message_check_message_limits (BusDeferredMessage *deferred_message,
-+                                                               DBusError *error);
-+
-+
- #ifdef DBUS_ENABLE_EMBEDDED_TESTS
- extern BusResult (*bus_check_test_override) (DBusConnection *connection,
-                                                const char *privilege);
-diff --git a/bus/connection.c b/bus/connection.c
-index b348d42..ee93384 100644
---- a/bus/connection.c
-+++ b/bus/connection.c
-@@ -31,11 +31,13 @@
- #include "expirelist.h"
- #include "selinux.h"
- #include "apparmor.h"
-+#include "check.h"
- #include <dbus/dbus-list.h>
- #include <dbus/dbus-hash.h>
- #include <dbus/dbus-timeout.h>
- #include <dbus/dbus-connection-internal.h>
- #include <dbus/dbus-internals.h>
-+#include <dbus/dbus-message-internal.h>
- #ifdef DBUS_ENABLE_CYNARA
- #include <stdlib.h>
- #include <cynara-session.h>
-@@ -102,6 +104,7 @@ typedef struct
-   DBusMessage *oom_message;
-   DBusPreallocatedSend *oom_preallocated;
-   BusClientPolicy *policy;
-+  DBusList *deferred_messages;  /**< Queue of messages deferred due to pending policy check */
-   char *cached_loginfo_string;
-   BusSELinuxID *selinux_id;
-@@ -268,6 +271,8 @@ bus_connection_disconnected (DBusConnection *connection)
-       bus_transaction_execute_and_free (transaction);
-     }
-+  bus_connection_clear_deferred_messages(connection);
-+
-   bus_dispatch_remove_connection (connection);
-   
-   /* no more watching */
-@@ -2307,7 +2312,7 @@ bus_transaction_capture (BusTransaction *transaction,
-     {
-       DBusConnection *recipient = link->data;
--      if (!bus_transaction_send (transaction, recipient, message))
-+      if (!bus_transaction_send (transaction, recipient, message, FALSE))
-         goto out;
-     }
-@@ -2361,6 +2366,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
- {
-   DBusError error = DBUS_ERROR_INIT;
-   BusResult res;
-+  BusDeferredMessage *deferred_message;
-   /* We have to set the sender to the driver, and have
-    * to check security policy since it was not done in
-@@ -2401,7 +2407,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
-   res = bus_context_check_security_policy (bus_transaction_get_context (transaction),
-                                            transaction,
-                                            NULL, connection, connection, message, NULL,
--                                           &error, NULL);
-+                                           &error, &deferred_message);
-   if (res == BUS_RESULT_FALSE)
-     {
-       if (!bus_transaction_capture_error_reply (transaction, connection,
-@@ -2419,18 +2425,20 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
-     }
-   else if (res == BUS_RESULT_LATER)
-     {
--      _dbus_verbose ("Cannot delay sending message from bus driver, dropping it\n");
-       dbus_error_free (&error);
--      return TRUE;
-+      if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, FALSE, FALSE))
-+        return FALSE;
-+      return TRUE; /* pretend to have sent it */
-     }
--  return bus_transaction_send (transaction, connection, message);
-+  return bus_transaction_send (transaction, connection, message, FALSE);
- }
- dbus_bool_t
- bus_transaction_send (BusTransaction *transaction,
-                       DBusConnection *connection,
--                      DBusMessage    *message)
-+                      DBusMessage    *message,
-+                      dbus_bool_t     deferred_dispatch)
- {
-   MessageToSend *to_send;
-   BusConnectionData *d;
-@@ -2456,7 +2464,28 @@ bus_transaction_send (BusTransaction *transaction,
-   
-   d = BUS_CONNECTION_DATA (connection);
-   _dbus_assert (d != NULL);
--  
-+
-+  if (!deferred_dispatch && d->deferred_messages != NULL)
-+    {
-+      BusDeferredMessage *deferred_message;
-+      dbus_bool_t success;
-+      /* sender and addressed recipient are not required at this point as we only need to send message
-+       * to a single recipient without performing policy check. */
-+      deferred_message = bus_deferred_message_new (message,
-+                                                   NULL,
-+                                                   NULL,
-+                                                   connection,
-+                                                   BUS_RESULT_TRUE);
-+      if (deferred_message == NULL)
-+        return FALSE;
-+
-+      success = bus_deferred_message_queue_at_recipient(deferred_message, transaction,
-+          FALSE, FALSE);
-+      bus_deferred_message_unref(deferred_message);
-+
-+      return success;
-+    }
-+
-   to_send = dbus_new (MessageToSend, 1);
-   if (to_send == NULL)
-     {
-@@ -2708,6 +2737,131 @@ bus_transaction_add_cancel_hook (BusTransaction               *transaction,
-   return TRUE;
- }
-+void
-+bus_connection_dispatch_deferred (DBusConnection *connection)
-+{
-+  BusDeferredMessage *message;
-+
-+  _dbus_return_if_fail (connection != NULL);
-+
-+  while ((message = bus_connection_pop_deferred_message(connection)) != NULL)
-+    {
-+      bus_deferred_message_dispatch(message);
-+      bus_deferred_message_unref(message);
-+    }
-+}
-+
-+dbus_bool_t
-+bus_connection_has_deferred_messages (DBusConnection *connection)
-+{
-+  BusConnectionData *d = BUS_CONNECTION_DATA(connection);
-+  return d->deferred_messages != NULL ? TRUE : FALSE;
-+}
-+
-+dbus_bool_t
-+bus_connection_queue_deferred_message (DBusConnection *connection,
-+                                       BusDeferredMessage *message,
-+                                       dbus_bool_t prepend)
-+{
-+  BusConnectionData *d = BUS_CONNECTION_DATA(connection);
-+  dbus_bool_t success;
-+  if (prepend)
-+    success = _dbus_list_prepend(&d->deferred_messages, message);
-+  else
-+    success = _dbus_list_append(&d->deferred_messages, message);
-+
-+  if (success)
-+    {
-+      bus_deferred_message_ref(message);
-+      return TRUE;
-+    }
-+
-+  return FALSE;
-+}
-+
-+dbus_bool_t
-+bus_connection_replace_deferred_message (DBusConnection *connection,
-+                                         BusDeferredMessage *oldMessage,
-+                                         BusDeferredMessage *newMessage)
-+{
-+  DBusList *link;
-+  BusConnectionData *d = BUS_CONNECTION_DATA(connection);
-+
-+  link = _dbus_list_find_first(&d->deferred_messages, oldMessage);
-+  if (link == NULL)
-+    return FALSE;
-+
-+  if (!_dbus_list_insert_after(&d->deferred_messages, link, newMessage))
-+    return FALSE;
-+
-+  bus_deferred_message_ref(newMessage);
-+  _dbus_list_remove_link(&d->deferred_messages, link);
-+  bus_deferred_message_unref(oldMessage);
-+  return TRUE;
-+}
-+
-+BusDeferredMessage *
-+bus_connection_pop_deferred_message (DBusConnection *connection)
-+{
-+  DBusList *link;
-+  BusDeferredMessage *message;
-+  BusConnectionData *d = BUS_CONNECTION_DATA(connection);
-+
-+  link =_dbus_list_get_first_link(&d->deferred_messages);
-+  if (link != NULL)
-+    {
-+      message = link->data;
-+      if (!bus_deferred_message_waits_for_check(message))
-+        {
-+          _dbus_list_remove_link(&d->deferred_messages, link);
-+          return message;
-+        }
-+    }
-+
-+  return NULL;
-+}
-+
-+dbus_bool_t
-+bus_connection_putback_deferred_message (DBusConnection *connection, BusDeferredMessage *message)
-+{
-+  BusConnectionData *d = BUS_CONNECTION_DATA(connection);
-+  if (_dbus_list_prepend(&d->deferred_messages, message))
-+    {
-+      return TRUE;
-+    }
-+  return FALSE;
-+}
-+
-+void
-+bus_connection_clear_deferred_messages (DBusConnection *connection)
-+{
-+  BusConnectionData *d = BUS_CONNECTION_DATA(connection);
-+  DBusList *link;
-+  DBusList *next;
-+  BusDeferredMessage *message;
-+
-+  link =_dbus_list_get_first_link(&d->deferred_messages);
-+  while (link != NULL)
-+    {
-+      next = _dbus_list_get_next_link (&d->deferred_messages, link);
-+      message = link->data;
-+
-+      bus_deferred_message_unref(message);
-+      _dbus_list_remove_link(&d->deferred_messages, link);
-+
-+      link = next;
-+    }
-+}
-+
-+void
-+bus_connection_remove_deferred_message (DBusConnection *connection,
-+                                        BusDeferredMessage *message)
-+{
-+  BusConnectionData *d = BUS_CONNECTION_DATA(connection);
-+  if (_dbus_list_remove(&d->deferred_messages, message))
-+    bus_deferred_message_unref(message);
-+}
-+
- int
- bus_connections_get_n_active (BusConnections *connections)
- {
-diff --git a/bus/connection.h b/bus/connection.h
-index 71078ea..97dae96 100644
---- a/bus/connection.h
-+++ b/bus/connection.h
-@@ -85,6 +85,22 @@ dbus_bool_t bus_connection_preallocate_oom_error (DBusConnection *connection);
- void        bus_connection_send_oom_error        (DBusConnection *connection,
-                                                   DBusMessage    *in_reply_to);
-+dbus_bool_t         bus_connection_has_deferred_messages    (DBusConnection *connection);
-+dbus_bool_t         bus_connection_queue_deferred_message   (DBusConnection *connection,
-+                                                             BusDeferredMessage *message,
-+                                                             dbus_bool_t prepend);
-+BusDeferredMessage *bus_connection_pop_deferred_message     (DBusConnection *connection);
-+dbus_bool_t         bus_connection_putback_deferred_message (DBusConnection *connection,
-+                                                             BusDeferredMessage *message);
-+void                bus_connection_remove_deferred_message  (DBusConnection *connection,
-+                                                             BusDeferredMessage *message);
-+dbus_bool_t         bus_connection_replace_deferred_message (DBusConnection *connection,
-+                                                             BusDeferredMessage *oldMessage,
-+                                                             BusDeferredMessage *newMessage);
-+void                bus_connection_dispatch_deferred        (DBusConnection *connection);
-+void                bus_connection_clear_deferred_messages  (DBusConnection *connection);
-+
-+
- /* called by signals.c */
- dbus_bool_t bus_connection_add_match_rule      (DBusConnection *connection,
-                                                 BusMatchRule   *rule);
-@@ -137,7 +153,8 @@ BusTransaction* bus_transaction_new              (BusContext                   *
- BusContext*     bus_transaction_get_context      (BusTransaction               *transaction);
- dbus_bool_t     bus_transaction_send             (BusTransaction               *transaction,
-                                                   DBusConnection               *connection,
--                                                  DBusMessage                  *message);
-+                                                  DBusMessage                  *message,
-+                                                  dbus_bool_t                   deferred_dispatch);
- dbus_bool_t     bus_transaction_capture          (BusTransaction               *transaction,
-                                                   DBusConnection               *connection,
-                                                   DBusConnection               *addressed_recipient,
-diff --git a/bus/dispatch.c b/bus/dispatch.c
-index 50a22a3..7d30ce4 100644
---- a/bus/dispatch.c
-+++ b/bus/dispatch.c
-@@ -33,6 +33,7 @@
- #include "utils.h"
- #include "bus.h"
- #include "signals.h"
-+#include "dispatch.h"
- #include "test.h"
- #include <dbus/dbus-internals.h>
- #include <dbus/dbus-connection-internal.h>
-@@ -77,7 +78,7 @@ send_one_message (DBusConnection *connection,
-                                           NULL,
-                                           &stack_error,
-                                           &deferred_message);
--  if (result != BUS_RESULT_TRUE)
-+  if (result == BUS_RESULT_FALSE)
-     {
-       if (!bus_transaction_capture_error_reply (transaction, sender,
-                                                 &stack_error, message))
-@@ -112,9 +113,19 @@ send_one_message (DBusConnection *connection,
-       return TRUE; /* don't send it but don't return an error either */
-     }
-+  if (result == BUS_RESULT_LATER)
-+    {
-+      if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, FALSE, FALSE))
-+        {
-+          BUS_SET_OOM (error);
-+          return FALSE;
-+        }
-+      return TRUE; /* pretend to have sent it */
-+    }
-+
-   if (!bus_transaction_send (transaction,
-                              connection,
--                             message))
-+                             message, FALSE))
-     {
-       BUS_SET_OOM (error);
-       return FALSE;
-@@ -124,11 +135,12 @@ send_one_message (DBusConnection *connection,
- }
- BusResult
--bus_dispatch_matches (BusTransaction *transaction,
--                      DBusConnection *sender,
--                      DBusConnection *addressed_recipient,
--                      DBusMessage    *message,
--                      DBusError      *error)
-+bus_dispatch_matches (BusTransaction     *transaction,
-+                      DBusConnection     *sender,
-+                      DBusConnection     *addressed_recipient,
-+                      DBusMessage        *message,
-+                      BusDeferredMessage *dispatched_deferred_message,
-+                      DBusError          *error)
- {
-   DBusError tmp_error;
-   BusConnections *connections;
-@@ -137,7 +149,6 @@ bus_dispatch_matches (BusTransaction *transaction,
-   DBusList *link;
-   BusContext *context;
-   BusDeferredMessage *deferred_message;
--  BusResult res;
-   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-@@ -153,16 +164,80 @@ bus_dispatch_matches (BusTransaction *transaction,
-   /* First, send the message to the addressed_recipient, if there is one. */
-   if (addressed_recipient != NULL)
-     {
--      res = bus_context_check_security_policy (context, transaction,
-+      BusResult result;
-+      /* To maintain message order message needs to be appended at the recipient if there are already
-+       *  deferred messages and we are not doing deferred dispatch
-+       */
-+      if (dispatched_deferred_message == NULL && bus_connection_has_deferred_messages(addressed_recipient))
-+        {
-+          deferred_message = bus_deferred_message_new(message, sender,
-+              addressed_recipient, addressed_recipient, BUS_RESULT_LATER);
-+
-+          if (deferred_message == NULL)
-+            {
-+              BUS_SET_OOM(error);
-+              return BUS_RESULT_FALSE;
-+            }
-+
-+          if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, TRUE, FALSE))
-+            {
-+              bus_deferred_message_unref(deferred_message);
-+              BUS_SET_OOM(error);
-+              return BUS_RESULT_FALSE;
-+            }
-+
-+          bus_deferred_message_unref(deferred_message);
-+          return BUS_RESULT_TRUE; /* pretend to have sent it */
-+        }
-+
-+      if (dispatched_deferred_message != NULL)
-+        {
-+          result = bus_deferred_message_get_response(dispatched_deferred_message);
-+          if (result == BUS_RESULT_TRUE)
-+            {
-+              /* if we know the result of policy check we still need to check if message limits
-+               * are not exceeded. It is also required to add entry in expected replies list if
-+               * this is a method call
-+               */
-+              if (!bus_deferred_message_check_message_limits(dispatched_deferred_message, error))
-+                return BUS_RESULT_FALSE;
-+
-+              if (!bus_deferred_message_expect_method_reply(dispatched_deferred_message, transaction, error))
-+                return BUS_RESULT_FALSE;
-+            }
-+          else if (result == BUS_RESULT_FALSE)
-+            {
-+              bus_deferred_message_create_error(dispatched_deferred_message, "Rejected message", error);
-+              return BUS_RESULT_FALSE;
-+            }
-+        }
-+      else
-+        result = BUS_RESULT_LATER;
-+
-+      if (result == BUS_RESULT_LATER)
-+        result = bus_context_check_security_policy (context, transaction,
-                                                sender, addressed_recipient,
-                                                addressed_recipient,
-                                                message, NULL, error,
-                                                &deferred_message);
--      if (res == BUS_RESULT_FALSE)
-+
-+      if (result == BUS_RESULT_FALSE)
-         return BUS_RESULT_FALSE;
--      else if (res == BUS_RESULT_LATER)
-+      else if (result == BUS_RESULT_LATER)
-         {
-           BusDeferredMessageStatus status;
-+
-+          if (dispatched_deferred_message != NULL)
-+            {
-+              /* for deferred dispatch prepend message at the recipient */
-+              if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, TRUE, TRUE))
-+                {
-+                  BUS_SET_OOM(error);
-+                  return BUS_RESULT_FALSE;
-+                }
-+              return BUS_RESULT_TRUE; /* pretend to have sent it */
-+            }
-+
-           status = bus_deferred_message_get_status(deferred_message);
-           if (status & BUS_DEFERRED_MESSAGE_CHECK_SEND)
-@@ -173,13 +248,18 @@ bus_dispatch_matches (BusTransaction *transaction,
-             }
-           else if (status & BUS_DEFERRED_MESSAGE_CHECK_RECEIVE)
-             {
--              dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
--                              "Rejecting message because time is needed to check security policy");
--              return BUS_RESULT_FALSE;
-+              /* receive rule result not available - queue message at the recipient */
-+              if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, TRUE, FALSE))
-+                {
-+                  BUS_SET_OOM(error);
-+                  return BUS_RESULT_FALSE;
-+                }
-+
-+              return BUS_RESULT_TRUE; /* pretend to have sent it */
-             }
-           else
-             {
--              _dbus_verbose("deferred message has no status field set to send or receive unexpectedly\n");
-+              _dbus_verbose("deferred message has no status field set unexpectedly\n");
-               return BUS_RESULT_FALSE;
-             }
-         }
-@@ -196,7 +276,8 @@ bus_dispatch_matches (BusTransaction *transaction,
-         }
-       /* Dispatch the message */
--      if (!bus_transaction_send (transaction, addressed_recipient, message))
-+      if (!bus_transaction_send(transaction, addressed_recipient, message,
-+          dispatched_deferred_message != NULL ? TRUE : FALSE))
-         {
-           BUS_SET_OOM (error);
-           return BUS_RESULT_FALSE;
-@@ -534,7 +615,7 @@ bus_dispatch (DBusConnection *connection,
-    * match rules.
-    */
-   if (BUS_RESULT_LATER == bus_dispatch_matches (transaction, connection, addressed_recipient,
--                                                message, &error))
-+                                                message, NULL, &error))
-     {
-       /* Roll back and dispatch the message once the policy result is available */
-       bus_transaction_cancel_and_free (transaction);
-diff --git a/bus/dispatch.h b/bus/dispatch.h
-index afba6a2..f6102e8 100644
---- a/bus/dispatch.h
-+++ b/bus/dispatch.h
-@@ -29,10 +29,11 @@
- dbus_bool_t bus_dispatch_add_connection    (DBusConnection *connection);
- void        bus_dispatch_remove_connection (DBusConnection *connection);
--BusResult   bus_dispatch_matches           (BusTransaction *transaction,
--                                            DBusConnection *sender,
--                                            DBusConnection *recipient,
--                                            DBusMessage    *message,
--                                            DBusError      *error);
-+BusResult   bus_dispatch_matches           (BusTransaction     *transaction,
-+                                            DBusConnection     *sender,
-+                                            DBusConnection     *recipient,
-+                                            DBusMessage        *message,
-+                                            BusDeferredMessage *dispatched_deferred_message,
-+                                            DBusError           *error);
- #endif /* BUS_DISPATCH_H */
-diff --git a/bus/driver.c b/bus/driver.c
-index f414f64..d89a658 100644
---- a/bus/driver.c
-+++ b/bus/driver.c
-@@ -254,7 +254,7 @@ bus_driver_send_service_owner_changed (const char     *service_name,
-   if (!bus_transaction_capture (transaction, NULL, NULL, message))
-     goto oom;
--  res = bus_dispatch_matches (transaction, NULL, NULL, message, error);
-+  res = bus_dispatch_matches (transaction, NULL, NULL, message, NULL, error);
-   if (res == BUS_RESULT_TRUE)
-     retval = TRUE;
-   else
-diff --git a/bus/policy.c b/bus/policy.c
-index 7de92c6..483cc97 100644
---- a/bus/policy.c
-+++ b/bus/policy.c
-@@ -1122,6 +1122,9 @@ bus_client_policy_check_can_send (DBusConnection      *sender,
-       result = bus_check_privilege(check, message, sender, addressed_recipient, receiver,
-           privilege, BUS_DEFERRED_MESSAGE_CHECK_SEND, deferred_message);
-+      if (result == BUS_RESULT_LATER && deferred_message != NULL)
-+        bus_deferred_message_set_policy_check_info(*deferred_message, requested_reply,
-+            *toggles, privilege);
-     }
-   else
-     privilege = NULL;
-@@ -1372,6 +1375,9 @@ bus_client_policy_check_can_receive (BusClientPolicy     *policy,
-       result = bus_check_privilege(check, message, sender, addressed_recipient, proposed_recipient,
-                  privilege, BUS_DEFERRED_MESSAGE_CHECK_RECEIVE, deferred_message);
-+      if (result == BUS_RESULT_LATER && deferred_message != NULL)
-+        bus_deferred_message_set_policy_check_info(*deferred_message, requested_reply,
-+                    *toggles, privilege);
-     }
-   else
-       privilege = NULL;
--- 
-2.21.1
-