From 6238160415cedaad4292938ba1c8df26da5ca2c0 Mon Sep 17 00:00:00 2001
From: "A. Wilcox" <AWilcox@Wilcox-Tech.com>
Date: Fri, 16 Aug 2024 20:45:29 -0500
Subject: [PATCH 01/34] Revert "Drop split-usr and unmerged-usr support"
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

This reverts commit b0d3095fd6cc1791a38f57a1982116b4475244ba.

Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
---
 .semaphore/semaphore-runner.sh                |   2 +-
 README                                        |  35 ++++-
 catalog/meson.build                           |   2 +-
 catalog/systemd.bg.catalog.in                 |   2 +
 catalog/systemd.catalog.in                    |   3 -
 catalog/systemd.fr.catalog.in                 |   2 +
 catalog/systemd.it.catalog.in                 |   1 +
 catalog/systemd.pl.catalog.in                 |   3 -
 catalog/systemd.ru.catalog.in                 |   2 +
 docs/DISTRO_PORTING.md                        |   1 +
 hwdb.d/meson.build                            |   2 +-
 man/org.freedesktop.systemd1.xml              |  11 ++
 man/systemd.exec.xml                          |  11 +-
 meson.build                                   | 138 ++++++++++++------
 meson_options.txt                             |  14 +-
 rules.d/64-btrfs.rules.in                     |   2 +-
 rules.d/71-seat.rules.in                      |   4 +-
 rules.d/99-systemd.rules.in                   |   2 +-
 shell-completion/bash/systemctl.in            |   2 +-
 shell-completion/zsh/_systemctl.in            |   2 +-
 src/basic/constants.h                         |  17 ++-
 src/basic/path-lookup.c                       |   5 +-
 src/basic/path-lookup.h                       |   2 +-
 src/basic/path-util.h                         |   4 +-
 src/boot/meson.build                          |   3 +
 src/core/manager-serialize.c                  |  10 ++
 src/core/manager.c                            |   4 +-
 src/core/manager.h                            |   2 +
 src/core/meson.build                          |   4 +-
 src/core/namespace.c                          |   8 +-
 src/core/org.freedesktop.systemd1.policy.in   |   2 +-
 src/core/systemd.pc.in                        |  29 ++--
 src/cryptsetup/cryptsetup-generator.c         |   4 +-
 src/cryptsetup/cryptsetup-tokens/meson.build  |   2 +-
 src/delta/delta.c                             |  36 +++++
 src/dissect/meson.build                       |   2 +-
 src/fstab-generator/meson.build               |   2 +-
 src/import/meson.build                        |   2 +-
 src/integritysetup/integritysetup-generator.c |   4 +-
 src/libsystemd/libsystemd.pc.in               |   2 +-
 src/libsystemd/sd-hwdb/hwdb-internal.h        |   1 +
 src/libsystemd/sd-path/sd-path.c              |  27 ++--
 src/libudev/libudev.pc.in                     |   2 +-
 src/login/meson.build                         |   2 +
 src/machine/machinectl.c                      |   2 +-
 src/portable/meson.build                      |   2 +
 src/portable/portable.c                       |  10 +-
 src/resolve/meson.build                       |  14 +-
 src/rpm/macros.systemd.in                     |   6 +-
 src/rpm/meson.build                           |   4 +-
 src/rpm/triggers.systemd.in                   |   4 +-
 src/rpm/triggers.systemd.sh.in                |   4 +-
 src/shared/install.c                          |   5 +
 src/shared/kbd-util.c                         |   3 +-
 src/shared/meson.build                        |   2 +-
 src/shared/resolve-util.h                     |   2 +-
 src/shared/userdb-dropin.h                    |   3 +-
 src/shared/userdb.c                           |   2 +-
 src/sysext/meson.build                        |   4 +-
 src/systemctl/meson.build                     |   1 +
 src/systemctl/systemctl-sysv-compat.c         |   2 +-
 src/udev/meson.build                          |   2 +-
 src/userdb/20-systemd-userdb.conf.in          |   2 +-
 .../xdg-autostart-service.c                   |   2 +-
 sysctl.d/50-coredump.conf.in                  |   2 +-
 test/fuzz/fuzz-catalog/systemd.pl.catalog     |   2 +
 test/test-fstab-generator.sh                  |   5 +
 test/test-functions                           |  10 +-
 units/emergency.service.in                    |   2 +-
 units/initrd-parse-etc.service.in             |   2 +-
 units/rescue.service.in                       |   2 +-
 units/systemd-backlight@.service.in           |   4 +-
 units/systemd-battery-check.service.in        |   2 +-
 units/systemd-binfmt.service.in               |   4 +-
 units/systemd-bless-boot.service.in           |   2 +-
 .../systemd-boot-check-no-failures.service.in |   2 +-
 units/systemd-coredump@.service.in            |   2 +-
 units/systemd-fsck-root.service.in            |   2 +-
 units/systemd-fsck@.service.in                |   2 +-
 units/systemd-growfs-root.service.in          |   2 +-
 units/systemd-growfs@.service.in              |   2 +-
 units/systemd-hibernate.service.in            |   2 +-
 units/systemd-homed.service.in                |   2 +-
 units/systemd-hostnamed.service.in            |   2 +-
 units/systemd-hybrid-sleep.service.in         |   2 +-
 units/systemd-importd.service.in              |   2 +-
 units/systemd-initctl.service.in              |   2 +-
 units/systemd-journal-gatewayd.service.in     |   2 +-
 units/systemd-journal-remote.service.in       |   2 +-
 units/systemd-journal-upload.service.in       |   2 +-
 units/systemd-journald.service.in             |   2 +-
 units/systemd-journald@.service.in            |   2 +-
 units/systemd-localed.service.in              |   2 +-
 units/systemd-logind.service.in               |   2 +-
 units/systemd-machined.service.in             |   2 +-
 units/systemd-modules-load.service.in         |   2 +-
 units/systemd-network-generator.service.in    |   2 +-
 units/systemd-networkd-wait-online.service.in |   2 +-
 .../systemd-networkd-wait-online@.service.in  |   2 +-
 units/systemd-networkd.service.in             |   2 +-
 units/systemd-oomd.service.in                 |   2 +-
 units/systemd-pcrfs-root.service.in           |   2 +-
 units/systemd-pcrfs@.service.in               |   2 +-
 units/systemd-pcrmachine.service.in           |   2 +-
 units/systemd-pcrphase-initrd.service.in      |   4 +-
 units/systemd-pcrphase-sysinit.service.in     |   4 +-
 units/systemd-pcrphase.service.in             |   4 +-
 units/systemd-portabled.service.in            |   2 +-
 units/systemd-pstore.service.in               |   2 +-
 units/systemd-quotacheck@.service.in          |   2 +-
 units/systemd-random-seed.service.in          |   4 +-
 units/systemd-remount-fs.service.in           |   2 +-
 units/systemd-repart.service                  |   2 +-
 units/systemd-resolved.service.in             |   2 +-
 units/systemd-rfkill.service.in               |   2 +-
 .../systemd-suspend-then-hibernate.service.in |   2 +-
 units/systemd-suspend.service.in              |   2 +-
 units/systemd-sysctl.service.in               |   2 +-
 units/systemd-sysupdate-reboot.service.in     |   2 +-
 units/systemd-sysupdate.service.in            |   2 +-
 units/systemd-time-wait-sync.service.in       |   2 +-
 units/systemd-timedated.service.in            |   2 +-
 units/systemd-timesyncd.service.in            |   2 +-
 units/systemd-udevd.service.in                |   2 +-
 units/systemd-update-done.service.in          |   2 +-
 units/systemd-update-utmp-runlevel.service.in |   2 +-
 units/systemd-update-utmp.service.in          |   4 +-
 units/systemd-user-sessions.service.in        |   4 +-
 units/systemd-userdbd.service.in              |   2 +-
 units/systemd-vconsole-setup.service.in       |   2 +-
 units/systemd-volatile-root.service.in        |   2 +-
 units/user-runtime-dir@.service.in            |   4 +-
 units/user@.service.in                        |   2 +-
 133 files changed, 425 insertions(+), 235 deletions(-)

diff --git a/.semaphore/semaphore-runner.sh b/.semaphore/semaphore-runner.sh
index bc0cb6a9005d..831b45f062ed 100755
--- a/.semaphore/semaphore-runner.sh
+++ b/.semaphore/semaphore-runner.sh
@@ -94,7 +94,7 @@ EOF
             # disable autopkgtests which are not for upstream
             sed -i '/# NOUPSTREAM/ q' debian/tests/control
             # enable more unit tests
-            sed -i '/^CONFFLAGS =/ s/=/= --werror -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true -Dman=true /' debian/rules
+            sed -i '/^CONFFLAGS =/ s/=/= --werror -Dtests=unsafe -Dsplit-usr=true -Dslow-tests=true -Dfuzz-tests=true -Dman=true /' debian/rules
             # no orig tarball
             echo '1.0' >debian/source/format
 
diff --git a/README b/README
index 7c7bbaf07015..a24f4097dd40 100644
--- a/README
+++ b/README
@@ -266,14 +266,13 @@ REQUIREMENTS:
         make use of DynamicUser= now, hence enabling nss-systemd is not
         optional.
 
-        Note that the build prefix for systemd must be /usr/. (Moreover, packages
+        Note that the build prefix for systemd must be /usr. (Moreover, packages
         systemd relies on — such as D-Bus — really should use the same prefix,
-        otherwise you are on your own.) Split-usr and unmerged-usr systems are no
-        longer supported, and moving everything under /usr/ is required. Systems
-        with a separate /usr/ partition must mount it before transitioning into it
-        (i.e.: from the initrd). For more information see:
-        https://systemd.io/SEPARATE_USR_IS_BROKEN
-        https://systemd.io/THE_CASE_FOR_THE_USR_MERGE
+        otherwise you are on your own.) -Dsplit-usr=false (which is the default
+        and does not need to be specified) is the recommended setting.
+        -Dsplit-usr=true can be used to give a semblance of support for systems
+        with programs installed split between / and /usr. Moving everything
+        under /usr is strongly encouraged.
 
         Additional packages are necessary to run some tests:
         - nc                 (used by test/TEST-12-ISSUE-3171)
@@ -413,6 +412,28 @@ SYSV INIT.D SCRIPTS:
         needs to look like, and provide an implementation at the marked places.
 
 WARNINGS and TAINT FLAGS:
+        systemd will warn during early boot if /usr is not already mounted at
+        this point (that means: either located on the same file system as / or
+        already mounted in the initrd). While in systemd itself very little
+        will break if /usr is on a separate late-mounted partition, many of its
+        dependencies very likely will break sooner or later in one form or
+        another. For example, udev rules tend to refer to binaries in /usr,
+        binaries that link to libraries in /usr, or binaries that refer to data
+        files in /usr. Since these breakages are not always directly visible,
+        systemd will warn about this. Such setups are not really supported by
+        the basic set of Linux OS components. Taint flag 'split-usr' will be
+        set when this condition is detected.
+
+        For more information on this issue consult
+        https://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
+
+        systemd will warn if the filesystem is not usr-merged (i.e.: /bin, /sbin
+        and /lib* are not symlinks to their counterparts under /usr). Taint flag
+        'unmerged-usr' will be set when this condition is detected.
+
+        For more information on this issue consult
+        https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge
+
         systemd requires that the /run mount point exists. systemd also
         requires that /var/run is a symlink to /run. Taint flag 'var-run-bad'
         will be set when this condition is detected.
diff --git a/catalog/meson.build b/catalog/meson.build
index 3c62749cf982..1cc977992db5 100644
--- a/catalog/meson.build
+++ b/catalog/meson.build
@@ -35,4 +35,4 @@ foreach file : in_files
 endforeach
 
 meson.add_install_script(sh, '-c',
-                         'test -n "$DESTDIR" || @0@/journalctl --update-catalog'.format(bindir))
+                         'test -n "$DESTDIR" || @0@/journalctl --update-catalog'.format(rootbindir))
diff --git a/catalog/systemd.bg.catalog.in b/catalog/systemd.bg.catalog.in
index e1c32ede7820..08123a7b2606 100644
--- a/catalog/systemd.bg.catalog.in
+++ b/catalog/systemd.bg.catalog.in
@@ -395,6 +395,8 @@ Defined-By: systemd
 Support: %SUPPORT_URL%
 
 Възможни са следните етикети:
+⁃ „split-usr“ — „/usr“ е отделна файлова система, която не е била монтирана при
+  стартирането на systemd
 ⁃ „cgroups-missing“ — ядрото е компилирано без поддръжка на „cgroup“ или е
   ограничен достъпът до тази подсистема
 ⁃ „var-run-bad“ — „/var/run“ не е символна връзка към „/run“
diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in
index 2831152763ec..f2a24ee6a101 100644
--- a/catalog/systemd.catalog.in
+++ b/catalog/systemd.catalog.in
@@ -558,9 +558,6 @@ Defined-By: systemd
 Support: %SUPPORT_URL%
 
 The following "tags" are possible:
-- "unmerged-usr" - /bin, /sbin, /lib* are not symlinks to their counterparts
-  under /usr/
-- "unmerged-bin" - /usr/sbin is not a symlink to /usr/bin/
 - "var-run-bad" — /var/run is not a symlink to /run/
 - "cgroupsv1" - the system is using the deprecated cgroup v1 hierarchy
 - "local-hwclock" - the local hardware clock (RTC) is configured to be in
diff --git a/catalog/systemd.fr.catalog.in b/catalog/systemd.fr.catalog.in
index 6b28ecb779e3..c25380c8a269 100644
--- a/catalog/systemd.fr.catalog.in
+++ b/catalog/systemd.fr.catalog.in
@@ -337,6 +337,8 @@ Defined-By: systemd
 Support: %SUPPORT_URL%
 
 Les étiquettes suivantes sont possibles :
+- "split-usr" — /usr est un système de fichiers séparé et nétait pas
+  monté quand systemd a été démarré
 - "cgroups-missing" — le noyau a été compilé sans le support des groupes
   de contrôle (cgroups) ou l'accès aux fichiers d'interface est restreint
 - "var-run-bad" — /var/run n'est pas un lien symbolique vers /run
diff --git a/catalog/systemd.it.catalog.in b/catalog/systemd.it.catalog.in
index bcbbcc2eb0e0..fc2531405c54 100644
--- a/catalog/systemd.it.catalog.in
+++ b/catalog/systemd.it.catalog.in
@@ -403,6 +403,7 @@ Defined-By: systemd
 Support: %SUPPORT_URL%
 
 I seguenti "tags" sono possibili:
+- "split-usr" — /usr è un file system separato e non è stato montato all'avvio di systemd
 - "cgroups-missing" — il kernel era compilato senza supporto cgroup o l'accesso ai
   file attesi è ristretto.
 - "var-run-bad" — /var/run non è un link simbolico (symlink) a /run
diff --git a/catalog/systemd.pl.catalog.in b/catalog/systemd.pl.catalog.in
index 75039e9fcd4e..5956afe099d8 100644
--- a/catalog/systemd.pl.catalog.in
+++ b/catalog/systemd.pl.catalog.in
@@ -564,9 +564,6 @@ Defined-By: systemd
 Support: %SUPPORT_URL%
 
 Możliwe są następujące „etykiety”:
-• „unmerged-usr” — /bin, /sbin, /lib* nie są dowiązaniami symbolicznymi
-  do swoich odpowiedników pod /usr/,
-• „unmerged-bin” — /usr/sbin nie jest dowiązaniem symbolicznym do /usr/bin/,
 • „var-run-bad” — /var/run nie jest dowiązaniem symbolicznym do /run/,
 • „cgroupsv1” — system używa przestarzałej hierarchii cgroup v1,
 • „local-hwclock” — lokalny zegar sprzętowy (RTC) jest skonfigurowany
diff --git a/catalog/systemd.ru.catalog.in b/catalog/systemd.ru.catalog.in
index 2d0d8c82a080..d49c39347529 100644
--- a/catalog/systemd.ru.catalog.in
+++ b/catalog/systemd.ru.catalog.in
@@ -388,6 +388,8 @@ Defined-By: systemd
 Support: %SUPPORT_URL%
 
 Перечень всех возможных меток, указывающих на проблемы конфигурации:
