]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #24054 from keszybz/initrd-no-reload
authorFrantisek Sumsal <frantisek@sumsal.cz>
Thu, 18 Aug 2022 13:15:14 +0000 (13:15 +0000)
committerGitHub <noreply@github.com>
Thu, 18 Aug 2022 13:15:14 +0000 (13:15 +0000)
Don't do daemon-reload in the initrd

1  2 
TODO
meson.build
src/boot/bootctl.c
src/portable/portablectl.c
src/sulogin-shell/sulogin-shell.c

diff --combined TODO
index 1d155910d0bdd038312ae4e1458c6cb69dbf7575,a09db24912f700904e590513f830892853ec85b9..6a04978b53ac248c8f29682a0b7ee2879ea5ceed
--- 1/TODO
--- 2/TODO
+++ b/TODO
@@@ -77,108 -77,8 +77,108 @@@ Janitorial Clean-ups
  * rework mount.c and swap.c to follow proper state enumeration/deserialization
    semantics, like we do for device.c now
  
 +Deprecations and removals:
 +
 +* Remove any support for booting without /usr pre-mounted in the initrd entirely.
 +  Update INITRD_INTERFACE.md accordingly.
 +
 +* 2019-10 – Remove POINTINGSTICK_CONST_ACCEL references from the hwdb, see #9573
 +
 +* remove cgrouspv1 support EOY 2023. As per
 +  https://lists.freedesktop.org/archives/systemd-devel/2022-July/048120.html
 +  and then rework cgroupsv2 support around fds, i.e. keep one fd per active
 +  unit around, and always operate on that, instead of cgroup fs paths.
 +
 +* drop support for kernels that lack ambient capabilities support (i.e. make
 +  4.3 new baseline). Then drop support for "!!" modifier for ExecStart= which
 +  is only supported for such old kernels.
 +
 +* drop support for getrandom()-less kernels. (GRND_INSECURE means once kernel
 +  5.6 becomes our baseline). See
 +  https://github.com/systemd/systemd/pull/24101#issuecomment-1193966468 for
 +  details. Maybe before that: at taint-flags/warn about kernels that lack
 +  getrandom()/environments where it is blocked.
 +
 +* drop support for LOOP_CONFIGURE-less loopback block devices, once kernel
 +  baseline is 5.8.
 +
 +* drop fd_is_mount_point() fallback mess once we can rely on
 +  STATX_ATTR_MOUNT_ROOT to exist i.e. kernel baseline 5.8
 +
 +* rework our PID tracking in services and so on, to be strictly based on pidfd,
 +  once kernel baseline is 5.13.
 +
 +* ~2023: remove support for TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT
 +
  Features:
  
 +* sd-stub/sd-boot: write RNG seed to LINUX_EFI_RANDOM_SEED_TABLE_GUID config
 +  table as well. (and possibly drop our efi var). Current kernels will pick up
 +  the seed from there already, if EFI_RNG_PROTOCOL is not implemented by
 +  firmware.
 +
 +* sd-boot: include domain specific hash string in hash function for random seed
 +  plus sizes of everything. also include DMI/SMBIOS blob
 +
 +* accept a random seed via DMI/SMBIOS vendor string that is credited to the
 +  kernel RNG, as cheap alternative to virtio-rng
 +
 +* sd-stub: invoke random seed logic the same way as in sd-boot, except if
 +  random seed EFI variable is already set. That way, the variable set will be
 +  set in all cases: if you just use sd-stub, or just sd-boot, or both.
 +
 +* sd-boot: we probably should include all BootXY EFI variable defined boot
 +  entries in our menu, and then suppress ourselves. Benefit: instant
 +  compatibility with all other OSes which register things there, in particular
 +  on other disks. Always boot into them via NextBoot EFI variable, to not
 +  affect PCR values.
 +
 +* systemd-measure tool:
 +  - pre-calculate PCR 12 (command line) + PCR 13 (sysext) the same way we can precalculate PCR 11
 +  - sign pre-calculated hashes in a way compatible with TPM2 PCR hash signature
 +    policies, in a way they can be included in unified PE kernel images, and
 +    made available to userspace. There, this should be consumed by
 +    systemd-cryptsetup to implement PCR signature based TPM volume unlock
 +    policies.
 +
 +* in sd-boot: load EFI drivers from a new PE section. That way, one can have a
 +  "supercharged" sd-boot binary, that could carry ext4 drivers built-in.
 +
 +* sd-bus: document that sd_bus_process() only returns messages that non of the
 +  filters/handlers installed on the connection took possession of.
 +
 +* sd-device: add an API for opening a child device, given a device object
 +
 +* sd-device: add an API for acquiring list of child devices, given a device
 +  objects (i.e. all child dirents that dirs or symlinks to dirs)
 +
 +* sd-device: maybe pin the sysfs dir with an fd, during the entire runtime of
 +  an sd_device, then always work based on that.
 +
 +* add small wrapper around qemu that implements sd_notify/AF_VSOCK + machined and
 +  maybe some other stuff and boots it
 +
 +* maybe add new flags to gpt partition tables for rootfs and usrfs indicating
 +  purpose, i.e. whether something is supposed to be bootable in a VM, on
 +  baremetal, on an nspawn-style container, if it is a portable service image,
 +  or a sysext for initrd, for host os, or for portable container. Then hook
 +  portabled/… up to udev to watch block devices coming up with the flags set, and
 +  use it.
 +
 +* portabled: read a credential "portable.extra" or so, that takes a list of
 +  file system paths to enable on start.
 +
 +* sd-boot should look for information what to boot in SMBIOS, too, so that VM
 +  managers can tell sd-boot what to boot into and suchlike
 +
 +* PID 1 should look for an SMBIOS variable that encodes an AF_VSOCK address it
 +  should send sd_notify() ready notifications to. That way a VMM can boot up a
 +  system, and generically know when it finished booting.
 +
 +* add "systemd-sysext identify" verb, that you can point on any file in /usr/
 +  and that determines from which overlayfs layer it originates, which image, and with
 +  what it was signed.
 +
  * journald: generate recognizable log events whenever we shutdown journald
    cleanly, and when we migrate run → var. This way tools can verify that a
    previous boot terminated cleanly, because either of these two messages must
  * networkd/udevd: add a way to define additional .link, .network, .netdev files
    via the credentials logic.
  
 -* fstab-generator: allow definining additional fstab-like mounts via
 +* fstab-generator: allow defining additional fstab-like mounts via
    credentials (similar: crypttab-generator, verity-generator,
    integrity-generator)
  
  * resolved: allow defining additional /etc/hosts entries via a credential (it
    might make sense to then synthesize a new combined /etc/hosts file in /run
    and bind mount it on /etc/hosts for other clients that want to read it.
 +  Similar, allow picking up DNS server IP addresses from credential.
 +
 +* repart: allow defining additional partitions via credential
 +
 +* tmpfiles: add snippet that provisions /etc/hosts, /etc/motd,
 +  /root/.ssh/authorized_keys from credential
 +
 +* timesyncd: pick NTP server info from credential
  
  * define a JSON format for units, separating out unit definitions from unit
    runtime state. Then, expose it:
  * pam_systemd: on interactive logins, maybe show SUPPORT_END information at
    login time, á la motd
  
 -* similar to the existing fw_cfg support, also support reading system
 -  credentials from DMI vendor fields, as supported by qemu
 -
 -* sd-boot: instead of uncondtionally deriving the ESP to search boot loader
 +* sd-boot: instead of unconditionally deriving the ESP to search boot loader
    spec entries in from the paths of sd-boot binary, let's optionally allow it
 -  to be configured on sd-boot cmdline + efi var. Usecase: embedd sd-boot in the
 +  to be configured on sd-boot cmdline + efi var. Usecase: embed sd-boot in the
    UEFI firmware (for example, ovmf supports that via qemu cmdline option), and
 -  use it to load stuff from the ESP).
 +  use it to load stuff from the ESP.
  
  * make tmpfiles read lines from creds, so that we can provision SSH host keys
    via creds. Similar: sysusers, sysctl, homed
  * ask dracut to generate usr= on the kernel cmdline so that we don't need to
    read /etc/fstab from the root fs from the initrd and do daemon-reload
  
 -* document that process resource limits are bullshit
 -
  * add PR_SET_DUMPABLE service setting
  
  * homed/userdb: maybe define a "companion" dir for home directories where apps
    cloud-init/ignitation and similar can parameterize the host with data they
    acquire.
  
 -* Add ConditionCredentialExists= or so, that allows conditionalizing services
 -  depending on whether a specific system credential is set. Usecase: a service
 -  similar to the ssh keygen service that installs any SSH host key supplied via
 -  system credentials into /etc/ssh.
 -
 -* drop support for kernels that lack ambient capabilities support (i.e. make
 -  4.3 new baseline). Then drop support for "!!" modifier for ExecStart= which
 -  is only supported for such old kernels
 -
  * sd-event: compat wd reuse in inotify code: keep a set of removed watch
    descriptors, and clear this set piecemeal when we see the IN_IGNORED event
    for it, or when read() returns EAGAIN or on IN_Q_OVERFLOW. Then, whenever we
    case the same wd is reused multiple times before we start processing
    IN_IGNORED again)
  
 -* sd-stub: set efi var indicating stub features, i.e. whether they pick up
 -  creds, sysexts and so on. similar to existing variable of sd-boot
 -
 -* sd-stub: set efi vars declaring TPM PCRs we measured creds/cmdline + sysext
 -  into (even if we hardcode them)
 -
  * systemd-fstab-generator: support addition mount specifications via kernel
    cmdline. Usecase: invoke a VM, and mount a host homedir into it via
    virtio-fs.
    - sd-stub: automatically pick up microcode from ESP (/loader/microcode/*)
      and synthesize initrd from it, and measure it. Signing is not necessary, as
      microcode does that on its own. Pass as first initrd to kernel.
 -  - sd-stub should measure the kernel/initrd/… into a separate PCR, so that we
 -    have one PCR we can bind the encrypted creds to that is not effected by
 -    anything else but what we drop in via kernel-install, i.e. by earlier EFI
 -    code running (i.e. like PCR 4)
  
  * Add a new service type very similar to Type=notify, that goes one step
    further and extends the protocol to cover reloads. Specifically, SIGHUP will
    dep in the base OS image)
  
  * sysext: automatically activate sysext images dropped in via new sd-stub
 -  sysext pickup logic.
 +  sysext pickup logic. (must insist on verity + signature on those though)
  
  * add concept for "exitrd" as inverse of "initrd", that we can transition to at
    shutdown, and has similar security semantics. This should then take the place
    what must be read-only, what requires encryption, and what requires
    authentication.
  
 -* in uefi stub: query firmware regarding which PCRs are being used, store that
 -  in EFI var. then use this when enrolling TPM2 in cryptsetup to verify that
 -  the selected PCRs actually are used by firmware.
 +* in uefi stub: query firmware regarding which PCR banks are being used, store
 +  that in EFI var. then use this when enrolling TPM2 in cryptsetup to verify
 +  that the selected PCRs actually are used by firmware.
  
  * rework recursive read-only remount to use new mount API
  
  
  * if /usr/bin/swapoff fails due to OOM, log a friendly explanatory message about it
  
 -* Remove any support for booting without /usr pre-mounted in the initrd entirely.
 -  Update INITRD_INTERFACE.md accordingly.
 -
  * pid1: Move to tracking of main pid/control pid of units per pidfd
  
  * pid1: support new clone3() fork-into-cgroup feature
  
  * fstab-generator: default to tmpfs-as-root if only usr= is specified on the kernel cmdline
  
- * initrd-parse-etc.service: can we skip daemon-reload if /sysroot/etc/fstab is missing?
-   Note that we start initrd-fs.target and initrd-cleanup.target there, so a straightforward
-   ConditionPathExists= is not enough.
  * docs: bring https://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime up to date
  
  * add a job mode that will fail if a transaction would mean stopping
    - show whether UEFI audit mode is available
    - teach it to prepare an ESP wholesale, i.e. with mkfs.vfat invocation
    - teach it to copy in unified kernel images and maybe type #1 boot loader spec entries from host
 -  - make it operate on loopback files, dissecting enough to find ESP to operate on
    - bootspec: properly support boot attempt counters when parsing entry file names
  
  * kernel-install:
diff --combined meson.build
index a7e3e8774438a7aa288701cbeabb997e97ef0b98,e6e32050902ea7482aca47ea049a59fd26c359ca..aa2ae27a93d96dbcc319bcb642d569e86a6c8d99
@@@ -310,8 -310,6 +310,8 @@@ conf.set_quoted('STATUS_UNIT_FORMAT_DEF
  
  conf.set10('FIRST_BOOT_FULL_PRESET',                          get_option('first-boot-full-preset'))
  
 +conf.set10('EFI_TPM_PCR_COMPAT',                              get_option('efi-tpm-pcr-compat'))
 +
  #####################################################################
  
  cc = meson.get_compiler('c')
@@@ -392,11 -390,6 +392,11 @@@ possible_common_cc_flags = 
  
  c_args = get_option('c_args')
  
 +# Our json library does not support -ffinite-math-only, which is enabled by -Ofast or -ffast-math.
 +if (('-Ofast' in c_args or '-ffast-math' in c_args or '-ffinite-math-only' in c_args) and '-fno-finite-math-only' not in c_args)
 +        error('-Ofast, -ffast-math, or -ffinite-math-only is specified in c_args.')
 +endif
 +
  # Disable -Wmaybe-uninitialized when compiling with -Os/-O1/-O3/etc. There are
  # too many false positives with gcc >= 8. Effectively, we only test with -O0
  # and -O2; this should be enough to catch most important cases without too much
@@@ -513,6 -506,7 +513,6 @@@ decl_headers = ''
  #include <uchar.h>
  #include <sys/mount.h>
  #include <sys/stat.h>
 -#include <linux/fs.h>
  '''
  
  foreach decl : ['char16_t',
          # We get -1 if the size cannot be determined
          have = cc.sizeof(decl, prefix : decl_headers, args : '-D_GNU_SOURCE') > 0
  
 +        if decl == 'struct mount_attr'
 +                if have
 +                        want_linux_fs_h = false
 +                else
 +                        have = cc.sizeof(decl,
 +                                         prefix : decl_headers + '#include <linux/fs.h>',
 +                                         args : '-D_GNU_SOURCE') > 0
 +                        want_linux_fs_h = have
 +                endif
 +        endif
 +
          if decl == 'struct statx'
                  if have
                          want_linux_stat_h = false
  endforeach
  
  conf.set10('WANT_LINUX_STAT_H', want_linux_stat_h)
 +conf.set10('WANT_LINUX_FS_H', want_linux_fs_h)
  
  foreach ident : ['secure_getenv', '__secure_getenv']
          conf.set10('HAVE_' + ident.to_upper(), cc.has_function(ident))
@@@ -797,7 -779,7 +797,7 @@@ if default_net_naming_scheme != 'latest
  endif
  
  time_epoch = get_option('time-epoch')
 -if time_epoch == -1
 +if time_epoch <= 0
          time_epoch = run_command(sh, '-c', 'echo "$SOURCE_DATE_EPOCH"', check : true).stdout().strip()
          if time_epoch == '' and git.found() and fs.exists('.git')
                  # If we're in a git repository, use the creation time of the latest git tag.
                  time_epoch = run_command(stat, '-c', '%Y', NEWS,
                                           check : true).stdout()
          endif
 -        time_epoch = time_epoch.to_int()
 +        time_epoch = time_epoch.strip().to_int()
  endif
  conf.set('TIME_EPOCH', time_epoch)
  
@@@ -830,7 -812,7 +830,7 @@@ foreach tuple : [['system-alloc-uid-min
                   ['system-alloc-gid-min', 'SYS_GID_MIN', 1],
                   ['system-gid-max',       'SYS_GID_MAX', 999]]
          v = get_option(tuple[0])
 -        if v == -1
 +        if v <= 0
                  v = run_command(
                          awk,
                          '/^\s*@0@\s+/ { uid=$2 } END { print uid }'.format(tuple[1]),
@@@ -876,7 -858,7 +876,7 @@@ if not meson.is_cross_build(
          endif
          id_result = run_command('id', '-u', nobody_user, check : false)
          if id_result.returncode() == 0
 -                id = id_result.stdout().to_int()
 +                id = id_result.stdout().strip().to_int()
                  if id != 65534
                          warning('\n' +
                                  'The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) +
          endif
          id_result = run_command('id', '-g', nobody_group, check : false)
          if id_result.returncode() == 0
 -                id = id_result.stdout().to_int()
 +                id = id_result.stdout().strip().to_int()
                  if id != 65534
                          warning('\n' +
                                  'The local group with the configured group name "@0@" of the nobody group does not have GID 65534 (it has @1@).\n'.format(nobody_group, id) +
@@@ -938,8 -920,8 +938,8 @@@ foreach option : ['adm-gid'
          val = get_option(option)
  
          # Ensure provided GID argument is numeric, otherwise fall back to default assignment
 -        conf.set(name, val >= 0 ? val : '-')
 -        if val >= 0
 +        conf.set(name, val > 0 ? val : '-')
 +        if val > 0
                  static_ugids += '@0@:@1@'.format(option, val)
          endif
  endforeach
@@@ -2231,7 -2213,7 +2231,7 @@@ exe = executable
          dependencies : [versiondep,
                          libseccomp],
          install_rpath : rootpkglibdir,
 -        install : conf.get('ENABLE_ANALYZE'))
 +        install : conf.get('ENABLE_ANALYZE') == 1)
  public_programs += exe
  
  if want_tests != 'false'
@@@ -2265,19 -2247,11 +2265,19 @@@ public_programs += executable
          install_rpath : rootpkglibdir,
          install : true)
  
 +if get_option('link-journalctl-shared')
 +        journalctl_link_with = [libshared]
 +else
 +        journalctl_link_with = [libsystemd_static,
 +                                libshared_static,
 +                                libbasic_gcrypt]
 +endif
 +
  public_programs += executable(
          'journalctl',
          journalctl_sources,
          include_directories : includes,
 -        link_with : [libshared],
 +        link_with : [journalctl_link_with],
          dependencies : [threads,
                          libdl,
                          libxz,
@@@ -2324,6 -2298,10 +2324,10 @@@ exe = executable
          install : true,
          install_dir : systemgeneratordir)
  
+ meson.add_install_script(meson_make_symlink,
+                          systemgeneratordir / 'systemd-fstab-generator',
+                          rootlibexecdir / 'systemd-sysroot-fstab-check')
  if want_tests != 'false'
          test('test-fstab-generator',
               test_fstab_generator_sh,
@@@ -2541,18 -2519,6 +2545,18 @@@ if conf.get('HAVE_BLKID') == 1 and conf
                  install_rpath : rootpkglibdir,
                  install : true,
                  install_dir : systemgeneratordir)
 +
 +        if conf.get('HAVE_OPENSSL') == 1
 +                executable(
 +                        'systemd-measure',
 +                        'src/boot/measure.c',
 +                        include_directories : includes,
 +                        link_with : [libshared],
 +                        dependencies : [libopenssl],
 +                        install_rpath : rootpkglibdir,
 +                        install : true,
 +                        install_dir : rootlibexecdir)
 +        endif
  endif
  
  executable(
@@@ -4310,7 -4276,7 +4314,7 @@@ foreach tuple : 
          # components
          ['backlight'],
          ['binfmt'],
 -        ['bpf-framework',         conf.get('BPF_FRAMEWORK') == 1],
 +        ['bpf-framework',          conf.get('BPF_FRAMEWORK') == 1],
          ['coredump'],
          ['environment.d'],
          ['efi'],
          ['resolve'],
          ['rfkill'],
          ['sysext'],
 -        ['systemd-analyze',       conf.get('ENABLE_ANALYZE') == 1],
 +        ['systemd-analyze',        conf.get('ENABLE_ANALYZE') == 1],
          ['sysupdate'],
          ['sysusers'],
          ['timedated'],
          ['idn'],
          ['polkit'],
          ['nscd'],
 -        ['legacy-pkla',           install_polkit_pkla],
 +        ['legacy-pkla',            install_polkit_pkla],
          ['kmod'],
          ['dbus'],
          ['glib'],
          ['tpm'],
 -        ['man pages',             want_man],
 -        ['html pages',            want_html],
 -        ['man page indices',      want_man and have_lxml],
 +        ['man pages',              want_man],
 +        ['html pages',             want_html],
 +        ['man page indices',       want_man and have_lxml],
          ['SysV compat'],
          ['compat-mutable-uid-boundaries'],
          ['utmp'],
          ['ldconfig'],
 -        ['adm group',             get_option('adm-group')],
 -        ['wheel group',           get_option('wheel-group')],
 +        ['adm group',              get_option('adm-group')],
 +        ['wheel group',            get_option('wheel-group')],
          ['gshadow'],
          ['debug hashmap'],
          ['debug mmap cache'],
          ['debug siphash'],
 -        ['valgrind',              conf.get('VALGRIND') == 1],
 -        ['trace logging',         conf.get('LOG_TRACE') == 1],
 -        ['install tests',         install_tests],
 -        ['link-udev-shared',      get_option('link-udev-shared')],
 -        ['link-systemctl-shared', get_option('link-systemctl-shared')],
 -        ['link-networkd-shared',  get_option('link-networkd-shared')],
 -        ['link-timesyncd-shared', get_option('link-timesyncd-shared')],
 -        ['link-boot-shared',      get_option('link-boot-shared')],
 +        ['valgrind',               conf.get('VALGRIND') == 1],
 +        ['trace logging',          conf.get('LOG_TRACE') == 1],
 +        ['install tests',          install_tests],
 +        ['link-udev-shared',       get_option('link-udev-shared')],
 +        ['link-systemctl-shared',  get_option('link-systemctl-shared')],
 +        ['link-networkd-shared',   get_option('link-networkd-shared')],
 +        ['link-timesyncd-shared',  get_option('link-timesyncd-shared')],
 +        ['link-journalctl-shared', get_option('link-journalctl-shared')],
 +        ['link-boot-shared',       get_option('link-boot-shared')],
          ['first-boot-full-preset'],
          ['fexecve'],
 -        ['standalone-binaries',   get_option('standalone-binaries')],
 -        ['coverage',              get_option('b_coverage')],
 +        ['standalone-binaries',    get_option('standalone-binaries')],
 +        ['coverage',               get_option('b_coverage')],
  ]
  
          if tuple.length() >= 2
diff --combined src/boot/bootctl.c
index f04463157a514f34c7c273732d736f02d1fb6399,4907b3ce3deba1bf378087aa77b84524c36f0a77..10da1c8d7f2973bae0de00fd60d4f7157c4e31e5
@@@ -456,21 -456,13 +456,21 @@@ static const char *get_efi_arch(void) 
          return EFI_MACHINE_TYPE_NAME;
  }
  
 -static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) {
 +static int enumerate_binaries(
 +                const char *esp_path,
 +                const char *path,
 +                const char *prefix,
 +                char **previous,
 +                bool *is_first) {
 +
          _cleanup_closedir_ DIR *d = NULL;
          const char *p;
          int c = 0, r;
  
          assert(esp_path);
          assert(path);
 +        assert(previous);
 +        assert(is_first);
  
          p = prefix_roota(esp_path, path);
          d = opendir(p);
                  r = get_file_version(fd, &v);
                  if (r < 0)
                          return r;
 +
 +                if (*previous) { /* let's output the previous entry now, since now we know that there will be one more, and can draw the tree glyph properly */
 +                        printf("         %s %s%s\n",
 +                               *is_first ? "File:" : "     ",
 +                               special_glyph(SPECIAL_GLYPH_TREE_BRANCH), *previous);
 +                        *is_first = false;
 +                        *previous = mfree(*previous);
 +                }
 +
 +                /* Do not output this entry immediately, but store what should be printed in a state
 +                 * variable, because we only will know the tree glyph to print (branch or final edge) once we
 +                 * read one more entry */
                  if (r > 0)
 -                        printf("         File: %s/%s/%s (%s%s%s)\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), path, de->d_name, ansi_highlight(), v, ansi_normal());
 +                        r = asprintf(previous, "/%s/%s (%s%s%s)", path, de->d_name, ansi_highlight(), v, ansi_normal());
                  else
 -                        printf("         File: %s/%s/%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), path, de->d_name);
 +                        r = asprintf(previous, "/%s/%s", path, de->d_name);
 +                if (r < 0)
 +                        return log_oom();
  
                  c++;
          }
  }
  
  static int status_binaries(const char *esp_path, sd_id128_t partition) {
 -        int r;
 +        _cleanup_free_ char *last = NULL;
 +        bool is_first = true;
 +        int r, k;
  
 -        printf("Available Boot Loaders on ESP:\n");
 +        printf("%sAvailable Boot Loaders on ESP:%s\n", ansi_underline(), ansi_normal());
  
          if (!esp_path) {
                  printf("          ESP: Cannot find or access mount point of ESP.\n\n");
                  printf(" (/dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR ")", SD_ID128_FORMAT_VAL(partition));
          printf("\n");
  
 -        r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
 -        if (r < 0)
 -                goto finish;
 -        if (r == 0 && !arg_quiet)
 -                log_info("systemd-boot not installed in ESP.");
 +        r = enumerate_binaries(esp_path, "EFI/systemd", NULL, &last, &is_first);
 +        if (r < 0) {
 +                printf("\n");
 +                return r;
 +        }
 +
 +        k = enumerate_binaries(esp_path, "EFI/BOOT", "boot", &last, &is_first);
 +        if (k < 0) {
 +                printf("\n");
 +                return k;
 +        }
 +
 +        if (last) /* let's output the last entry now, since now we know that there will be no more, and can draw the tree glyph properly */
 +                printf("         %s %s%s\n",
 +                       is_first ? "File:" : "     ",
 +                       special_glyph(SPECIAL_GLYPH_TREE_RIGHT), last);
  
 -        r = enumerate_binaries(esp_path, "EFI/BOOT", "boot");
 -        if (r < 0)
 -                goto finish;
          if (r == 0 && !arg_quiet)
 +                log_info("systemd-boot not installed in ESP.");
 +        if (k == 0 && !arg_quiet)
                  log_info("No default/fallback boot loader installed in ESP.");
  
 -        r = 0;
 -
 -finish:
          printf("\n");
 -        return r;
 +        return 0;
  }
  
 -static int print_efi_option(uint16_t id, bool in_order) {
 +static int print_efi_option(uint16_t id, int *n_printed, bool in_order) {
          _cleanup_free_ char *title = NULL;
          _cleanup_free_ char *path = NULL;
          sd_id128_t partition;
          bool active;
          int r;
  
 +        assert(n_printed);
 +
          r = efi_get_boot_option(id, &title, &partition, &path, &active);
          if (r < 0)
 -                return r;
 +                return log_error_errno(r, "Failed to read boot option %u: %m", id);
  
          /* print only configured entries with partition information */
 -        if (!path || sd_id128_is_null(partition))
 +        if (!path || sd_id128_is_null(partition)) {
 +                log_debug("Ignoring boot entry %u without partition information.", id);
                  return 0;
 +        }
  
          efi_tilt_backslashes(path);
  
 +        if (*n_printed == 0) /* Print section title before first entry */
 +                printf("%sBoot Loaders Listed in EFI Variables:%s\n", ansi_underline(), ansi_normal());
 +
          printf("        Title: %s%s%s\n", ansi_highlight(), strna(title), ansi_normal());
          printf("           ID: 0x%04X\n", id);
          printf("       Status: %sactive%s\n", active ? "" : "in", in_order ? ", boot-order" : "");
          printf("         File: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), path);
          printf("\n");
  
 -        return 0;
 +        (*n_printed)++;
 +        return 1;
  }
  
  static int status_variables(void) {
          _cleanup_free_ uint16_t *options = NULL, *order = NULL;
 -        int n_options, n_order;
 +        int n_options, n_order, n_printed = 0;
  
          n_options = efi_get_boot_options(&options);
          if (n_options == -ENOENT)
                  return log_error_errno(n_order, "Failed to read EFI boot order: %m");
  
          /* print entries in BootOrder first */
 -        printf("Boot Loaders Listed in EFI Variables:\n");
          for (int i = 0; i < n_order; i++)
 -                print_efi_option(order[i], true);
 +                (void) print_efi_option(order[i], &n_printed, /* in_order= */ true);
  
          /* print remaining entries */
          for (int i = 0; i < n_options; i++) {
                          if (options[i] == order[j])
                                  goto next_option;
  
 -                print_efi_option(options[i], false);
 +                (void) print_efi_option(options[i], &n_printed, /* in_order= */ false);
  
          next_option:
                  continue;
          }
  
 +        if (n_printed == 0)
 +                printf("No boot loaders listed in EFI Variables.\n\n");
 +
          return 0;
  }
  
@@@ -696,8 -655,8 +696,8 @@@ static int status_entries
                  dollar_boot_partition_uuid = esp_partition_uuid;
          }
  
 -        printf("Boot Loader Entries:\n"
 -               "        $BOOT: %s", dollar_boot_path);
 +        printf("%sBoot Loader Entries:%s\n"
 +               "        $BOOT: %s", ansi_underline(), ansi_normal(), dollar_boot_path);
          if (!sd_id128_is_null(dollar_boot_partition_uuid))
                  printf(" (/dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR ")",
                         SD_ID128_FORMAT_VAL(dollar_boot_partition_uuid));
          if (config->default_entry < 0)
                  printf("%zu entries, no entry could be determined as default.\n", config->n_entries);
          else {
 -                printf("Default Boot Loader Entry:\n");
 +                printf("%sDefault Boot Loader Entry:%s\n", ansi_underline(), ansi_normal());
  
                  r = show_boot_entry(
                                  boot_config_default_entry(config),
@@@ -913,7 -872,7 +913,7 @@@ static int copy_one_file(const char *es
                                         "Failed to resolve path %s%s%s: %m",
                                         p,
                                         root ? " under directory " : "",
 -                                       root ?: "");
 +                                       strempty(root));
  
          q = path_join("/EFI/systemd/", dest_name);
          if (!q)
@@@ -959,7 -918,7 +959,7 @@@ static int install_binaries(const char 
          if (r == -ENOENT && root && arg_install_source == ARG_INSTALL_SOURCE_AUTO)
                  r = chase_symlinks_and_opendir(BOOTLIBDIR, NULL, CHASE_PREFIX_ROOT, &path, &d);
          if (r < 0)
 -                return log_error_errno(r, "Failed to open boot loader directory %s%s: %m", root ?: "", BOOTLIBDIR);
 +                return log_error_errno(r, "Failed to open boot loader directory %s%s: %m", strempty(root), BOOTLIBDIR);
  
          const char *suffix = strjoina(arch, ".efi");
          const char *suffix_signed = strjoina(arch, ".efi.signed");
@@@ -1755,7 -1714,7 +1755,7 @@@ static int verb_status(int argc, char *
                  static const struct {
                          uint64_t flag;
                          const char *name;
 -                } flags[] = {
 +                } loader_flags[] = {
                          { EFI_LOADER_FEATURE_BOOT_COUNTING,           "Boot counting"                         },
                          { EFI_LOADER_FEATURE_CONFIG_TIMEOUT,          "Menu timeout control"                  },
                          { EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT, "One-shot menu timeout control"         },
                          { EFI_LOADER_FEATURE_XBOOTLDR,                "Support for XBOOTLDR partition"        },
                          { EFI_LOADER_FEATURE_RANDOM_SEED,             "Support for passing random seed to OS" },
                          { EFI_LOADER_FEATURE_LOAD_DRIVER,             "Load drop-in drivers"                  },
 +                        { EFI_LOADER_FEATURE_SORT_KEY,                "Support Type #1 sort-key field"        },
 +                        { EFI_LOADER_FEATURE_SAVED_ENTRY,             "Support @saved pseudo-entry"           },
 +                        { EFI_LOADER_FEATURE_DEVICETREE,              "Support Type #1 devicetree field"      },
 +                };
 +                static const struct {
 +                        uint64_t flag;
 +                        const char *name;
 +                } stub_flags[] = {
 +                        { EFI_STUB_FEATURE_REPORT_BOOT_PARTITION,     "Stub sets ESP information"                            },
 +                        { EFI_STUB_FEATURE_PICK_UP_CREDENTIALS,       "Picks up credentials from boot partition"             },
 +                        { EFI_STUB_FEATURE_PICK_UP_SYSEXTS,           "Picks up system extension images from boot partition" },
 +                        { EFI_STUB_FEATURE_THREE_PCRS,                "Measures kernel+command line+sysexts"                 },
                  };
                  _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL;
                  sd_id128_t loader_part_uuid = SD_ID128_NULL;
 -                uint64_t loader_features = 0;
 +                uint64_t loader_features = 0, stub_features = 0;
                  Tpm2Support s;
                  int have;
  
                  read_efi_var(EFI_LOADER_VARIABLE(StubInfo), &stub);
                  read_efi_var(EFI_LOADER_VARIABLE(LoaderImageIdentifier), &loader_path);
                  (void) efi_loader_get_features(&loader_features);
 +                (void) efi_stub_get_features(&stub_features);
  
                  if (loader_path)
                          efi_tilt_backslashes(loader_path);
                          r = log_warning_errno(k, "Failed to read EFI variable LoaderDevicePartUUID: %m");
  
                  SecureBootMode secure = efi_get_secure_boot_mode();
 -                printf("System:\n");
 +                printf("%sSystem:%s\n", ansi_underline(), ansi_normal());
                  printf("      Firmware: %s%s (%s)%s\n", ansi_highlight(), strna(fw_type), strna(fw_info), ansi_normal());
                  printf(" Firmware Arch: %s\n", get_efi_arch());
                  printf("   Secure Boot: %sd (%s)\n",
                  }
                  printf("\n");
  
 -                printf("Current Boot Loader:\n");
 +                printf("%sCurrent Boot Loader:%s\n", ansi_underline(), ansi_normal());
                  printf("      Product: %s%s%s\n", ansi_highlight(), strna(loader), ansi_normal());
  
 -                for (size_t i = 0; i < ELEMENTSOF(flags); i++)
 -                        print_yes_no_line(i == 0, FLAGS_SET(loader_features, flags[i].flag), flags[i].name);
 +                for (size_t i = 0; i < ELEMENTSOF(loader_flags); i++)
 +                        print_yes_no_line(i == 0, FLAGS_SET(loader_features, loader_flags[i].flag), loader_flags[i].name);
  
                  sd_id128_t bootloader_esp_uuid;
                  bool have_bootloader_esp_uuid = efi_loader_get_device_part_uuid(&bootloader_esp_uuid) >= 0;
  
                  print_yes_no_line(false, have_bootloader_esp_uuid, "Boot loader sets ESP information");
-                 if (have_bootloader_esp_uuid && !sd_id128_equal(esp_uuid, bootloader_esp_uuid))
-                         printf("WARNING: The boot loader reports a different ESP UUID than detected!\n");
+                 if (have_bootloader_esp_uuid && !sd_id128_is_null(esp_uuid) &&
+                     !sd_id128_equal(esp_uuid, bootloader_esp_uuid))
+                         printf("WARNING: The boot loader reports a different ESP UUID than detected ("SD_ID128_UUID_FORMAT_STR" vs. "SD_ID128_UUID_FORMAT_STR")!\n",
+                                SD_ID128_FORMAT_VAL(bootloader_esp_uuid),
+                                SD_ID128_FORMAT_VAL(esp_uuid));
  
 -                if (stub)
 +                if (stub) {
                          printf("         Stub: %s\n", stub);
 +                        for (size_t i = 0; i < ELEMENTSOF(stub_flags); i++)
 +                                print_yes_no_line(i == 0, FLAGS_SET(stub_features, stub_flags[i].flag), stub_flags[i].name);
 +                }
                  if (!sd_id128_is_null(loader_part_uuid))
                          printf("          ESP: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n",
                                 SD_ID128_FORMAT_VAL(loader_part_uuid));
                  printf("         File: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(loader_path));
                  printf("\n");
  
 -                printf("Random Seed:\n");
 +                printf("%sRandom Seed:%s\n", ansi_underline(), ansi_normal());
                  have = access(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderRandomSeed)), F_OK) >= 0;
                  printf(" Passed to OS: %s\n", yes_no(have));
                  have = access(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderSystemToken)), F_OK) >= 0;
  
                  printf("\n");
          } else
 -                printf("System:\n    Not booted with EFI\n\n");
 +                printf("%sSystem:%s\n"
 +                       "Not booted with EFI\n\n",
 +                       ansi_underline(), ansi_normal());
  
          if (arg_esp_path) {
                  k = status_binaries(arg_esp_path, esp_uuid);
index f46260307acb8127c4ce68c5570afbf5ef1d9d29,4005a5c796d5060cc0af8fc0768ab32e15a28542..c3c22220c22770c3ab4db84506edcca6f17396bc
@@@ -249,7 -249,7 +249,7 @@@ static int maybe_reload(sd_bus **bus) 
                  return bus_log_create_error(r);
  
          /* Reloading the daemon may take long, hence set a longer timeout here */
-         r = sd_bus_call(*bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
+         r = sd_bus_call(*bus, m, DAEMON_RELOAD_TIMEOUT_SEC, &error, NULL);
          if (r < 0)
                  return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
  
@@@ -597,9 -597,11 +597,9 @@@ static int maybe_start_stop_restart(sd_
          if (!arg_now)
                  return 0;
  
 -        r = sd_bus_call_method(
 +        r = bus_call_method(
                          bus,
 -                        "org.freedesktop.systemd1",
 -                        "/org/freedesktop/systemd1",
 -                        "org.freedesktop.systemd1.Manager",
 +                        bus_systemd_mgr,
                          method,
                          &error,
                          &reply,
index 06f17c6a8e9125a130d6efbacd42d39641c95ea5,718cf37607f34ef411c0b19c7901f42e64dfff74..5648dfd83baaa321914f5a201150c7e241a966b2
@@@ -8,7 -8,6 +8,7 @@@
  
  #include "sd-bus.h"
  
 +#include "bus-locator.h"
  #include "bus-util.h"
  #include "bus-error.h"
  #include "def.h"
@@@ -25,19 -24,18 +25,16 @@@ static int reload_manager(sd_bus *bus) 
  
          log_info("Reloading system manager configuration");
  
 -        r = sd_bus_message_new_method_call(
 +        r = bus_message_new_method_call(
                          bus,
                          &m,
 -                        "org.freedesktop.systemd1",
 -                        "/org/freedesktop/systemd1",
 -                        "org.freedesktop.systemd1.Manager",
 +                        bus_systemd_mgr,
                          "Reload");
          if (r < 0)
                  return bus_log_create_error(r);
  
-         /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
-          * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
-          * their timeout, and for everything else there's the same time budget in place. */
-         r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
+         /* Reloading the daemon may take long, hence set a longer timeout here */
+         r = sd_bus_call(bus, m, DAEMON_RELOAD_TIMEOUT_SEC, &error, NULL);
          if (r < 0)
                  return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
  
@@@ -51,13 -49,14 +48,13 @@@ static int start_default_target(sd_bus 
          log_info("Starting "SPECIAL_DEFAULT_TARGET);
  
          /* Start this unit only if we can replace basic.target with it */
 -        r = sd_bus_call_method(bus,
 -                               "org.freedesktop.systemd1",
 -                               "/org/freedesktop/systemd1",
 -                               "org.freedesktop.systemd1.Manager",
 -                               "StartUnit",
 -                               &error,
 -                               NULL,
 -                               "ss", SPECIAL_DEFAULT_TARGET, "isolate");
 +        r = bus_call_method(
 +                        bus,
 +                        bus_systemd_mgr,
 +                        "StartUnit",
 +                        &error,
 +                        NULL,
 +                        "ss", SPECIAL_DEFAULT_TARGET, "isolate");
  
          if (r < 0)
                  return log_error_errno(r, "Failed to start "SPECIAL_DEFAULT_TARGET": %s", bus_error_message(&error, r));