diff --git a/debian/changelog b/debian/changelog
index 7546c78635aaaecb704d62bde591defc27bc159b..caddbcd29fbaaca5fe8b426c058eb6d1bed4d97e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,71 @@
+systemd (241-7~deb10u4co1) UNRELEASED; urgency=medium
+
+  * PLEASE SUMMARIZE remaining Apertis changes
+
+ -- root <ritesh.sarraf@collabora.co.uk>  Tue, 26 May 2020 11:41:53 +0000
+
+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@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.
+    Since kernel 5.2 (but also stable kernels like 4.19.53) the kernel
+    thankfully returns proper errors when we write a value out of range to
+    the sysctl. Which however breaks writing ULONG_MAX to request the
+    maximum value. Hence let's write the new maximum value instead,
+    LONG_MAX. (Closes: #945018)
+  * core: change ownership/mode of the execution directories also for static
+    users.
+    This ensures that execution directories like CacheDirectory and
+    StateDirectory are properly chowned to the user specified in User= before
+    launching the service. (Closes: #919231)
+
+ -- Michael Biebl <biebl@debian.org>  Wed, 29 Jan 2020 19:07:53 +0100
+
+systemd (241-7~deb10u2) buster; urgency=medium
+
+  * core: never propagate reload failure to service result.
+    Fixes a regression introduced in v239 where the main process of a
+    service unit gets killed on reload if ExecReload fails. (Closes: #936032)
+  * shared/seccomp: add sync_file_range2.
+    Some architectures need the arguments to be reordered because of alignment
+    issues. Otherwise, it's the same as sync_file_range.
+    Fixes sync_file_range failures in nspawn containers on arm, ppc.
+    (Closes: #935091)
+  * core: factor root_directory application out of apply_working_directory.
+    Fixes RootDirectory not working when used in combination with User.
+    (Closes: #939408)
+  * shared/bus-util: drop trusted annotation from
+    bus_open_system_watch_bind_with_description().
+    This ensures that access controls on systemd-resolved's D-Bus interface
+    are enforced properly.
+    (CVE-2019-15718, Closes: #939353)
+  * login: add a missing error check for session_set_leader()
+    Fixes assertion due to insufficient function return check.
+    (Closes: #939998)
+  * d/e/r/73-usb-net-by-mac.rules: import net.ifnames only for network devices
+    (Closes: #934589)
+  * d/e/r/73-usb-net-by-mac.rules: skip if iface name was provided by user-space
+  * namespace: make MountFlags=shared work again (Closes: #939551)
+  * mount/generators: do not make unit wanted by its device unit.
+    Among other things, this fixes StopWhenUnneeded=true being broken for
+    mount units. (Closes: #941758)
+
+ -- Michael Biebl <biebl@debian.org>  Wed, 16 Oct 2019 15:24:54 +0200
+
 systemd (241-7~deb10u1co4) apertis; urgency=medium
 
   * AppArmor: Fix conflict with chaiwala-apparmor-profiles
diff --git a/debian/extra/initramfs-tools/hooks/udev b/debian/extra/initramfs-tools/hooks/udev
index 6305d0970f6002c4846e7ee6ff1e920042ee08e3..bbbd351d7f4a66082f30bd347ab9f3ac43d93e5e 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/extra/rules/73-usb-net-by-mac.rules b/debian/extra/rules/73-usb-net-by-mac.rules
index 8969f5917649cc15e4555aceeb00240cb201ea47..20c3e84ff0eef9e3f21aae0f5932a4cf53437a33 100644
--- a/debian/extra/rules/73-usb-net-by-mac.rules
+++ b/debian/extra/rules/73-usb-net-by-mac.rules
@@ -1,12 +1,17 @@
 # Use MAC based names for network interfaces which are directly or indirectly
 # on USB and have an universally administered (stable) MAC address (second bit
 # is 0). Don't do this when ifnames is disabled via kernel command line or
-# customizing/disabling 99-default.link (or previously 80-net-setup-link.rules).
+# customizing/disabling 99-default.link (or previously 80-net-setup-link.rules)
+# or if the interface name was provided by user-space.
+
+ACTION=="remove", GOTO="usb_net_by_mac_end"
+SUBSYSTEM!="net", GOTO="usb_net_by_mac_end"
+ATTR{name_assign_type}=="3", GOTO="usb_net_by_mac_end"
 
 IMPORT{cmdline}="net.ifnames"
 ENV{net.ifnames}=="0", GOTO="usb_net_by_mac_end"
 
-ACTION=="add", SUBSYSTEM=="net", SUBSYSTEMS=="usb", NAME=="", \
+SUBSYSTEMS=="usb", NAME=="", \
     ATTR{address}=="?[014589cd]:*", \
     TEST!="/etc/udev/rules.d/80-net-setup-link.rules", \
     TEST!="/etc/systemd/network/99-default.link", \
diff --git a/debian/gbp.conf b/debian/gbp.conf
index b0e000121b07f36a3f87d83418e7a1f9c8918f67..9591e256db5c7cda5b189fdd00b2a95ed8eaf4e1 100644
--- a/debian/gbp.conf
+++ b/debian/gbp.conf
@@ -1,7 +1,8 @@
 [DEFAULT]
 pristine-tar = True
 patch-numbers = False
-debian-branch = buster
+debian-branch = debian/buster
+upstream-branch = upstream/latest
 
 [dch]
 full = True
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 0000000000000000000000000000000000000000..4f3c521c0d241aa6ed9350112d8ea5cfddd12d5d
--- /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@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 0000000000000000000000000000000000000000..a7c9cc52f9ce483543f13ea0852c59a1b31e2e78
--- /dev/null
+++ b/debian/patches/bus-polkit-rename-return-error-parameter-to-ret_error.patch
@@ -0,0 +1,67 @@
+From: Lennart Poettering <lennart@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 0000000000000000000000000000000000000000..ffd349f41253e925b0893d9b831c724220547437
--- /dev/null
+++ b/debian/patches/bus-util-treat-org.freedesktop.DBus.Error.ServiceUnknown-.patch
@@ -0,0 +1,34 @@
+From: Yu Watanabe <watanabe.yu+github@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/core-change-ownership-mode-of-the-execution-directories-a.patch b/debian/patches/core-change-ownership-mode-of-the-execution-directories-a.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6f8b0fc1908b6a4afa0816428792825905f04d93
--- /dev/null
+++ b/debian/patches/core-change-ownership-mode-of-the-execution-directories-a.patch
@@ -0,0 +1,85 @@
+From: Lennart Poettering <lennart@poettering.net>
+Date: Thu, 14 Mar 2019 17:19:30 +0100
+Subject: core: change ownership/mode of the execution directories also for
+ static users
+
+It's probably unexpected if we do a recursive chown() when dynamic users
+are used but not on static users.
+
+hence, let's tweak the logic slightly, and recursively chown in both
+cases, except when operating on the configuration directory.
+
+Fixes: #11842
+(cherry picked from commit 206e9864de460dd79d9edd7bedb47dee168765e1)
+---
+ src/core/execute.c | 47 ++++++++++++++++++++++++++---------------------
+ 1 file changed, 26 insertions(+), 21 deletions(-)
+
+diff --git a/src/core/execute.c b/src/core/execute.c
+index 5486e37..5c3930e 100644
+--- a/src/core/execute.c
++++ b/src/core/execute.c
+@@ -2151,37 +2151,42 @@ static int setup_exec_directory(
+                         if (r < 0)
+                                 goto fail;
+ 
+-                        /* Lock down the access mode */
+-                        if (chmod(pp, context->directories[type].mode) < 0) {
+-                                r = -errno;
+-                                goto fail;
+-                        }
+                 } else {
+                         r = mkdir_label(p, context->directories[type].mode);
+                         if (r < 0) {
+-                                struct stat st;
+-
+                                 if (r != -EEXIST)
+                                         goto fail;
+ 
+-                                if (stat(p, &st) < 0) {
+-                                        r = -errno;
+-                                        goto fail;
+-                                }
+-                                if (((st.st_mode ^ context->directories[type].mode) & 07777) != 0)
+-                                        log_warning("%s \'%s\' already exists but the mode is different. "
+-                                                    "(filesystem: %o %sMode: %o)",
+-                                                    exec_directory_type_to_string(type), *rt,
+-                                                    st.st_mode & 07777, exec_directory_type_to_string(type), context->directories[type].mode & 07777);
+-                                if (!context->dynamic_user)
++                                if (type == EXEC_DIRECTORY_CONFIGURATION) {
++                                        struct stat st;
++
++                                        /* Don't change the owner/access mode of the configuration directory,
++                                         * as in the common case it is not written to by a service, and shall
++                                         * not be writable. */
++
++                                        if (stat(p, &st) < 0) {
++                                                r = -errno;
++                                                goto fail;
++                                        }
++
++                                        /* Still complain if the access mode doesn't match */
++                                        if (((st.st_mode ^ context->directories[type].mode) & 07777) != 0)
++                                                log_warning("%s \'%s\' already exists but the mode is different. "
++                                                            "(File system: %o %sMode: %o)",
++                                                            exec_directory_type_to_string(type), *rt,
++                                                            st.st_mode & 07777, exec_directory_type_to_string(type), context->directories[type].mode & 07777);
++
+                                         continue;
++                                }
+                         }
+                 }
+ 
+-                /* Don't change the owner of the configuration directory, as in the common case it is not written to by
+-                 * a service, and shall not be writable. */
+-                if (type == EXEC_DIRECTORY_CONFIGURATION)
+-                        continue;
++                /* Lock down the access mode (we use chmod_and_chown() to make this idempotent. We don't
++                 * specifiy UID/GID here, so that path_chown_recursive() can optimize things depending on the
++                 * current UID/GID ownership.) */
++                r = chmod_and_chown(pp ?: p, context->directories[type].mode, UID_INVALID, GID_INVALID);
++                if (r < 0)
++                        goto fail;
+ 
+                 /* Then, change the ownership of the whole tree, if necessary */
+                 r = path_chown_recursive(pp ?: p, uid, gid);
diff --git a/debian/patches/core-factor-root_directory-application-out-of-apply_worki.patch b/debian/patches/core-factor-root_directory-application-out-of-apply_worki.patch
new file mode 100644
index 0000000000000000000000000000000000000000..3ee945a4ae946df2aab4419e6be92786420eba70
--- /dev/null
+++ b/debian/patches/core-factor-root_directory-application-out-of-apply_worki.patch
@@ -0,0 +1,89 @@
+From: Joerg Behrmann <behrmann@physik.fu-berlin.de>
+Date: Fri, 21 Jun 2019 13:51:53 +0200
+Subject: core: factor root_directory application out of
+ apply_working_directory
+
+Fixes: #12498
+(cherry picked from commit fa97f63067a05b4e793fd4e0a2b54797459b4812)
+---
+ src/core/execute.c | 38 ++++++++++++++++++++++++++++----------
+ 1 file changed, 28 insertions(+), 10 deletions(-)
+
+diff --git a/src/core/execute.c b/src/core/execute.c
+index a708231..47518f4 100644
+--- a/src/core/execute.c
++++ b/src/core/execute.c
+@@ -2480,7 +2480,6 @@ static int apply_working_directory(
+                 const ExecContext *context,
+                 const ExecParameters *params,
+                 const char *home,
+-                const bool needs_mount_ns,
+                 int *exit_status) {
+ 
+         const char *d, *wd;
+@@ -2502,15 +2501,9 @@ static int apply_working_directory(
+         else
+                 wd = "/";
+ 
+-        if (params->flags & EXEC_APPLY_CHROOT) {
+-                if (!needs_mount_ns && context->root_directory)
+-                        if (chroot(context->root_directory) < 0) {
+-                                *exit_status = EXIT_CHROOT;
+-                                return -errno;
+-                        }
+-
++        if (params->flags & EXEC_APPLY_CHROOT)
+                 d = wd;
+-        } else
++        else
+                 d = prefix_roota(context->root_directory, wd);
+ 
+         if (chdir(d) < 0 && !context->working_directory_missing_ok) {
+@@ -2521,6 +2514,26 @@ static int apply_working_directory(
+         return 0;
+ }
+ 
++static int apply_root_directory(
++                const ExecContext *context,
++                const ExecParameters *params,
++                const bool needs_mount_ns,
++                int *exit_status) {
++
++        assert(context);
++        assert(exit_status);
++
++        if (params->flags & EXEC_APPLY_CHROOT) {
++                if (!needs_mount_ns && context->root_directory)
++                        if (chroot(context->root_directory) < 0) {
++                                *exit_status = EXIT_CHROOT;
++                                return -errno;
++                        }
++        }
++
++        return 0;
++}
++
+ static int setup_keyring(
+                 const Unit *u,
+                 const ExecContext *context,
+@@ -3425,6 +3438,11 @@ static int exec_child(
+                 }
+         }
+ 
++        /* chroot to root directory first, before we lose the ability to chroot */
++        r = apply_root_directory(context, params, needs_mount_namespace, exit_status);
++        if (r < 0)
++                return log_unit_error_errno(unit, r, "Chrooting to the requested root directory failed: %m");
++
+         if (needs_setuid) {
+                 if (context->user) {
+                         r = enforce_user(context, uid);
+@@ -3457,7 +3475,7 @@ static int exec_child(
+ 
+         /* Apply working directory here, because the working directory might be on NFS and only the user running
+          * this service might have the correct privilege to change to the working directory */
+-        r = apply_working_directory(context, params, home, needs_mount_namespace, exit_status);
++        r = apply_working_directory(context, params, home, exit_status);
+         if (r < 0)
+                 return log_unit_error_errno(unit, r, "Changing to the requested working directory failed: %m");
+ 
diff --git a/debian/patches/core-never-propagate-reload-failure-to-service-result.patch b/debian/patches/core-never-propagate-reload-failure-to-service-result.patch
new file mode 100644
index 0000000000000000000000000000000000000000..062434d106aab305ef7aa86547dcc7b221486e61
--- /dev/null
+++ b/debian/patches/core-never-propagate-reload-failure-to-service-result.patch
@@ -0,0 +1,23 @@
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 17 Jul 2019 19:16:33 +0200
+Subject: core: never propagate reload failure to service result
+
+Fixes: #11238
+(cherry picked from commit d611cfa748aaf600832160132774074e808c82c7)
+---
+ src/core/service.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/service.c b/src/core/service.c
+index 324dcf2..5f5bcb3 100644
+--- a/src/core/service.c
++++ b/src/core/service.c
+@@ -3335,7 +3335,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
+                                 service_exec_command_to_string(s->control_command_id),
+                                 code, status);
+ 
+-                if (s->result == SERVICE_SUCCESS)
++                if (s->state != SERVICE_RELOAD && s->result == SERVICE_SUCCESS)
+                         s->result = f;
+ 
+                 if (s->control_command &&
diff --git a/debian/patches/core-set-fs.file-max-sysctl-to-LONG_MAX-rather-than-ULONG.patch b/debian/patches/core-set-fs.file-max-sysctl-to-LONG_MAX-rather-than-ULONG.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6465a1f4c4b7a58fa00e668905fdeae3563d6755
--- /dev/null
+++ b/debian/patches/core-set-fs.file-max-sysctl-to-LONG_MAX-rather-than-ULONG.patch
@@ -0,0 +1,34 @@
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 17 Jun 2019 10:51:25 +0200
+Subject: core: set fs.file-max sysctl to LONG_MAX rather than ULONG_MAX
+
+Since kernel 5.2 the kernel thankfully returns proper errors when we
+write a value out of range to the sysctl. Which however breaks writing
+ULONG_MAX to request the maximum value. Hence let's write the new
+maximum value instead, LONG_MAX.
+
+/cc @brauner
+
+Fixes: #12803
+(cherry picked from commit 6e2f78948403a4cce45b9e34311c9577c624f066)
+---
+ src/core/main.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/core/main.c b/src/core/main.c
+index bc7fcc6..255e204 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -1200,9 +1200,9 @@ static void bump_file_max_and_nr_open(void) {
+ #endif
+ 
+ #if BUMP_PROC_SYS_FS_FILE_MAX
+-        /* I so wanted to use STRINGIFY(ULONG_MAX) here, but alas we can't as glibc/gcc define that as
+-         * "(0x7fffffffffffffffL * 2UL + 1UL)". Seriously. 😢 */
+-        if (asprintf(&t, "%lu\n", ULONG_MAX) < 0) {
++        /* The maximum the kernel allows for this since 5.2 is LONG_MAX, use that. (Previously thing where
++         * different but the operation would fail silently.) */
++        if (asprintf(&t, "%li\n", LONG_MAX) < 0) {
+                 log_oom();
+                 return;
+         }
diff --git a/debian/patches/debian/Revert-core-set-RLIMIT_CORE-to-unlimited-by-default.patch b/debian/patches/debian/Revert-core-set-RLIMIT_CORE-to-unlimited-by-default.patch
index f48d84156c8cb4723f6d3525da6dd39e79d008cc..9e1ab1323b78b0e68a282d280e659897efd8a311 100644
--- a/debian/patches/debian/Revert-core-set-RLIMIT_CORE-to-unlimited-by-default.patch
+++ b/debian/patches/debian/Revert-core-set-RLIMIT_CORE-to-unlimited-by-default.patch
@@ -19,7 +19,7 @@ Bug-Debian: https://bugs.debian.org/815020
  2 files changed, 1 insertion(+), 3 deletions(-)
 
 diff --git a/src/core/main.c b/src/core/main.c
-index bc7fcc6..87bee9f 100644
+index 255e204..7f8dfe4 100644
 --- a/src/core/main.c
 +++ b/src/core/main.c
 @@ -2459,8 +2459,6 @@ int main(int argc, char *argv[]) {
diff --git a/debian/patches/debian/Use-Debian-specific-config-files.patch b/debian/patches/debian/Use-Debian-specific-config-files.patch
index ba4d9ba9f5107125da63b3104a1143ea5a12682e..1ad26080822f0e26adb775a4c2dcab63a8b47b20 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/execute-remove-one-redundant-comparison-check.patch b/debian/patches/execute-remove-one-redundant-comparison-check.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d29ece3973c1a482e68e05de966ad91b5b9e4132
--- /dev/null
+++ b/debian/patches/execute-remove-one-redundant-comparison-check.patch
@@ -0,0 +1,29 @@
+From: Lennart Poettering <lennart@poettering.net>
+Date: Thu, 14 Mar 2019 17:01:46 +0100
+Subject: execute: remove one redundant comparison check
+
+(cherry picked from commit d484580ca6f0e79abe6f3f5c677323a22d9e22d7)
+---
+ src/core/execute.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/src/core/execute.c b/src/core/execute.c
+index f2a4c54..5486e37 100644
+--- a/src/core/execute.c
++++ b/src/core/execute.c
+@@ -2158,11 +2158,12 @@ static int setup_exec_directory(
+                         }
+                 } else {
+                         r = mkdir_label(p, context->directories[type].mode);
+-                        if (r < 0 && r != -EEXIST)
+-                                goto fail;
+-                        if (r == -EEXIST) {
++                        if (r < 0) {
+                                 struct stat st;
+ 
++                                if (r != -EEXIST)
++                                        goto fail;
++
+                                 if (stat(p, &st) < 0) {
+                                         r = -errno;
+                                         goto fail;
diff --git a/debian/patches/login-add-a-missing-error-check-for-session_set_leader.patch b/debian/patches/login-add-a-missing-error-check-for-session_set_leader.patch
new file mode 100644
index 0000000000000000000000000000000000000000..ba8bfa946d31c6498b92f9e87d85e5941e979871
--- /dev/null
+++ b/debian/patches/login-add-a-missing-error-check-for-session_set_leader.patch
@@ -0,0 +1,29 @@
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Thu, 14 Feb 2019 10:59:13 +0900
+Subject: login: add a missing error check for session_set_leader()
+
+session_set_leader() may fail. If it fails, then manager_start_scope()
+will trigger assertion.
+
+This may be related to RHBZ#1663704.
+
+(cherry picked from commit fe3ab8458b9c0ead4b3e14ac25b342d8c34376fe)
+---
+ src/login/logind-dbus.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
+index 8ab498f..b9ea370 100644
+--- a/src/login/logind-dbus.c
++++ b/src/login/logind-dbus.c
+@@ -790,7 +790,9 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
+                 goto fail;
+ 
+         session_set_user(session, user);
+-        session_set_leader(session, leader);
++        r = session_set_leader(session, leader);
++        if (r < 0)
++                goto fail;
+ 
+         session->type = t;
+         session->class = c;
diff --git a/debian/patches/mount-generators-do-not-make-unit-wanted-by-its-device-un.patch b/debian/patches/mount-generators-do-not-make-unit-wanted-by-its-device-un.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d38962faffb8cac161e52125c5fbbc5a50848640
--- /dev/null
+++ b/debian/patches/mount-generators-do-not-make-unit-wanted-by-its-device-un.patch
@@ -0,0 +1,58 @@
+From: Tom Yan <tom.ty89@gmail.com>
+Date: Wed, 9 Jan 2019 23:35:24 +0800
+Subject: mount/generators: do not make unit wanted by its device unit
+
+As device units will be reloaded by systemd whenever the corresponding device generates a "changed" event, if the mount unit / cryptsetup service is wanted by its device unit, the former can be restarted by systemd unexpectedly after the user stopped them explicitly. It is not sensible at all and can be considered dangerous. Neither is the behaviour conventional (as `auto` in fstab should only affect behaviour on boot and `mount -a`) or ever documented at all (not even in systemd, see systemd.mount(5) and crypttab(5)).
+
+(cherry picked from commit 142b8142d7bb84f07ac33fc00527a4d48ac8ef9f)
+---
+ src/core/mount.c                      | 6 +-----
+ src/cryptsetup/cryptsetup-generator.c | 4 ----
+ 2 files changed, 1 insertion(+), 9 deletions(-)
+
+diff --git a/src/core/mount.c b/src/core/mount.c
+index c31cad6..7064fa1 100644
+--- a/src/core/mount.c
++++ b/src/core/mount.c
+@@ -338,7 +338,6 @@ static int mount_add_mount_dependencies(Mount *m) {
+ }
+ 
+ static int mount_add_device_dependencies(Mount *m) {
+-        bool device_wants_mount;
+         UnitDependencyMask mask;
+         MountParameters *p;
+         UnitDependency dep;
+@@ -368,9 +367,6 @@ static int mount_add_device_dependencies(Mount *m) {
+         if (path_equal(m->where, "/"))
+                 return 0;
+ 
+-        device_wants_mount =
+-                mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager);
+-
+         /* Mount units from /proc/self/mountinfo are not bound to devices
+          * by default since they're subject to races when devices are
+          * unplugged. But the user can still force this dep with an
+@@ -381,7 +377,7 @@ static int mount_add_device_dependencies(Mount *m) {
+         /* We always use 'what' from /proc/self/mountinfo if mounted */
+         mask = m->from_proc_self_mountinfo ? UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT : UNIT_DEPENDENCY_FILE;
+ 
+-        r = unit_add_node_dependency(UNIT(m), p->what, device_wants_mount, dep, mask);
++        r = unit_add_node_dependency(UNIT(m), p->what, false, dep, mask);
+         if (r < 0)
+                 return r;
+ 
+diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
+index 8759a26..ea18e84 100644
+--- a/src/cryptsetup/cryptsetup-generator.c
++++ b/src/cryptsetup/cryptsetup-generator.c
+@@ -287,10 +287,6 @@ static int create_disk(
+                 return log_error_errno(r, "Failed to write unit file %s: %m", n);
+ 
+         if (!noauto) {
+-                r = generator_add_symlink(arg_dest, d, "wants", n);
+-                if (r < 0)
+-                        return r;
+-
+                 r = generator_add_symlink(arg_dest,
+                                           netdev ? "remote-cryptsetup.target" : "cryptsetup.target",
+                                           nofail ? "wants" : "requires", n);
diff --git a/debian/patches/mount-remove-unused-mount_is_auto-and-mount_is_automount.patch b/debian/patches/mount-remove-unused-mount_is_auto-and-mount_is_automount.patch
new file mode 100644
index 0000000000000000000000000000000000000000..58acfc80249799b9b9c0a5eb414a306a712107e6
--- /dev/null
+++ b/debian/patches/mount-remove-unused-mount_is_auto-and-mount_is_automount.patch
@@ -0,0 +1,34 @@
+From: Tom Yan <tom.ty89@gmail.com>
+Date: Thu, 10 Jan 2019 00:19:43 +0800
+Subject: mount: remove unused mount_is_auto and mount_is_automount
+
+(cherry picked from commit d0fe45cb151774827a3aca4ea5a19856dec9f600)
+---
+ src/core/mount.c | 14 --------------
+ 1 file changed, 14 deletions(-)
+
+diff --git a/src/core/mount.c b/src/core/mount.c
+index 7064fa1..8da818b 100644
+--- a/src/core/mount.c
++++ b/src/core/mount.c
+@@ -101,20 +101,6 @@ static bool mount_is_bind(const MountParameters *p) {
+         return false;
+ }
+ 
+-static bool mount_is_auto(const MountParameters *p) {
+-        assert(p);
+-
+-        return !fstab_test_option(p->options, "noauto\0");
+-}
+-
+-static bool mount_is_automount(const MountParameters *p) {
+-        assert(p);
+-
+-        return fstab_test_option(p->options,
+-                                 "comment=systemd.automount\0"
+-                                 "x-systemd.automount\0");
+-}
+-
+ static bool mount_is_bound_to_device(const Mount *m) {
+         const MountParameters *p;
+ 
diff --git a/debian/patches/namespace-make-MountFlags-shared-work-again.patch b/debian/patches/namespace-make-MountFlags-shared-work-again.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2954e67c4b102deb3c4c441eec3a666628ac2239
--- /dev/null
+++ b/debian/patches/namespace-make-MountFlags-shared-work-again.patch
@@ -0,0 +1,58 @@
+From: Franck Bui <fbui@suse.com>
+Date: Wed, 13 Feb 2019 18:45:36 +0100
+Subject: namespace: make MountFlags=shared work again
+
+Since commit 0722b359342d2a9f9e0d453875624387a0ba1be2, the root mountpoint is
+unconditionnally turned to slave which breaks units that are using explicitly
+MountFlags=shared (and no other options that would implicitly require a slave
+root mountpoint).
+
+Here is a test case:
+
+  $ systemctl cat test-shared-mount-flag.service
+  # /etc/systemd/system/test-shared-mount-flag.service
+  [Service]
+  Type=simple
+  ExecStartPre=/usr/bin/mkdir -p /mnt/tmp
+  ExecStart=/bin/sh -c "/usr/bin/mount -t tmpfs -o size=10M none /mnt/tmp && sleep infinity"
+  ExecStop=-/bin/sh -c "/usr/bin/umount /mnt/tmp"
+  MountFlags=shared
+
+  $ systemctl start test-shared-mount-flag.service
+  $ findmnt /mnt/tmp
+  $
+
+Mount on /mnt/tmp is not visible from the host although MountFlags=shared was
+used.
+
+This patch fixes that and turns the root mountpoint to slave when it's really
+required.
+
+(cherry picked from commit 37ed15d7edaf59a1fc7c9e3552cd93a83f3814ef)
+---
+ src/core/execute.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/execute.c b/src/core/execute.c
+index 47518f4..f2a4c54 100644
+--- a/src/core/execute.c
++++ b/src/core/execute.c
+@@ -1839,7 +1839,7 @@ static bool exec_needs_mount_namespace(
+         if (context->n_temporary_filesystems > 0)
+                 return true;
+ 
+-        if (context->mount_flags != 0)
++        if (!IN_SET(context->mount_flags, 0, MS_SHARED))
+                 return true;
+ 
+         if (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir))
+@@ -2435,6 +2435,9 @@ static int apply_mount_namespace(
+         else
+                 ns_info = (NamespaceInfo) {};
+ 
++        if (context->mount_flags == MS_SHARED)
++                log_unit_debug(u, "shared mount propagation hidden by other fs namespacing unit settings: ignoring");
++
+         r = setup_namespace(root_dir, root_image,
+                             &ns_info, context->read_write_paths,
+                             needs_sandboxing ? context->read_only_paths : NULL,
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 0000000000000000000000000000000000000000..c6ffacfb88531ac43f35095ba6c8ceac622ec98e
--- /dev/null
+++ b/debian/patches/polkit-on-async-pk-requests-re-validate-action-details.patch
@@ -0,0 +1,81 @@
+From: Lennart Poettering <lennart@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 0000000000000000000000000000000000000000..98e43cacad3e9454844af1d032b25e1fd72aa7c4
--- /dev/null
+++ b/debian/patches/polkit-reuse-some-common-bus-message-appending-code.patch
@@ -0,0 +1,107 @@
+From: Lennart Poettering <lennart@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 0000000000000000000000000000000000000000..683fb3b10f5e2138ca41da79359401991d9c3bc4
--- /dev/null
+++ b/debian/patches/polkit-use-structured-initialization.patch
@@ -0,0 +1,36 @@
+From: Lennart Poettering <lennart@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 0000000000000000000000000000000000000000..2175b789275aea5deabd153dfef3c4c83394c500
--- /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);
diff --git a/debian/patches/resolve-fix-memleak.patch b/debian/patches/resolve-fix-memleak.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f37f3229b33e24879027e21f46079082ba2bb590
--- /dev/null
+++ b/debian/patches/resolve-fix-memleak.patch
@@ -0,0 +1,32 @@
+From: Yu Watanabe <watanabe.yu+github@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 0000000000000000000000000000000000000000..b19d8fcdf869e8ffe053b883ecb38cbebec061ed
--- /dev/null
+++ b/debian/patches/sd-bus-introduce-API-for-re-enqueuing-incoming-messages.patch
@@ -0,0 +1,65 @@
+From: Lennart Poettering <lennart@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 acquired 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 ec8ad9e39645147330e117b499f33be4703c9021..95e5f7f2b8c4d8f1ab259d62d194b94a18ebcfba 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -31,6 +31,27 @@ network-read-link-specific-sysctl-value.patch
 networkd-fix-link_up-12505.patch
 network-do-not-send-ipv6-token-to-kernel.patch
 meson-make-nologin-path-build-time-configurable.patch
+core-never-propagate-reload-failure-to-service-result.patch
+shared-seccomp-add-sync_file_range2.patch
+core-factor-root_directory-application-out-of-apply_worki.patch
+shared-bus-util-drop-trusted-annotation-from-bus_open_sys.patch
+login-add-a-missing-error-check-for-session_set_leader.patch
+namespace-make-MountFlags-shared-work-again.patch
+mount-generators-do-not-make-unit-wanted-by-its-device-un.patch
+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
+shared-split-out-polkit-stuff-from-bus-util.c-bus-polkit..patch
+bus-polkit-rename-return-error-parameter-to-ret_error.patch
+polkit-reuse-some-common-bus-message-appending-code.patch
+polkit-on-async-pk-requests-re-validate-action-details.patch
+polkit-use-structured-initialization.patch
+sd-bus-introduce-API-for-re-enqueuing-incoming-messages.patch
+polkit-when-authorizing-via-PK-let-s-re-resolve-callback-.patch
+Fix-typo-in-function-name.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-bus-util-drop-trusted-annotation-from-bus_open_sys.patch b/debian/patches/shared-bus-util-drop-trusted-annotation-from-bus_open_sys.patch
new file mode 100644
index 0000000000000000000000000000000000000000..bd736b6535f490a0ca8dfbaa2b55c8548880a4a8
--- /dev/null
+++ b/debian/patches/shared-bus-util-drop-trusted-annotation-from-bus_open_sys.patch
@@ -0,0 +1,32 @@
+From: =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Tue, 27 Aug 2019 19:00:34 +0200
+Subject: shared/bus-util: drop trusted annotation from
+ bus_open_system_watch_bind_with_description()
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1746057
+
+This only affects systemd-resolved. bus_open_system_watch_bind_with_description()
+is also used in timesyncd, but it has no methods, only read-only properties, and
+in networkd, but it annotates all methods with SD_BUS_VTABLE_UNPRIVILEGED and does
+polkit checks.
+
+(cherry picked from commit 35e528018f315798d3bffcb592b32a0d8f5162bd)
+---
+ src/shared/bus-util.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
+index cbcf698..9d31fba 100644
+--- a/src/shared/bus-util.c
++++ b/src/shared/bus-util.c
+@@ -1696,10 +1696,6 @@ int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *descri
+         if (r < 0)
+                 return r;
+ 
+-        r = sd_bus_set_trusted(bus, true);
+-        if (r < 0)
+-                return r;
+-
+         r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
+         if (r < 0)
+                 return r;
diff --git a/debian/patches/shared-seccomp-add-sync_file_range2.patch b/debian/patches/shared-seccomp-add-sync_file_range2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..eb4f839fbbc0e6436b9ae765b2d839f545dda680
--- /dev/null
+++ b/debian/patches/shared-seccomp-add-sync_file_range2.patch
@@ -0,0 +1,24 @@
+From: =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Mon, 19 Aug 2019 08:51:39 +0200
+Subject: shared/seccomp: add sync_file_range2
+
+Some architectures need the arguments to be reordered because of alignment
+issues. Otherwise, it's the same as sync_file_range.
+
+(cherry picked from commit a8fb09f57395613d472d7b555db6e0ce802a8c84)
+---
+ src/shared/seccomp-util.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
+index cc58b3c..958128c 100644
+--- a/src/shared/seccomp-util.c
++++ b/src/shared/seccomp-util.c
+@@ -756,6 +756,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
+                 "msync\0"
+                 "sync\0"
+                 "sync_file_range\0"
++                "sync_file_range2\0"
+                 "syncfs\0"
+         },
+         [SYSCALL_FILTER_SET_SYSTEM_SERVICE] = {
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 0000000000000000000000000000000000000000..3a14551f38386c3afb503f76d07f483ae808cf0d
--- /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@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 0e9ff407b590aa33bff650d48335df3e1a0fd0da..478276b58abbee8d9e7762c7a97aa773df6808b8 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