+- "split-usr" — каталог /usr расположен на отдельной файловой системе,
+  которая не была смонтирована на момент запуска systemd
 - "cgroups-missing" — ядро собрано без поддержки контрольных групп, либо
   отсутствуют права для доступа к интерфейсным файлам контрольных групп
 - "var-run-bad" — /var/run не является символьной ссылкой на /run
diff --git a/docs/DISTRO_PORTING.md b/docs/DISTRO_PORTING.md
index cb230937f447..e5ee7995bd6e 100644
--- a/docs/DISTRO_PORTING.md
+++ b/docs/DISTRO_PORTING.md
@@ -13,6 +13,7 @@ You need to make the follow changes to adapt systemd to your distribution:
 
 1. Find the right configure parameters for:
 
+   * `-Drootprefix=`
    * `-Dsysvinit-path=`
    * `-Dsysvrcnd-path=`
    * `-Drc-local=`
diff --git a/hwdb.d/meson.build b/hwdb.d/meson.build
index b69b6d8f2518..780537facc19 100644
--- a/hwdb.d/meson.build
+++ b/hwdb.d/meson.build
@@ -55,7 +55,7 @@ if conf.get('ENABLE_HWDB') == 1
                 install_emptydir(sysconfdir / 'udev/hwdb.d')
 
                 meson.add_install_script(sh, '-c',
-                                         'test -n "$DESTDIR" || @0@/systemd-hwdb update'.format(bindir))
+                                         'test -n "$DESTDIR" || @0@/systemd-hwdb update'.format(rootbindir))
         endif
 
         if want_tests != 'false'
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
index b0b45097e30a..290054fa42a8 100644
--- a/man/org.freedesktop.systemd1.xml
+++ b/man/org.freedesktop.systemd1.xml
@@ -1654,6 +1654,17 @@ node /org/freedesktop/systemd1 {
       used to lower the chance of bogus bug reports. The following taints are currently known:</para>
 
       <variablelist>
+        <varlistentry>
+          <term><literal>split-usr</literal></term>
+
+          <listitem><para><filename>/usr/</filename> was not available when systemd was first invoked. It
+          must either be part of the root file system, or it must be mounted before
+          <command>systemd</command> is invoked. See
+          <ulink url="https://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken">
+          Booting Without /usr is Broken</ulink> for details why this is bad.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><literal>unmerged-usr</literal></term>
 
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index 21527f756d66..4dda7b2c43b8 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -3658,11 +3658,12 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
           <listitem><para>Colon-separated list of directories to use when launching
           executables. <command>systemd</command> uses a fixed value of
           <literal><filename>/usr/local/sbin</filename>:<filename>/usr/local/bin</filename>:<filename>/usr/sbin</filename>:<filename>/usr/bin</filename></literal>
-          in the system manager. In case of the user manager, a different path may be configured by the
-          distribution. It is recommended to not rely on the order of entries, and have only one program
-          with a given name in <varname>$PATH</varname>.</para>
-
-          <xi:include href="version-info.xml" xpointer="v208"/></listitem>
+          in the system manager. When compiled for systems with "unmerged <filename>/usr/</filename>"
+          (<filename>/bin</filename> is not a symlink to <filename>/usr/bin</filename>),
+          <literal>:<filename>/sbin</filename>:<filename>/bin</filename></literal> is appended. In case of
+          the user manager, a different path may be configured by the distribution. It is recommended to
+          not rely on the order of entries, and have only one program with a given name in
+          <varname>$PATH</varname>.</para></listitem>
         </varlistentry>
 
         <varlistentry>
diff --git a/meson.build b/meson.build
index 737f9f0c6600..c068acc169a3 100644
--- a/meson.build
+++ b/meson.build
@@ -84,6 +84,14 @@ endif
 #####################################################################
 
 fs = import('fs')
+if get_option('split-usr') == 'auto'
+        split_usr = not fs.is_symlink('/bin')
+else
+        split_usr = get_option('split-usr') == 'true'
+endif
+conf.set10('HAVE_SPLIT_USR', split_usr,
+           description : '/usr/bin and /bin directories are separate')
+
 if get_option('split-bin') == 'auto'
         split_bin = not fs.is_symlink('/usr/sbin')
 else
@@ -92,6 +100,15 @@ endif
 conf.set10('HAVE_SPLIT_BIN', split_bin,
            description : 'bin and sbin directories are separate')
 
+rootprefixdir = get_option('rootprefix')
+# Unusual rootprefixdir values are used by some distros
+# (see https://github.com/systemd/systemd/pull/7461).
+rootprefix_default = split_usr ? '/' : '/usr'
+if rootprefixdir == ''
+        rootprefixdir = rootprefix_default
+endif
+rootprefixdir_noslash = rootprefixdir == '/' ? '' : rootprefixdir
+
 have_standalone_binaries = get_option('standalone-binaries')
 
 sysvinit_path = get_option('sysvinit-path')
@@ -115,8 +132,11 @@ prefixdir = get_option('prefix')
 if not prefixdir.startswith('/')
         error('Prefix is not absolute: "@0@"'.format(prefixdir))
 endif
+if prefixdir != rootprefixdir and rootprefixdir != '/' and not prefixdir.strip('/').startswith(rootprefixdir.strip('/') + '/')
+        error('Prefix is not below root prefix (now rootprefix=@0@ prefix=@1@)'.format(
+                rootprefixdir, prefixdir))
+endif
 
-prefixdir_noslash = '/' + prefixdir.strip('/')
 bindir = prefixdir / get_option('bindir')
 sbindir = prefixdir / (split_bin ? 'sbin' : 'bin')
 sbin_to_bin = split_bin ? '../bin/' : ''
@@ -126,8 +146,20 @@ includedir = prefixdir / get_option('includedir')
 datadir = prefixdir / get_option('datadir')
 localstatedir = '/' / get_option('localstatedir')
 
-libexecdir = prefixdir / 'lib/systemd'
-pkglibdir = libdir / 'systemd'
+rootbindir = rootprefixdir / 'bin'
+rootsbindir = rootprefixdir / (split_bin ? 'sbin' : 'bin')
+rootlibexecdir = rootprefixdir / 'lib/systemd'
+
+rootlibdir = get_option('rootlibdir')
+if rootlibdir == ''
+        # This will be a relative path if libdir is in prefix.
+        rootlibdir = get_option('libdir')
+endif
+if not rootlibdir.startswith('/')
+        # If we have a relative path, add rootprefixdir to the front.
+        rootlibdir = rootprefixdir / rootlibdir
+endif
+rootpkglibdir = rootlibdir / 'systemd'
 
 install_sysconfdir = get_option('install-sysconfdir') != 'false'
 install_sysconfdir_samples = get_option('install-sysconfdir') == 'true'
@@ -142,7 +174,7 @@ rpmmacrosdir = get_option('rpmmacrosdir')
 if rpmmacrosdir != 'no'
         rpmmacrosdir = prefixdir / rpmmacrosdir
 endif
-modprobedir = prefixdir / 'lib/modprobe.d'
+modprobedir = rootprefixdir / 'lib/modprobe.d'
 
 # Our own paths
 pkgdatadir = datadir / 'systemd'
@@ -156,16 +188,16 @@ sysusersdir = prefixdir / 'lib/sysusers.d'
 sysctldir = prefixdir / 'lib/sysctl.d'
 binfmtdir = prefixdir / 'lib/binfmt.d'
 modulesloaddir = prefixdir / 'lib/modules-load.d'
-networkdir = prefixdir / 'lib/systemd/network'
-systemgeneratordir = libexecdir / 'system-generators'
+networkdir = rootprefixdir / 'lib/systemd/network'
+systemgeneratordir = rootlibexecdir / 'system-generators'
 usergeneratordir = prefixdir / 'lib/systemd/user-generators'
 systemenvgeneratordir = prefixdir / 'lib/systemd/system-environment-generators'
 userenvgeneratordir = prefixdir / 'lib/systemd/user-environment-generators'
-systemshutdowndir = libexecdir / 'system-shutdown'
-systemsleepdir = libexecdir / 'system-sleep'
-systemunitdir = prefixdir / 'lib/systemd/system'
-systempresetdir = prefixdir / 'lib/systemd/system-preset'
-udevlibexecdir = prefixdir / 'lib/udev'
+systemshutdowndir = rootlibexecdir / 'system-shutdown'
+systemsleepdir = rootlibexecdir / 'system-sleep'
+systemunitdir = rootprefixdir / 'lib/systemd/system'
+systempresetdir = rootprefixdir / 'lib/systemd/system-preset'
+udevlibexecdir = rootprefixdir / 'lib/udev'
 udevrulesdir = udevlibexecdir / 'rules.d'
 udevhwdbdir = udevlibexecdir / 'hwdb.d'
 catalogdir = prefixdir / 'lib/systemd/catalog'
@@ -179,12 +211,13 @@ testdata_dir = testsdir / 'testdata'
 systemdstatedir = localstatedir / 'lib/systemd'
 catalogstatedir = systemdstatedir / 'catalog'
 randomseeddir = localstatedir / 'lib/systemd'
-profiledir = libexecdir / 'portable' / 'profile'
-repartdefinitionsdir = libexecdir / 'repart/definitions'
-ntpservicelistdir = prefixdir / 'lib/systemd/ntp-units.d'
+profiledir = rootlibexecdir / 'portable' / 'profile'
+repartdefinitionsdir = rootlibexecdir / 'repart/definitions'
+ntpservicelistdir = rootprefixdir / 'lib/systemd/ntp-units.d'
 credstoredir = prefixdir / 'lib/credstore'
 pcrlockdir = prefixdir / 'lib/pcrlock.d'
 mimepackagesdir = prefixdir / 'share/mime/packages'
+libexecdir = rootlibexecdir
 
 configfiledir = get_option('configfiledir')
 if configfiledir == ''
@@ -199,12 +232,12 @@ endif
 
 pamlibdir = get_option('pamlibdir')
 if pamlibdir == ''
-        pamlibdir = libdir / 'security'
+        pamlibdir = rootlibdir / 'security'
 endif
 
 pamconfdir = get_option('pamconfdir')
 if pamconfdir == ''
-        pamconfdir = prefixdir / 'lib/pam.d'
+        pamconfdir = rootlibdir / 'pam.d'
 endif
 
 sshconfdir = get_option('sshconfdir')
@@ -225,7 +258,7 @@ conf.set('SSHDPRIVSEPDIR', sshdprivsepdir, description : 'SSH privilege separati
 
 libcryptsetup_plugins_dir = get_option('libcryptsetup-plugins-dir')
 if libcryptsetup_plugins_dir == ''
-        libcryptsetup_plugins_dir = libdir / 'cryptsetup'
+        libcryptsetup_plugins_dir = rootlibdir / 'cryptsetup'
 endif
 
 memory_accounting_default = get_option('memory-accounting-default')
@@ -234,7 +267,6 @@ if status_unit_format_default == 'auto'
         status_unit_format_default = conf.get('BUILD_MODE_DEVELOPER') == 1 ? 'name' : 'description'
 endif
 
-conf.set_quoted('BINDIR',                                     bindir)
 conf.set_quoted('BINFMT_DIR',                                 binfmtdir)
 conf.set_quoted('BOOTLIBDIR',                                 bootlibdir)
 conf.set_quoted('CATALOG_DATABASE',                           catalogstatedir / 'database')
@@ -251,39 +283,43 @@ conf.set_quoted('MODULESLOAD_DIR',                            modulesloaddir)
 conf.set_quoted('PKGSYSCONFDIR',                              pkgsysconfdir)
 conf.set_quoted('POLKIT_AGENT_BINARY_PATH',                   bindir / 'pkttyagent')
 conf.set_quoted('PREFIX',                                     prefixdir)
-conf.set_quoted('PREFIX_NOSLASH',                             prefixdir_noslash)
 conf.set_quoted('RANDOM_SEED',                                randomseeddir / 'random-seed')
 conf.set_quoted('RANDOM_SEED_DIR',                            randomseeddir)
 conf.set_quoted('RC_LOCAL_PATH',                              get_option('rc-local'))
+conf.set_quoted('ROOTBINDIR',                                 rootbindir)
+conf.set_quoted('ROOTLIBDIR',                                 rootlibdir)
+conf.set_quoted('ROOTLIBEXECDIR',                             rootlibexecdir)
+conf.set_quoted('ROOTPREFIX',                                 rootprefixdir)
+conf.set_quoted('ROOTPREFIX_NOSLASH',                         rootprefixdir_noslash)
 conf.set_quoted('SSHCONFDIR',                                 sshconfdir)
 conf.set_quoted('SSHDCONFDIR',                                sshdconfdir)
 conf.set_quoted('SYSCONF_DIR',                                sysconfdir)
 conf.set_quoted('SYSCTL_DIR',                                 sysctldir)
-conf.set_quoted('SYSTEMCTL_BINARY_PATH',                      bindir / 'systemctl')
-conf.set_quoted('SYSTEMD_BINARY_PATH',                        libexecdir / 'systemd')
-conf.set_quoted('SYSTEMD_EXECUTOR_BINARY_PATH',               libexecdir / 'systemd-executor')
+conf.set_quoted('SYSTEMCTL_BINARY_PATH',                      rootbindir / 'systemctl')
+conf.set_quoted('SYSTEMD_BINARY_PATH',                        rootlibexecdir / 'systemd')
+conf.set_quoted('SYSTEMD_EXECUTOR_BINARY_PATH',               rootlibexecdir / 'systemd-executor')
 conf.set_quoted('SYSTEMD_CATALOG_DIR',                        catalogdir)
-conf.set_quoted('SYSTEMD_CGROUPS_AGENT_PATH',                 libexecdir / 'systemd-cgroups-agent')
-conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH',                    bindir / 'systemd-cryptsetup')
-conf.set_quoted('SYSTEMD_EXPORT_PATH',                        libexecdir / 'systemd-export')
-conf.set_quoted('SYSTEMD_FSCK_PATH',                          libexecdir / 'systemd-fsck')
-conf.set_quoted('SYSTEMD_GROWFS_PATH',                        libexecdir / 'systemd-growfs')
-conf.set_quoted('SYSTEMD_HOMEWORK_PATH',                      libexecdir / 'systemd-homework')
-conf.set_quoted('SYSTEMD_IMPORT_FS_PATH',                     libexecdir / 'systemd-import-fs')
-conf.set_quoted('SYSTEMD_IMPORT_PATH',                        libexecdir / 'systemd-import')
-conf.set_quoted('SYSTEMD_INTEGRITYSETUP_PATH',                libexecdir / 'systemd-integritysetup')
+conf.set_quoted('SYSTEMD_CGROUPS_AGENT_PATH',                 rootlibexecdir / 'systemd-cgroups-agent')
+conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH',                    rootlibexecdir / 'systemd-cryptsetup')
+conf.set_quoted('SYSTEMD_EXPORT_PATH',                        rootlibexecdir / 'systemd-export')
+conf.set_quoted('SYSTEMD_FSCK_PATH',                          rootlibexecdir / 'systemd-fsck')
+conf.set_quoted('SYSTEMD_GROWFS_PATH',                        rootlibexecdir / 'systemd-growfs')
+conf.set_quoted('SYSTEMD_HOMEWORK_PATH',                      rootlibexecdir / 'systemd-homework')
+conf.set_quoted('SYSTEMD_IMPORT_FS_PATH',                     rootlibexecdir / 'systemd-import-fs')
+conf.set_quoted('SYSTEMD_IMPORT_PATH',                        rootlibexecdir / 'systemd-import')
+conf.set_quoted('SYSTEMD_INTEGRITYSETUP_PATH',                rootlibexecdir / 'systemd-integritysetup')
 conf.set_quoted('SYSTEMD_KBD_MODEL_MAP',                      pkgdatadir / 'kbd-model-map')
 conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP',              pkgdatadir / 'language-fallback-map')
-conf.set_quoted('SYSTEMD_MAKEFS_PATH',                        libexecdir / 'systemd-makefs')
-conf.set_quoted('SYSTEMD_PULL_PATH',                          libexecdir / 'systemd-pull')
-conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH',               libexecdir / 'systemd-shutdown')
+conf.set_quoted('SYSTEMD_MAKEFS_PATH',                        rootlibexecdir / 'systemd-makefs')
+conf.set_quoted('SYSTEMD_PULL_PATH',                          rootlibexecdir / 'systemd-pull')
+conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH',               rootlibexecdir / 'systemd-shutdown')
 conf.set_quoted('SYSTEMD_TEST_DATA',                          testdata_dir)
-conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', bindir / 'systemd-tty-ask-password-agent')
-conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH',                 libexecdir / 'systemd-update-helper')
-conf.set_quoted('SYSTEMD_USERWORK_PATH',                      libexecdir / 'systemd-userwork')
-conf.set_quoted('SYSTEMD_MOUNTWORK_PATH',                     libexecdir / 'systemd-mountwork')
-conf.set_quoted('SYSTEMD_NSRESOURCEWORK_PATH',                libexecdir / 'systemd-nsresourcework')
-conf.set_quoted('SYSTEMD_VERITYSETUP_PATH',                   libexecdir / 'systemd-veritysetup')
+conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', rootbindir / 'systemd-tty-ask-password-agent')
+conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH',                 rootlibexecdir / 'systemd-update-helper')
+conf.set_quoted('SYSTEMD_USERWORK_PATH',                      rootlibexecdir / 'systemd-userwork')
+conf.set_quoted('SYSTEMD_MOUNTWORK_PATH',                     rootlibexecdir / 'systemd-mountwork')
+conf.set_quoted('SYSTEMD_NSRESOURCEWORK_PATH',                rootlibexecdir / 'systemd-nsresourcework')
+conf.set_quoted('SYSTEMD_VERITYSETUP_PATH',                   rootlibexecdir / 'systemd-veritysetup')
 conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR',                     pkgsysconfdir / 'system')
 conf.set_quoted('SYSTEM_DATA_UNIT_DIR',                       systemunitdir)
 conf.set_quoted('SYSTEM_ENV_GENERATOR_DIR',                   systemenvgeneratordir)
@@ -305,7 +341,7 @@ conf.set_quoted('USER_ENV_GENERATOR_DIR',                     userenvgeneratordi
 conf.set_quoted('USER_GENERATOR_DIR',                         usergeneratordir)
 conf.set_quoted('USER_KEYRING_PATH',                          pkgsysconfdir / 'import-pubring.gpg')
 conf.set_quoted('USER_PRESET_DIR',                            userpresetdir)
-conf.set_quoted('VENDOR_KEYRING_PATH',                        libexecdir / 'import-pubring.gpg')
+conf.set_quoted('VENDOR_KEYRING_PATH',                        rootlibexecdir / 'import-pubring.gpg')
 
 conf.set('ANSI_OK_COLOR',                                     'ANSI_' + get_option('ok-color').underscorify().to_upper())
 conf.set10('ENABLE_URLIFY',                                   get_option('urlify'))
@@ -2098,7 +2134,7 @@ libsystemd = shared_library(
         link_depends : libsystemd_sym,
         install : true,
         install_tag: 'libsystemd',
-        install_dir : libdir)
+        install_dir : rootlibdir)
 
 install_libsystemd_static = static_library(
         'systemd',
@@ -2109,7 +2145,7 @@ install_libsystemd_static = static_library(
         build_by_default : static_libsystemd != 'false',
         install : static_libsystemd != 'false',
         install_tag: 'libsystemd',
-        install_dir : libdir,
+        install_dir : rootlibdir,
         pic : static_libsystemd_pic,
         dependencies : [libblkid,
                         libcap,
@@ -2144,7 +2180,7 @@ libudev = shared_library(
         link_depends : libudev_sym,
         install : true,
         install_tag: 'libudev',
-        install_dir : libdir)
+        install_dir : rootlibdir)
 
 install_libudev_static = static_library(
         'udev',
@@ -2157,7 +2193,7 @@ install_libudev_static = static_library(
         build_by_default : static_libudev != 'false',
         install : static_libudev != 'false',
         install_tag: 'libudev',
-        install_dir : libdir,
+        install_dir : rootlibdir,
         link_depends : libudev_sym,
         dependencies : [libmount,
                         libshared_deps,
@@ -2197,7 +2233,7 @@ endif
 executable_template = {
         'include_directories' : includes,
         'link_with' : libshared,
-        'install_rpath' : pkglibdir,
+        'install_rpath' : rootpkglibdir,
         'install' : true,
 }
 
@@ -2903,11 +2939,14 @@ alt_time_epoch = run_command('date', '-Is', '-u', '-d', '@@0@'.format(time_epoch
                              check : true).stdout().strip()
 
 summary({
+        'split /usr' :                      split_usr,
         'split bin-sbin' :                  split_bin,
         'prefix directory' :                prefixdir,
+        'rootprefix directory' :            rootprefixdir,
         'sysconf directory' :               sysconfdir,
         'include directory' :               includedir,
         'lib directory' :                   libdir,
+        'rootlib directory' :               rootlibdir,
         'SysV init scripts' :               sysvinit_path,
         'SysV rc?.d directories' :          sysvrcnd_path,
         'PAM modules directory' :           pamlibdir,
@@ -3139,3 +3178,10 @@ summary({
         'enabled' :  ', '.join(found),
         'disabled' : ', '.join(missing)},
         section : 'Features')
+
+if rootprefixdir != rootprefix_default
+        warning('\n' +
+                'Note that the installation prefix was changed to "@0@".\n'.format(rootprefixdir) +
+                'systemd used fixed names for unit file directories and other paths, so anything\n' +
+                'except the default ("@0@") is strongly discouraged.'.format(rootprefix_default))
+endif
diff --git a/meson_options.txt b/meson_options.txt
index 909e2d53e8b0..67b1fc1b7e9e 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -11,14 +11,14 @@ option('vcs-tag', type : 'boolean', value : true,
 option('mode', type : 'combo', choices : ['developer', 'release'],
        description : 'autoenable features suitable for systemd development/release builds')
 
-option('split-usr', type : 'combo', choices : ['auto', 'true', 'false'], deprecated: true,
-       description : 'This option is deprecated and will be removed in a future release')
+option('split-usr', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : '''/bin, /sbin aren't symlinks into /usr''')
 option('split-bin', type : 'combo', choices : ['auto', 'true', 'false'],
-       description : 'sbin is not a symlink to bin')
-option('rootlibdir', type : 'string', deprecated: true,
-       description : 'This option is deprecated and will be removed in a future release')
-option('rootprefix', type : 'string', deprecated: true,
-       description : 'This option is deprecated and will be removed in a future release')
+       description : '''sbin is not a symlink to bin''')
+option('rootlibdir', type : 'string',
+       description : '''[/usr]/lib/x86_64-linux-gnu or such''')
+option('rootprefix', type : 'string',
+       description : '''override the root prefix [default '/' if split-usr and '/usr' otherwise]''')
 option('link-udev-shared', type : 'boolean',
        description : 'link systemd-udevd and its helpers to libsystemd-shared.so')
 option('link-executor-shared', type : 'boolean',
diff --git a/rules.d/64-btrfs.rules.in b/rules.d/64-btrfs.rules.in
index 039d759f621d..df6e12a5ddc5 100644
--- a/rules.d/64-btrfs.rules.in
+++ b/rules.d/64-btrfs.rules.in
@@ -12,6 +12,6 @@ IMPORT{builtin}="btrfs ready $devnode"
 ENV{ID_BTRFS_READY}=="0", ENV{SYSTEMD_READY}="0"
 
 # reconsider pending devices in case when multidevice volume awaits
-ENV{ID_BTRFS_READY}=="1", RUN+="{{BINDIR}}/udevadm trigger -s block -p ID_BTRFS_READY=0"
+ENV{ID_BTRFS_READY}=="1", RUN+="{{ROOTBINDIR}}/udevadm trigger -s block -p ID_BTRFS_READY=0"
 
 LABEL="btrfs_end"
diff --git a/rules.d/71-seat.rules.in b/rules.d/71-seat.rules.in
index 1fd7ec23b097..25e4ee7e5893 100644
--- a/rules.d/71-seat.rules.in
+++ b/rules.d/71-seat.rules.in
@@ -71,11 +71,11 @@ SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}
 SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \
                   ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \
                   ENV{ID_AVOID_LOOP}=="", \
-                  RUN+="{{BINDIR}}/udevadm trigger --parent-match=%p/.."
+                  RUN+="{{ROOTBINDIR}}/udevadm trigger --parent-match=%p/.."
 
 TAG=="seat", ENV{ID_PATH}=="", IMPORT{builtin}="path_id"
 TAG=="seat", ENV{ID_FOR_SEAT}=="", ENV{ID_PATH_TAG}!="", ENV{ID_FOR_SEAT}="$env{SUBSYSTEM}-$env{ID_PATH_TAG}"
 
-SUBSYSTEM=="input", ATTR{name}=="Wiebetech LLC Wiebetech", RUN+="{{BINDIR}}/loginctl lock-sessions"
+SUBSYSTEM=="input", ATTR{name}=="Wiebetech LLC Wiebetech", RUN+="{{ROOTBINDIR}}/loginctl lock-sessions"
 
 LABEL="seat_end"
diff --git a/rules.d/99-systemd.rules.in b/rules.d/99-systemd.rules.in
index 8ba6f177f845..5cacff93c5fa 100644
--- a/rules.d/99-systemd.rules.in
+++ b/rules.d/99-systemd.rules.in
@@ -68,7 +68,7 @@ SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:
 SUBSYSTEM=="udc", TAG+="systemd", ENV{SYSTEMD_WANTS}+="usb-gadget.target"
 
 # Apply sysctl variables to network devices (and only to those) as they appear.
-ACTION=="add", SUBSYSTEM=="net", KERNEL!="lo", RUN+="{{LIBEXECDIR}}/systemd-sysctl --prefix=/net/ipv4/conf/$name --prefix=/net/ipv4/neigh/$name --prefix=/net/ipv6/conf/$name --prefix=/net/ipv6/neigh/$name"
+ACTION=="add", SUBSYSTEM=="net", KERNEL!="lo", RUN+="{{ROOTLIBEXECDIR}}/systemd-sysctl --prefix=/net/ipv4/conf/$name --prefix=/net/ipv4/neigh/$name --prefix=/net/ipv6/conf/$name --prefix=/net/ipv6/neigh/$name"
 
 {% if ENABLE_BACKLIGHT %}
 # Pull in backlight save/restore for all backlight devices and
diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
index f4576c4355b7..74507e9cfd32 100644
--- a/shell-completion/bash/systemctl.in
+++ b/shell-completion/bash/systemctl.in
@@ -13,7 +13,7 @@ __systemctl() {
 }
 
 __systemd_properties() {
-    {{LIBEXECDIR}}/systemd --dump-bus-properties
+    {{ROOTLIBEXECDIR}}/systemd --dump-bus-properties
 }
 
 __contains_word () {
diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
index df9045f229bc..d9f4686f89d1 100644
--- a/shell-completion/zsh/_systemctl.in
+++ b/shell-completion/zsh/_systemctl.in
@@ -472,7 +472,7 @@ done
 
 (( $+functions[_systemctl_unit_properties] )) ||
     _systemctl_unit_properties() {
-		local -a _sys_all_properties=( ${(f)"$({{LIBEXECDIR}}/systemd --no-pager --dump-bus-properties 2>/dev/null)"} )
+		local -a _sys_all_properties=( ${(f)"$({{ROOTLIBEXECDIR}}/systemd --no-pager --dump-bus-properties 2>/dev/null)"} )
         _wanted systemd-unit-properties expl 'unit property' \
 			_values -s , "${_sys_all_properties[@]}"
     }
diff --git a/src/basic/constants.h b/src/basic/constants.h
index e70817c51f84..cec9c478a2c4 100644
--- a/src/basic/constants.h
+++ b/src/basic/constants.h
@@ -56,19 +56,32 @@
 #define NOTIFY_FD_MAX 768
 #define NOTIFY_BUFFER_MAX PIPE_BUF
 
+#if HAVE_SPLIT_USR
+#  define _CONF_PATHS_SPLIT_USR_NULSTR(n) "/lib/" n "\0"
+#  define _CONF_PATHS_SPLIT_USR(n) , "/lib/" n
+#else
+#  define _CONF_PATHS_SPLIT_USR_NULSTR(n)
+#  define _CONF_PATHS_SPLIT_USR(n)
+#endif
+
 /* Return a nulstr for a standard cascade of configuration paths, suitable to pass to
  * conf_files_list_nulstr() to implement drop-in directories for extending configuration files. */
 #define CONF_PATHS_NULSTR(n)                    \
         "/etc/" n "\0"                          \
         "/run/" n "\0"                          \
         "/usr/local/lib/" n "\0"                \
-        "/usr/lib/" n "\0"
+        "/usr/lib/" n "\0"                      \
+        _CONF_PATHS_SPLIT_USR_NULSTR(n)
 
 #define CONF_PATHS(n)                           \
         "/etc/" n,                              \
         "/run/" n,                              \
         "/usr/local/lib/" n,                    \
-        "/usr/lib/" n
+        "/usr/lib/" n                           \
+        _CONF_PATHS_SPLIT_USR(n)
+
+#define CONF_PATHS_USR_STRV(n)                  \
+        STRV_MAKE(CONF_PATHS_USR(n))
 
 #define CONF_PATHS_STRV(n)                      \
         STRV_MAKE(CONF_PATHS(n))
diff --git a/src/basic/path-lookup.c b/src/basic/path-lookup.c
index 540256b73b84..3d3df61fb927 100644
--- a/src/basic/path-lookup.c
+++ b/src/basic/path-lookup.c
@@ -551,6 +551,10 @@ int lookup_paths_init(
         assert(scope >= 0);
         assert(scope < _RUNTIME_SCOPE_MAX);
 
+#if HAVE_SPLIT_USR
+        flags |= LOOKUP_PATHS_SPLIT_USR;
+#endif
+
         if (!empty_or_root(root_dir)) {
                 if (scope == RUNTIME_SCOPE_USER)
                         return -EINVAL;
@@ -642,7 +646,6 @@ int lookup_paths_init(
                                         "/usr/local/lib/systemd/system",
                                         SYSTEM_DATA_UNIT_DIR,
                                         "/usr/lib/systemd/system",
-                                        /* To be used ONLY for images which might be legacy split-usr */
                                         STRV_IFNOTNULL(flags & LOOKUP_PATHS_SPLIT_USR ? "/lib/systemd/system" : NULL),
                                         STRV_IFNOTNULL(generator_late));
                         break;
diff --git a/src/basic/path-lookup.h b/src/basic/path-lookup.h
index 0db2c5a98caf..cbf1bcf24e54 100644
--- a/src/basic/path-lookup.h
+++ b/src/basic/path-lookup.h
@@ -10,7 +10,7 @@
 typedef enum LookupPathsFlags {
         LOOKUP_PATHS_EXCLUDE_GENERATED   = 1 << 0,
         LOOKUP_PATHS_TEMPORARY_GENERATED = 1 << 1,
-        LOOKUP_PATHS_SPLIT_USR           = 1 << 2, /* Legacy, use ONLY for image payloads which might be old */
+        LOOKUP_PATHS_SPLIT_USR           = 1 << 2,
 } LookupPathsFlags;
 
 typedef struct LookupPaths {
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 792b8ff2cbc6..a224091db4ce 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -17,8 +17,8 @@
 #define PATH_MERGED_BIN(x) x "bin"
 #define PATH_MERGED_BIN_NULSTR(x) x "bin\0"
 
-#define DEFAULT_PATH_WITH_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/")
-#define DEFAULT_PATH_WITHOUT_SBIN PATH_MERGED_BIN("/usr/local/") ":" PATH_MERGED_BIN("/usr/")
+#define DEFAULT_PATH_WITH_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/") ":" PATH_SPLIT_BIN("/")
+#define DEFAULT_PATH_WITHOUT_SBIN PATH_MERGED_BIN("/usr/local/") ":" PATH_MERGED_BIN("/usr/") ":" PATH_MERGED_BIN("/")
 
 #define DEFAULT_PATH_COMPAT PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/") ":" PATH_SPLIT_BIN("/")
 
diff --git a/src/boot/meson.build b/src/boot/meson.build
index 55b9bd6294b0..ec1ba21d49f5 100644
--- a/src/boot/meson.build
+++ b/src/boot/meson.build
@@ -30,6 +30,7 @@ executables += [
                 ],
                 'sources' : bootctl_sources,
                 'link_with' : boot_link_with,
+                'install_dir' : rootbindir,
                 'dependencies' : libblkid,
         },
         libexec_template + {
@@ -41,6 +42,7 @@ executables += [
                 ],
                 'sources' : files('bless-boot.c'),
                 'link_with' : boot_link_with,
+                'install_dir' : rootlibexecdir,
                 'dependencies' : libblkid,
         },
         generator_template + {
@@ -65,5 +67,6 @@ executables += [
         libexec_template + {
                 'name' : 'systemd-boot-check-no-failures',
                 'sources' : files('boot-check-no-failures.c'),
+                'install_dir' : rootlibexecdir,
         },
 ]
diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c
index 1d2959abf439..03803a810172 100644
--- a/src/core/manager-serialize.c
+++ b/src/core/manager-serialize.c
@@ -90,6 +90,7 @@ int manager_serialize(
         (void) serialize_item_format(f, "current-job-id", "%" PRIu32, m->current_job_id);
         (void) serialize_item_format(f, "n-installed-jobs", "%u", m->n_installed_jobs);
         (void) serialize_item_format(f, "n-failed-jobs", "%u", m->n_failed_jobs);
+        (void) serialize_bool(f, "taint-usr", m->taint_usr);
         (void) serialize_bool(f, "ready-sent", m->ready_sent);
         (void) serialize_bool(f, "taint-logged", m->taint_logged);
         (void) serialize_bool(f, "service-watchdogs", m->service_watchdogs);
@@ -354,6 +355,15 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         else
                                 m->n_failed_jobs += n;
 
+                } else if ((val = startswith(l, "taint-usr="))) {
+                        int b;
+
+                        b = parse_boolean(val);
+                        if (b < 0)
+                                log_notice("Failed to parse taint /usr flag '%s', ignoring.", val);
+                        else
+                                m->taint_usr = m->taint_usr || b;
+
                 } else if ((val = startswith(l, "ready-sent="))) {
                         int b;
 
diff --git a/src/core/manager.c b/src/core/manager.c
index 5997ef0cf13b..cc2e145260dc 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1056,6 +1056,9 @@ int manager_new(RuntimeScope runtime_scope, ManagerTestRunFlags test_run_flags,
 
                 log_debug("Using systemd-executor binary from '%s'.", executor_path);
         }
+        m->taint_usr =
+                !in_initrd() &&
+                dir_is_empty("/usr", /* ignore_hidden_or_backup= */ false) > 0;
 
         /* Note that we do not set up the notify fd here. We do that after deserialization,
          * since they might have gotten serialized across the reexec. */
@@ -4946,7 +4949,6 @@ static int manager_dispatch_handoff_timestamp_fd(sd_event_source *source, int fd
         FOREACH_ARRAY(u, units, n_units) {
                 if (!UNIT_VTABLE(*u)->notify_handoff_timestamp)
                         continue;
-
                 UNIT_VTABLE(*u)->notify_handoff_timestamp(*u, ucred, &dt);
         }
 
diff --git a/src/core/manager.h b/src/core/manager.h
index 0641b2726f0f..cdb1e36d3fea 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -388,6 +388,8 @@ struct Manager {
         /* Flags */
         bool dispatching_load_queue;
 
+        bool taint_usr;
+
         /* Have we already sent out the READY=1 notification? */
         bool ready_sent;
 
diff --git a/src/core/meson.build b/src/core/meson.build
index dbeb752977c8..5fa5abc82c75 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -142,7 +142,7 @@ libcore = shared_library(
         link_whole: libcore_static,
         link_with : libshared,
         install : true,
-        install_dir : pkglibdir)
+        install_dir : rootpkglibdir)
 
 core_includes = [includes, include_directories('.')]
 
@@ -261,7 +261,7 @@ if install_sysconfdir
 endif
 
 install_emptydir(sbindir)
-meson.add_install_script(sh, '-c', ln_s.format(libexecdir / 'systemd', sbindir / 'init'))
+meson.add_install_script(sh, '-c', ln_s.format(rootlibexecdir / 'systemd', rootsbindir / 'init'))
 
 ############################################################
 
diff --git a/src/core/namespace.c b/src/core/namespace.c
index a9b98bcd32b2..e2f37287075e 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -154,7 +154,7 @@ static const MountEntry protect_kernel_tunables_sys_table[] = {
 
 /* ProtectKernelModules= option */
 static const MountEntry protect_kernel_modules_table[] = {
-        { "/usr/lib/modules",    MOUNT_INACCESSIBLE, true  },
+        { "/lib/modules",        MOUNT_INACCESSIBLE, true  },
 };
 
 /* ProtectKernelLogs= option */
@@ -195,6 +195,9 @@ static const MountEntry protect_system_yes_table[] = {
         { "/usr",                MOUNT_READ_ONLY,     false },
         { "/boot",               MOUNT_READ_ONLY,     true  },
         { "/efi",                MOUNT_READ_ONLY,     true  },
+        { "/lib",                MOUNT_READ_ONLY,     true  },
+        { "/bin",                MOUNT_READ_ONLY,     true  },
+        { "/sbin",               MOUNT_READ_ONLY,     true  },
 };
 
 /* ProtectSystem=full includes ProtectSystem=yes */
@@ -203,6 +206,9 @@ static const MountEntry protect_system_full_table[] = {
         { "/boot",               MOUNT_READ_ONLY,     true  },
         { "/efi",                MOUNT_READ_ONLY,     true  },
         { "/etc",                MOUNT_READ_ONLY,     false },
+        { "/lib",                MOUNT_READ_ONLY,     false },
+        { "/bin",                MOUNT_READ_ONLY,     false },
+        { "/sbin",               MOUNT_READ_ONLY,     false },
 };
 
 /* ProtectSystem=strict table. In this strict mode, we mount everything read-only, except for /proc, /dev,
diff --git a/src/core/org.freedesktop.systemd1.policy.in b/src/core/org.freedesktop.systemd1.policy.in
index 0083e0b58521..9e9a20f66f67 100644
--- a/src/core/org.freedesktop.systemd1.policy.in
+++ b/src/core/org.freedesktop.systemd1.policy.in
@@ -26,7 +26,7 @@
                         <allow_inactive>no</allow_inactive>
                         <allow_active>auth_admin_keep</allow_active>
                 </defaults>
-                <annotate key="org.freedesktop.policykit.exec.path">{{LIBEXECDIR}}/systemd-reply-password</annotate>
+                <annotate key="org.freedesktop.policykit.exec.path">{{ROOTLIBEXECDIR}}/systemd-reply-password</annotate>
         </action>
 
         <action id="org.freedesktop.systemd1.manage-units">
diff --git a/src/core/systemd.pc.in b/src/core/systemd.pc.in
index f3b85b01909a..693433b34b87 100644
--- a/src/core/systemd.pc.in
+++ b/src/core/systemd.pc.in
@@ -11,24 +11,19 @@
 # considered deprecated (though there is no plan to remove them). New names
 # shall have underscores.
 
-# root_prefix and rootprefix are deprecated since we dropped support for split-usr
-# however we used to install units in root_prefix and a lot of downstream software
-# overrode this variable in their build system to support installing units elsewhere.
-# To stop those builds from silently breaking we keep root_prefix around but have
-# it as an alias for prefix
-root_prefix={{PREFIX_NOSLASH}}
+prefix=/usr
+root_prefix={{ROOTPREFIX_NOSLASH}}
 rootprefix=${root_prefix}
-prefix=${rootprefix}
 sysconf_dir={{SYSCONF_DIR}}
 sysconfdir=${sysconf_dir}
 
-systemd_util_dir=${prefix}/lib/systemd
+systemd_util_dir=${root_prefix}/lib/systemd
 systemdutildir=${systemd_util_dir}
 
-systemd_system_unit_dir=${prefix}/lib/systemd/system
+systemd_system_unit_dir=${rootprefix}/lib/systemd/system
 systemdsystemunitdir=${systemd_system_unit_dir}
 
-systemd_system_preset_dir=${prefix}/lib/systemd/system-preset
+systemd_system_preset_dir=${rootprefix}/lib/systemd/system-preset
 systemdsystempresetdir=${systemd_system_preset_dir}
 
 systemd_user_unit_dir=${prefix}/lib/systemd/user
@@ -49,7 +44,7 @@ systemdsystemunitpath=${systemd_system_unit_path}
 systemd_user_unit_path=${systemd_user_conf_dir}:/etc/systemd/user:/run/systemd/user:/usr/local/lib/systemd/user:/usr/local/share/systemd/user:${systemd_user_unit_dir}:/usr/lib/systemd/user:/usr/share/systemd/user
 systemduserunitpath=${systemd_user_unit_path}
 
-systemd_system_generator_dir=${prefix}/lib/systemd/system-generators
+systemd_system_generator_dir=${root_prefix}/lib/systemd/system-generators
 systemdsystemgeneratordir=${systemd_system_generator_dir}
 
 systemd_user_generator_dir=${prefix}/lib/systemd/user-generators
@@ -61,10 +56,10 @@ systemdsystemgeneratorpath=${systemd_system_generator_path}
 systemd_user_generator_path=/run/systemd/user-generators:/etc/systemd/user-generators:/usr/local/lib/systemd/user-generators:${systemd_user_generator_dir}
 systemdusergeneratorpath=${systemd_user_generator_path}
 
-systemd_sleep_dir=${prefix}/lib/systemd/system-sleep
+systemd_sleep_dir=${root_prefix}/lib/systemd/system-sleep
 systemdsleepdir=${systemd_sleep_dir}
 
-systemd_shutdown_dir=${prefix}/lib/systemd/system-shutdown
+systemd_shutdown_dir=${root_prefix}/lib/systemd/system-shutdown
 systemdshutdowndir=${systemd_shutdown_dir}
 
 tmpfiles_dir=${prefix}/lib/tmpfiles.d
@@ -72,16 +67,16 @@ tmpfilesdir=${tmpfiles_dir}
 
 user_tmpfiles_dir=${prefix}/share/user-tmpfiles.d
 
-sysusers_dir=${prefix}/lib/sysusers.d
+sysusers_dir=${rootprefix}/lib/sysusers.d
 sysusersdir=${sysusers_dir}
 
-sysctl_dir=${prefix}/lib/sysctl.d
+sysctl_dir=${rootprefix}/lib/sysctl.d
 sysctldir=${sysctl_dir}
 
-binfmt_dir=${prefix}/lib/binfmt.d
+binfmt_dir=${rootprefix}/lib/binfmt.d
 binfmtdir=${binfmt_dir}
 
-modules_load_dir=${prefix}/lib/modules-load.d
+modules_load_dir=${rootprefix}/lib/modules-load.d
 modulesloaddir=${modules_load_dir}
 
 catalog_dir=${prefix}/lib/systemd/catalog
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 4db25d362f05..b42fe806a547 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -536,13 +536,13 @@ static int create_disk(
                 }
 
                 fprintf(f,
-                        "ExecStartPost=" LIBEXECDIR "/systemd-makefs '%s' '/dev/mapper/%s'\n",
+                        "ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs '%s' '/dev/mapper/%s'\n",
                         tmp_fstype_escaped ?: "ext4", name_escaped);
         }
 
         if (swap)
                 fprintf(f,
-                        "ExecStartPost=" LIBEXECDIR "/systemd-makefs swap '/dev/mapper/%s'\n",
+                        "ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs swap '/dev/mapper/%s'\n",
                         name_escaped);
 
         r = fflush_and_check(f);
diff --git a/src/cryptsetup/cryptsetup-tokens/meson.build b/src/cryptsetup/cryptsetup-tokens/meson.build
index b26940c6a3b1..9f9c1f20b649 100644
--- a/src/cryptsetup/cryptsetup-tokens/meson.build
+++ b/src/cryptsetup/cryptsetup-tokens/meson.build
@@ -30,7 +30,7 @@ template = {
                 libshared,
         ],
         'version-script' : meson.current_source_dir() / 'cryptsetup-token.sym',
-        'install_rpath' : pkglibdir,
+        'install_rpath' : rootpkglibdir,
         'install' : true,
         'install_dir' : libcryptsetup_plugins_dir,
 }
diff --git a/src/delta/delta.c b/src/delta/delta.c
index 3433250549bb..a82f7f5ee17a 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -35,6 +35,9 @@ static const char prefixes[] =
         "/usr/local/share\0"
         "/usr/lib\0"
         "/usr/share\0"
+#if HAVE_SPLIT_USR
+        "/lib\0"
+#endif
         ;
 
 static const char suffixes[] =
@@ -365,6 +368,36 @@ static int enumerate_dir(
         return 0;
 }
 
+static int should_skip_path(const char *prefix, const char *suffix) {
+#if HAVE_SPLIT_USR
+        _cleanup_free_ char *target = NULL, *dirname = NULL;
+
+        dirname = path_join(prefix, suffix);
+        if (!dirname)
+                return -ENOMEM;
+
+        if (chase(dirname, NULL, 0, &target, NULL) < 0)
+                return false;
+
+        NULSTR_FOREACH(p, prefixes) {
+                _cleanup_free_ char *tmp = NULL;
+
+                if (path_startswith(dirname, p))
+                        continue;
+
+                tmp = path_join(p, suffix);
+                if (!tmp)
+                        return -ENOMEM;
+
+                if (path_equal(target, tmp)) {
+                        log_debug("%s redirects to %s, skipping.", dirname, target);
+                        return true;
+                }
+        }
+#endif
+        return false;
+}
+
 static int process_suffix(const char *suffix, const char *onlyprefix) {
         char *f, *key;
         OrderedHashmap *top, *bottom, *drops, *h;
@@ -388,6 +421,9 @@ static int process_suffix(const char *suffix, const char *onlyprefix) {
         NULSTR_FOREACH(p, prefixes) {
                 _cleanup_free_ char *t = NULL;
 
+                if (should_skip_path(p, suffix) > 0)
+                        continue;
+
                 t = path_join(p, suffix);
                 if (!t) {
                         r = -ENOMEM;
diff --git a/src/dissect/meson.build b/src/dissect/meson.build
index e422dbdd27b2..c6a485db97ec 100644
--- a/src/dissect/meson.build
+++ b/src/dissect/meson.build
@@ -13,5 +13,5 @@ if conf.get('HAVE_BLKID') == 1
         install_emptydir(sbindir)
         meson.add_install_script(sh, '-c',
                                  ln_s.format(bindir / 'systemd-dissect',
-                                             sbindir / 'mount.ddi'))
+                                             rootsbindir / 'mount.ddi'))
 endif
diff --git a/src/fstab-generator/meson.build b/src/fstab-generator/meson.build
index 7b90580e9063..2146d24474bb 100644
--- a/src/fstab-generator/meson.build
+++ b/src/fstab-generator/meson.build
@@ -9,4 +9,4 @@ executables += [
 
 meson.add_install_script(sh, '-c',
                          ln_s.format(systemgeneratordir / 'systemd-fstab-generator',
-                                     libexecdir / 'systemd-sysroot-fstab-check'))
+                                     rootlibexecdir / 'systemd-sysroot-fstab-check'))
diff --git a/src/import/meson.build b/src/import/meson.build
index 184dd7bbf2dc..ed5290df9cf6 100644
--- a/src/import/meson.build
+++ b/src/import/meson.build
@@ -129,5 +129,5 @@ install_data('org.freedesktop.import1.policy',
              install_dir : polkitpolicydir)
 
 install_data('import-pubring.gpg',
-             install_dir : libexecdir)
+             install_dir : rootlibexecdir)
 # TODO: shouldn't this be in pkgdatadir?
diff --git a/src/integritysetup/integritysetup-generator.c b/src/integritysetup/integritysetup-generator.c
index 72b890575ce1..ea187e0c191a 100644
--- a/src/integritysetup/integritysetup-generator.c
+++ b/src/integritysetup/integritysetup-generator.c
@@ -101,8 +101,8 @@ static int create_disk(
                 "Type=oneshot\n"
                 "RemainAfterExit=yes\n"
                 "TimeoutSec=infinity\n"
-                "ExecStart=" LIBEXECDIR "/systemd-integritysetup attach '%s' '%s' '%s' '%s'\n"
-                "ExecStop=" LIBEXECDIR "/systemd-integritysetup detach '%s'\n",
+                "ExecStart=" ROOTLIBEXECDIR "/systemd-integritysetup attach '%s' '%s' '%s' '%s'\n"
+                "ExecStop=" ROOTLIBEXECDIR "/systemd-integritysetup detach '%s'\n",
                 name_escaped, device, empty_to_dash(key_file_escaped), empty_to_dash(options),
                 name_escaped);
 
diff --git a/src/libsystemd/libsystemd.pc.in b/src/libsystemd/libsystemd.pc.in
index 3a43ef60710e..da6e4e667ef7 100644
--- a/src/libsystemd/libsystemd.pc.in
+++ b/src/libsystemd/libsystemd.pc.in
@@ -9,7 +9,7 @@
 
 prefix={{PREFIX}}
 exec_prefix={{PREFIX}}
-libdir={{LIBDIR}}
+libdir={{ROOTLIBDIR}}
 includedir={{INCLUDE_DIR}}
 
 Name: systemd
diff --git a/src/libsystemd/sd-hwdb/hwdb-internal.h b/src/libsystemd/sd-hwdb/hwdb-internal.h
index 9db3b314416e..5302679a6252 100644
--- a/src/libsystemd/sd-hwdb/hwdb-internal.h
+++ b/src/libsystemd/sd-hwdb/hwdb-internal.h
@@ -86,4 +86,5 @@ struct trie_value_entry2_f {
         "/etc/systemd/hwdb/hwdb.bin\0"          \
         "/etc/udev/hwdb.bin\0"                  \
         "/usr/lib/systemd/hwdb/hwdb.bin\0"      \
+        _CONF_PATHS_SPLIT_USR_NULSTR("systemd/hwdb/hwdb.bin") \
         UDEVLIBEXECDIR "/hwdb.bin\0"
diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c
index 8edbde9c8ec4..0d68a4394514 100644
--- a/src/libsystemd/sd-path/sd-path.c
+++ b/src/libsystemd/sd-path/sd-path.c
@@ -311,7 +311,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
                 return from_user_dir("XDG_DESKTOP_DIR", buffer, ret);
 
         case SD_PATH_SYSTEMD_UTIL:
-                *ret = PREFIX_NOSLASH "/lib/systemd";
+                *ret = ROOTPREFIX_NOSLASH "/lib/systemd";
                 return 0;
 
         case SD_PATH_SYSTEMD_SYSTEM_UNIT:
@@ -319,7 +319,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
                 return 0;
 
         case SD_PATH_SYSTEMD_SYSTEM_PRESET:
-                *ret = PREFIX_NOSLASH "/lib/systemd/system-preset";
+                *ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-preset";
                 return 0;
 
         case SD_PATH_SYSTEMD_USER_UNIT:
@@ -327,7 +327,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
                 return 0;
 
         case SD_PATH_SYSTEMD_USER_PRESET:
-                *ret = PREFIX_NOSLASH "/lib/systemd/user-preset";
+                *ret = ROOTPREFIX_NOSLASH "/lib/systemd/user-preset";
                 return 0;
 
         case SD_PATH_SYSTEMD_SYSTEM_CONF:
@@ -347,11 +347,11 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
                 return 0;
 
         case SD_PATH_SYSTEMD_SLEEP:
-                *ret = PREFIX_NOSLASH "/lib/systemd/system-sleep";
+                *ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-sleep";
                 return 0;
 
         case SD_PATH_SYSTEMD_SHUTDOWN:
-                *ret = PREFIX_NOSLASH "/lib/systemd/system-shutdown";
+                *ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-shutdown";
                 return 0;
 
         case SD_PATH_TMPFILES:
@@ -359,19 +359,19 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
                 return 0;
 
         case SD_PATH_SYSUSERS:
-                *ret = PREFIX_NOSLASH "/lib/sysusers.d";
+                *ret = ROOTPREFIX_NOSLASH "/lib/sysusers.d";
                 return 0;
 
         case SD_PATH_SYSCTL:
-                *ret = PREFIX_NOSLASH "/lib/sysctl.d";
+                *ret = ROOTPREFIX_NOSLASH "/lib/sysctl.d";
                 return 0;
 
         case SD_PATH_BINFMT:
-                *ret = PREFIX_NOSLASH "/lib/binfmt.d";
+                *ret = ROOTPREFIX_NOSLASH "/lib/binfmt.d";
                 return 0;
 
         case SD_PATH_MODULES_LOAD:
-                *ret = PREFIX_NOSLASH "/lib/modules-load.d";
+                *ret = ROOTPREFIX_NOSLASH "/lib/modules-load.d";
                 return 0;
 
         case SD_PATH_CATALOG:
@@ -531,6 +531,9 @@ static int get_search(uint64_t type, char ***ret) {
                                                true,
                                                ARRAY_SBIN_BIN("/usr/local/"),
                                                ARRAY_SBIN_BIN("/usr/"),
+#if HAVE_SPLIT_USR
+                                               ARRAY_SBIN_BIN("/"),
+#endif
                                                NULL);
 
         case SD_PATH_SEARCH_LIBRARY_PRIVATE:
@@ -541,6 +544,9 @@ static int get_search(uint64_t type, char ***ret) {
                                                false,
                                                "/usr/local/lib",
                                                "/usr/lib",
+#if HAVE_SPLIT_USR
+                                               "/lib",
+#endif
                                                NULL);
 
         case SD_PATH_SEARCH_LIBRARY_ARCH:
@@ -550,6 +556,9 @@ static int get_search(uint64_t type, char ***ret) {
                                                "LD_LIBRARY_PATH",
                                                true,
                                                LIBDIR,
+#if HAVE_SPLIT_USR
+                                               ROOTLIBDIR,
+#endif
                                                NULL);
 
         case SD_PATH_SEARCH_SHARED:
diff --git a/src/libudev/libudev.pc.in b/src/libudev/libudev.pc.in
index 6541bcb1ab6b..1d6487fa4084 100644
--- a/src/libudev/libudev.pc.in
+++ b/src/libudev/libudev.pc.in
@@ -9,7 +9,7 @@
 
 prefix={{PREFIX}}
 exec_prefix={{PREFIX}}
-libdir={{LIBDIR}}
+libdir={{ROOTLIBDIR}}
 includedir={{INCLUDE_DIR}}
 
 Name: libudev
diff --git a/src/login/meson.build b/src/login/meson.build
index 43db03184c58..5636dbde41ae 100644
--- a/src/login/meson.build
+++ b/src/login/meson.build
@@ -50,6 +50,7 @@ executables += [
                 'dbus' : true,
                 'conditions' : ['ENABLE_LOGIND'],
                 'sources' : systemd_logind_sources,
+                'install_dir' : rootlibexecdir,
                 'link_with' : [
                         liblogind_core,
                         libshared,
@@ -64,6 +65,7 @@ executables += [
                 'public' : true,
                 'conditions' : ['ENABLE_LOGIND'],
                 'sources' : loginctl_sources,
+                'install_dir' : rootbindir,
                 'dependencies' : [
                         liblz4_cflags,
                         libxz_cflags,
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 1b63e6d20378..e419289e5c78 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1997,7 +1997,7 @@ static int chainload_importctl(int argc, char *argv[]) {
                 log_debug("Chainloading: %s", joined);
         }
 
-        r = invoke_callout_binary(BINDIR "/importctl", c);
+        r = invoke_callout_binary(ROOTBINDIR "/importctl", c);
         return log_error_errno(r, "Failed to invoke 'importctl': %m");
 }
 
diff --git a/src/portable/meson.build b/src/portable/meson.build
index 210829b85145..e168b509c340 100644
--- a/src/portable/meson.build
+++ b/src/portable/meson.build
@@ -25,6 +25,7 @@ executables += [
                 'conditions' : ['ENABLE_PORTABLED'],
                 'sources' : systemd_portabled_sources,
                 'link_with' : portabled_link_with,
+                'install_dir' : rootlibexecdir,
                 'dependencies' : [
                         libselinux,
                         threads,
@@ -36,6 +37,7 @@ executables += [
                 'conditions' : ['ENABLE_PORTABLED'],
                 'sources' : files('portablectl.c'),
                 'link_with' : portabled_link_with,
+                'install_dir' : rootbindir,
                 'dependencies' : threads,
         },
 ]
diff --git a/src/portable/portable.c b/src/portable/portable.c
index 53418c417b51..153c8dfb74f5 100644
--- a/src/portable/portable.c
+++ b/src/portable/portable.c
@@ -245,8 +245,8 @@ static int extract_now(
         }
 
         /* Then, send unit file data to the parent (or/and add it to the hashmap). For that we use our usual unit
-         * discovery logic. Note that we force looking inside of /lib/systemd/system/ for units too, as the
-         * image might have a legacy split-usr layout. */
+         * discovery logic. Note that we force looking inside of /lib/systemd/system/ for units too, as we mightbe
+         * compiled for a split-usr system but the image might be a legacy-usr one. */
         r = lookup_paths_init(&paths, RUNTIME_SCOPE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, where);
         if (r < 0)
                 return log_debug_errno(r, "Failed to acquire lookup paths: %m");
@@ -1664,7 +1664,7 @@ int portable_attach(
                                 strempty(extensions_joined));
         }
 
-        r = lookup_paths_init(&paths, RUNTIME_SCOPE_SYSTEM, /* flags= */ 0, NULL);
+        r = lookup_paths_init(&paths, RUNTIME_SCOPE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL);
         if (r < 0)
                 return r;
 
@@ -1854,7 +1854,7 @@ int portable_detach(
 
         assert(name_or_path);
 
-        r = lookup_paths_init(&paths, RUNTIME_SCOPE_SYSTEM, /* flags= */ 0, NULL);
+        r = lookup_paths_init(&paths, RUNTIME_SCOPE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL);
         if (r < 0)
                 return r;
 
@@ -2040,7 +2040,7 @@ static int portable_get_state_internal(
         assert(name_or_path);
         assert(ret);
 
-        r = lookup_paths_init(&paths, RUNTIME_SCOPE_SYSTEM, /* flags= */ 0, NULL);
+        r = lookup_paths_init(&paths, RUNTIME_SCOPE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL);
         if (r < 0)
                 return r;
 
diff --git a/src/resolve/meson.build b/src/resolve/meson.build
index d336b2c07bf4..ae1bc2a825dc 100644
--- a/src/resolve/meson.build
+++ b/src/resolve/meson.build
@@ -144,6 +144,7 @@ executables += [
                             files('resolved.c'),
                 'include_directories' : resolve_includes,
                 'link_with' : link_with,
+                'install_dir': rootlibexecdir,
                 'dependencies' : systemd_resolved_dependencies,
         },
         executable_template + {
@@ -152,6 +153,7 @@ executables += [
                 'conditions' : ['ENABLE_RESOLVE'],
                 'sources' : resolvectl_sources,
                 'link_with' : link_with,
+                'install_dir': rootbindir,
                 'dependencies' : [
                         lib_openssl_or_gcrypt,
                         libidn,
@@ -231,17 +233,17 @@ if conf.get('ENABLE_RESOLVE') == 1
         install_data('org.freedesktop.resolve1.policy',
                      install_dir : polkitpolicydir)
         install_data('resolv.conf',
-                     install_dir : libexecdir)
+                     install_dir : rootlibexecdir)
 
-        install_emptydir(sbindir)
+        install_emptydir(rootsbindir)
         meson.add_install_script(sh, '-c',
-                                 ln_s.format(bindir / 'resolvectl',
-                                             sbindir / 'resolvconf'))
+                                 ln_s.format(rootbindir / 'resolvectl',
+                                             rootsbindir / 'resolvconf'))
 
         # symlink for backwards compatibility after rename
         meson.add_install_script(sh, '-c',
-                                 ln_s.format(bindir / 'resolvectl',
-                                             bindir / 'systemd-resolve'))
+                                 ln_s.format(rootbindir / 'resolvectl',
+                                             rootbindir / 'systemd-resolve'))
 endif
 
 custom_target(
diff --git a/src/rpm/macros.systemd.in b/src/rpm/macros.systemd.in
index ce65ec670042..815e8ce9c838 100644
--- a/src/rpm/macros.systemd.in
+++ b/src/rpm/macros.systemd.in
@@ -5,7 +5,7 @@
 
 # RPM macros for packages installing systemd unit files
 
-%_systemd_util_dir {{LIBEXECDIR}}
+%_systemd_util_dir {{ROOTLIBEXECDIR}}
 %_unitdir {{SYSTEM_DATA_UNIT_DIR}}
 %_userunitdir {{USER_DATA_UNIT_DIR}}
 %_presetdir {{SYSTEM_PRESET_DIR}}
@@ -187,10 +187,10 @@ SYSTEMD_INLINE_EOF\
 
 %sysctl_apply() \
 %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# sysctl_apply}} \
-[ -x {{LIBEXECDIR}}/systemd-sysctl ] && {{LIBEXECDIR}}/systemd-sysctl %{?*} || : \
+[ -x {{ROOTLIBEXECDIR}}/systemd-sysctl ] && {{ROOTLIBEXECDIR}}/systemd-sysctl %{?*} || : \
 %{nil}
 
 %binfmt_apply() \
 %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# binfmt_apply}} \
-[ -x {{LIBEXECDIR}}/systemd-binfmt ] && {{LIBEXECDIR}}/systemd-binfmt %{?*} || : \
+[ -x {{ROOTLIBEXECDIR}}/systemd-binfmt ] && {{ROOTLIBEXECDIR}}/systemd-binfmt %{?*} || : \
 %{nil}
diff --git a/src/rpm/meson.build b/src/rpm/meson.build
index af39ff145ab9..817665912a9f 100644
--- a/src/rpm/meson.build
+++ b/src/rpm/meson.build
@@ -3,8 +3,8 @@
 in_files = [
         ['macros.systemd',        rpmmacrosdir != 'no', rpmmacrosdir],
 
-        # we conditionalize on rpmmacrosdir, but install into libexecdir
-        ['systemd-update-helper', rpmmacrosdir != 'no', libexecdir],
+        # we conditionalize on rpmmacrosdir, but install into rootlibexecdir
+        ['systemd-update-helper', rpmmacrosdir != 'no', rootlibexecdir],
 
         ['triggers.systemd',      false],
         ['triggers.systemd.sh',   false]]
diff --git a/src/rpm/triggers.systemd.in b/src/rpm/triggers.systemd.in
index d480ab84b6bb..60b963fffdfd 100644
--- a/src/rpm/triggers.systemd.in
+++ b/src/rpm/triggers.systemd.in
@@ -58,7 +58,7 @@ assert(rpm.execute("journalctl", "--update-catalog"))
 -- This script will automatically apply binfmt rules if files have been
 -- installed or updated in {{BINFMT_DIR}}.
 if posix.access("/run/systemd/system") then
-    assert(rpm.execute("{{LIBEXECDIR}}/systemd-binfmt"))
+    assert(rpm.execute("{{ROOTLIBEXECDIR}}/systemd-binfmt"))
 end
 
 %transfiletriggerin -P 1000600 -p <lua> -- {{TMPFILES_DIR}}
@@ -78,5 +78,5 @@ end
 -- This script will automatically apply sysctl rules if files have been
 -- installed or updated in {{SYSCTL_DIR}}.
 if posix.access("/run/systemd/system") then
-    assert(rpm.execute("{{LIBEXECDIR}}/systemd-sysctl"))
+    assert(rpm.execute("{{ROOTLIBEXECDIR}}/systemd-sysctl"))
 end
diff --git a/src/rpm/triggers.systemd.sh.in b/src/rpm/triggers.systemd.sh.in
index 1b94f7d73a05..8c301f5ed9d6 100644
--- a/src/rpm/triggers.systemd.sh.in
+++ b/src/rpm/triggers.systemd.sh.in
@@ -61,7 +61,7 @@ journalctl --update-catalog || :
 if test -d "/run/systemd/system"; then
   # systemd-binfmt might fail if binfmt_misc kernel module is not loaded
   # during install
-  {{LIBEXECDIR}}/systemd-binfmt || :
+  {{ROOTLIBEXECDIR}}/systemd-binfmt || :
 fi
 
 %transfiletriggerin -P 1000600 -- {{TMPFILES_DIR}}
@@ -83,5 +83,5 @@ fi
 # This script will automatically apply sysctl rules if files have been
 # installed or updated in {{SYSCTL_DIR}}.
 if test -d "/run/systemd/system"; then
-  {{LIBEXECDIR}}/systemd-sysctl || :
+  {{ROOTLIBEXECDIR}}/systemd-sysctl || :
 fi
diff --git a/src/shared/install.c b/src/shared/install.c
index 53566b7eef7f..50e899274450 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -266,6 +266,11 @@ static int path_is_vendor_or_generator(const LookupPaths *lp, const char *path)
         if (path_startswith(rpath, "/usr"))
                 return true;
 
+#if HAVE_SPLIT_USR
+        if (path_startswith(rpath, "/lib"))
+                return true;
+#endif
+
         if (path_is_generator(lp, rpath))
                 return true;
 
diff --git a/src/shared/kbd-util.c b/src/shared/kbd-util.c
index 60e0429b82a8..2b918138cb67 100644
--- a/src/shared/kbd-util.c
+++ b/src/shared/kbd-util.c
@@ -14,7 +14,8 @@
 #define KBD_KEYMAP_DIRS                         \
         "/usr/share/keymaps/",                  \
         "/usr/share/kbd/keymaps/",              \
-        "/usr/lib/kbd/keymaps/"
+        "/usr/lib/kbd/keymaps/",                \
+        "/lib/kbd/keymaps/"
 
 int keymap_directories(char ***ret) {
         assert(ret);
diff --git a/src/shared/meson.build b/src/shared/meson.build
index e513c0ec1c27..e7ce0cf4935c 100644
--- a/src/shared/meson.build
+++ b/src/shared/meson.build
@@ -363,7 +363,7 @@ libshared = shared_library(
         dependencies : [libshared_deps,
                         userspace],
         install : true,
-        install_dir : pkglibdir)
+        install_dir : rootpkglibdir)
 
 shared_fdisk_sources = files('fdisk-util.c')
 
diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h
index 2d210f9af755..7c9008c7053f 100644
--- a/src/shared/resolve-util.h
+++ b/src/shared/resolve-util.h
@@ -96,4 +96,4 @@ DnsCacheMode dns_cache_mode_from_string(const char *s) _pure_;
 #define PRIVATE_STUB_RESOLV_CONF "/run/systemd/resolve/stub-resolv.conf"
 
 /* A static resolv.conf file containing no domains, but only our own DNS server address */
-#define PRIVATE_STATIC_RESOLV_CONF LIBEXECDIR "/resolv.conf"
+#define PRIVATE_STATIC_RESOLV_CONF ROOTLIBEXECDIR "/resolv.conf"
diff --git a/src/shared/userdb-dropin.h b/src/shared/userdb-dropin.h
index 3bd1b9c8451f..fad3981f7c6b 100644
--- a/src/shared/userdb-dropin.h
+++ b/src/shared/userdb-dropin.h
@@ -13,7 +13,8 @@
         "/run/" n "\0"                          \
         "/run/host/" n "\0"                     \
         "/usr/local/lib/" n "\0"                \
-        "/usr/lib/" n "\0"
+        "/usr/lib/" n "\0"                      \
+        _CONF_PATHS_SPLIT_USR_NULSTR(n)
 
 int dropin_user_record_by_name(const char *name, const char *path, UserDBFlags flags, UserRecord **ret);
 int dropin_user_record_by_uid(uid_t uid, const char *path, UserDBFlags flags, UserRecord **ret);
diff --git a/src/shared/userdb.c b/src/shared/userdb.c
index 75dece344293..353388125f79 100644
--- a/src/shared/userdb.c
+++ b/src/shared/userdb.c
@@ -1448,7 +1448,7 @@ int userdb_block_nss_systemd(int b) {
 
         /* Note that we might be called from libnss_systemd.so.2 itself, but that should be fine, really. */
 
-        dl = dlopen(LIBDIR "/libnss_systemd.so.2", RTLD_LAZY|RTLD_NODELETE);
+        dl = dlopen(ROOTLIBDIR "/libnss_systemd.so.2", RTLD_LAZY|RTLD_NODELETE);
         if (!dl) {
                 /* If the file isn't installed, don't complain loudly */
                 log_debug("Failed to dlopen(libnss_systemd.so.2), ignoring: %s", dlerror());
diff --git a/src/sysext/meson.build b/src/sysext/meson.build
index 2983970d802a..09b68fde382a 100644
--- a/src/sysext/meson.build
+++ b/src/sysext/meson.build
@@ -10,6 +10,6 @@ executables += [
 ]
 
 if conf.get('ENABLE_SYSEXT') == 1
-        meson.add_install_script(sh, '-c', ln_s.format(bindir / 'systemd-sysext',
-                                                       bindir / 'systemd-confext'))
+        meson.add_install_script(sh, '-c', ln_s.format(rootbindir / 'systemd-sysext',
+                                                       rootbindir / 'systemd-confext'))
 endif
diff --git a/src/systemctl/meson.build b/src/systemctl/meson.build
index 88f73bf502a7..30d173ed123c 100644
--- a/src/systemctl/meson.build
+++ b/src/systemctl/meson.build
@@ -53,6 +53,7 @@ executables += [
                 'public' : true,
                 'sources' : systemctl_sources,
                 'link_with' : systemctl_link_with,
+                'install_dir' : rootbindir,
                 'dependencies' : [
                         libcap,
                         liblz4_cflags,
diff --git a/src/systemctl/systemctl-sysv-compat.c b/src/systemctl/systemctl-sysv-compat.c
index 8ee16eb13f88..b55675c83aa1 100644
--- a/src/systemctl/systemctl-sysv-compat.c
+++ b/src/systemctl/systemctl-sysv-compat.c
@@ -137,7 +137,7 @@ int enable_sysv_units(const char *verb, char **args) {
         while (args[f]) {
 
                 const char *argv[] = {
-                        LIBEXECDIR "/systemd-sysv-install",
+                        ROOTLIBEXECDIR "/systemd-sysv-install",
                         NULL, /* --root= */
                         NULL, /* verb */
                         NULL, /* service */
diff --git a/src/udev/meson.build b/src/udev/meson.build
index 3535551e7440..33d9aef9fbad 100644
--- a/src/udev/meson.build
+++ b/src/udev/meson.build
@@ -97,7 +97,7 @@ link_config_gperf_c = custom_target(
 
 if get_option('link-udev-shared')
         udev_link_with = [libshared]
-        udev_rpath = pkglibdir
+        udev_rpath = rootpkglibdir
 else
         udev_link_with = [libshared_static,
                           libsystemd_static]
diff --git a/src/userdb/20-systemd-userdb.conf.in b/src/userdb/20-systemd-userdb.conf.in
index 031fc3a4b89b..823907a5fe31 100644
--- a/src/userdb/20-systemd-userdb.conf.in
+++ b/src/userdb/20-systemd-userdb.conf.in
@@ -2,5 +2,5 @@
 #
 # Make sure SSH authorized keys recorded in user records can be consumed by SSH
 #
-AuthorizedKeysCommand {{BINDIR}}/userdbctl ssh-authorized-keys %u
+AuthorizedKeysCommand {{ROOTBINDIR}}/userdbctl ssh-authorized-keys %u
 AuthorizedKeysCommandUser root
diff --git a/src/xdg-autostart-generator/xdg-autostart-service.c b/src/xdg-autostart-generator/xdg-autostart-service.c
index 480d1009c3e5..6778c90535b2 100644
--- a/src/xdg-autostart-generator/xdg-autostart-service.c
+++ b/src/xdg-autostart-generator/xdg-autostart-service.c
@@ -668,7 +668,7 @@ int xdg_autostart_service_generate_unit(
 
                 /* Just assume the values are reasonably sane */
                 fprintf(f,
-                        "ExecCondition=" LIBEXECDIR "/systemd-xdg-autostart-condition \"%s\" \"%s\"\n",
+                        "ExecCondition=" ROOTLIBEXECDIR "/systemd-xdg-autostart-condition \"%s\" \"%s\"\n",
                         e_only_show_in,
                         e_not_show_in);
         }
diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in
index 90c080bdfefa..5fb551a8cf9f 100644
--- a/sysctl.d/50-coredump.conf.in
+++ b/sysctl.d/50-coredump.conf.in
@@ -13,7 +13,7 @@
 # the core dump.
 #
 # See systemd-coredump(8) and core(5).
-kernel.core_pattern=|{{LIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h
+kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h
 
 # Allow 16 coredumps to be dispatched in parallel by the kernel.
 # We collect metadata from /proc/%P/, and thus need to make sure the crashed
diff --git a/test/fuzz/fuzz-catalog/systemd.pl.catalog b/test/fuzz/fuzz-catalog/systemd.pl.catalog
index 99a62ce5e0b6..a064813fab94 100644
--- a/test/fuzz/fuzz-catalog/systemd.pl.catalog
+++ b/test/fuzz/fuzz-catalog/systemd.pl.catalog
@@ -376,6 +376,8 @@ Defined-By: systemd
 Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
 
 Możliwe są następujące „etykiety”:
+• „split-usr” — /usr jest oddzielnym systemem plików, który nie był
+  zamontowany w czasie uruchomienia systemd,
 • „cgroups-missing” — jądro zostało skompilowane bez obsługi cgroups
   lub dostęp do oczekiwanych plików interfejsu jest ograniczony,
 • „var-run-bad” — /var/run nie jest dowiązaniem symbolicznym do /run,
diff --git a/test/test-fstab-generator.sh b/test/test-fstab-generator.sh
index af8fa7c226d5..476312133e43 100755
--- a/test/test-fstab-generator.sh
+++ b/test/test-fstab-generator.sh
@@ -59,6 +59,11 @@ test_one() (
         touch "$i"
     done
 
+    # For split-usr system
+    for i in "$out"/systemd-*.service; do
+        sed -i -e 's:ExecStart=/lib/systemd/:ExecStart=/usr/lib/systemd/:' "$i"
+    done
+
     if [[ "${input##*/}" =~ \.fstab\.input ]]; then
         for i in "$out"/*.{automount,mount,swap}; do
             sed -i -e 's:SourcePath=.*$:SourcePath=/etc/fstab:' "$i"
diff --git a/test/test-functions b/test/test-functions
index 04fe20f5478c..5ed9041eb182 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -95,7 +95,7 @@ else
 fi
 
 if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
-    echo "WARNING! Cannot determine libdir from pkg-config, assuming /usr/lib/systemd" >&2
+    echo "WARNING! Cannot determine rootlibdir from pkg-config, assuming /usr/lib/systemd" >&2
     ROOTLIBDIR=/usr/lib/systemd
 fi
 
@@ -2183,6 +2183,14 @@ install_keymaps() {
 
     dinfo "Install console keymaps"
 
+    if command -v meson >/dev/null \
+            && [[ "$(meson configure "${BUILD_DIR:?}" | grep 'split-usr' | awk '{ print $2 }')" == "true" ]] \
+            || [[ ! -L /lib ]]; then
+        prefix+=(
+            "/lib"
+        )
+    fi
+
     if (( $# == 0 )); then
         for p in "${prefix[@]}"; do
             # The first three paths may be deprecated.
diff --git a/units/emergency.service.in b/units/emergency.service.in
index 25aa8ec5106d..c21336ff0251 100644
--- a/units/emergency.service.in
+++ b/units/emergency.service.in
@@ -20,7 +20,7 @@ Before=rescue.service
 Environment=HOME=/root
 WorkingDirectory=-/root
 ExecStartPre=-plymouth --wait quit
-ExecStart=-{{LIBEXECDIR}}/systemd-sulogin-shell emergency
+ExecStart=-{{ROOTLIBEXECDIR}}/systemd-sulogin-shell emergency
 Type=idle
 StandardInput=tty-force
 StandardOutput=inherit
diff --git a/units/initrd-parse-etc.service.in b/units/initrd-parse-etc.service.in
index 1eef2bd9be8b..fb8c941832bc 100644
--- a/units/initrd-parse-etc.service.in
+++ b/units/initrd-parse-etc.service.in
@@ -23,7 +23,7 @@ OnFailureJobMode=replace-irreversibly
 [Service]
 Type=oneshot
 
-ExecStart={{LIBEXECDIR}}/systemd-sysroot-fstab-check
+ExecStart={{ROOTLIBEXECDIR}}/systemd-sysroot-fstab-check
 
 # We want to enqueue initrd-cleanup.service/start after we finished the part
 # above. It can't be part of the initial transaction, because non-oneshot units
diff --git a/units/rescue.service.in b/units/rescue.service.in
index add604724a7e..c95a44dcdbc6 100644
--- a/units/rescue.service.in
+++ b/units/rescue.service.in
@@ -19,7 +19,7 @@ Before=shutdown.target
 Environment=HOME=/root
 WorkingDirectory=-/root
 ExecStartPre=-plymouth --wait quit
-ExecStart=-{{LIBEXECDIR}}/systemd-sulogin-shell rescue
+ExecStart=-{{ROOTLIBEXECDIR}}/systemd-sulogin-shell rescue
 Type=idle
 StandardInput=tty-force
 StandardOutput=inherit
diff --git a/units/systemd-backlight@.service.in b/units/systemd-backlight@.service.in
index e7e35ecf0d0b..981d0f278ee3 100644
--- a/units/systemd-backlight@.service.in
+++ b/units/systemd-backlight@.service.in
@@ -19,7 +19,7 @@ Before=sysinit.target shutdown.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-backlight load %i
-ExecStop={{LIBEXECDIR}}/systemd-backlight save %i
+ExecStart={{ROOTLIBEXECDIR}}/systemd-backlight load %i
+ExecStop={{ROOTLIBEXECDIR}}/systemd-backlight save %i
 TimeoutSec=90s
 StateDirectory=systemd/backlight
diff --git a/units/systemd-battery-check.service.in b/units/systemd-battery-check.service.in
index ee87118a074b..30d5ea145fc8 100644
--- a/units/systemd-battery-check.service.in
+++ b/units/systemd-battery-check.service.in
@@ -22,5 +22,5 @@ Before=initrd-root-device.target systemd-hibernate-resume.service
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-battery-check
+ExecStart={{ROOTLIBEXECDIR}}/systemd-battery-check
 FailureAction=poweroff-force
diff --git a/units/systemd-binfmt.service.in b/units/systemd-binfmt.service.in
index 318bf8efc290..44024436b13d 100644
--- a/units/systemd-binfmt.service.in
+++ b/units/systemd-binfmt.service.in
@@ -28,6 +28,6 @@ ConditionDirectoryNotEmpty=|/run/binfmt.d
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-binfmt
-ExecStop={{LIBEXECDIR}}/systemd-binfmt --unregister
+ExecStart={{ROOTLIBEXECDIR}}/systemd-binfmt
+ExecStop={{ROOTLIBEXECDIR}}/systemd-binfmt --unregister
 TimeoutSec=90s
diff --git a/units/systemd-bless-boot.service.in b/units/systemd-bless-boot.service.in
index e7a45481447d..557f77b16f63 100644
--- a/units/systemd-bless-boot.service.in
+++ b/units/systemd-bless-boot.service.in
@@ -19,4 +19,4 @@ Before=shutdown.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-bless-boot good
+ExecStart={{ROOTLIBEXECDIR}}/systemd-bless-boot good
diff --git a/units/systemd-boot-check-no-failures.service.in b/units/systemd-boot-check-no-failures.service.in
index 2e17cb9c8e8b..2eb4c79966ed 100644
--- a/units/systemd-boot-check-no-failures.service.in
+++ b/units/systemd-boot-check-no-failures.service.in
@@ -16,7 +16,7 @@ Before=boot-complete.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-boot-check-no-failures
+ExecStart={{ROOTLIBEXECDIR}}/systemd-boot-check-no-failures
 
 [Install]
 RequiredBy=boot-complete.target
diff --git a/units/systemd-coredump@.service.in b/units/systemd-coredump@.service.in
index 012c60d2f684..15bfb243b41d 100644
--- a/units/systemd-coredump@.service.in
+++ b/units/systemd-coredump@.service.in
@@ -17,7 +17,7 @@ Requires=systemd-journald.socket
 Before=shutdown.target
 
 [Service]
-ExecStart=-{{LIBEXECDIR}}/systemd-coredump
+ExecStart=-{{ROOTLIBEXECDIR}}/systemd-coredump
 IPAddressDeny=any
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
diff --git a/units/systemd-fsck-root.service.in b/units/systemd-fsck-root.service.in
index ebe8262a49e2..8cfbe7ce9879 100644
--- a/units/systemd-fsck-root.service.in
+++ b/units/systemd-fsck-root.service.in
@@ -20,5 +20,5 @@ OnFailureJobMode=replace-irreversibly
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-fsck
+ExecStart={{ROOTLIBEXECDIR}}/systemd-fsck
 TimeoutSec=infinity
diff --git a/units/systemd-fsck@.service.in b/units/systemd-fsck@.service.in
index 8eb4821d41f5..a3a7a2e36720 100644
--- a/units/systemd-fsck@.service.in
+++ b/units/systemd-fsck@.service.in
@@ -20,5 +20,5 @@ Before=systemd-quotacheck.service shutdown.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-fsck %f
+ExecStart={{ROOTLIBEXECDIR}}/systemd-fsck %f
 TimeoutSec=infinity
diff --git a/units/systemd-growfs-root.service.in b/units/systemd-growfs-root.service.in
index a6568638b02c..0468774cb002 100644
--- a/units/systemd-growfs-root.service.in
+++ b/units/systemd-growfs-root.service.in
@@ -19,5 +19,5 @@ Before=shutdown.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-growfs /
+ExecStart={{ROOTLIBEXECDIR}}/systemd-growfs /
 TimeoutSec=infinity
diff --git a/units/systemd-growfs@.service.in b/units/systemd-growfs@.service.in
index 8099b1ea4701..90fb0a86619b 100644
--- a/units/systemd-growfs@.service.in
+++ b/units/systemd-growfs@.service.in
@@ -20,5 +20,5 @@ Before=shutdown.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-growfs %f
+ExecStart={{ROOTLIBEXECDIR}}/systemd-growfs %f
 TimeoutSec=infinity
diff --git a/units/systemd-hibernate.service.in b/units/systemd-hibernate.service.in
index c43195bc076d..94181fcc6d1b 100644
--- a/units/systemd-hibernate.service.in
+++ b/units/systemd-hibernate.service.in
@@ -16,4 +16,4 @@ After=sleep.target
 
 [Service]
 Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-sleep hibernate
+ExecStart={{ROOTLIBEXECDIR}}/systemd-sleep hibernate
diff --git a/units/systemd-homed.service.in b/units/systemd-homed.service.in
index b54e5d30b200..2063f6ddfd7d 100644
--- a/units/systemd-homed.service.in
+++ b/units/systemd-homed.service.in
@@ -20,7 +20,7 @@ DeviceAllow=/dev/loop-control rw
 DeviceAllow=/dev/mapper/control rw
 DeviceAllow=block-* rw
 DeviceAllow=char-hidraw rw
-ExecStart={{LIBEXECDIR}}/systemd-homed
+ExecStart={{ROOTLIBEXECDIR}}/systemd-homed
 KillMode=mixed
 LimitNOFILE={{HIGH_RLIMIT_NOFILE}}
 LockPersonality=yes
diff --git a/units/systemd-hostnamed.service.in b/units/systemd-hostnamed.service.in
index ab00c24b53b2..48bffe3e4e72 100644
--- a/units/systemd-hostnamed.service.in
+++ b/units/systemd-hostnamed.service.in
@@ -18,7 +18,7 @@ Documentation=man:org.freedesktop.hostname1(5)
 Type=notify
 BusName=org.freedesktop.hostname1
 CapabilityBoundingSet=CAP_SYS_ADMIN
-ExecStart={{LIBEXECDIR}}/systemd-hostnamed
+ExecStart={{ROOTLIBEXECDIR}}/systemd-hostnamed
 IPAddressDeny=any
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
diff --git a/units/systemd-hybrid-sleep.service.in b/units/systemd-hybrid-sleep.service.in
index c85215bdacfd..ec5142085e82 100644
--- a/units/systemd-hybrid-sleep.service.in
+++ b/units/systemd-hybrid-sleep.service.in
@@ -16,4 +16,4 @@ After=sleep.target
 
 [Service]
 Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-sleep hybrid-sleep
+ExecStart={{ROOTLIBEXECDIR}}/systemd-sleep hybrid-sleep
diff --git a/units/systemd-importd.service.in b/units/systemd-importd.service.in
index daa93776e178..dab382a55fa3 100644
--- a/units/systemd-importd.service.in
+++ b/units/systemd-importd.service.in
@@ -14,7 +14,7 @@ Documentation=man:org.freedesktop.import1(5)
 
 [Service]
 Type=notify
-ExecStart={{LIBEXECDIR}}/systemd-importd
+ExecStart={{ROOTLIBEXECDIR}}/systemd-importd
 BusName=org.freedesktop.import1
 KillMode=mixed
 CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD CAP_SETFCAP CAP_SYS_ADMIN CAP_SETPCAP CAP_DAC_OVERRIDE CAP_LINUX_IMMUTABLE
diff --git a/units/systemd-initctl.service.in b/units/systemd-initctl.service.in
index 6a19058186ca..efac5c4b1143 100644
--- a/units/systemd-initctl.service.in
+++ b/units/systemd-initctl.service.in
@@ -13,7 +13,7 @@ Documentation=man:systemd-initctl.service(8)
 DefaultDependencies=no
 
 [Service]
-ExecStart={{LIBEXECDIR}}/systemd-initctl
+ExecStart={{ROOTLIBEXECDIR}}/systemd-initctl
 NoNewPrivileges=yes
 NotifyAccess=all
 SystemCallArchitectures=native
diff --git a/units/systemd-journal-gatewayd.service.in b/units/systemd-journal-gatewayd.service.in
index 27ae42cccee8..81c53fa01f41 100644
--- a/units/systemd-journal-gatewayd.service.in
+++ b/units/systemd-journal-gatewayd.service.in
@@ -14,7 +14,7 @@ Requires=systemd-journal-gatewayd.socket
 
 [Service]
 DynamicUser=yes
-ExecStart={{LIBEXECDIR}}/systemd-journal-gatewayd
+ExecStart={{ROOTLIBEXECDIR}}/systemd-journal-gatewayd
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
 PrivateDevices=yes
diff --git a/units/systemd-journal-remote.service.in b/units/systemd-journal-remote.service.in
index 651741099055..d8f28f252c0e 100644
--- a/units/systemd-journal-remote.service.in
+++ b/units/systemd-journal-remote.service.in
@@ -13,7 +13,7 @@ Documentation=man:systemd-journal-remote(8) man:journal-remote.conf(5)
 Requires=systemd-journal-remote.socket
 
 [Service]
-ExecStart={{LIBEXECDIR}}/systemd-journal-remote --listen-https=-3 --output=/var/log/journal/remote/
+ExecStart={{ROOTLIBEXECDIR}}/systemd-journal-remote --listen-https=-3 --output=/var/log/journal/remote/
 LockPersonality=yes
 LogsDirectory=journal/remote
 MemoryDenyWriteExecute=yes
diff --git a/units/systemd-journal-upload.service.in b/units/systemd-journal-upload.service.in
index 273511e72f7f..7e64870e9d5d 100644
--- a/units/systemd-journal-upload.service.in
+++ b/units/systemd-journal-upload.service.in
@@ -15,7 +15,7 @@ After=network-online.target
 
 [Service]
 DynamicUser=yes
-ExecStart={{LIBEXECDIR}}/systemd-journal-upload --save-state
+ExecStart={{ROOTLIBEXECDIR}}/systemd-journal-upload --save-state
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
 PrivateDevices=yes
diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
index 4404af963bb4..669d3bef9a9f 100644
--- a/units/systemd-journald.service.in
+++ b/units/systemd-journald.service.in
@@ -30,7 +30,7 @@ IgnoreOnIsolate=yes
 
 [Service]
 DeviceAllow=char-* rw
-ExecStart={{LIBEXECDIR}}/systemd-journald
+ExecStart={{ROOTLIBEXECDIR}}/systemd-journald
 FileDescriptorStoreMax=4224
 # Ensure services using StandardOutput=journal do not break when journald is stopped
 FileDescriptorStorePreserve=yes
diff --git a/units/systemd-journald@.service.in b/units/systemd-journald@.service.in
index b705ce08ff5c..35c998285f2f 100644
--- a/units/systemd-journald@.service.in
+++ b/units/systemd-journald@.service.in
@@ -16,7 +16,7 @@ After=systemd-journald@%i.socket systemd-journald-varlink@%i.socket
 [Service]
 CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE
 DevicePolicy=closed
-ExecStart={{LIBEXECDIR}}/systemd-journald %i
+ExecStart={{ROOTLIBEXECDIR}}/systemd-journald %i
 FileDescriptorStoreMax=4224
 Group=systemd-journal
 IPAddressDeny=any
diff --git a/units/systemd-localed.service.in b/units/systemd-localed.service.in
index 4de89aa8ddd9..13020914d9a6 100644
--- a/units/systemd-localed.service.in
+++ b/units/systemd-localed.service.in
@@ -18,7 +18,7 @@ Documentation=man:org.freedesktop.locale1(5)
 Type=notify
 BusName=org.freedesktop.locale1
 CapabilityBoundingSet=
-ExecStart={{LIBEXECDIR}}/systemd-localed
+ExecStart={{ROOTLIBEXECDIR}}/systemd-localed
 IPAddressDeny=any
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in
index cc1b6be429c9..2912301a3a41 100644
--- a/units/systemd-logind.service.in
+++ b/units/systemd-logind.service.in
@@ -30,7 +30,7 @@ DeviceAllow=char-drm rw
 DeviceAllow=char-input rw
 DeviceAllow=char-tty rw
 DeviceAllow=char-vcs rw
-ExecStart={{LIBEXECDIR}}/systemd-logind
+ExecStart={{ROOTLIBEXECDIR}}/systemd-logind
 FileDescriptorStoreMax=768
 IPAddressDeny=any
 LockPersonality=yes
diff --git a/units/systemd-machined.service.in b/units/systemd-machined.service.in
index 47aa5deeedc5..d3f8abd9e4c6 100644
--- a/units/systemd-machined.service.in
+++ b/units/systemd-machined.service.in
@@ -19,7 +19,7 @@ RequiresMountsFor=/var/lib/machines
 [Service]
 BusName=org.freedesktop.machine1
 CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD CAP_LINUX_IMMUTABLE
-ExecStart={{LIBEXECDIR}}/systemd-machined
+ExecStart={{ROOTLIBEXECDIR}}/systemd-machined
 IPAddressDeny=any
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
diff --git a/units/systemd-modules-load.service.in b/units/systemd-modules-load.service.in
index ad262fa13ab1..9c5be76d2181 100644
--- a/units/systemd-modules-load.service.in
+++ b/units/systemd-modules-load.service.in
@@ -27,5 +27,5 @@ ConditionKernelCommandLine=|rd.modules_load
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-modules-load
+ExecStart={{ROOTLIBEXECDIR}}/systemd-modules-load
 TimeoutSec=90s
diff --git a/units/systemd-network-generator.service.in b/units/systemd-network-generator.service.in
index f7d13d308467..c5cf7b1cd0ea 100644
--- a/units/systemd-network-generator.service.in
+++ b/units/systemd-network-generator.service.in
@@ -20,7 +20,7 @@ Before=shutdown.target initrd-switch-root.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-network-generator
+ExecStart={{ROOTLIBEXECDIR}}/systemd-network-generator
 ImportCredential=network.netdev.*
 ImportCredential=network.link.*
 ImportCredential=network.network.*
diff --git a/units/systemd-networkd-wait-online.service.in b/units/systemd-networkd-wait-online.service.in
index 7768121f5fc2..3dc5ce926527 100644
--- a/units/systemd-networkd-wait-online.service.in
+++ b/units/systemd-networkd-wait-online.service.in
@@ -19,7 +19,7 @@ Before=network-online.target shutdown.target
 
 [Service]
 Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-networkd-wait-online
+ExecStart={{ROOTLIBEXECDIR}}/systemd-networkd-wait-online
 RemainAfterExit=yes
 
 [Install]
diff --git a/units/systemd-networkd-wait-online@.service.in b/units/systemd-networkd-wait-online@.service.in
index 60d173490b38..b7a1e409f443 100644
--- a/units/systemd-networkd-wait-online@.service.in
+++ b/units/systemd-networkd-wait-online@.service.in
@@ -19,7 +19,7 @@ Before=network-online.target shutdown.target
 
 [Service]
 Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-networkd-wait-online -i %i
+ExecStart={{ROOTLIBEXECDIR}}/systemd-networkd-wait-online -i %i
 RemainAfterExit=yes
 
 [Install]
diff --git a/units/systemd-networkd.service.in b/units/systemd-networkd.service.in
index 6141fdbb6d78..cf7aff4caeda 100644
--- a/units/systemd-networkd.service.in
+++ b/units/systemd-networkd.service.in
@@ -24,7 +24,7 @@ AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET
 BusName=org.freedesktop.network1
 CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW
 DeviceAllow=char-* rw
-ExecStart=!!{{LIBEXECDIR}}/systemd-networkd
+ExecStart=!!{{ROOTLIBEXECDIR}}/systemd-networkd
 FileDescriptorStoreMax=512
 ImportCredential=network.wireguard.*
 LockPersonality=yes
diff --git a/units/systemd-oomd.service.in b/units/systemd-oomd.service.in
index 82bd6245f83a..c138f5eefaff 100644
--- a/units/systemd-oomd.service.in
+++ b/units/systemd-oomd.service.in
@@ -26,7 +26,7 @@ After=systemd-oomd.socket
 AmbientCapabilities=CAP_KILL CAP_DAC_OVERRIDE
 BusName=org.freedesktop.oom1
 CapabilityBoundingSet=CAP_KILL CAP_DAC_OVERRIDE
-ExecStart={{LIBEXECDIR}}/systemd-oomd
+ExecStart={{ROOTLIBEXECDIR}}/systemd-oomd
 IPAddressDeny=any
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
diff --git a/units/systemd-pcrfs-root.service.in b/units/systemd-pcrfs-root.service.in
index 5b40a91ca649..a3d78a27382f 100644
--- a/units/systemd-pcrfs-root.service.in
+++ b/units/systemd-pcrfs-root.service.in
@@ -20,4 +20,4 @@ ConditionSecurity=measured-uki
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-pcrextend --graceful --file-system=/
+ExecStart={{ROOTLIBEXECDIR}}/systemd-pcrphase --graceful --file-system=/
diff --git a/units/systemd-pcrfs@.service.in b/units/systemd-pcrfs@.service.in
index 203d7b9782e1..964422e603cf 100644
--- a/units/systemd-pcrfs@.service.in
+++ b/units/systemd-pcrfs@.service.in
@@ -21,4 +21,4 @@ ConditionSecurity=measured-uki
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-pcrextend --graceful --file-system=%f
+ExecStart={{ROOTLIBEXECDIR}}/systemd-pcrphase --graceful --file-system=%f
diff --git a/units/systemd-pcrmachine.service.in b/units/systemd-pcrmachine.service.in
index 65caf2ed4928..278c5b7640ae 100644
--- a/units/systemd-pcrmachine.service.in
+++ b/units/systemd-pcrmachine.service.in
@@ -20,4 +20,4 @@ ConditionSecurity=measured-uki
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-pcrextend --graceful --machine-id
+ExecStart={{ROOTLIBEXECDIR}}/systemd-pcrphase --graceful --machine-id
diff --git a/units/systemd-pcrphase-initrd.service.in b/units/systemd-pcrphase-initrd.service.in
index 6fcf94de76c5..c6b7e5975964 100644
--- a/units/systemd-pcrphase-initrd.service.in
+++ b/units/systemd-pcrphase-initrd.service.in
@@ -20,5 +20,5 @@ ConditionSecurity=measured-uki
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-pcrextend --graceful enter-initrd
-ExecStop={{LIBEXECDIR}}/systemd-pcrextend --graceful leave-initrd
+ExecStart={{ROOTLIBEXECDIR}}/systemd-pcrphase --graceful enter-initrd
+ExecStop={{ROOTLIBEXECDIR}}/systemd-pcrphase --graceful leave-initrd
diff --git a/units/systemd-pcrphase-sysinit.service.in b/units/systemd-pcrphase-sysinit.service.in
index 8c0c0c82a2c7..e4680609bf8e 100644
--- a/units/systemd-pcrphase-sysinit.service.in
+++ b/units/systemd-pcrphase-sysinit.service.in
@@ -20,5 +20,5 @@ ConditionSecurity=measured-uki
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-pcrextend --graceful sysinit
-ExecStop={{LIBEXECDIR}}/systemd-pcrextend --graceful final
+ExecStart={{ROOTLIBEXECDIR}}/systemd-pcrphase --graceful sysinit
+ExecStop={{ROOTLIBEXECDIR}}/systemd-pcrphase --graceful final
diff --git a/units/systemd-pcrphase.service.in b/units/systemd-pcrphase.service.in
index 04ace12e14d4..1c54df829ca3 100644
--- a/units/systemd-pcrphase.service.in
+++ b/units/systemd-pcrphase.service.in
@@ -18,5 +18,5 @@ ConditionSecurity=measured-uki
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-pcrextend --graceful ready
-ExecStop={{LIBEXECDIR}}/systemd-pcrextend --graceful shutdown
+ExecStart={{ROOTLIBEXECDIR}}/systemd-pcrphase --graceful ready
+ExecStop={{ROOTLIBEXECDIR}}/systemd-pcrphase --graceful shutdown
diff --git a/units/systemd-portabled.service.in b/units/systemd-portabled.service.in
index b4ec252c0394..ab660ce36c8d 100644
--- a/units/systemd-portabled.service.in
+++ b/units/systemd-portabled.service.in
@@ -14,7 +14,7 @@ Documentation=man:org.freedesktop.portable1(5)
 RequiresMountsFor=/var/lib/portables
 
 [Service]
-ExecStart={{LIBEXECDIR}}/systemd-portabled
+ExecStart={{ROOTLIBEXECDIR}}/systemd-portabled
 BusName=org.freedesktop.portable1
 CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD
 MemoryDenyWriteExecute=yes
diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
index 0b5a20a3532e..02ac29caa4ed 100644
--- a/units/systemd-pstore.service.in
+++ b/units/systemd-pstore.service.in
@@ -20,7 +20,7 @@ Wants=modprobe@efi_pstore.service
 
 [Service]
 Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-pstore
+ExecStart={{ROOTLIBEXECDIR}}/systemd-pstore
 RemainAfterExit=yes
 StateDirectory=systemd/pstore
 
diff --git a/units/systemd-quotacheck@.service.in b/units/systemd-quotacheck@.service.in
index f2b8db7abb89..735dd76f2bae 100644
--- a/units/systemd-quotacheck@.service.in
+++ b/units/systemd-quotacheck@.service.in
@@ -23,5 +23,5 @@ Conflicts=shutdown.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-quotacheck %f
+ExecStart={{ROOTLIBEXECDIR}}/systemd-quotacheck %f
 TimeoutSec=infinity
diff --git a/units/systemd-random-seed.service.in b/units/systemd-random-seed.service.in
index 99b5f33ea262..820fdd8536dd 100644
--- a/units/systemd-random-seed.service.in
+++ b/units/systemd-random-seed.service.in
@@ -25,8 +25,8 @@ Before=shutdown.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-random-seed load
-ExecStop={{LIBEXECDIR}}/systemd-random-seed save
+ExecStart={{ROOTLIBEXECDIR}}/systemd-random-seed load
+ExecStop={{ROOTLIBEXECDIR}}/systemd-random-seed save
 
 # This service waits until the kernel's entropy pool is initialized, and may be
 # used as ordering barrier for service that require an initialized entropy
diff --git a/units/systemd-remount-fs.service.in b/units/systemd-remount-fs.service.in
index 4ac8978ff22f..cbb792ea68ee 100644
--- a/units/systemd-remount-fs.service.in
+++ b/units/systemd-remount-fs.service.in
@@ -22,4 +22,4 @@ Before=shutdown.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-remount-fs
+ExecStart={{ROOTLIBEXECDIR}}/systemd-remount-fs
diff --git a/units/systemd-repart.service b/units/systemd-repart.service
index 1f7e2a612a71..8285788a4fae 100644
--- a/units/systemd-repart.service
+++ b/units/systemd-repart.service
@@ -29,7 +29,7 @@ Before=shutdown.target initrd-switch-root.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart=systemd-repart --dry-run=no
+ExecStart={{ROOTBINDIR}}/systemd-repart --dry-run=no
 
 # The tool returns 76 if it can't find the root block device
 SuccessExitStatus=76
diff --git a/units/systemd-resolved.service.in b/units/systemd-resolved.service.in
index 4aa0788ac4e3..7305d7904bb3 100644
--- a/units/systemd-resolved.service.in
+++ b/units/systemd-resolved.service.in
@@ -24,7 +24,7 @@ Wants=nss-lookup.target
 AmbientCapabilities=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE
 BusName=org.freedesktop.resolve1
 CapabilityBoundingSet=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE
-ExecStart=!!{{LIBEXECDIR}}/systemd-resolved
+ExecStart=!!{{ROOTLIBEXECDIR}}/systemd-resolved
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
 NoNewPrivileges=yes
diff --git a/units/systemd-rfkill.service.in b/units/systemd-rfkill.service.in
index 072ae643b087..a5b6cc4b7f91 100644
--- a/units/systemd-rfkill.service.in
+++ b/units/systemd-rfkill.service.in
@@ -19,7 +19,7 @@ After=sys-devices-virtual-misc-rfkill.device
 Before=shutdown.target
 
 [Service]
-ExecStart={{LIBEXECDIR}}/systemd-rfkill
+ExecStart={{ROOTLIBEXECDIR}}/systemd-rfkill
 NoNewPrivileges=yes
 StateDirectory=systemd/rfkill
 TimeoutSec=90s
diff --git a/units/systemd-suspend-then-hibernate.service.in b/units/systemd-suspend-then-hibernate.service.in
index d7ab2c195e59..f9c96757be65 100644
--- a/units/systemd-suspend-then-hibernate.service.in
+++ b/units/systemd-suspend-then-hibernate.service.in
@@ -16,4 +16,4 @@ After=sleep.target
 
 [Service]
 Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-sleep suspend-then-hibernate
+ExecStart={{ROOTLIBEXECDIR}}/systemd-sleep suspend-then-hibernate
diff --git a/units/systemd-suspend.service.in b/units/systemd-suspend.service.in
index aa264e860c5b..2515575e1040 100644
--- a/units/systemd-suspend.service.in
+++ b/units/systemd-suspend.service.in
@@ -16,4 +16,4 @@ After=sleep.target
 
 [Service]
 Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-sleep suspend
+ExecStart={{ROOTLIBEXECDIR}}/systemd-sleep suspend
diff --git a/units/systemd-sysctl.service.in b/units/systemd-sysctl.service.in
index 4179753cde50..7307601a7dfb 100644
--- a/units/systemd-sysctl.service.in
+++ b/units/systemd-sysctl.service.in
@@ -19,6 +19,6 @@ ConditionPathIsReadWrite=/proc/sys/net/
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-sysctl
+ExecStart={{ROOTLIBEXECDIR}}/systemd-sysctl
 TimeoutSec=90s
 ImportCredential=sysctl.*
diff --git a/units/systemd-sysupdate-reboot.service.in b/units/systemd-sysupdate-reboot.service.in
index 5d4011a21327..9d7b7d1657ad 100644
--- a/units/systemd-sysupdate-reboot.service.in
+++ b/units/systemd-sysupdate-reboot.service.in
@@ -14,7 +14,7 @@ ConditionVirtualization=!container
 
 [Service]
 Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-sysupdate reboot
+ExecStart={{ROOTLIBEXECDIR}}/systemd-sysupdate reboot
 
 [Install]
 Also=systemd-sysupdate-reboot.timer
diff --git a/units/systemd-sysupdate.service.in b/units/systemd-sysupdate.service.in
index 1becbec5edeb..085a9c4a22c2 100644
--- a/units/systemd-sysupdate.service.in
+++ b/units/systemd-sysupdate.service.in
@@ -17,7 +17,7 @@ ConditionVirtualization=!container
 [Service]
 Type=simple
 NotifyAccess=main
-ExecStart={{LIBEXECDIR}}/systemd-sysupdate update
+ExecStart={{ROOTLIBEXECDIR}}/systemd-sysupdate update
 CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD CAP_SETFCAP CAP_SYS_ADMIN CAP_SETPCAP CAP_DAC_OVERRIDE CAP_LINUX_IMMUTABLE
 NoNewPrivileges=yes
 MemoryDenyWriteExecute=yes
diff --git a/units/systemd-time-wait-sync.service.in b/units/systemd-time-wait-sync.service.in
index 6b99393f6908..25adecc86b19 100644
--- a/units/systemd-time-wait-sync.service.in
+++ b/units/systemd-time-wait-sync.service.in
@@ -28,7 +28,7 @@ Conflicts=shutdown.target
 
 [Service]
 Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-time-wait-sync
+ExecStart={{ROOTLIBEXECDIR}}/systemd-time-wait-sync
 TimeoutStartSec=infinity
 RemainAfterExit=yes
 
diff --git a/units/systemd-timedated.service.in b/units/systemd-timedated.service.in
index 06c3306a6eb6..d73b398244b5 100644
--- a/units/systemd-timedated.service.in
+++ b/units/systemd-timedated.service.in
@@ -18,7 +18,7 @@ Type=notify
 BusName=org.freedesktop.timedate1
 CapabilityBoundingSet=CAP_SYS_TIME
 DeviceAllow=char-rtc r
-ExecStart={{LIBEXECDIR}}/systemd-timedated
+ExecStart={{ROOTLIBEXECDIR}}/systemd-timedated
 IPAddressDeny=any
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in
index cf233fbffd4f..c60646109138 100644
--- a/units/systemd-timesyncd.service.in
+++ b/units/systemd-timesyncd.service.in
@@ -26,7 +26,7 @@ CapabilityBoundingSet=CAP_SYS_TIME
 # correct time to work, but we likely won't acquire that without NTP. Let's
 # break this chicken-and-egg cycle here.
 Environment=SYSTEMD_NSS_RESOLVE_VALIDATE=0
-ExecStart=!!{{LIBEXECDIR}}/systemd-timesyncd
+ExecStart=!!{{ROOTLIBEXECDIR}}/systemd-timesyncd
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
 NoNewPrivileges=yes
diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in
index f4a44820880d..3cc35a976848 100644
--- a/units/systemd-udevd.service.in
+++ b/units/systemd-udevd.service.in
@@ -26,7 +26,7 @@ OOMScoreAdjust=-1000
 Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket
 Restart=always
 RestartSec=0
-ExecStart={{LIBEXECDIR}}/systemd-udevd
+ExecStart={{ROOTLIBEXECDIR}}/systemd-udevd
 KillMode=mixed
 TasksMax=infinity
 PrivateMounts=yes
diff --git a/units/systemd-update-done.service.in b/units/systemd-update-done.service.in
index 4ea43c7dca7e..53cc6dd621bd 100644
--- a/units/systemd-update-done.service.in
+++ b/units/systemd-update-done.service.in
@@ -20,4 +20,4 @@ ConditionNeedsUpdate=|/var
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-update-done
+ExecStart={{ROOTLIBEXECDIR}}/systemd-update-done
diff --git a/units/systemd-update-utmp-runlevel.service.in b/units/systemd-update-utmp-runlevel.service.in
index 17772d4576c4..18c92f9b5a4c 100644
--- a/units/systemd-update-utmp-runlevel.service.in
+++ b/units/systemd-update-utmp-runlevel.service.in
@@ -22,4 +22,4 @@ Before=shutdown.target
 
 [Service]
 Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-update-utmp runlevel
+ExecStart={{ROOTLIBEXECDIR}}/systemd-update-utmp runlevel
diff --git a/units/systemd-update-utmp.service.in b/units/systemd-update-utmp.service.in
index 1a88b7b2b891..73a848390e95 100644
--- a/units/systemd-update-utmp.service.in
+++ b/units/systemd-update-utmp.service.in
@@ -22,5 +22,5 @@ RequiresMountsFor=/var/log/wtmp
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-update-utmp reboot
-ExecStop={{LIBEXECDIR}}/systemd-update-utmp shutdown
+ExecStart={{ROOTLIBEXECDIR}}/systemd-update-utmp reboot
+ExecStop={{ROOTLIBEXECDIR}}/systemd-update-utmp shutdown
diff --git a/units/systemd-user-sessions.service.in b/units/systemd-user-sessions.service.in
index ae694bf21b51..adca848c2a60 100644
--- a/units/systemd-user-sessions.service.in
+++ b/units/systemd-user-sessions.service.in
@@ -15,5 +15,5 @@ After=remote-fs.target nss-user-lookup.target network.target home.mount
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-user-sessions start
-ExecStop={{LIBEXECDIR}}/systemd-user-sessions stop
+ExecStart={{ROOTLIBEXECDIR}}/systemd-user-sessions start
+ExecStop={{ROOTLIBEXECDIR}}/systemd-user-sessions stop
diff --git a/units/systemd-userdbd.service.in b/units/systemd-userdbd.service.in
index 1c092654b99c..b57661100cd0 100644
--- a/units/systemd-userdbd.service.in
+++ b/units/systemd-userdbd.service.in
@@ -17,7 +17,7 @@ DefaultDependencies=no
 
 [Service]
 CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_SYS_RESOURCE
-ExecStart={{LIBEXECDIR}}/systemd-userdbd
+ExecStart={{ROOTLIBEXECDIR}}/systemd-userdbd
 IPAddressDeny=any
 LimitNOFILE={{HIGH_RLIMIT_NOFILE}}
 LockPersonality=yes
diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in
index c6c5bc9130a3..2884e84e6cfe 100644
--- a/units/systemd-vconsole-setup.service.in
+++ b/units/systemd-vconsole-setup.service.in
@@ -31,6 +31,6 @@ Type=oneshot
 SuccessExitStatus=SIGTERM
 RemainAfterExit=yes
 
-ExecStart={{LIBEXECDIR}}/systemd-vconsole-setup
+ExecStart={{ROOTLIBEXECDIR}}/systemd-vconsole-setup
 
 ImportCredential=vconsole.*
diff --git a/units/systemd-volatile-root.service.in b/units/systemd-volatile-root.service.in
index 6f221dc5ecb4..5a0ec89fd685 100644
--- a/units/systemd-volatile-root.service.in
+++ b/units/systemd-volatile-root.service.in
@@ -19,4 +19,4 @@ AssertPathExists=/etc/initrd-release
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-volatile-root yes /sysroot
+ExecStart={{ROOTLIBEXECDIR}}/systemd-volatile-root yes /sysroot
diff --git a/units/user-runtime-dir@.service.in b/units/user-runtime-dir@.service.in
index 241e9267bb0c..e49eb20441fc 100644
--- a/units/user-runtime-dir@.service.in
+++ b/units/user-runtime-dir@.service.in
@@ -14,8 +14,8 @@ After=systemd-logind.service dbus.service
 IgnoreOnIsolate=yes
 
 [Service]
-ExecStart={{LIBEXECDIR}}/systemd-user-runtime-dir start %i
-ExecStop={{LIBEXECDIR}}/systemd-user-runtime-dir stop %i
+ExecStart={{ROOTLIBEXECDIR}}/systemd-user-runtime-dir start %i
+ExecStop={{ROOTLIBEXECDIR}}/systemd-user-runtime-dir stop %i
 Type=oneshot
 RemainAfterExit=yes
 Slice=user-%i.slice
diff --git a/units/user@.service.in b/units/user@.service.in
index 569546574721..03791f338f8d 100644
--- a/units/user@.service.in
+++ b/units/user@.service.in
@@ -18,7 +18,7 @@ IgnoreOnIsolate=yes
 User=%i
 PAMName=systemd-user
 Type=notify-reload
-ExecStart={{LIBEXECDIR}}/systemd --user
+ExecStart={{ROOTLIBEXECDIR}}/systemd --user
 Slice=user-%i.slice
 KillMode=mixed
 Delegate=pids memory cpu
-- 
2.41.0

