summaryrefslogtreecommitdiffstats
path: root/debian/patches/polkit-when-authorizing-via-PK-let-s-re-resolve-callback-.patch
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debian/patches/polkit-when-authorizing-via-PK-let-s-re-resolve-callback-.patch166
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);