Bug#956216: buster-pu: package systemd/241-7~deb10u3

Michael Biebl biebl at debian.org
Mon Apr 27 18:17:14 BST 2020


Am 25.04.20 um 21:41 schrieb Adam D. Barratt:
> On Wed, 2020-04-08 at 16:11 +0200, Michael Biebl wrote:
> I'd be OK with that, but this will need a KiBi-ack, so CCing and
> tagging accordingly.

After talking to KiBi on IRC, we decided to include the fix for #958397
as well. I kept the changes minimal and only included 60-rules in
udev-udeb and the initramfs.

We might consider a different, opt-out approach for udev-rules in the
future as suggested by Steve [1] and Marco [2]. But that's probably too
invasive for a stable upload.

Updated debdiff is attached. The changes to the previous debdiff can be
found at
https://salsa.debian.org/systemd-team/systemd/-/commit/4b7f1d2b1763574cfc9ef43e728045518d440c1a


Regards,
Michael

[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=958397#12
[2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=958397#22
-------------- next part --------------
diff --git a/debian/changelog b/debian/changelog
index 1d263f7..14ef57f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,18 @@
+systemd (241-7~deb10u4) buster; urgency=medium
+
+  * polkit: when authorizing via PolicyKit re-resolve callback/userdata
+    instead of caching it.
+    This fixes a heap use-after-free vulnerability in systemd, when
+    asynchronous PolicyKit queries are performed while handling DBus messages.
+    CVE-2020-1712 (Closes: #950732)
+  * Install 60-block.rules in udev-udeb and initramfs-tools.
+    The block device rules were split out from 60-persistent-storage.rules
+    into its own rules file in v220. Those rules ensure that change events
+    are emitted and the udev db is updated after metadata changes.
+    Thanks to Pascal Hambourg (Closes: #958397)
+
+ -- Michael Biebl <biebl at debian.org>  Mon, 27 Apr 2020 19:02:57 +0200
+
 systemd (241-7~deb10u3) buster; urgency=medium
 
   * core: set fs.file-max sysctl to LONG_MAX rather than ULONG_MAX.
diff --git a/debian/extra/initramfs-tools/hooks/udev b/debian/extra/initramfs-tools/hooks/udev
index 6305d09..bbbd351 100755
--- a/debian/extra/initramfs-tools/hooks/udev
+++ b/debian/extra/initramfs-tools/hooks/udev
@@ -28,7 +28,8 @@ if [ -d /etc/systemd/network ]; then
 fi
 
 mkdir -p "$DESTDIR/lib/udev/rules.d/"
-for rules in 50-firmware.rules 50-udev-default.rules 60-persistent-storage.rules \
+for rules in 50-firmware.rules 50-udev-default.rules \
+        60-block.rules 60-persistent-storage.rules \
         61-persistent-storage-android.rules 71-seat.rules 73-special-net-names.rules \
         73-usb-net-by-mac.rules 75-net-description.rules \
         80-net-setup-link.rules 80-drivers.rules; do
diff --git a/debian/patches/Fix-typo-in-function-name.patch b/debian/patches/Fix-typo-in-function-name.patch
new file mode 100644
index 0000000..4f3c521
--- /dev/null
+++ b/debian/patches/Fix-typo-in-function-name.patch
@@ -0,0 +1,77 @@
+From: =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= <zbyszek at in.waw.pl>
+Date: Tue, 4 Feb 2020 18:39:04 +0100
+Subject: Fix typo in function name
+
+(cherry picked from commit bc130b6858327b382b07b3985cf48e2aa9016b2d)
+(cherry picked from commit b4eb8848240c3540180e4768216a0b884a5ed783)
+(cherry picked from commit f14fa558ae9e139c94ee3af4a1ef1df313b2ff66)
+(cherry picked from commit dd8aa0871d9cafa60a916d4ec01dd82d64edf7ed)
+---
+ TODO                                | 2 +-
+ src/libsystemd/sd-bus/bus-message.h | 2 +-
+ src/libsystemd/sd-bus/sd-bus.c      | 8 ++++----
+ src/shared/bus-polkit.c             | 2 +-
+ 4 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/TODO b/TODO
+index 462db57..327fead 100644
+--- a/TODO
++++ b/TODO
+@@ -138,7 +138,7 @@ Features:
+ 
+ * the a-posteriori stopping of units bound to units that disappeared logic
+   should be reworked: there should be a queue of units, and we should only
+-  enqeue stop jobs from a defer event that processes queue instead of
++  enqueue stop jobs from a defer event that processes queue instead of
+   right-away when we find a unit that is bound to one that doesn't exist
+   anymore. (similar to how the stop-unneeded queue has been reworked the same
+   way)
+diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h
+index 7fd3f11..849d638 100644
+--- a/src/libsystemd/sd-bus/bus-message.h
++++ b/src/libsystemd/sd-bus/bus-message.h
+@@ -211,4 +211,4 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m);
+ 
+ void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m);
+ void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m);
+-int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m);
++int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m);
+diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
+index 94380af..c20adcf 100644
+--- a/src/libsystemd/sd-bus/sd-bus.c
++++ b/src/libsystemd/sd-bus/sd-bus.c
+@@ -4145,7 +4145,7 @@ _public_ int sd_bus_get_close_on_exit(sd_bus *bus) {
+         return bus->close_on_exit;
+ }
+ 
+-int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m) {
++int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) {
+         int r;
+ 
+         assert_return(bus, -EINVAL);
+@@ -4157,9 +4157,9 @@ int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m) {
+         if (!BUS_IS_OPEN(bus->state))
+                 return -ENOTCONN;
+ 
+-        /* Re-enqeue a message for reading. This is primarily useful for PolicyKit-style authentication,
+-         * where we want accept a message, then determine we need to interactively authenticate the user, and
+-         * when we have that process the message again. */
++        /* Re-enqueue a message for reading. This is primarily useful for PolicyKit-style authentication,
++         * where we accept a message, then determine we need to interactively authenticate the user, and then
++         * we want to process the message again. */
+ 
+         r = bus_rqueue_make_room(bus);
+         if (r < 0)
+diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c
+index 02c11aa..d1d2456 100644
+--- a/src/shared/bus-polkit.c
++++ b/src/shared/bus-polkit.c
+@@ -236,7 +236,7 @@ static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_e
+         if (r < 0)
+                 goto fail;
+ 
+-        r = sd_bus_enqeue_for_read(sd_bus_message_get_bus(q->request), q->request);
++        r = sd_bus_enqueue_for_read(sd_bus_message_get_bus(q->request), q->request);
+         if (r < 0)
+                 goto fail;
+ 
diff --git a/debian/patches/bus-polkit-rename-return-error-parameter-to-ret_error.patch b/debian/patches/bus-polkit-rename-return-error-parameter-to-ret_error.patch
new file mode 100644
index 0000000..a7c9cc5
--- /dev/null
+++ b/debian/patches/bus-polkit-rename-return-error-parameter-to-ret_error.patch
@@ -0,0 +1,67 @@
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 22 Jan 2020 14:29:43 +0100
+Subject: bus-polkit: rename return error parameter to ret_error
+
+(cherry picked from commit 773b1a7916bfce3aa2a21ecf534d475032e8528e)
+(cherry picked from commit 5b2442d5c3ec1c86a3a8d1c1abe3234a570ba5e6)
+(cherry picked from commit 4441844d5889a39d9d059c30e5d94c916d9d6735)
+(cherry picked from commit 816d5e2d6dd83a3bd0ff56a352295831cb937198)
+---
+ src/shared/bus-polkit.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c
+index da4aee5..f93aa17 100644
+--- a/src/shared/bus-polkit.c
++++ b/src/shared/bus-polkit.c
+@@ -37,7 +37,7 @@ int bus_test_polkit(
+                 const char **details,
+                 uid_t good_user,
+                 bool *_challenge,
+-                sd_bus_error *e) {
++                sd_bus_error *ret_error) {
+ 
+         int r;
+ 
+@@ -102,11 +102,11 @@ int bus_test_polkit(
+                 if (r < 0)
+                         return r;
+ 
+-                r = sd_bus_call(call->bus, request, 0, e, &reply);
++                r = sd_bus_call(call->bus, request, 0, ret_error, &reply);
+                 if (r < 0) {
+                         /* Treat no PK available as access denied */
+-                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
+-                                sd_bus_error_free(e);
++                        if (sd_bus_error_has_name(ret_error, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
++                                sd_bus_error_free(ret_error);
+                                 return -EACCES;
+                         }
+ 
+@@ -196,7 +196,7 @@ int bus_verify_polkit_async(
+                 bool interactive,
+                 uid_t good_user,
+                 Hashmap **registry,
+-                sd_bus_error *error) {
++                sd_bus_error *ret_error) {
+ 
+ #if ENABLE_POLKIT
+         _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
+@@ -237,7 +237,7 @@ int bus_verify_polkit_async(
+                                 return -EACCES;
+ 
+                         /* Copy error from polkit reply */
+-                        sd_bus_error_copy(error, e);
++                        sd_bus_error_copy(ret_error, e);
+                         return -sd_bus_error_get_errno(e);
+                 }
+ 
+@@ -251,7 +251,7 @@ int bus_verify_polkit_async(
+                         return 1;
+ 
+                 if (challenge)
+-                        return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
++                        return sd_bus_error_set(ret_error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
+ 
+                 return -EACCES;
+         }
diff --git a/debian/patches/bus-util-treat-org.freedesktop.DBus.Error.ServiceUnknown-.patch b/debian/patches/bus-util-treat-org.freedesktop.DBus.Error.ServiceUnknown-.patch
new file mode 100644
index 0000000..ffd349f
--- /dev/null
+++ b/debian/patches/bus-util-treat-org.freedesktop.DBus.Error.ServiceUnknown-.patch
@@ -0,0 +1,34 @@
+From: Yu Watanabe <watanabe.yu+github at gmail.com>
+Date: Thu, 4 Apr 2019 13:35:29 +0900
+Subject: bus-util: treat org.freedesktop.DBus.Error.ServiceUnknown nicely
+ when polkit does not exist
+
+Fixes #12209.
+
+(cherry picked from commit 8c69fe79df6394f6b8b8d0bb536a265caf417868)
+(cherry picked from commit 0bb488b22144aeb87d93e97123f71babe116261f)
+---
+ src/shared/bus-util.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
+index 9d31fba..a406dd8 100644
+--- a/src/shared/bus-util.c
++++ b/src/shared/bus-util.c
+@@ -410,14 +410,14 @@ int bus_verify_polkit_async(
+                 if (sd_bus_message_is_method_error(q->reply, NULL)) {
+                         const sd_bus_error *e;
+ 
+-                        /* Copy error from polkit reply */
+                         e = sd_bus_message_get_error(q->reply);
+-                        sd_bus_error_copy(error, e);
+ 
+                         /* Treat no PK available as access denied */
+                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
+                                 return -EACCES;
+ 
++                        /* Copy error from polkit reply */
++                        sd_bus_error_copy(error, e);
+                         return -sd_bus_error_get_errno(e);
+                 }
+ 
diff --git a/debian/patches/debian/Use-Debian-specific-config-files.patch b/debian/patches/debian/Use-Debian-specific-config-files.patch
index ba4d9ba..1ad2608 100644
--- a/debian/patches/debian/Use-Debian-specific-config-files.patch
+++ b/debian/patches/debian/Use-Debian-specific-config-files.patch
@@ -80,10 +80,10 @@ index aa4a89c..8f36bbe 100644
                  char *s;
  
 diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c
-index 6b6b32a..cb63d45 100644
+index c203c7a..f4ee123 100644
 --- a/src/locale/keymap-util.c
 +++ b/src/locale/keymap-util.c
-@@ -95,6 +95,7 @@ void locale_simplify(char *locale[_VARIABLE_LC_MAX]) {
+@@ -97,6 +97,7 @@ void locale_simplify(char *locale[_VARIABLE_LC_MAX]) {
  int locale_read_data(Context *c, sd_bus_message *m) {
          struct stat st;
          int r;
@@ -91,7 +91,7 @@ index 6b6b32a..cb63d45 100644
  
          /* Do not try to re-read the file within single bus operation. */
          if (m) {
-@@ -105,7 +106,11 @@ int locale_read_data(Context *c, sd_bus_message *m) {
+@@ -107,7 +108,11 @@ int locale_read_data(Context *c, sd_bus_message *m) {
                  c->locale_cache = sd_bus_message_ref(m);
          }
  
@@ -104,7 +104,7 @@ index 6b6b32a..cb63d45 100644
          if (r < 0 && errno != ENOENT)
                  return -errno;
  
-@@ -120,7 +125,7 @@ int locale_read_data(Context *c, sd_bus_message *m) {
+@@ -122,7 +127,7 @@ int locale_read_data(Context *c, sd_bus_message *m) {
                  c->locale_mtime = t;
                  context_free_locale(c);
  
@@ -113,7 +113,7 @@ index 6b6b32a..cb63d45 100644
                                     "LANG",              &c->locale[VARIABLE_LANG],
                                     "LANGUAGE",          &c->locale[VARIABLE_LANGUAGE],
                                     "LC_CTYPE",          &c->locale[VARIABLE_LC_CTYPE],
-@@ -201,8 +206,6 @@ int vconsole_read_data(Context *c, sd_bus_message *m) {
+@@ -203,8 +208,6 @@ int vconsole_read_data(Context *c, sd_bus_message *m) {
  }
  
  int x11_read_data(Context *c, sd_bus_message *m) {
@@ -122,7 +122,7 @@ index 6b6b32a..cb63d45 100644
          struct stat st;
          usec_t t;
          int r;
-@@ -216,7 +219,7 @@ int x11_read_data(Context *c, sd_bus_message *m) {
+@@ -218,7 +221,7 @@ int x11_read_data(Context *c, sd_bus_message *m) {
                  c->x11_cache = sd_bus_message_ref(m);
          }
  
@@ -131,7 +131,7 @@ index 6b6b32a..cb63d45 100644
                  if (errno != ENOENT)
                          return -errno;
  
-@@ -233,61 +236,14 @@ int x11_read_data(Context *c, sd_bus_message *m) {
+@@ -235,61 +238,14 @@ int x11_read_data(Context *c, sd_bus_message *m) {
          c->x11_mtime = t;
          context_free_x11(c);
  
@@ -200,7 +200,7 @@ index 6b6b32a..cb63d45 100644
  
          return 0;
  }
-@@ -296,9 +252,18 @@ int locale_write_data(Context *c, char ***settings) {
+@@ -298,9 +254,18 @@ int locale_write_data(Context *c, char ***settings) {
          _cleanup_strv_free_ char **l = NULL;
          struct stat st;
          int r, p;
@@ -219,7 +219,7 @@ index 6b6b32a..cb63d45 100644
          for (p = 0; p < _VARIABLE_LC_MAX; p++) {
                  _cleanup_free_ char *t = NULL;
                  char **u;
-@@ -321,20 +286,20 @@ int locale_write_data(Context *c, char ***settings) {
+@@ -323,20 +288,20 @@ int locale_write_data(Context *c, char ***settings) {
          }
  
          if (strv_isempty(l)) {
@@ -243,7 +243,7 @@ index 6b6b32a..cb63d45 100644
                  c->locale_mtime = timespec_load(&st.st_mtim);
  
          return 0;
-@@ -402,70 +367,104 @@ int vconsole_write_data(Context *c) {
+@@ -404,70 +369,104 @@ int vconsole_write_data(Context *c) {
  }
  
  int x11_write_data(Context *c) {
@@ -392,7 +392,7 @@ index 6b6b32a..cb63d45 100644
          return r;
  }
 diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
-index 324d4a4..4d54ac3 100644
+index 398d4f4..d681d58 100644
 --- a/src/timedate/timedated.c
 +++ b/src/timedate/timedated.c
 @@ -215,6 +215,7 @@ static int context_read_data(Context *c) {
diff --git a/debian/patches/polkit-on-async-pk-requests-re-validate-action-details.patch b/debian/patches/polkit-on-async-pk-requests-re-validate-action-details.patch
new file mode 100644
index 0000000..c6ffacf
--- /dev/null
+++ b/debian/patches/polkit-on-async-pk-requests-re-validate-action-details.patch
@@ -0,0 +1,81 @@
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 22 Jan 2020 16:52:10 +0100
+Subject: polkit: on async pk requests, re-validate action/details
+
+When we do an async pk request, let's store which action/details we used
+for the original request, and when we are called for the second time,
+let's compare. If the action/details changed, let's not allow the access
+to go through.
+
+(cherry picked from commit 7f56982289275ce84e20f0554475864953e6aaab)
+(cherry picked from commit 0697d0d972c8d91395eb539a8e87e4aec8b37b75)
+(cherry picked from commit 54791aff01aa93a8b621808d80ab506b54f245c8)
+(cherry picked from commit 70d0f5ea5952a0cedd84c352070613df4ba5fc8f)
+---
+ src/shared/bus-polkit.c | 30 +++++++++++++++++++++++++++---
+ 1 file changed, 27 insertions(+), 3 deletions(-)
+
+diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c
+index 81193b8..6343dd6 100644
+--- a/src/shared/bus-polkit.c
++++ b/src/shared/bus-polkit.c
+@@ -155,6 +155,9 @@ int bus_test_polkit(
+ #if ENABLE_POLKIT
+ 
+ typedef struct AsyncPolkitQuery {
++        char *action;
++        char **details;
++
+         sd_bus_message *request, *reply;
+         sd_bus_message_handler_t callback;
+         void *userdata;
+@@ -175,6 +178,9 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) {
+         sd_bus_message_unref(q->request);
+         sd_bus_message_unref(q->reply);
+ 
++        free(q->action);
++        strv_free(q->details);
++
+         free(q);
+ }
+ 
+@@ -239,11 +245,17 @@ int bus_verify_polkit_async(
+         if (q) {
+                 int authorized, challenge;
+ 
+-                /* This is the second invocation of this function, and
+-                 * there's already a response from polkit, let's
+-                 * process it */
++                /* This is the second invocation of this function, and there's already a response from
++                 * polkit, let's process it */
+                 assert(q->reply);
+ 
++                /* If the operation we want to authenticate changed between the first and the second time,
++                 * let's not use this authentication, it might be out of date as the object and context we
++                 * operate on might have changed. */
++                if (!streq(q->action, action) ||
++                    !strv_equal(q->details, (char**) details))
++                        return -ESTALE;
++
+                 if (sd_bus_message_is_method_error(q->reply, NULL)) {
+                         const sd_bus_error *e;
+ 
+@@ -339,6 +351,18 @@ int bus_verify_polkit_async(
+         q->callback = callback;
+         q->userdata = userdata;
+ 
++        q->action = strdup(action);
++        if (!q->action) {
++                async_polkit_query_free(q);
++                return -ENOMEM;
++        }
++
++        q->details = strv_copy((char**) details);
++        if (!q->details) {
++                async_polkit_query_free(q);
++                return -ENOMEM;
++        }
++
+         r = hashmap_put(*registry, call, q);
+         if (r < 0) {
+                 async_polkit_query_free(q);
diff --git a/debian/patches/polkit-reuse-some-common-bus-message-appending-code.patch b/debian/patches/polkit-reuse-some-common-bus-message-appending-code.patch
new file mode 100644
index 0000000..98e43ca
--- /dev/null
+++ b/debian/patches/polkit-reuse-some-common-bus-message-appending-code.patch
@@ -0,0 +1,107 @@
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 22 Jan 2020 16:44:43 +0100
+Subject: polkit: reuse some common bus message appending code
+
+(cherry picked from commit 95f82ae9d774f3508ce89dcbdd0714ef7385df59)
+(cherry picked from commit 2589995acdb297a073270b54d8fff54b98fa57e9)
+(cherry picked from commit 81532beddcc3b7946a573e15641742c452c66db7)
+(cherry picked from commit 18b7b7fe307f03928bfea3ef0663048b7be6e4fb)
+---
+ src/shared/bus-polkit.c | 56 ++++++++++++++++++++++++++++---------------------
+ 1 file changed, 32 insertions(+), 24 deletions(-)
+
+diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c
+index f93aa17..81193b8 100644
+--- a/src/shared/bus-polkit.c
++++ b/src/shared/bus-polkit.c
+@@ -30,6 +30,34 @@ static int check_good_user(sd_bus_message *m, uid_t good_user) {
+         return sender_uid == good_user;
+ }
+ 
++#if ENABLE_POLKIT
++static int bus_message_append_strv_key_value(
++                sd_bus_message *m,
++                const char **l) {
++
++        const char **k, **v;
++        int r;
++
++        assert(m);
++
++        r = sd_bus_message_open_container(m, 'a', "{ss}");
++        if (r < 0)
++                return r;
++
++        STRV_FOREACH_PAIR(k, v, l) {
++                r = sd_bus_message_append(m, "{ss}", *k, *v);
++                if (r < 0)
++                        return r;
++        }
++
++        r = sd_bus_message_close_container(m);
++        if (r < 0)
++                return r;
++
++        return r;
++}
++#endif
++
+ int bus_test_polkit(
+                 sd_bus_message *call,
+                 int capability,
+@@ -60,7 +88,7 @@ int bus_test_polkit(
+                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
+                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+                 int authorized = false, challenge = false;
+-                const char *sender, **k, **v;
++                const char *sender;
+ 
+                 sender = sd_bus_message_get_sender(call);
+                 if (!sender)
+@@ -84,17 +112,7 @@ int bus_test_polkit(
+                 if (r < 0)
+                         return r;
+ 
+-                r = sd_bus_message_open_container(request, 'a', "{ss}");
+-                if (r < 0)
+-                        return r;
+-
+-                STRV_FOREACH_PAIR(k, v, details) {
+-                        r = sd_bus_message_append(request, "{ss}", *k, *v);
+-                        if (r < 0)
+-                                return r;
+-                }
+-
+-                r = sd_bus_message_close_container(request);
++                r = bus_message_append_strv_key_value(request, details);
+                 if (r < 0)
+                         return r;
+ 
+@@ -201,7 +219,7 @@ int bus_verify_polkit_async(
+ #if ENABLE_POLKIT
+         _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
+         AsyncPolkitQuery *q;
+-        const char *sender, **k, **v;
++        const char *sender;
+         sd_bus_message_handler_t callback;
+         void *userdata;
+         int c;
+@@ -305,17 +323,7 @@ int bus_verify_polkit_async(
+         if (r < 0)
+                 return r;
+ 
+-        r = sd_bus_message_open_container(pk, 'a', "{ss}");
+-        if (r < 0)
+-                return r;
+-
+-        STRV_FOREACH_PAIR(k, v, details) {
+-                r = sd_bus_message_append(pk, "{ss}", *k, *v);
+-                if (r < 0)
+-                        return r;
+-        }
+-
+-        r = sd_bus_message_close_container(pk);
++        r = bus_message_append_strv_key_value(pk, details);
+         if (r < 0)
+                 return r;
+ 
diff --git a/debian/patches/polkit-use-structured-initialization.patch b/debian/patches/polkit-use-structured-initialization.patch
new file mode 100644
index 0000000..683fb3b
--- /dev/null
+++ b/debian/patches/polkit-use-structured-initialization.patch
@@ -0,0 +1,36 @@
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 22 Jan 2020 16:53:59 +0100
+Subject: polkit: use structured initialization
+
+(cherry picked from commit f4425c72c7395ec93ae00052916a66e2f60f200b)
+(cherry picked from commit 5926f9f1723fd753a0c524ed96a13538c851395e)
+(cherry picked from commit 4d80c8f158333117dabb0e6f7592059cddb1d6d0)
+(cherry picked from commit 9131bb3d45e6384309eea42affd1aa757ef28cd7)
+---
+ src/shared/bus-polkit.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c
+index 6343dd6..c42c39a 100644
+--- a/src/shared/bus-polkit.c
++++ b/src/shared/bus-polkit.c
+@@ -343,13 +343,15 @@ int bus_verify_polkit_async(
+         if (r < 0)
+                 return r;
+ 
+-        q = new0(AsyncPolkitQuery, 1);
++        q = new(AsyncPolkitQuery, 1);
+         if (!q)
+                 return -ENOMEM;
+ 
+-        q->request = sd_bus_message_ref(call);
+-        q->callback = callback;
+-        q->userdata = userdata;
++        *q = (AsyncPolkitQuery) {
++                .request = sd_bus_message_ref(call),
++                .callback = callback,
++                .userdata = userdata,
++        };
+ 
+         q->action = strdup(action);
+         if (!q->action) {
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 at 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);
diff --git a/debian/patches/resolve-fix-memleak.patch b/debian/patches/resolve-fix-memleak.patch
new file mode 100644
index 0000000..f37f322
--- /dev/null
+++ b/debian/patches/resolve-fix-memleak.patch
@@ -0,0 +1,32 @@
+From: Yu Watanabe <watanabe.yu+github at gmail.com>
+Date: Fri, 12 Jul 2019 14:19:36 +0900
+Subject: resolve: fix memleak
+
+(cherry picked from commit 2400ae29a55aab8659fa778f02d1884b86a95062)
+(cherry picked from commit 7727e6c0ae1769ba7ea9959aa721236c025adbdf)
+(cherry picked from commit 9755ac0744f858cfa952033552ac6f2401e0f2d0)
+---
+ src/resolve/resolved-manager.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
+index b3d35c8..2017b0e 100644
+--- a/src/resolve/resolved-manager.c
++++ b/src/resolve/resolved-manager.c
+@@ -11,6 +11,7 @@
+ 
+ #include "af-list.h"
+ #include "alloc-util.h"
++#include "bus-util.h"
+ #include "dirent-util.h"
+ #include "dns-domain.h"
+ #include "fd-util.h"
+@@ -689,6 +690,8 @@ Manager *manager_free(Manager *m) {
+         manager_mdns_stop(m);
+         manager_dns_stub_stop(m);
+ 
++        bus_verify_polkit_async_registry_free(m->polkit_registry);
++
+         sd_bus_flush_close_unref(m->bus);
+ 
+         sd_event_source_unref(m->sigusr1_event_source);
diff --git a/debian/patches/sd-bus-introduce-API-for-re-enqueuing-incoming-messages.patch b/debian/patches/sd-bus-introduce-API-for-re-enqueuing-incoming-messages.patch
new file mode 100644
index 0000000..a628fdd
--- /dev/null
+++ b/debian/patches/sd-bus-introduce-API-for-re-enqueuing-incoming-messages.patch
@@ -0,0 +1,65 @@
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 22 Jan 2020 17:05:17 +0100
+Subject: sd-bus: introduce API for re-enqueuing incoming messages
+
+When authorizing via PolicyKit we want to process incoming method calls
+twice: once to process and figure out that we need PK authentication,
+and a second time after we aquired PK authentication to actually execute
+the operation. With this new call sd_bus_enqueue_for_read() we have a
+way to put an incoming message back into the read queue for this
+purpose.
+
+This might have other uses too, for example debugging.
+
+(cherry picked from commit 1068447e6954dc6ce52f099ed174c442cb89ed54)
+
+zjs: patch modified to not make the function public
+(cherry picked from commit 83bfc0d8dd026814d23e3fdfa46806394f775526)
+(cherry picked from commit 2e504c92d195d407cec3ba9ed156b195c31a5f3f)
+(cherry picked from commit 351627d4bfa39dd05f28d889967383af2372de6d)
+---
+ src/libsystemd/sd-bus/bus-message.h |  1 +
+ src/libsystemd/sd-bus/sd-bus.c      | 24 ++++++++++++++++++++++++
+ 2 files changed, 25 insertions(+)
+
+diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h
+index 0115437..7fd3f11 100644
+--- a/src/libsystemd/sd-bus/bus-message.h
++++ b/src/libsystemd/sd-bus/bus-message.h
+@@ -211,3 +211,4 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m);
+ 
+ void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m);
+ void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m);
++int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m);
+diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
+index 1ff858f..94380af 100644
+--- a/src/libsystemd/sd-bus/sd-bus.c
++++ b/src/libsystemd/sd-bus/sd-bus.c
+@@ -4144,3 +4144,27 @@ _public_ int sd_bus_get_close_on_exit(sd_bus *bus) {
+ 
+         return bus->close_on_exit;
+ }
++
++int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m) {
++        int r;
++
++        assert_return(bus, -EINVAL);
++        assert_return(bus = bus_resolve(bus), -ENOPKG);
++        assert_return(m, -EINVAL);
++        assert_return(m->sealed, -EINVAL);
++        assert_return(!bus_pid_changed(bus), -ECHILD);
++
++        if (!BUS_IS_OPEN(bus->state))
++                return -ENOTCONN;
++
++        /* Re-enqeue a message for reading. This is primarily useful for PolicyKit-style authentication,
++         * where we want accept a message, then determine we need to interactively authenticate the user, and
++         * when we have that process the message again. */
++
++        r = bus_rqueue_make_room(bus);
++        if (r < 0)
++                return r;
++
++        bus->rqueue[bus->rqueue_size++] = sd_bus_message_ref(m);
++        return 0;
++}
diff --git a/debian/patches/series b/debian/patches/series
index d1a5bd2..1f3cd3d 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -42,6 +42,8 @@ mount-remove-unused-mount_is_auto-and-mount_is_automount.patch
 core-set-fs.file-max-sysctl-to-LONG_MAX-rather-than-ULONG.patch
 execute-remove-one-redundant-comparison-check.patch
 core-change-ownership-mode-of-the-execution-directories-a.patch
+bus-util-treat-org.freedesktop.DBus.Error.ServiceUnknown-.patch
+resolve-fix-memleak.patch
 debian/Use-Debian-specific-config-files.patch
 debian/Bring-tmpfiles.d-tmp.conf-in-line-with-Debian-defaul.patch
 debian/Make-run-lock-tmpfs-an-API-fs.patch
diff --git a/debian/patches/shared-split-out-polkit-stuff-from-bus-util.c-bus-polkit..patch b/debian/patches/shared-split-out-polkit-stuff-from-bus-util.c-bus-polkit..patch
new file mode 100644
index 0000000..3a14551
--- /dev/null
+++ b/debian/patches/shared-split-out-polkit-stuff-from-bus-util.c-bus-polkit..patch
@@ -0,0 +1,1190 @@
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 22 Jan 2020 11:39:22 +0100
+Subject: =?utf-8?q?shared=3A_split_out_polkit_stuff_from_bus-util=2Ec_?=
+ =?utf-8?q?=E2=86=92_bus-polkit=2Ec?=
+
+It's enough, complex stuff to warrant its own source file.
+
+No other changes, just splitting out.
+
+(cherry picked from commit 269e4d2d6b75329ae39a71ebe2c14500e03cda95)
+(cherry picked from commit 0a19ff7004e4a567566a0a7be6b050cf34c0bfe5)
+(cherry picked from commit 31a1d569db43af04669ec487f3e741ddc6d12969)
+(cherry picked from commit a4722a8df23f6612c47f1bb848a6a7c81dcbdccb)
+---
+ src/core/dbus-unit.c               |   1 +
+ src/core/dbus.c                    |   2 +-
+ src/hostname/hostnamed.c           |   2 +-
+ src/import/importd.c               |   2 +-
+ src/locale/keymap-util.c           |   2 +
+ src/locale/localed.c               |   2 +-
+ src/login/logind-dbus.c            |   1 +
+ src/login/logind-seat-dbus.c       |   1 +
+ src/login/logind-session-dbus.c    |   1 +
+ src/login/logind-user-dbus.c       |   1 +
+ src/login/logind.c                 |   2 +-
+ src/machine/image-dbus.c           |   1 +
+ src/machine/machine-dbus.c         |   1 +
+ src/machine/machined-dbus.c        |   1 +
+ src/machine/machined.c             |   2 +-
+ src/network/networkd-link-bus.c    |   2 +
+ src/network/networkd-manager-bus.c |   3 +
+ src/network/networkd-manager.c     |   1 +
+ src/portable/portabled-bus.c       |   2 +-
+ src/portable/portabled-image-bus.c |   1 +
+ src/portable/portabled.c           |   2 +-
+ src/resolve/resolved-bus.c         |   1 +
+ src/resolve/resolved-dnssd-bus.c   |   5 +-
+ src/resolve/resolved-link-bus.c    |   1 +
+ src/resolve/resolved-manager.c     |   2 +-
+ src/shared/bus-polkit.c            | 358 +++++++++++++++++++++++++++++++++++++
+ src/shared/bus-polkit.h            |  11 ++
+ src/shared/bus-util.c              | 357 +-----------------------------------
+ src/shared/bus-util.h              |   7 +-
+ src/shared/meson.build             |   2 +
+ src/timedate/timedated.c           |   2 +-
+ 31 files changed, 406 insertions(+), 373 deletions(-)
+ create mode 100644 src/shared/bus-polkit.c
+ create mode 100644 src/shared/bus-polkit.h
+
+diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
+index 17c2003..ce0fbdb 100644
+--- a/src/core/dbus-unit.c
++++ b/src/core/dbus-unit.c
+@@ -5,6 +5,7 @@
+ #include "alloc-util.h"
+ #include "bpf-firewall.h"
+ #include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "cgroup-util.h"
+ #include "condition.h"
+ #include "dbus-job.h"
+diff --git a/src/core/dbus.c b/src/core/dbus.c
+index 255b86e..91c06ce 100644
+--- a/src/core/dbus.c
++++ b/src/core/dbus.c
+@@ -10,7 +10,7 @@
+ #include "bus-common-errors.h"
+ #include "bus-error.h"
+ #include "bus-internal.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "dbus-automount.h"
+ #include "dbus-cgroup.h"
+ #include "dbus-device.h"
+diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
+index 7777450..9b98f32 100644
+--- a/src/hostname/hostnamed.c
++++ b/src/hostname/hostnamed.c
+@@ -7,7 +7,7 @@
+ 
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "def.h"
+ #include "env-file-label.h"
+ #include "env-file.h"
+diff --git a/src/import/importd.c b/src/import/importd.c
+index 2426933..15430d8 100644
+--- a/src/import/importd.c
++++ b/src/import/importd.c
+@@ -7,7 +7,7 @@
+ 
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "def.h"
+ #include "fd-util.h"
+ #include "float.h"
+diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c
+index 6b6b32a..c203c7a 100644
+--- a/src/locale/keymap-util.c
++++ b/src/locale/keymap-util.c
+@@ -6,7 +6,9 @@
+ #include <unistd.h>
+ 
+ #include "bus-util.h"
++#include "bus-polkit.h"
+ #include "def.h"
++#include "env-file-label.h"
+ #include "env-file.h"
+ #include "env-file-label.h"
+ #include "env-util.h"
+diff --git a/src/locale/localed.c b/src/locale/localed.c
+index f851d35..0bc02a0 100644
+--- a/src/locale/localed.c
++++ b/src/locale/localed.c
+@@ -14,7 +14,7 @@
+ #include "alloc-util.h"
+ #include "bus-error.h"
+ #include "bus-message.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "def.h"
+ #include "keymap-util.h"
+ #include "locale-util.h"
+diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
+index b9ea370..91350fd 100644
+--- a/src/login/logind-dbus.c
++++ b/src/login/logind-dbus.c
+@@ -12,6 +12,7 @@
+ #include "audit-util.h"
+ #include "bus-common-errors.h"
+ #include "bus-error.h"
++#include "bus-polkit.h"
+ #include "bus-unit-util.h"
+ #include "bus-util.h"
+ #include "cgroup-util.h"
+diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
+index 6ee5a1c..28ea5b7 100644
+--- a/src/login/logind-seat-dbus.c
++++ b/src/login/logind-seat-dbus.c
+@@ -6,6 +6,7 @@
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+ #include "bus-label.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "logind-seat.h"
+ #include "logind.h"
+diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
+index df5bfba..bd5c1fe 100644
+--- a/src/login/logind-session-dbus.c
++++ b/src/login/logind-session-dbus.c
+@@ -6,6 +6,7 @@
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+ #include "bus-label.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "fd-util.h"
+ #include "logind-session-device.h"
+diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
+index fcaeba1..129696e 100644
+--- a/src/login/logind-user-dbus.c
++++ b/src/login/logind-user-dbus.c
+@@ -4,6 +4,7 @@
+ #include <string.h>
+ 
+ #include "alloc-util.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "format-util.h"
+ #include "logind-user.h"
+diff --git a/src/login/logind.c b/src/login/logind.c
+index 95ec0a5..171b898 100644
+--- a/src/login/logind.c
++++ b/src/login/logind.c
+@@ -10,7 +10,7 @@
+ 
+ #include "alloc-util.h"
+ #include "bus-error.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "cgroup-util.h"
+ #include "def.h"
+ #include "device-util.h"
+diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
+index 7e7f0d5..1322f3e 100644
+--- a/src/machine/image-dbus.c
++++ b/src/machine/image-dbus.c
+@@ -5,6 +5,7 @@
+ 
+ #include "alloc-util.h"
+ #include "bus-label.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "copy.h"
+ #include "dissect-image.h"
+diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
+index 7a558df..39905e5 100644
+--- a/src/machine/machine-dbus.c
++++ b/src/machine/machine-dbus.c
+@@ -15,6 +15,7 @@
+ #include "bus-common-errors.h"
+ #include "bus-internal.h"
+ #include "bus-label.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "copy.h"
+ #include "env-file.h"
+diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
+index fea9cc2..f00be23 100644
+--- a/src/machine/machined-dbus.c
++++ b/src/machine/machined-dbus.c
+@@ -9,6 +9,7 @@
+ #include "alloc-util.h"
+ #include "btrfs-util.h"
+ #include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "cgroup-util.h"
+ #include "fd-util.h"
+diff --git a/src/machine/machined.c b/src/machine/machined.c
+index 0b92b1c..e3456d8 100644
+--- a/src/machine/machined.c
++++ b/src/machine/machined.c
+@@ -8,7 +8,7 @@
+ 
+ #include "alloc-util.h"
+ #include "bus-error.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "cgroup-util.h"
+ #include "dirent-util.h"
+ #include "fd-util.h"
+diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c
+index 0dbcd86..beee910 100644
+--- a/src/network/networkd-link-bus.c
++++ b/src/network/networkd-link-bus.c
+@@ -1,6 +1,8 @@
+ /* SPDX-License-Identifier: LGPL-2.1+ */
+ 
+ #include "alloc-util.h"
++#include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "networkd-link.h"
+ #include "networkd-manager.h"
+diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c
+index 8c52783..7628878 100644
+--- a/src/network/networkd-manager-bus.c
++++ b/src/network/networkd-manager-bus.c
+@@ -1,7 +1,10 @@
+ /* SPDX-License-Identifier: LGPL-2.1+ */
+ 
+ #include "alloc-util.h"
++#include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
++#include "networkd-link.h"
+ #include "networkd-manager.h"
+ #include "strv.h"
+ 
+diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
+index acb9a75..bd29fd0 100644
+--- a/src/network/networkd-manager.c
++++ b/src/network/networkd-manager.c
+@@ -9,6 +9,7 @@
+ #include "sd-netlink.h"
+ 
+ #include "alloc-util.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "conf-parser.h"
+ #include "def.h"
+diff --git a/src/portable/portabled-bus.c b/src/portable/portabled-bus.c
+index 3cbdb0b..708ec94 100644
+--- a/src/portable/portabled-bus.c
++++ b/src/portable/portabled-bus.c
+@@ -3,7 +3,7 @@
+ #include "alloc-util.h"
+ #include "btrfs-util.h"
+ #include "bus-common-errors.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "fd-util.h"
+ #include "io-util.h"
+ #include "machine-image.h"
+diff --git a/src/portable/portabled-image-bus.c b/src/portable/portabled-image-bus.c
+index 3605598..beebcf8 100644
+--- a/src/portable/portabled-image-bus.c
++++ b/src/portable/portabled-image-bus.c
+@@ -3,6 +3,7 @@
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+ #include "bus-label.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "fd-util.h"
+ #include "fileio.h"
+diff --git a/src/portable/portabled.c b/src/portable/portabled.c
+index 49a359f..f5a34ff 100644
+--- a/src/portable/portabled.c
++++ b/src/portable/portabled.c
+@@ -4,7 +4,7 @@
+ #include "sd-daemon.h"
+ 
+ #include "alloc-util.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "def.h"
+ #include "main-func.h"
+ #include "portabled-bus.h"
+diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
+index 5b547ba..1638d3b 100644
+--- a/src/resolve/resolved-bus.c
++++ b/src/resolve/resolved-bus.c
+@@ -2,6 +2,7 @@
+ 
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "dns-domain.h"
+ #include "missing_capability.h"
+diff --git a/src/resolve/resolved-dnssd-bus.c b/src/resolve/resolved-dnssd-bus.c
+index 24bb37b..f7dcb3b 100644
+--- a/src/resolve/resolved-dnssd-bus.c
++++ b/src/resolve/resolved-dnssd-bus.c
+@@ -1,9 +1,10 @@
++/* SPDX-License-Identifier: LGPL-2.1+ */
+ 
+ #include "alloc-util.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "missing_capability.h"
+-#include "resolved-dnssd.h"
+ #include "resolved-dnssd-bus.h"
++#include "resolved-dnssd.h"
+ #include "resolved-link.h"
+ #include "strv.h"
+ #include "user-util.h"
+diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c
+index 96093ff..53f017c 100644
+--- a/src/resolve/resolved-link-bus.c
++++ b/src/resolve/resolved-link-bus.c
+@@ -2,6 +2,7 @@
+ 
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "parse-util.h"
+ #include "resolve-util.h"
+diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
+index 2017b0e..422ec23 100644
+--- a/src/resolve/resolved-manager.c
++++ b/src/resolve/resolved-manager.c
+@@ -11,7 +11,7 @@
+ 
+ #include "af-list.h"
+ #include "alloc-util.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "dirent-util.h"
+ #include "dns-domain.h"
+ #include "fd-util.h"
+diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c
+new file mode 100644
+index 0000000..da4aee5
+--- /dev/null
++++ b/src/shared/bus-polkit.c
+@@ -0,0 +1,358 @@
++/* SPDX-License-Identifier: LGPL-2.1+ */
++
++#include "bus-internal.h"
++#include "bus-message.h"
++#include "bus-polkit.h"
++#include "strv.h"
++#include "user-util.h"
++
++static int check_good_user(sd_bus_message *m, uid_t good_user) {
++        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
++        uid_t sender_uid;
++        int r;
++
++        assert(m);
++
++        if (good_user == UID_INVALID)
++                return 0;
++
++        r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
++        if (r < 0)
++                return r;
++
++        /* Don't trust augmented credentials for authorization */
++        assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
++
++        r = sd_bus_creds_get_euid(creds, &sender_uid);
++        if (r < 0)
++                return r;
++
++        return sender_uid == good_user;
++}
++
++int bus_test_polkit(
++                sd_bus_message *call,
++                int capability,
++                const char *action,
++                const char **details,
++                uid_t good_user,
++                bool *_challenge,
++                sd_bus_error *e) {
++
++        int r;
++
++        assert(call);
++        assert(action);
++
++        /* Tests non-interactively! */
++
++        r = check_good_user(call, good_user);
++        if (r != 0)
++                return r;
++
++        r = sd_bus_query_sender_privilege(call, capability);
++        if (r < 0)
++                return r;
++        else if (r > 0)
++                return 1;
++#if ENABLE_POLKIT
++        else {
++                _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
++                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
++                int authorized = false, challenge = false;
++                const char *sender, **k, **v;
++
++                sender = sd_bus_message_get_sender(call);
++                if (!sender)
++                        return -EBADMSG;
++
++                r = sd_bus_message_new_method_call(
++                                call->bus,
++                                &request,
++                                "org.freedesktop.PolicyKit1",
++                                "/org/freedesktop/PolicyKit1/Authority",
++                                "org.freedesktop.PolicyKit1.Authority",
++                                "CheckAuthorization");
++                if (r < 0)
++                        return r;
++
++                r = sd_bus_message_append(
++                                request,
++                                "(sa{sv})s",
++                                "system-bus-name", 1, "name", "s", sender,
++                                action);
++                if (r < 0)
++                        return r;
++
++                r = sd_bus_message_open_container(request, 'a', "{ss}");
++                if (r < 0)
++                        return r;
++
++                STRV_FOREACH_PAIR(k, v, details) {
++                        r = sd_bus_message_append(request, "{ss}", *k, *v);
++                        if (r < 0)
++                                return r;
++                }
++
++                r = sd_bus_message_close_container(request);
++                if (r < 0)
++                        return r;
++
++                r = sd_bus_message_append(request, "us", 0, NULL);
++                if (r < 0)
++                        return r;
++
++                r = sd_bus_call(call->bus, request, 0, e, &reply);
++                if (r < 0) {
++                        /* Treat no PK available as access denied */
++                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
++                                sd_bus_error_free(e);
++                                return -EACCES;
++                        }
++
++                        return r;
++                }
++
++                r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
++                if (r < 0)
++                        return r;
++
++                r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
++                if (r < 0)
++                        return r;
++
++                if (authorized)
++                        return 1;
++
++                if (_challenge) {
++                        *_challenge = challenge;
++                        return 0;
++                }
++        }
++#endif
++
++        return -EACCES;
++}
++
++#if ENABLE_POLKIT
++
++typedef struct AsyncPolkitQuery {
++        sd_bus_message *request, *reply;
++        sd_bus_message_handler_t callback;
++        void *userdata;
++        sd_bus_slot *slot;
++        Hashmap *registry;
++} AsyncPolkitQuery;
++
++static void async_polkit_query_free(AsyncPolkitQuery *q) {
++
++        if (!q)
++                return;
++
++        sd_bus_slot_unref(q->slot);
++
++        if (q->registry && q->request)
++                hashmap_remove(q->registry, q->request);
++
++        sd_bus_message_unref(q->request);
++        sd_bus_message_unref(q->reply);
++
++        free(q);
++}
++
++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;
++        int r;
++
++        assert(reply);
++        assert(q);
++
++        q->slot = sd_bus_slot_unref(q->slot);
++        q->reply = sd_bus_message_ref(reply);
++
++        r = sd_bus_message_rewind(q->request, true);
++        if (r < 0) {
++                r = sd_bus_reply_method_errno(q->request, r, NULL);
++                goto finish;
++        }
++
++        r = q->callback(q->request, q->userdata, &error_buffer);
++        r = bus_maybe_reply_error(q->request, r, &error_buffer);
++
++finish:
++        async_polkit_query_free(q);
++
++        return r;
++}
++
++#endif
++
++int bus_verify_polkit_async(
++                sd_bus_message *call,
++                int capability,
++                const char *action,
++                const char **details,
++                bool interactive,
++                uid_t good_user,
++                Hashmap **registry,
++                sd_bus_error *error) {
++
++#if ENABLE_POLKIT
++        _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
++        AsyncPolkitQuery *q;
++        const char *sender, **k, **v;
++        sd_bus_message_handler_t callback;
++        void *userdata;
++        int c;
++#endif
++        int r;
++
++        assert(call);
++        assert(action);
++        assert(registry);
++
++        r = check_good_user(call, good_user);
++        if (r != 0)
++                return r;
++
++#if ENABLE_POLKIT
++        q = hashmap_get(*registry, call);
++        if (q) {
++                int authorized, challenge;
++
++                /* This is the second invocation of this function, and
++                 * there's already a response from polkit, let's
++                 * process it */
++                assert(q->reply);
++
++                if (sd_bus_message_is_method_error(q->reply, NULL)) {
++                        const sd_bus_error *e;
++
++                        e = sd_bus_message_get_error(q->reply);
++
++                        /* Treat no PK available as access denied */
++                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) ||
++                            sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER))
++                                return -EACCES;
++
++                        /* Copy error from polkit reply */
++                        sd_bus_error_copy(error, e);
++                        return -sd_bus_error_get_errno(e);
++                }
++
++                r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
++                if (r >= 0)
++                        r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
++                if (r < 0)
++                        return r;
++
++                if (authorized)
++                        return 1;
++
++                if (challenge)
++                        return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
++
++                return -EACCES;
++        }
++#endif
++
++        r = sd_bus_query_sender_privilege(call, capability);
++        if (r < 0)
++                return r;
++        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;
++
++        c = sd_bus_message_get_allow_interactive_authorization(call);
++        if (c < 0)
++                return c;
++        if (c > 0)
++                interactive = true;
++
++        r = hashmap_ensure_allocated(registry, NULL);
++        if (r < 0)
++                return r;
++
++        r = sd_bus_message_new_method_call(
++                        call->bus,
++                        &pk,
++                        "org.freedesktop.PolicyKit1",
++                        "/org/freedesktop/PolicyKit1/Authority",
++                        "org.freedesktop.PolicyKit1.Authority",
++                        "CheckAuthorization");
++        if (r < 0)
++                return r;
++
++        r = sd_bus_message_append(
++                        pk,
++                        "(sa{sv})s",
++                        "system-bus-name", 1, "name", "s", sender,
++                        action);
++        if (r < 0)
++                return r;
++
++        r = sd_bus_message_open_container(pk, 'a', "{ss}");
++        if (r < 0)
++                return r;
++
++        STRV_FOREACH_PAIR(k, v, details) {
++                r = sd_bus_message_append(pk, "{ss}", *k, *v);
++                if (r < 0)
++                        return r;
++        }
++
++        r = sd_bus_message_close_container(pk);
++        if (r < 0)
++                return r;
++
++        r = sd_bus_message_append(pk, "us", interactive, NULL);
++        if (r < 0)
++                return r;
++
++        q = new0(AsyncPolkitQuery, 1);
++        if (!q)
++                return -ENOMEM;
++
++        q->request = sd_bus_message_ref(call);
++        q->callback = callback;
++        q->userdata = userdata;
++
++        r = hashmap_put(*registry, call, q);
++        if (r < 0) {
++                async_polkit_query_free(q);
++                return r;
++        }
++
++        q->registry = *registry;
++
++        r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
++        if (r < 0) {
++                async_polkit_query_free(q);
++                return r;
++        }
++
++        return 0;
++#endif
++
++        return -EACCES;
++}
++
++void bus_verify_polkit_async_registry_free(Hashmap *registry) {
++#if ENABLE_POLKIT
++        hashmap_free_with_destructor(registry, async_polkit_query_free);
++#endif
++}
+diff --git a/src/shared/bus-polkit.h b/src/shared/bus-polkit.h
+new file mode 100644
+index 0000000..29b3923
+--- /dev/null
++++ b/src/shared/bus-polkit.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: LGPL-2.1+ */
++#pragma once
++
++#include "sd-bus.h"
++
++#include "hashmap.h"
++
++int bus_test_polkit(sd_bus_message *call, int capability, const char *action, const char **details, uid_t good_user, bool *_challenge, sd_bus_error *e);
++
++int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *action, const char **details, bool interactive, uid_t good_user, Hashmap **registry, sd_bus_error *error);
++void bus_verify_polkit_async_registry_free(Hashmap *registry);
+diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
+index a406dd8..c9d7e76 100644
+--- a/src/shared/bus-util.c
++++ b/src/shared/bus-util.c
+@@ -11,7 +11,6 @@
+ #include <sys/socket.h>
+ #include <unistd.h>
+ 
+-#include "sd-bus-protocol.h"
+ #include "sd-bus.h"
+ #include "sd-daemon.h"
+ #include "sd-event.h"
+@@ -24,15 +23,14 @@
+ #include "bus-util.h"
+ #include "cap-list.h"
+ #include "cgroup-util.h"
+-#include "def.h"
+-#include "escape.h"
+-#include "fd-util.h"
+ #include "missing.h"
+ #include "mountpoint-util.h"
+ #include "nsflags.h"
+ #include "parse-util.h"
+ #include "proc-cmdline.h"
++#include "path-util.h"
+ #include "rlimit-util.h"
++#include "socket-util.h"
+ #include "stdio-util.h"
+ #include "strv.h"
+ #include "user-util.h"
+@@ -187,357 +185,6 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
+         return has_owner;
+ }
+ 
+-static int check_good_user(sd_bus_message *m, uid_t good_user) {
+-        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+-        uid_t sender_uid;
+-        int r;
+-
+-        assert(m);
+-
+-        if (good_user == UID_INVALID)
+-                return 0;
+-
+-        r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
+-        if (r < 0)
+-                return r;
+-
+-        /* Don't trust augmented credentials for authorization */
+-        assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
+-
+-        r = sd_bus_creds_get_euid(creds, &sender_uid);
+-        if (r < 0)
+-                return r;
+-
+-        return sender_uid == good_user;
+-}
+-
+-int bus_test_polkit(
+-                sd_bus_message *call,
+-                int capability,
+-                const char *action,
+-                const char **details,
+-                uid_t good_user,
+-                bool *_challenge,
+-                sd_bus_error *e) {
+-
+-        int r;
+-
+-        assert(call);
+-        assert(action);
+-
+-        /* Tests non-interactively! */
+-
+-        r = check_good_user(call, good_user);
+-        if (r != 0)
+-                return r;
+-
+-        r = sd_bus_query_sender_privilege(call, capability);
+-        if (r < 0)
+-                return r;
+-        else if (r > 0)
+-                return 1;
+-#if ENABLE_POLKIT
+-        else {
+-                _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
+-                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+-                int authorized = false, challenge = false;
+-                const char *sender, **k, **v;
+-
+-                sender = sd_bus_message_get_sender(call);
+-                if (!sender)
+-                        return -EBADMSG;
+-
+-                r = sd_bus_message_new_method_call(
+-                                call->bus,
+-                                &request,
+-                                "org.freedesktop.PolicyKit1",
+-                                "/org/freedesktop/PolicyKit1/Authority",
+-                                "org.freedesktop.PolicyKit1.Authority",
+-                                "CheckAuthorization");
+-                if (r < 0)
+-                        return r;
+-
+-                r = sd_bus_message_append(
+-                                request,
+-                                "(sa{sv})s",
+-                                "system-bus-name", 1, "name", "s", sender,
+-                                action);
+-                if (r < 0)
+-                        return r;
+-
+-                r = sd_bus_message_open_container(request, 'a', "{ss}");
+-                if (r < 0)
+-                        return r;
+-
+-                STRV_FOREACH_PAIR(k, v, details) {
+-                        r = sd_bus_message_append(request, "{ss}", *k, *v);
+-                        if (r < 0)
+-                                return r;
+-                }
+-
+-                r = sd_bus_message_close_container(request);
+-                if (r < 0)
+-                        return r;
+-
+-                r = sd_bus_message_append(request, "us", 0, NULL);
+-                if (r < 0)
+-                        return r;
+-
+-                r = sd_bus_call(call->bus, request, 0, e, &reply);
+-                if (r < 0) {
+-                        /* Treat no PK available as access denied */
+-                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
+-                                sd_bus_error_free(e);
+-                                return -EACCES;
+-                        }
+-
+-                        return r;
+-                }
+-
+-                r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
+-                if (r < 0)
+-                        return r;
+-
+-                r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
+-                if (r < 0)
+-                        return r;
+-
+-                if (authorized)
+-                        return 1;
+-
+-                if (_challenge) {
+-                        *_challenge = challenge;
+-                        return 0;
+-                }
+-        }
+-#endif
+-
+-        return -EACCES;
+-}
+-
+-#if ENABLE_POLKIT
+-
+-typedef struct AsyncPolkitQuery {
+-        sd_bus_message *request, *reply;
+-        sd_bus_message_handler_t callback;
+-        void *userdata;
+-        sd_bus_slot *slot;
+-        Hashmap *registry;
+-} AsyncPolkitQuery;
+-
+-static void async_polkit_query_free(AsyncPolkitQuery *q) {
+-
+-        if (!q)
+-                return;
+-
+-        sd_bus_slot_unref(q->slot);
+-
+-        if (q->registry && q->request)
+-                hashmap_remove(q->registry, q->request);
+-
+-        sd_bus_message_unref(q->request);
+-        sd_bus_message_unref(q->reply);
+-
+-        free(q);
+-}
+-
+-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;
+-        int r;
+-
+-        assert(reply);
+-        assert(q);
+-
+-        q->slot = sd_bus_slot_unref(q->slot);
+-        q->reply = sd_bus_message_ref(reply);
+-
+-        r = sd_bus_message_rewind(q->request, true);
+-        if (r < 0) {
+-                r = sd_bus_reply_method_errno(q->request, r, NULL);
+-                goto finish;
+-        }
+-
+-        r = q->callback(q->request, q->userdata, &error_buffer);
+-        r = bus_maybe_reply_error(q->request, r, &error_buffer);
+-
+-finish:
+-        async_polkit_query_free(q);
+-
+-        return r;
+-}
+-
+-#endif
+-
+-int bus_verify_polkit_async(
+-                sd_bus_message *call,
+-                int capability,
+-                const char *action,
+-                const char **details,
+-                bool interactive,
+-                uid_t good_user,
+-                Hashmap **registry,
+-                sd_bus_error *error) {
+-
+-#if ENABLE_POLKIT
+-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
+-        AsyncPolkitQuery *q;
+-        const char *sender, **k, **v;
+-        sd_bus_message_handler_t callback;
+-        void *userdata;
+-        int c;
+-#endif
+-        int r;
+-
+-        assert(call);
+-        assert(action);
+-        assert(registry);
+-
+-        r = check_good_user(call, good_user);
+-        if (r != 0)
+-                return r;
+-
+-#if ENABLE_POLKIT
+-        q = hashmap_get(*registry, call);
+-        if (q) {
+-                int authorized, challenge;
+-
+-                /* This is the second invocation of this function, and
+-                 * there's already a response from polkit, let's
+-                 * process it */
+-                assert(q->reply);
+-
+-                if (sd_bus_message_is_method_error(q->reply, NULL)) {
+-                        const sd_bus_error *e;
+-
+-                        e = sd_bus_message_get_error(q->reply);
+-
+-                        /* Treat no PK available as access denied */
+-                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
+-                                return -EACCES;
+-
+-                        /* Copy error from polkit reply */
+-                        sd_bus_error_copy(error, e);
+-                        return -sd_bus_error_get_errno(e);
+-                }
+-
+-                r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
+-                if (r >= 0)
+-                        r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
+-
+-                if (r < 0)
+-                        return r;
+-
+-                if (authorized)
+-                        return 1;
+-
+-                if (challenge)
+-                        return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
+-
+-                return -EACCES;
+-        }
+-#endif
+-
+-        r = sd_bus_query_sender_privilege(call, capability);
+-        if (r < 0)
+-                return r;
+-        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;
+-
+-        c = sd_bus_message_get_allow_interactive_authorization(call);
+-        if (c < 0)
+-                return c;
+-        if (c > 0)
+-                interactive = true;
+-
+-        r = hashmap_ensure_allocated(registry, NULL);
+-        if (r < 0)
+-                return r;
+-
+-        r = sd_bus_message_new_method_call(
+-                        call->bus,
+-                        &pk,
+-                        "org.freedesktop.PolicyKit1",
+-                        "/org/freedesktop/PolicyKit1/Authority",
+-                        "org.freedesktop.PolicyKit1.Authority",
+-                        "CheckAuthorization");
+-        if (r < 0)
+-                return r;
+-
+-        r = sd_bus_message_append(
+-                        pk,
+-                        "(sa{sv})s",
+-                        "system-bus-name", 1, "name", "s", sender,
+-                        action);
+-        if (r < 0)
+-                return r;
+-
+-        r = sd_bus_message_open_container(pk, 'a', "{ss}");
+-        if (r < 0)
+-                return r;
+-
+-        STRV_FOREACH_PAIR(k, v, details) {
+-                r = sd_bus_message_append(pk, "{ss}", *k, *v);
+-                if (r < 0)
+-                        return r;
+-        }
+-
+-        r = sd_bus_message_close_container(pk);
+-        if (r < 0)
+-                return r;
+-
+-        r = sd_bus_message_append(pk, "us", interactive, NULL);
+-        if (r < 0)
+-                return r;
+-
+-        q = new0(AsyncPolkitQuery, 1);
+-        if (!q)
+-                return -ENOMEM;
+-
+-        q->request = sd_bus_message_ref(call);
+-        q->callback = callback;
+-        q->userdata = userdata;
+-
+-        r = hashmap_put(*registry, call, q);
+-        if (r < 0) {
+-                async_polkit_query_free(q);
+-                return r;
+-        }
+-
+-        q->registry = *registry;
+-
+-        r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
+-        if (r < 0) {
+-                async_polkit_query_free(q);
+-                return r;
+-        }
+-
+-        return 0;
+-#endif
+-
+-        return -EACCES;
+-}
+-
+-void bus_verify_polkit_async_registry_free(Hashmap *registry) {
+-#if ENABLE_POLKIT
+-        hashmap_free_with_destructor(registry, async_polkit_query_free);
+-#endif
+-}
+-
+ int bus_check_peercred(sd_bus *c) {
+         struct ucred ucred;
+         int fd, r;
+diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
+index 71c248f..c9cbf76 100644
+--- a/src/shared/bus-util.h
++++ b/src/shared/bus-util.h
+@@ -9,8 +9,8 @@
+ #include "sd-bus.h"
+ #include "sd-event.h"
+ 
+-#include "hashmap.h"
+ #include "macro.h"
++#include "set.h"
+ #include "string-util.h"
+ 
+ typedef enum BusTransport {
+@@ -51,11 +51,6 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error);
+ 
+ int bus_check_peercred(sd_bus *c);
+ 
+-int bus_test_polkit(sd_bus_message *call, int capability, const char *action, const char **details, uid_t good_user, bool *_challenge, sd_bus_error *e);
+-
+-int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *action, const char **details, bool interactive, uid_t good_user, Hashmap **registry, sd_bus_error *error);
+-void bus_verify_polkit_async_registry_free(Hashmap *registry);
+-
+ int bus_connect_system_systemd(sd_bus **_bus);
+ int bus_connect_user_systemd(sd_bus **_bus);
+ 
+diff --git a/src/shared/meson.build b/src/shared/meson.build
+index 99d6ba1..f6d1092 100644
+--- a/src/shared/meson.build
++++ b/src/shared/meson.build
+@@ -25,6 +25,8 @@ shared_sources = files('''
+         bus-unit-util.h
+         bus-util.c
+         bus-util.h
++        bus-polkit.c
++        bus-polkit.h
+         calendarspec.c
+         calendarspec.h
+         cgroup-show.c
+diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
+index 324d4a4..398d4f4 100644
+--- a/src/timedate/timedated.c
++++ b/src/timedate/timedated.c
+@@ -11,7 +11,7 @@
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+ #include "bus-error.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "clock-util.h"
+ #include "def.h"
+ #include "fileio-label.h"
diff --git a/debian/udev-udeb.install b/debian/udev-udeb.install
index 0e9ff40..478276b 100644
--- a/debian/udev-udeb.install
+++ b/debian/udev-udeb.install
@@ -5,6 +5,7 @@ lib/udev/ata_id
 lib/udev/scsi_id
 lib/udev/cdrom_id
 lib/udev/rules.d/50-udev-default.rules
+lib/udev/rules.d/60-block.rules
 lib/udev/rules.d/60-cdrom_id.rules
 lib/udev/rules.d/60-input-id.rules
 lib/udev/rules.d/60-persistent-input.rules
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://alioth-lists.debian.net/pipermail/pkg-systemd-maintainers/attachments/20200427/1d762c0f/attachment-0001.sig>


More information about the Pkg-systemd-maintainers mailing list