diff options
author | Adrian Szyndela <adrian.s@samsung.com> | 2020-09-14 13:06:02 +0200 |
---|---|---|
committer | Adrian Szyndela <adrian.s@samsung.com> | 2020-09-14 17:22:45 +0200 |
commit | a4be7ede41f45ab0996bf9f3cfd3b78d9a84117b (patch) | |
tree | f951dddc839211e1d7ac83b76b215fbfbed05ed7 | |
parent | 8da5f63846d9a3173e06b0fcca17459ec201c126 (diff) | |
download | dbus-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.c | 28 | ||||
-rw-r--r-- | bus/check.c | 71 | ||||
-rw-r--r-- | bus/check.h | 9 | ||||
-rw-r--r-- | bus/connection.c | 23 | ||||
-rw-r--r-- | bus/connection.h | 3 | ||||
-rw-r--r-- | bus/cynara.c | 48 | ||||
-rw-r--r-- | bus/dispatch.c | 17 |
7 files changed, 86 insertions, 113 deletions
@@ -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) { |