diff options
Diffstat (limited to 'debian/patches/polkit-when-authorizing-via-PK-let-s-re-resolve-callback-.patch')
-rw-r--r-- | debian/patches/polkit-when-authorizing-via-PK-let-s-re-resolve-callback-.patch | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/debian/patches/polkit-when-authorizing-via-PK-let-s-re-resolve-callback-.patch b/debian/patches/polkit-when-authorizing-via-PK-let-s-re-resolve-callback-.patch new file mode 100644 index 0000000..2175b78 --- /dev/null +++ b/debian/patches/polkit-when-authorizing-via-PK-let-s-re-resolve-callback-.patch @@ -0,0 +1,166 @@ +From: Lennart Poettering <lennart@poettering.net> +Date: Wed, 22 Jan 2020 17:07:47 +0100 +Subject: polkit: when authorizing via PK let's re-resolve callback/userdata + instead of caching it + +Previously, when doing an async PK query we'd store the original +callback/userdata pair and call it again after the PK request is +complete. This is problematic, since PK queries might be slow and in the +meantime the userdata might be released and re-acquired. Let's avoid +this by always traversing through the message handlers so that we always +re-resolve the callback and userdata pair and thus can be sure it's +up-to-date and properly valid. + +(cherry picked from commit 637486261528e8aa3da9f26a4487dc254f4b7abb) +(cherry picked from commit e2d4cb9843c50eff76e9104fec6b448c0d7c8814) +(cherry picked from commit fb21e13e8ecbe25d80c1219b14e6495795df18ef) +(cherry picked from commit c3141774dfb84b1526c4991bb775457c739eb179) +--- + src/shared/bus-polkit.c | 78 ++++++++++++++++++++++++++++++++----------------- + 1 file changed, 52 insertions(+), 26 deletions(-) + +diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c +index c42c39a..02c11aa 100644 +--- a/src/shared/bus-polkit.c ++++ b/src/shared/bus-polkit.c +@@ -159,14 +159,13 @@ typedef struct AsyncPolkitQuery { + char **details; + + sd_bus_message *request, *reply; +- sd_bus_message_handler_t callback; +- void *userdata; + sd_bus_slot *slot; ++ + Hashmap *registry; ++ sd_event_source *defer_event_source; + } AsyncPolkitQuery; + + static void async_polkit_query_free(AsyncPolkitQuery *q) { +- + if (!q) + return; + +@@ -181,9 +180,24 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) { + free(q->action); + strv_free(q->details); + ++ if (q->defer_event_source) ++ (void) sd_event_source_set_enabled(q->defer_event_source, SD_EVENT_OFF); ++ sd_event_source_unref(q->defer_event_source); + free(q); + } + ++static int async_polkit_defer(sd_event_source *s, void *userdata) { ++ AsyncPolkitQuery *q = userdata; ++ ++ assert(s); ++ ++ /* This is called as idle event source after we processed the async polkit reply, hopefully after the ++ * method call we re-enqueued has been properly processed. */ ++ ++ async_polkit_query_free(q); ++ return 0; ++} ++ + static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + AsyncPolkitQuery *q = userdata; +@@ -192,21 +206,46 @@ static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_e + assert(reply); + assert(q); + ++ assert(q->slot); + q->slot = sd_bus_slot_unref(q->slot); ++ ++ assert(!q->reply); + q->reply = sd_bus_message_ref(reply); + ++ /* Now, let's dispatch the original message a second time be re-enqueing. This will then traverse the ++ * whole message processing again, and thus re-validating and re-retrieving the "userdata" field ++ * again. ++ * ++ * We install an idle event loop event to clean-up the PolicyKit request data when we are idle again, ++ * i.e. after the second time the message is processed is complete. */ ++ ++ assert(!q->defer_event_source); ++ r = sd_event_add_defer(sd_bus_get_event(sd_bus_message_get_bus(reply)), &q->defer_event_source, async_polkit_defer, q); ++ if (r < 0) ++ goto fail; ++ ++ r = sd_event_source_set_priority(q->defer_event_source, SD_EVENT_PRIORITY_IDLE); ++ if (r < 0) ++ goto fail; ++ ++ r = sd_event_source_set_enabled(q->defer_event_source, SD_EVENT_ONESHOT); ++ if (r < 0) ++ goto fail; ++ + r = sd_bus_message_rewind(q->request, true); +- if (r < 0) { +- r = sd_bus_reply_method_errno(q->request, r, NULL); +- goto finish; +- } ++ if (r < 0) ++ goto fail; ++ ++ r = sd_bus_enqeue_for_read(sd_bus_message_get_bus(q->request), q->request); ++ if (r < 0) ++ goto fail; + +- r = q->callback(q->request, q->userdata, &error_buffer); +- r = bus_maybe_reply_error(q->request, r, &error_buffer); ++ return 1; + +-finish: ++fail: ++ log_debug_errno(r, "Processing asynchronous PolicyKit reply failed, ignoring: %m"); ++ (void) sd_bus_reply_method_errno(q->request, r, NULL); + async_polkit_query_free(q); +- + return r; + } + +@@ -225,11 +264,9 @@ int bus_verify_polkit_async( + #if ENABLE_POLKIT + _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL; + AsyncPolkitQuery *q; +- const char *sender; +- sd_bus_message_handler_t callback; +- void *userdata; + int c; + #endif ++ const char *sender; + int r; + + assert(call); +@@ -293,20 +330,11 @@ int bus_verify_polkit_async( + else if (r > 0) + return 1; + +-#if ENABLE_POLKIT +- if (sd_bus_get_current_message(call->bus) != call) +- return -EINVAL; +- +- callback = sd_bus_get_current_handler(call->bus); +- if (!callback) +- return -EINVAL; +- +- userdata = sd_bus_get_current_userdata(call->bus); +- + sender = sd_bus_message_get_sender(call); + if (!sender) + return -EBADMSG; + ++#if ENABLE_POLKIT + c = sd_bus_message_get_allow_interactive_authorization(call); + if (c < 0) + return c; +@@ -349,8 +377,6 @@ int bus_verify_polkit_async( + + *q = (AsyncPolkitQuery) { + .request = sd_bus_message_ref(call), +- .callback = callback, +- .userdata = userdata, + }; + + q->action = strdup(action); |