summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Szyndela <adrian.s@samsung.com>2020-09-14 13:06:02 +0200
committerAdrian Szyndela <adrian.s@samsung.com>2020-09-14 17:22:45 +0200
commita4be7ede41f45ab0996bf9f3cfd3b78d9a84117b (patch)
treef951dddc839211e1d7ac83b76b215fbfbed05ed7
parent8da5f63846d9a3173e06b0fcca17459ec201c126 (diff)
downloaddbus-sandbox/adrians/cynara-concurrent.tar.gz
dbus-sandbox/adrians/cynara-concurrent.tar.bz2
dbus-sandbox/adrians/cynara-concurrent.zip
deferring: check policy right away for both send and receivesandbox/adrians/cynara-concurrent
This makes checking policy at the moments, when sender is still present, so the policy can be checked for both sender and receiver. This way only potential waiting for cynara check is left with no need to access any connection data. Change-Id: I6544740c6e31dee286261fe3cddb3f692c669c4d
-rw-r--r--bus/bus.c28
-rw-r--r--bus/check.c71
-rw-r--r--bus/check.h9
-rw-r--r--bus/connection.c23
-rw-r--r--bus/connection.h3
-rw-r--r--bus/cynara.c48
-rw-r--r--bus/dispatch.c17
7 files changed, 86 insertions, 113 deletions
diff --git a/bus/bus.c b/bus/bus.c
index eb932f66..de9dde8b 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -1563,6 +1563,7 @@ bus_context_check_security_policy (BusContext *context,
dbus_bool_t requested_reply;
const char *privilege;
char *out_rule = NULL;
+ BusResult can_send_result;
type = dbus_message_get_type (message);
src = dbus_message_get_sender (message);
@@ -1748,18 +1749,16 @@ bus_context_check_security_policy (BusContext *context,
log = FALSE;
if (sender_policy) {
- switch (bus_client_policy_check_can_send (sender,
- sender_policy,
- context->registry,
- requested_reply,
- addressed_recipient,
- proposed_recipient,
- message, &toggles, &log, &privilege,
- deferred_message, &out_rule))
+ can_send_result = bus_client_policy_check_can_send (sender,
+ sender_policy,
+ context->registry,
+ requested_reply,
+ addressed_recipient,
+ proposed_recipient,
+ message, &toggles, &log, &privilege,
+ deferred_message, &out_rule);
+ if (can_send_result == BUS_RESULT_FALSE)
{
- case BUS_RESULT_TRUE:
- break;
- case BUS_RESULT_FALSE:
complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
"Rejected send message", toggles,
message, sender, proposed_recipient, requested_reply,
@@ -1770,10 +1769,6 @@ bus_context_check_security_policy (BusContext *context,
if (out_rule)
free (out_rule);
return BUS_RESULT_FALSE;
- break;
- case BUS_RESULT_LATER:
- return BUS_RESULT_LATER;
- break;
}
}
@@ -1813,6 +1808,9 @@ bus_context_check_security_policy (BusContext *context,
}
}
+ if (can_send_result == BUS_RESULT_LATER)
+ return BUS_RESULT_LATER;
+
/* See if limits on size have been exceeded */
if (!bus_context_check_recipient_message_limits(context, proposed_recipient, sender, message,
requested_reply, error))
diff --git a/bus/check.c b/bus/check.c
index 0f3c8ed8..53362461 100644
--- a/bus/check.c
+++ b/bus/check.c
@@ -130,6 +130,7 @@ bus_check_get_cynara (BusCheck *check)
static void
bus_check_enable_dispatch_callback (BusDeferredMessage *deferred_message,
+ BusDeferredMessageStatus check_type,
BusResult result)
{
_dbus_verbose("bus_check_enable_dispatch_callback called deferred_message=%p\n", deferred_message);
@@ -140,53 +141,23 @@ bus_check_enable_dispatch_callback (BusDeferredMessage *deferred_message,
static void
bus_check_queued_message_reply_callback (BusDeferredMessage *deferred_message,
+ BusDeferredMessageStatus check_type,
BusResult result)
{
- int status;
-
_dbus_verbose("bus_check_queued_message_reply_callback called message=%p\n", deferred_message);
if (!(dbus_connection_get_is_connected(deferred_message->proposed_recipient)
&& 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;
+ deferred_message->status &= ~check_type; /* mark message as not waiting for response of this type*/
+ if (deferred_message->response != BUS_RESULT_FALSE)
+ 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 = NULL;
-
- 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, NULL);
- 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;
- }
- }
- }
+ _dbus_assert (deferred_message->response != BUS_RESULT_LATER || deferred_message->status != 0);
- bus_connection_dispatch_deferred(deferred_message->proposed_recipient);
+ if (!deferred_message->status)
+ bus_connection_dispatch_deferred(deferred_message->proposed_recipient);
}
static void
@@ -406,6 +377,8 @@ bus_deferred_message_expect_method_reply(BusDeferredMessage *deferred_message, B
int type = dbus_message_get_type(deferred_message->message);
if (type == DBUS_MESSAGE_TYPE_METHOD_CALL &&
deferred_message->sender &&
+ dbus_connection_get_is_connected(deferred_message->sender) &&
+ bus_connection_is_active(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),
@@ -495,14 +468,6 @@ bus_deferred_message_dispatch (BusDeferredMessage *deferred_message)
goto out;
}
- /* do not attempt to send message if sender has disconnected */
- if (deferred_message->sender != NULL && !(dbus_connection_get_is_connected(deferred_message->sender) && 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);
@@ -567,19 +532,6 @@ out:
}
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;
@@ -605,11 +557,12 @@ bus_deferred_message_get_response (BusDeferredMessage *deferred_message)
void
bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
+ BusDeferredMessageStatus check_type,
BusResult result)
{
if (deferred_message->response_callback != NULL)
{
- deferred_message->response_callback(deferred_message, result);
+ deferred_message->response_callback(deferred_message, check_type, result);
}
}
diff --git a/bus/check.h b/bus/check.h
index 3c6b2a12..6e6faaf9 100644
--- a/bus/check.h
+++ b/bus/check.h
@@ -29,15 +29,15 @@
#include "policy.h"
-typedef void (*BusCheckResponseFunc) (BusDeferredMessage *message,
- BusResult result);
-
typedef enum {
BUS_DEFERRED_MESSAGE_CHECK_SEND = 1 << 0,
BUS_DEFERRED_MESSAGE_CHECK_RECEIVE = 1 << 1,
BUS_DEFERRED_MESSAGE_CHECK_OWN = 1 << 2,
} BusDeferredMessageStatus;
+typedef void (*BusCheckResponseFunc) (BusDeferredMessage *message,
+ BusDeferredMessageStatus check_type,
+ BusResult result);
BusCheck *bus_check_new (BusContext *context,
DBusError *error);
@@ -68,13 +68,12 @@ BusResult bus_deferred_message_dispatch (BusDeferredMessage
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,
+ BusDeferredMessageStatus check_type,
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);
diff --git a/bus/connection.c b/bus/connection.c
index dcb47bac..89cf979a 100644
--- a/bus/connection.c
+++ b/bus/connection.c
@@ -2842,29 +2842,6 @@ bus_connection_queue_deferred_message (DBusConnection *connection,
return FALSE;
}
-dbus_bool_t
-bus_connection_replace_deferred_message (DBusConnection *connection,
- BusDeferredMessage *oldMessage,
- BusDeferredMessage *newMessage)
-{
- DBusList *link;
- BusConnectionData *d = BUS_CONNECTION_DATA(connection);
-
- _dbus_assert (d != NULL);
-
- 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)
{
diff --git a/bus/connection.h b/bus/connection.h
index 85607be0..acaee151 100644
--- a/bus/connection.h
+++ b/bus/connection.h
@@ -94,9 +94,6 @@ dbus_bool_t bus_connection_putback_deferred_message (DBusConnection *con
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);
diff --git a/bus/cynara.c b/bus/cynara.c
index 98255cd5..cdcc5da9 100644
--- a/bus/cynara.c
+++ b/bus/cynara.c
@@ -49,6 +49,12 @@ typedef struct BusCynara
DBusWatch *cynara_watch;
} BusCynara;
+typedef struct BusCynaraCheckData
+{
+ BusDeferredMessage *deferred_message;
+ BusDeferredMessageStatus check_type;
+} BusCynaraCheckData;
+
static dbus_bool_t bus_cynara_watch_callback(DBusWatch *watch,
unsigned int flags,
void *data);
@@ -63,6 +69,20 @@ static void bus_cynara_check_response_callback (cynara_check_id check_id,
void *user_response_data);
#endif
+static BusCynaraCheckData *
+bus_cynara_check_data_new(BusDeferredMessage *deferred_message, BusDeferredMessageStatus check_type)
+{
+ BusCynaraCheckData *data;
+
+ data = dbus_new(BusCynaraCheckData, 1);
+ if (data == NULL)
+ return NULL;
+
+ data->deferred_message = deferred_message;
+ data->check_type = check_type;
+
+ return data;
+}
BusCynara *
bus_cynara_new(BusCheck *check, DBusError *error)
@@ -148,8 +168,9 @@ bus_cynara_check_privilege (BusCynara *cynara,
char user[32];
cynara_check_id check_id;
DBusConnection *connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender;
- BusDeferredMessage *deferred_message;
+ BusDeferredMessage *deferred_message = NULL;
BusResult return_result;
+ BusCynaraCheckData *callback_data;
_dbus_assert(connection != NULL);
@@ -208,9 +229,16 @@ bus_cynara_check_privilege (BusCynara *cynara,
bus_deferred_message_ref(deferred_message);
}
- /* callback is supposed to unref deferred_message*/
+ callback_data = bus_cynara_check_data_new(deferred_message, check_type);
+ if (callback_data == NULL)
+ {
+ _dbus_verbose("Failed to allocate memory for deferred message callback data\n");
+ return_result = BUS_RESULT_FALSE;
+ }
+
+ /* callback is supposed to unref deferred_message and free callback_data */
result = cynara_async_create_request(cynara->cynara, label, session_id, user, privilege, &check_id,
- &bus_cynara_check_response_callback, deferred_message);
+ &bus_cynara_check_response_callback, callback_data);
if (result == CYNARA_API_SUCCESS)
{
_dbus_verbose("Created Cynara request: client=%s session_id=%s user=%s privilege=%s check_id=%u "
@@ -336,12 +364,22 @@ bus_cynara_check_response_callback (cynara_check_id check_id,
int response,
void *user_response_data)
{
- BusDeferredMessage *deferred_message = user_response_data;
+ BusCynaraCheckData *check_data = user_response_data;
+ BusDeferredMessage *deferred_message;
BusResult result;
+ BusDeferredMessageStatus check_type;
_dbus_verbose("Cynara callback: check_id=%u, cause=%s response=%i response_data=%p\n",
(unsigned int)check_id, call_cause_to_string(cause), response, user_response_data);
+ if (check_data == NULL)
+ return;
+
+ deferred_message = check_data->deferred_message;
+ check_type = check_data->check_type;
+
+ dbus_free(check_data);
+
if (deferred_message == NULL)
return;
@@ -350,7 +388,7 @@ bus_cynara_check_response_callback (cynara_check_id check_id,
else
result = BUS_RESULT_FALSE;
- bus_deferred_message_response_received(deferred_message, result);
+ bus_deferred_message_response_received(deferred_message, check_type, result);
bus_deferred_message_unref(deferred_message);
}
diff --git a/bus/dispatch.c b/bus/dispatch.c
index 9d2e893d..d829296c 100644
--- a/bus/dispatch.c
+++ b/bus/dispatch.c
@@ -151,7 +151,11 @@ bus_dispatch_matches (BusTransaction *transaction,
* or for signals with no particular recipient
*/
- _dbus_assert (sender == NULL || bus_connection_is_active (sender));
+ /*
+ * With deferred messages, dispatch may happen when there is no sender anymore.
+ * Policy rules involving the sender should be checked before, anyway.
+ */
+/* _dbus_assert (sender == NULL || bus_connection_is_active (sender)); */
_dbus_assert (dbus_message_get_sender (message) != NULL);
context = bus_transaction_get_context (transaction);
@@ -165,8 +169,15 @@ bus_dispatch_matches (BusTransaction *transaction,
*/
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);
+ result = bus_context_check_security_policy(context, transaction,
+ sender, addressed_recipient, addressed_recipient, message, NULL, error,
+ &deferred_message);
+
+ if (deferred_message == NULL)
+ deferred_message = bus_deferred_message_new(message, sender,
+ addressed_recipient, addressed_recipient, result);
+ else
+ bus_deferred_message_ref(deferred_message);
if (deferred_message == NULL)
{