]> git.proxmox.com Git - systemd.git/commitdiff
New upstream version 252.2
authorLuca Boccassi <bluca@debian.org>
Mon, 28 Nov 2022 22:25:21 +0000 (22:25 +0000)
committerLuca Boccassi <bluca@debian.org>
Mon, 28 Nov 2022 22:25:21 +0000 (22:25 +0000)
49 files changed:
docs/CNAME [new file with mode: 0644]
docs/ENVIRONMENT.md
meson.build
src/basic/fd-util.c
src/basic/fd-util.h
src/basic/process-util.c
src/basic/process-util.h
src/basic/strv.c
src/basic/strv.h
src/basic/util.c
src/boot/bootctl.c
src/boot/efi/boot.c
src/boot/efi/drivers.c
src/boot/efi/linux.c
src/boot/efi/secure-boot.c
src/boot/efi/secure-boot.h
src/boot/efi/shim.c
src/boot/efi/util.c
src/boot/measure.c
src/core/selinux-access.c
src/core/timer.c
src/fuzz/fuzz-compress.c
src/journal/test-journal-interleaving.c
src/kernel-install/kernel-install.in
src/libsystemd/sd-bus/sd-bus.c
src/libsystemd/sd-journal/sd-journal.c
src/network/networkd-ipv4acd.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-wifi.c
src/nspawn/nspawn-seccomp.c
src/oom/oomd-util.c
src/oom/test-oomd-util.c
src/partition/repart.c
src/portable/portable.c
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-server.c
src/resolve/resolved-dnstls-openssl.c
src/shared/bootspec.c
src/shared/dissect-image.c
src/shared/dissect-image.h
src/shared/find-esp.c
src/shared/switch-root.c
src/shared/tpm2-util.c
src/shared/udev-util.c
src/systemctl/systemctl-show.c
src/test/meson.build
src/tmpfiles/tmpfiles.c
src/udev/udev-builtin-blkid.c

diff --git a/docs/CNAME b/docs/CNAME
new file mode 100644 (file)
index 0000000..cdcf4d9
--- /dev/null
@@ -0,0 +1 @@
+systemd.io
\ No newline at end of file
index a840dd0c9085f0c82beb765b182ebf6da9a7783b..ab3add6031aef7e6138b936e3eb1f25cbb0f93bd 100644 (file)
@@ -73,13 +73,9 @@ All tools:
   (relevant in particular for the system manager and `systemd-hostnamed`).
   Must be a valid hostname (either a single label or a FQDN).
 
-* `$SYSTEMD_IN_INITRD=[auto|lenient|0|1]` — if set, specifies initrd detection
-  method. Defaults to `auto`. Behavior is defined as follows:
-  `auto`: Checks if `/etc/initrd-release` exists, and a temporary fs is mounted
-          on `/`. If both conditions meet, then it's in initrd.
-  `lenient`: Similar to `auto`, but the rootfs check is skipped.
-  `0|1`: Simply overrides initrd detection. This is useful for debugging and
-         testing initrd-only programs in the main system.
+* `$SYSTEMD_IN_INITRD` — takes a boolean. If set, overrides initrd detection.
+  This is useful for debugging and testing initrd-only programs in the main
+  system.
 
 * `$SYSTEMD_BUS_TIMEOUT=SECS` — specifies the maximum time to wait for method call
   completion. If no time unit is specified, assumes seconds. The usual other units
index 775053446690ca6db1fad2d1b2e6bf29d5f7be21..35704947e3dffaa3d4f1b9ab34038ae843166e6b 100644 (file)
@@ -1474,11 +1474,14 @@ if want_tpm2 != 'false' and not skip_deps
         tpm2 = dependency('tss2-esys tss2-rc tss2-mu',
                           required : want_tpm2 == 'true')
         have = tpm2.found()
+        have_esys3 = tpm2.version().version_compare('>= 3.0.0')
 else
         have = false
+        have_esys3 = false
         tpm2 = []
 endif
 conf.set10('HAVE_TPM2', have)
+conf.set10('HAVE_TSS2_ESYS3', have_esys3)
 
 want_elfutils = get_option('elfutils')
 if want_elfutils != 'false' and not skip_deps
@@ -3838,7 +3841,7 @@ exe = custom_target(
         install_dir : bindir)
 public_programs += exe
 
-if want_tests != 'false'
+if want_tests != 'false' and want_kernel_install
         test('test-kernel-install',
              test_kernel_install_sh,
              args : [exe.full_path(), loaderentry_install])
index cee20a9a815c2e54bc6f46e25541ca386c361d7f..66bb7569bbb39831666ab65eff2be4629472832c 100644 (file)
@@ -174,12 +174,35 @@ int fd_cloexec(int fd, bool cloexec) {
         return RET_NERRNO(fcntl(fd, F_SETFD, nflags));
 }
 
+int fd_cloexec_many(const int fds[], size_t n_fds, bool cloexec) {
+        int ret = 0, r;
+
+        assert(n_fds == 0 || fds);
+
+        for (size_t i = 0; i < n_fds; i++) {
+                if (fds[i] < 0) /* Skip gracefully over already invalidated fds */
+                        continue;
+
+                r = fd_cloexec(fds[i], cloexec);
+                if (r < 0 && ret >= 0) /* Continue going, but return first error */
+                        ret = r;
+                else
+                        ret = 1; /* report if we did anything */
+        }
+
+        return ret;
+}
+
 _pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
         assert(n_fdset == 0 || fdset);
 
-        for (size_t i = 0; i < n_fdset; i++)
+        for (size_t i = 0; i < n_fdset; i++) {
+                if (fdset[i] < 0)
+                        continue;
+
                 if (fdset[i] == fd)
                         return true;
+        }
 
         return false;
 }
@@ -252,6 +275,10 @@ static int close_all_fds_special_case(const int except[], size_t n_except) {
         if (!have_close_range)
                 return 0;
 
+        if (n_except == 1 && except[0] < 0) /* Minor optimization: if we only got one fd, and it's invalid,
+                                             * we got none */
+                n_except = 0;
+
         switch (n_except) {
 
         case 0:
index d9896e27e8d5c0fc2876f3a4548485ab9b621416..29c7d86f27ddbb6b0f17ae1426cff33825fb3499 100644 (file)
@@ -56,6 +56,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(DIR*, closedir, NULL);
 
 int fd_nonblock(int fd, bool nonblock);
 int fd_cloexec(int fd, bool cloexec);
+int fd_cloexec_many(const int fds[], size_t n_fds, bool cloexec);
 
 int get_max_fd(void);
 
index fb0b38fa49da3ef7d139f1df28c485b8108baa33..0213f5913f5fed4da784e50150e806aa97b0e124 100644 (file)
@@ -1372,6 +1372,14 @@ int safe_fork_full(
                 }
         }
 
+        if (flags & FORK_CLOEXEC_OFF) {
+                r = fd_cloexec_many(except_fds, n_except_fds, false);
+                if (r < 0) {
+                        log_full_errno(prio, r, "Failed to turn off O_CLOEXEC on file descriptors: %m");
+                        _exit(EXIT_FAILURE);
+                }
+        }
+
         /* When we were asked to reopen the logs, do so again now */
         if (flags & FORK_REOPEN_LOG) {
                 log_open();
index f8c374a310367b745983ec9e95fed0bda8f69d3d..ed2f73673e7aaea7e58a3537b4ee5d7a4e45ebda 100644 (file)
@@ -150,6 +150,7 @@ typedef enum ForkFlags {
         FORK_STDOUT_TO_STDERR   = 1 << 11, /* Make stdout a copy of stderr */
         FORK_FLUSH_STDIO        = 1 << 12, /* fflush() stdout (and stderr) before forking */
         FORK_NEW_USERNS         = 1 << 13, /* Run child in its own user namespace */
+        FORK_CLOEXEC_OFF        = 1 << 14, /* In the child: turn off O_CLOEXEC on all fds in except_fds[] */
 } ForkFlags;
 
 int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
index eea34ca68d9a98f6317b190b5927f3536c40e7e6..24fc56a1a5cafcfbd53cdfdd92d7a8f4506da57b 100644 (file)
@@ -721,7 +721,7 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
         }
 
         if (!m) {
-                m = new0(char, 1);
+                m = new0(char, 2);
                 if (!m)
                         return -ENOMEM;
                 n = 1;
@@ -730,11 +730,9 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
                 m[n] = '\0';
 
         assert(n > 0);
-        *ret = m;
+        *ret = TAKE_PTR(m);
         *ret_size = n - 1;
 
-        m = NULL;
-
         return 0;
 }
 
index d6f5ac6ba581958471b9499c356020b59ba061b1..6c9fa479433611d34c0e369e0b7eed3113a405f8 100644 (file)
@@ -45,7 +45,7 @@ static inline int strv_extend(char ***l, const char *value) {
         return strv_extend_with_size(l, NULL, value);
 }
 
-int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
+int strv_extendf(char ***l, const char *format, ...) _printf_(2,3);
 int strv_extend_front(char ***l, const char *value);
 
 int strv_push_with_size(char ***l, size_t *n, char *value);
index d7ef382737e913a035e00f25d77642e90c4c4974..e6aaa2dc9b5428f903c58405bfd183643c4d9966 100644 (file)
@@ -52,59 +52,25 @@ int prot_from_flags(int flags) {
 
 bool in_initrd(void) {
         int r;
-        const char *e;
-        bool lenient = false;
 
         if (saved_in_initrd >= 0)
                 return saved_in_initrd;
 
-        /* We have two checks here:
-         *
-         * 1. the flag file /etc/initrd-release must exist
-         * 2. the root file system must be a memory file system
-         *
-         * The second check is extra paranoia, since misdetecting an
-         * initrd can have bad consequences due the initrd
-         * emptying when transititioning to the main systemd.
-         *
-         * If env var $SYSTEMD_IN_INITRD is not set or set to "auto",
-         * both checks are used. If it's set to "lenient", only check
-         * 1 is used. If set to a boolean value, then the boolean
-         * value is returned.
+        /* If /etc/initrd-release exists, we're in an initrd.
+         * This can be overridden by setting SYSTEMD_IN_INITRD=0|1.
          */
 
-        e = secure_getenv("SYSTEMD_IN_INITRD");
-        if (e) {
-                if (streq(e, "lenient"))
-                        lenient = true;
-                else if (!streq(e, "auto")) {
-                        r = parse_boolean(e);
-                        if (r >= 0) {
-                                saved_in_initrd = r > 0;
-                                return saved_in_initrd;
-                        }
-                        log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
-                }
-        }
-
-        if (!lenient) {
-                r = path_is_temporary_fs("/");
-                if (r < 0)
-                        log_debug_errno(r, "Couldn't determine if / is a temporary file system: %m");
+        r = getenv_bool_secure("SYSTEMD_IN_INITRD");
+        if (r < 0 && r != -ENXIO)
+                log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
 
+        if (r >= 0)
                 saved_in_initrd = r > 0;
-        }
-
-        r = access("/etc/initrd-release", F_OK);
-        if (r >= 0) {
-                if (saved_in_initrd == 0)
-                        log_debug("/etc/initrd-release exists, but it's not an initrd.");
-                else
-                        saved_in_initrd = 1;
-        } else {
-                if (errno != ENOENT)
-                        log_debug_errno(errno, "Failed to test if /etc/initrd-release exists: %m");
-                saved_in_initrd = 0;
+        else {
+                r = access("/etc/initrd-release", F_OK);
+                if (r < 0 && errno != ENOENT)
+                        log_debug_errno(r, "Failed to check if /etc/initrd-release exists, assuming it does not: %m");
+                saved_in_initrd = r >= 0;
         }
 
         return saved_in_initrd;
index b53df11764418a42bfea3467bd97020de6a4d075..7da48b4ca4d424a1399a6a161815e0176dc96963 100644 (file)
@@ -585,12 +585,16 @@ static int print_efi_option(uint16_t id, int *n_printed, bool in_order) {
         assert(n_printed);
 
         r = efi_get_boot_option(id, &title, &partition, &path, &active);
+        if (r == -ENOENT) {
+                log_debug_errno(r, "Boot option 0x%04X referenced but missing, ignoring: %m", id);
+                return 0;
+        }
         if (r < 0)
-                return log_error_errno(r, "Failed to read boot option %u: %m", id);
+                return log_error_errno(r, "Failed to read boot option 0x%04X: %m", id);
 
         /* print only configured entries with partition information */
         if (!path || sd_id128_is_null(partition)) {
-                log_debug("Ignoring boot entry %u without partition information.", id);
+                log_debug("Ignoring boot entry 0x%04X without partition information.", id);
                 return 0;
         }
 
index 4150b16ecf9bbd3b1f04d7c867f2205c21377cf4..b490a1d972df164eed057bed37801c8e46aa6a63 100644 (file)
@@ -471,7 +471,6 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
         _cleanup_free_ char16_t *device_part_uuid = NULL;
 
         assert(config);
-        assert(loaded_image_path);
 
         clear_screen(COLOR_NORMAL);
         console_query_mode(&x_max, &y_max);
@@ -619,7 +618,6 @@ static bool menu_run(
 
         assert(config);
         assert(chosen_entry);
-        assert(loaded_image_path);
 
         EFI_STATUS err;
         UINTN visible_max = 0;
@@ -1478,7 +1476,7 @@ static void config_entry_add_type1(
                         entry->loader = xstra_to_path(value);
 
                         /* do not add an entry for ourselves */
-                        if (loaded_image_path && strcaseeq16(entry->loader, loaded_image_path)) {
+                        if (strcaseeq16(entry->loader, loaded_image_path)) {
                                 entry->type = LOADER_UNDEFINED;
                                 break;
                         }
@@ -1908,12 +1906,11 @@ static ConfigEntry *config_entry_add_loader_auto(
         assert(root_dir);
         assert(id);
         assert(title);
-        assert(loader || loaded_image_path);
 
         if (!config->auto_entries)
                 return NULL;
 
-        if (loaded_image_path) {
+        if (!loader) {
                 loader = L"\\EFI\\BOOT\\BOOT" EFI_MACHINE_TYPE_NAME ".efi";
 
                 /* We are trying to add the default EFI loader here,
@@ -2562,7 +2559,6 @@ static void export_variables(
         char16_t uuid[37];
 
         assert(loaded_image);
-        assert(loaded_image_path);
 
         efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec);
         efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, 0);
@@ -2591,7 +2587,6 @@ static void config_load_all_entries(
 
         assert(config);
         assert(loaded_image);
-        assert(loaded_image_path);
         assert(root_dir);
 
         config_load_defaults(config, root_dir);
@@ -2650,7 +2645,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
         EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
         _cleanup_(file_closep) EFI_FILE *root_dir = NULL;
         _cleanup_(config_free) Config config = {};
-        char16_t *loaded_image_path;
+        _cleanup_free_ char16_t *loaded_image_path = NULL;
         EFI_STATUS err;
         uint64_t init_usec;
         bool menu = false;
@@ -2676,9 +2671,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
         if (err != EFI_SUCCESS)
                 return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
 
-        err = device_path_to_str(loaded_image->FilePath, &loaded_image_path);
-        if (err != EFI_SUCCESS)
-                return log_error_status_stall(err, L"Error getting loaded image path: %m");
+        (void) device_path_to_str(loaded_image->FilePath, &loaded_image_path);
 
         export_variables(loaded_image, loaded_image_path, init_usec);
 
index 39b65e74a6f413d11d21df8c0c06d3006bbe4a99..7f2057f5a15e89a3bacd78a855d12e21228bb8d7 100644 (file)
@@ -51,25 +51,23 @@ static EFI_STATUS load_one_driver(
 }
 
 EFI_STATUS reconnect_all_drivers(void) {
-          _cleanup_free_ EFI_HANDLE *handles = NULL;
-          UINTN n_handles = 0;
-          EFI_STATUS err;
+        _cleanup_free_ EFI_HANDLE *handles = NULL;
+        size_t n_handles = 0;
+        EFI_STATUS err;
 
-          /* Reconnects all handles, so that any loaded drivers can take effect. */
+        /* Reconnects all handles, so that any loaded drivers can take effect. */
 
-          err = BS->LocateHandleBuffer(AllHandles, NULL, NULL, &n_handles, &handles);
-          if (err != EFI_SUCCESS)
-                  return log_error_status_stall(err, L"Failed to get list of handles: %r", err);
+        err = BS->LocateHandleBuffer(AllHandles, NULL, NULL, &n_handles, &handles);
+        if (err != EFI_SUCCESS)
+                return log_error_status_stall(err, L"Failed to get list of handles: %r", err);
 
-          for (UINTN i = 0; i < n_handles; i++) {
-                  err = BS->ConnectController(handles[i], NULL, NULL, true);
-                  if (err == EFI_NOT_FOUND) /* No drivers for this handle */
-                          continue;
-                  if (err != EFI_SUCCESS)
-                          log_error_status_stall(err, L"Failed to reconnect handle %" PRIuN L", ignoring: %r", i, err);
-          }
+        for (size_t i = 0; i < n_handles; i++)
+                /* Some firmware gives us some bogus handles (or they might become bad due to
+                 * reconnecting everything). Security policy may also prevent us from doing so too.
+                 * There is nothing we can realistically do on errors anyways, so just ignore them. */
+                (void) BS->ConnectController(handles[i], NULL, NULL, true);
 
-          return EFI_SUCCESS;
+        return EFI_SUCCESS;
 }
 
 EFI_STATUS load_drivers(
index 75b95077094ca15bafdd8486ee4ae8ab802944eb..dd7eb48c8c832a365dc679da1dce59d3bb7aef20 100644 (file)
 #define STUB_PAYLOAD_GUID \
         { 0x55c5d1f8, 0x04cd, 0x46b5, { 0x8a, 0x20, 0xe5, 0x6c, 0xbb, 0x30, 0x52, 0xd0 } }
 
-static EFIAPI EFI_STATUS security_hook(
-                const SecurityOverride *this, uint32_t authentication_status, const EFI_DEVICE_PATH *file) {
+typedef struct {
+        const void *addr;
+        size_t len;
+        const EFI_DEVICE_PATH *device_path;
+} ValidationContext;
 
-        assert(this);
-        assert(this->hook == security_hook);
+static bool validate_payload(
+                const void *ctx, const EFI_DEVICE_PATH *device_path, const void *file_buffer, size_t file_size) {
 
-        if (file == this->payload_device_path)
-                return EFI_SUCCESS;
+        const ValidationContext *payload = ASSERT_PTR(ctx);
 
-        return this->original_security->FileAuthenticationState(
-                        this->original_security, authentication_status, file);
-}
-
-static EFIAPI EFI_STATUS security2_hook(
-                const SecurityOverride *this,
-                const EFI_DEVICE_PATH *device_path,
-                void *file_buffer,
-                size_t file_size,
-                BOOLEAN boot_policy) {
-
-        assert(this);
-        assert(this->hook == security2_hook);
+        if (device_path != payload->device_path)
+                return false;
 
-        if (file_buffer == this->payload && file_size == this->payload_len &&
-            device_path == this->payload_device_path)
-                return EFI_SUCCESS;
+        /* Security arch (1) protocol does not provide a file buffer. Instead we are supposed to fetch the payload
+         * ourselves, which is not needed as we already have everything in memory and the device paths match. */
+        if (file_buffer && (file_buffer != payload->addr || file_size != payload->len))
+                return false;
 
-        return this->original_security2->FileAuthentication(
-                        this->original_security2, device_path, file_buffer, file_size, boot_policy);
+        return true;
 }
 
 static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len, EFI_HANDLE *ret_image) {
@@ -79,19 +70,13 @@ static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len,
 
         /* We want to support unsigned kernel images as payload, which is safe to do under secure boot
          * because it is embedded in this stub loader (and since it is already running it must be trusted). */
-        SecurityOverride security_override = {
-                .hook = security_hook,
-                .payload = source,
-                .payload_len = len,
-                .payload_device_path = &payload_device_path.payload.Header,
-        }, security2_override = {
-                .hook = security2_hook,
-                .payload = source,
-                .payload_len = len,
-                .payload_device_path = &payload_device_path.payload.Header,
-        };
-
-        install_security_override(&security_override, &security2_override);
+        install_security_override(
+                        validate_payload,
+                        &(ValidationContext) {
+                                .addr = source,
+                                .len = len,
+                                .device_path = &payload_device_path.payload.Header,
+                        });
 
         EFI_STATUS ret = BS->LoadImage(
                         /*BootPolicy=*/false,
@@ -101,7 +86,7 @@ static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len,
                         len,
                         ret_image);
 
-        uninstall_security_override(&security_override, &security2_override);
+        uninstall_security_override();
 
         return ret;
 }
index 171b2c96b37d9b8e3dfbb0611f503b774e221cad..65457bf4232efc3b65bf2fcf285dd48749f053ce 100644 (file)
@@ -127,69 +127,91 @@ out_deallocate:
         return err;
 }
 
-static EFI_STATUS install_security_override_one(EFI_GUID guid, SecurityOverride *override) {
-        EFI_STATUS err;
-
-        assert(override);
-
-        _cleanup_free_ EFI_HANDLE *handles = NULL;
-        size_t n_handles = 0;
+static struct SecurityOverride {
+        EFI_SECURITY_ARCH_PROTOCOL *security;
+        EFI_SECURITY2_ARCH_PROTOCOL *security2;
+        EFI_SECURITY_FILE_AUTHENTICATION_STATE original_hook;
+        EFI_SECURITY2_FILE_AUTHENTICATION original_hook2;
+
+        security_validator_t validator;
+        const void *validator_ctx;
+} security_override;
+
+static EFIAPI EFI_STATUS security_hook(
+                const EFI_SECURITY_ARCH_PROTOCOL *this,
+                uint32_t authentication_status,
+                const EFI_DEVICE_PATH *file) {
+
+        assert(security_override.validator);
+        assert(security_override.security);
+        assert(security_override.original_hook);
+
+        if (security_override.validator(security_override.validator_ctx, file, NULL, 0))
+                return EFI_SUCCESS;
 
-        err = BS->LocateHandleBuffer(ByProtocol, &guid, NULL, &n_handles, &handles);
-        if (err != EFI_SUCCESS)
-                /* No security arch protocol around? */
-                return err;
+        return security_override.original_hook(security_override.security, authentication_status, file);
+}
 
-        /* There should only ever be one security arch protocol instance, but let's be paranoid here. */
-        assert(n_handles == 1);
+static EFIAPI EFI_STATUS security2_hook(
+                const EFI_SECURITY2_ARCH_PROTOCOL *this,
+                const EFI_DEVICE_PATH *device_path,
+                void *file_buffer,
+                size_t file_size,
+                BOOLEAN boot_policy) {
 
-        void *security = NULL;
-        err = BS->LocateProtocol(&guid, NULL, &security);
-        if (err != EFI_SUCCESS)
-                return log_error_status_stall(err, u"Error getting security arch protocol: %r", err);
+        assert(security_override.validator);
+        assert(security_override.security2);
+        assert(security_override.original_hook2);
 
-        err = BS->ReinstallProtocolInterface(handles[0], &guid, security, override);
-        if (err != EFI_SUCCESS)
-                return log_error_status_stall(err, u"Error overriding security arch protocol: %r", err);
+        if (security_override.validator(security_override.validator_ctx, device_path, file_buffer, file_size))
+                return EFI_SUCCESS;
 
-        override->original = security;
-        override->original_handle = handles[0];
-        return EFI_SUCCESS;
+        return security_override.original_hook2(
+                        security_override.security2, device_path, file_buffer, file_size, boot_policy);
 }
 
-/* This replaces the platform provided security arch protocols (defined in the UEFI Platform Initialization
- * Specification) with the provided override instances. If not running in secure boot or the protocols are
- * not available nothing happens. The override instances are provided with the necessary info to undo this
- * in uninstall_security_override(). */
-void install_security_override(SecurityOverride *override, SecurityOverride *override2) {
-        assert(override);
-        assert(override2);
+/* This replaces the platform provided security arch protocols hooks (defined in the UEFI Platform
+ * Initialization Specification) with our own that uses the given validator to decide if a image is to be
+ * trusted. If not running in secure boot or the protocols are not available nothing happens. The override
+ * must be removed with uninstall_security_override() after LoadImage() has been called.
+ *
+ * This is a hack as we do not own the security protocol instances and modifying them is not an official part
+ * of their spec. But there is little else we can do to circumvent secure boot short of implementing our own
+ * PE loader. We could replace the firmware instances with our own instance using
+ * ReinstallProtocolInterface(), but some firmware will still use the old ones. */
+void install_security_override(security_validator_t validator, const void *validator_ctx) {
+        EFI_STATUS err;
+
+        assert(validator);
 
         if (!secure_boot_enabled())
                 return;
 
-        (void) install_security_override_one((EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID, override);
-        (void) install_security_override_one((EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID, override2);
+        security_override = (struct SecurityOverride) {
+                .validator = validator,
+                .validator_ctx = validator_ctx,
+        };
+
+        EFI_SECURITY_ARCH_PROTOCOL *security = NULL;
+        err = BS->LocateProtocol(&(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID, NULL, (void **) &security);
+        if (err == EFI_SUCCESS) {
+                security_override.security = security;
+                security_override.original_hook = security->FileAuthenticationState;
+                security->FileAuthenticationState = security_hook;
+        }
+
+        EFI_SECURITY2_ARCH_PROTOCOL *security2 = NULL;
+        err = BS->LocateProtocol(&(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID, NULL, (void **) &security2);
+        if (err == EFI_SUCCESS) {
+                security_override.security2 = security2;
+                security_override.original_hook2 = security2->FileAuthentication;
+                security2->FileAuthentication = security2_hook;
+        }
 }
 
-void uninstall_security_override(SecurityOverride *override, SecurityOverride *override2) {
-        assert(override);
-        assert(override2);
-
-        /* We use assert_se here to guarantee the system is not in a weird state in the unlikely case of an
-         * error restoring the original protocols. */
-
-        if (override->original_handle)
-                assert_se(BS->ReinstallProtocolInterface(
-                                          override->original_handle,
-                                          &(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID,
-                                          override,
-                                          override->original) == EFI_SUCCESS);
-
-        if (override2->original_handle)
-                assert_se(BS->ReinstallProtocolInterface(
-                                          override2->original_handle,
-                                          &(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID,
-                                          override2,
-                                          override2->original) == EFI_SUCCESS);
+void uninstall_security_override(void) {
+        if (security_override.original_hook)
+                security_override.security->FileAuthenticationState = security_override.original_hook;
+        if (security_override.original_hook2)
+                security_override.security2->FileAuthentication = security_override.original_hook2;
 }
index 91b6770edb599f0c83d7bea55b9e987ce66afffd..e98de81c2a5b6675d4d23aa75ecabc9a1a0ea3cd 100644 (file)
@@ -17,23 +17,11 @@ SecureBootMode secure_boot_mode(void);
 
 EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path);
 
-typedef struct {
-        void *hook;
-
-        /* End of EFI_SECURITY_ARCH(2)_PROTOCOL. The rest is our own protocol instance data. */
-
-        EFI_HANDLE original_handle;
-        union {
-                void *original;
-                EFI_SECURITY_ARCH_PROTOCOL *original_security;
-                EFI_SECURITY2_ARCH_PROTOCOL *original_security2;
-        };
-
-        /* Used by the stub to identify the embedded image. */
-        const void *payload;
-        size_t payload_len;
-        const EFI_DEVICE_PATH *payload_device_path;
-} SecurityOverride;
-
-void install_security_override(SecurityOverride *override, SecurityOverride *override2);
-void uninstall_security_override(SecurityOverride *override, SecurityOverride *override2);
+typedef bool (*security_validator_t)(
+                const void *ctx,
+                const EFI_DEVICE_PATH *device_path,
+                const void *file_buffer,
+                size_t file_size);
+
+void install_security_override(security_validator_t validator, const void *validator_ctx);
+void uninstall_security_override(void);
index 3ae058cb846d1acb52bdcb104951463fddd58844..ac224336bccdb181af3c19da171fc99687849411 100644 (file)
@@ -23,7 +23,7 @@
 #endif
 
 struct ShimLock {
-        EFI_STATUS __sysv_abi__ (*shim_verify) (void *buffer, uint32_t size);
+        EFI_STATUS __sysv_abi__ (*shim_verify) (const void *buffer, uint32_t size);
 
         /* context is actually a struct for the PE header, but it isn't needed so void is sufficient just do define the interface
          * see shim.c/shim.h and PeHeader.h in the github shim repo */
@@ -41,79 +41,45 @@ bool shim_loaded(void) {
         return BS->LocateProtocol((EFI_GUID*) SHIM_LOCK_GUID, NULL, (void**) &shim_lock) == EFI_SUCCESS;
 }
 
-static bool shim_validate(void *data, uint32_t size) {
-        struct ShimLock *shim_lock;
-
-        if (!data)
-                return false;
-
-        if (BS->LocateProtocol((EFI_GUID*) SHIM_LOCK_GUID, NULL, (void**) &shim_lock) != EFI_SUCCESS)
-                return false;
-
-        if (!shim_lock)
-                return false;
-
-        return shim_lock->shim_verify(data, size) == EFI_SUCCESS;
-}
-
-static EFIAPI EFI_STATUS security2_hook(
-                const SecurityOverride *this,
-                const EFI_DEVICE_PATH *device_path,
-                void *file_buffer,
-                UINTN file_size,
-                BOOLEAN boot_policy) {
-
-        assert(this);
-        assert(this->hook == security2_hook);
-
-        if (shim_validate(file_buffer, file_size))
-                return EFI_SUCCESS;
-
-        return this->original_security2->FileAuthentication(
-                        this->original_security2, device_path, file_buffer, file_size, boot_policy);
-}
-
-static EFIAPI EFI_STATUS security_hook(
-                const SecurityOverride *this,
-                uint32_t authentication_status,
-                const EFI_DEVICE_PATH *device_path) {
+static bool shim_validate(
+                const void *ctx, const EFI_DEVICE_PATH *device_path, const void *file_buffer, size_t file_size) {
 
         EFI_STATUS err;
+        _cleanup_free_ char *file_buffer_owned = NULL;
 
-        assert(this);
-        assert(this->hook == security_hook);
+        if (!file_buffer) {
+                if (!device_path)
+                        return false;
 
-        if (!device_path)
-                return this->original_security->FileAuthenticationState(
-                                this->original_security, authentication_status, device_path);
+                EFI_HANDLE device_handle;
+                EFI_DEVICE_PATH *file_dp = (EFI_DEVICE_PATH *) device_path;
+                err = BS->LocateDevicePath(&FileSystemProtocol, &file_dp, &device_handle);
+                if (err != EFI_SUCCESS)
+                        return false;
 
-        EFI_HANDLE device_handle;
-        EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *) device_path;
-        err = BS->LocateDevicePath(&FileSystemProtocol, &dp, &device_handle);
-        if (err != EFI_SUCCESS)
-                return err;
+                _cleanup_(file_closep) EFI_FILE *root = NULL;
+                err = open_volume(device_handle, &root);
+                if (err != EFI_SUCCESS)
+                        return false;
 
-        _cleanup_(file_closep) EFI_FILE *root = NULL;
-        err = open_volume(device_handle, &root);
-        if (err != EFI_SUCCESS)
-                return err;
+                _cleanup_free_ char16_t *dp_str = NULL;
+                err = device_path_to_str(file_dp, &dp_str);
+                if (err != EFI_SUCCESS)
+                        return false;
 
-        _cleanup_free_ char16_t *dp_str = NULL;
-        err = device_path_to_str(dp, &dp_str);
-        if (err != EFI_SUCCESS)
-                return err;
+                err = file_read(root, dp_str, 0, 0, &file_buffer_owned, &file_size);
+                if (err != EFI_SUCCESS)
+                        return false;
 
-        char *file_buffer;
-        size_t file_size;
-        err = file_read(root, dp_str, 0, 0, &file_buffer, &file_size);
-        if (err != EFI_SUCCESS)
-                return err;
+                file_buffer = file_buffer_owned;
+        }
 
-        if (shim_validate(file_buffer, file_size))
-                return EFI_SUCCESS;
+        struct ShimLock *shim_lock;
+        err = BS->LocateProtocol((EFI_GUID *) SHIM_LOCK_GUID, NULL, (void **) &shim_lock);
+        if (err != EFI_SUCCESS)
+                return false;
 
-        return this->original_security->FileAuthenticationState(
-                        this->original_security, authentication_status, device_path);
+        return shim_lock->shim_verify(file_buffer, file_size) == EFI_SUCCESS;
 }
 
 EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path, EFI_HANDLE *ret_image) {
@@ -122,20 +88,14 @@ EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path
 
         bool have_shim = shim_loaded();
 
-        SecurityOverride security_override = {
-                .hook = security_hook,
-        }, security2_override = {
-                .hook = security2_hook,
-        };
-
         if (have_shim)
-                install_security_override(&security_override, &security2_override);
+                install_security_override(shim_validate, NULL);
 
         EFI_STATUS ret = BS->LoadImage(
                         /*BootPolicy=*/false, parent, (EFI_DEVICE_PATH *) device_path, NULL, 0, ret_image);
 
         if (have_shim)
-                uninstall_security_override(&security_override, &security2_override);
+                uninstall_security_override();
 
         return ret;
 }
index 5547d288de1b2bb5bc07e17476b4d6696bd7f689..57436dbf0cada22b0cc9801abd223aefc1ac6a54 100644 (file)
@@ -772,19 +772,51 @@ EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DE
 EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret) {
         EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *dp_to_text;
         EFI_STATUS err;
+        _cleanup_free_ char16_t *str = NULL;
 
         assert(dp);
         assert(ret);
 
         err = BS->LocateProtocol(&(EFI_GUID) EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, NULL, (void **) &dp_to_text);
-        if (err != EFI_SUCCESS)
-                return err;
+        if (err != EFI_SUCCESS) {
+                /* If the device path to text protocol is not available we can still do a best-effort attempt
+                 * to convert it ourselves if we are given filepath-only device path. */
+
+                size_t size = 0;
+                for (const EFI_DEVICE_PATH *node = dp; !IsDevicePathEnd(node);
+                     node = NextDevicePathNode(node)) {
+
+                        if (DevicePathType(node) != MEDIA_DEVICE_PATH ||
+                            DevicePathSubType(node) != MEDIA_FILEPATH_DP)
+                                return err;
+
+                        size_t path_size = DevicePathNodeLength(node);
+                        if (path_size <= offsetof(FILEPATH_DEVICE_PATH, PathName) || path_size % sizeof(char16_t))
+                                return EFI_INVALID_PARAMETER;
+                        path_size -= offsetof(FILEPATH_DEVICE_PATH, PathName);
+
+                        _cleanup_free_ char16_t *old = str;
+                        str = xmalloc(size + path_size);
+                        if (old) {
+                                memcpy(str, old, size);
+                                str[size / sizeof(char16_t) - 1] = '\\';
+                        }
+
+                        memcpy(str + (size / sizeof(char16_t)),
+                               ((uint8_t *) node) + offsetof(FILEPATH_DEVICE_PATH, PathName),
+                               path_size);
+                        size += path_size;
+                }
+
+                *ret = TAKE_PTR(str);
+                return EFI_SUCCESS;
+        }
 
-        char16_t *str = dp_to_text->ConvertDevicePathToText(dp, false, false);
+        str = dp_to_text->ConvertDevicePathToText(dp, false, false);
         if (!str)
                 return EFI_OUT_OF_RESOURCES;
 
-        *ret = str;
+        *ret = TAKE_PTR(str);
         return EFI_SUCCESS;
 }
 
index 4f16acedf063ef4fefb487b99a33efcefc0a2b45..0bbd3864493cda75ad2743d8812dbaad670842e3 100644 (file)
@@ -897,7 +897,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
                         }
 
                         _cleanup_free_ void *sig = malloc(ss);
-                        if (!ss) {
+                        if (!sig) {
                                 r = log_oom();
                                 goto finish;
                         }
index c69baa8a1a7ac31d9f9898d62fe984a30de8d283..c1744cff92da4369e43abeeb9f327900f5cd4cf7 100644 (file)
@@ -113,9 +113,9 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
 
                 if (r >= 0) {
                         if (type == SELINUX_AVC)
-                                audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0);
+                                audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, getuid());
                         else if (type == SELINUX_ERROR)
-                                audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_SELINUX_ERR, buf, NULL, NULL, NULL, 0);
+                                audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_SELINUX_ERR, buf, NULL, NULL, NULL, getuid());
 
                         return 0;
                 }
index 8bd430b931d1d540b8518d4c618391f88f7d09ff..b6810c8599b836833d32548a8f11703a709efe39 100644 (file)
@@ -948,11 +948,11 @@ static int activation_details_timer_append_env(ActivationDetails *details, char
         if (!dual_timestamp_is_set(&t->last_trigger))
                 return 0;
 
-        r = strv_extendf(strv, "TRIGGER_TIMER_REALTIME_USEC=%" USEC_FMT, t->last_trigger.realtime);
+        r = strv_extendf(strv, "TRIGGER_TIMER_REALTIME_USEC=" USEC_FMT, t->last_trigger.realtime);
         if (r < 0)
                 return r;
 
-        r = strv_extendf(strv, "TRIGGER_TIMER_MONOTONIC_USEC=%" USEC_FMT, t->last_trigger.monotonic);
+        r = strv_extendf(strv, "TRIGGER_TIMER_MONOTONIC_USEC=" USEC_FMT, t->last_trigger.monotonic);
         if (r < 0)
                 return r;
 
@@ -974,7 +974,7 @@ static int activation_details_timer_append_pair(ActivationDetails *details, char
         if (r < 0)
                 return r;
 
-        r = strv_extendf(strv, "%" USEC_FMT, t->last_trigger.realtime);
+        r = strv_extendf(strv, USEC_FMT, t->last_trigger.realtime);
         if (r < 0)
                 return r;
 
@@ -982,7 +982,7 @@ static int activation_details_timer_append_pair(ActivationDetails *details, char
         if (r < 0)
                 return r;
 
-        r = strv_extendf(strv, "%" USEC_FMT, t->last_trigger.monotonic);
+        r = strv_extendf(strv, USEC_FMT, t->last_trigger.monotonic);
         if (r < 0)
                 return r;
 
index 712ab3ffa9ea730b0a78aacdd7dc7bede8806599..10956cc5482b4ecd4d5251db50347039e09b4ab0 100644 (file)
@@ -55,7 +55,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 
         size_t sw_alloc = MAX(h->sw_alloc, 1u);
         buf2 = malloc(sw_alloc);
-        if (!buf) {
+        if (!buf2) {
                 log_oom();
                 return 0;
         }
index 378bf162ca92086b07fbc757df37a31f25687b1c..b3ae4b814375fb7cf2b5ae9f39611af119239b3e 100644 (file)
@@ -158,7 +158,6 @@ static void test_skip_one(void (*setup)(void)) {
          */
         assert_ret(sd_journal_open_directory(&j, t, 0));
         assert_ret(sd_journal_seek_head(j));
-        assert_ret(sd_journal_previous(j) == 0);
         assert_ret(sd_journal_next(j));
         test_check_numbers_down(j, 4);
         sd_journal_close(j);
@@ -167,7 +166,6 @@ static void test_skip_one(void (*setup)(void)) {
          */
         assert_ret(sd_journal_open_directory(&j, t, 0));
         assert_ret(sd_journal_seek_tail(j));
-        assert_ret(sd_journal_next(j) == 0);
         assert_ret(sd_journal_previous(j));
         test_check_numbers_up(j, 4);
         sd_journal_close(j);
@@ -176,7 +174,6 @@ static void test_skip_one(void (*setup)(void)) {
          */
         assert_ret(sd_journal_open_directory(&j, t, 0));
         assert_ret(sd_journal_seek_tail(j));
-        assert_ret(sd_journal_next(j) == 0);
         assert_ret(r = sd_journal_previous_skip(j, 4));
         assert_se(r == 4);
         test_check_numbers_down(j, 4);
@@ -186,7 +183,6 @@ static void test_skip_one(void (*setup)(void)) {
          */
         assert_ret(sd_journal_open_directory(&j, t, 0));
         assert_ret(sd_journal_seek_head(j));
-        assert_ret(sd_journal_previous(j) == 0);
         assert_ret(r = sd_journal_next_skip(j, 4));
         assert_se(r == 4);
         test_check_numbers_up(j, 4);
index 22eb4d2be144c30d73d086b2eb65efe68fe44452..fa2c0d5276aca016ea9478a7a6ed7481bbb209e9 100755 (executable)
@@ -158,8 +158,9 @@ if [ -z "$MACHINE_ID" ] && [ -f /etc/machine-info ]; then
     [ -n "$MACHINE_ID" ] && \
         log_verbose "machine-id $MACHINE_ID acquired from /etc/machine-info"
 fi
-if [ -z "$MACHINE_ID" ] && [ -f /etc/machine-id ]; then
+if [ -z "$MACHINE_ID" ] && [ -s /etc/machine-id ]; then
     read -r MACHINE_ID </etc/machine-id
+    [ "$MACHINE_ID" = "uninitialized" ] && unset MACHINE_ID
     [ -n "$MACHINE_ID" ] && \
         log_verbose "machine-id $MACHINE_ID acquired from /etc/machine-id"
 fi
index 3803a2c4c4b4df64b24d7c4bfc973a65e4a71479..bc716afabfac9f9d2fa2f78342a02952802bb79f 100644 (file)
@@ -3529,7 +3529,7 @@ static int bus_add_match_full(
                                                                  s);
 
                                 if (r < 0)
-                                        return r;
+                                        goto finish;
 
                                 /* Make the slot of the match call floating now. We need the reference, but we don't
                                  * want that this match pins the bus object, hence we first create it non-floating, but
index 53c0b2a01e93f6b2baf86afca650f6c4d6825f0e..1e4d128f051c025a2ab833091a8a79d2c1dab430 100644 (file)
@@ -606,9 +606,9 @@ static int find_location_for_match(
                 /* FIXME: missing: find by monotonic */
 
                 if (j->current_location.type == LOCATION_HEAD)
-                        return direction == DIRECTION_DOWN ? journal_file_next_entry_for_data(f, d, DIRECTION_DOWN, ret, offset) : 0;
+                        return journal_file_next_entry_for_data(f, d, DIRECTION_DOWN, ret, offset);
                 if (j->current_location.type == LOCATION_TAIL)
-                        return direction == DIRECTION_UP ? journal_file_next_entry_for_data(f, d, DIRECTION_UP, ret, offset) : 0;
+                        return journal_file_next_entry_for_data(f, d, DIRECTION_UP, ret, offset);
                 if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
                         return journal_file_move_to_entry_by_seqnum_for_data(f, d, j->current_location.seqnum, direction, ret, offset);
                 if (j->current_location.monotonic_set) {
@@ -701,9 +701,9 @@ static int find_location_with_matches(
                 /* No matches is simple */
 
                 if (j->current_location.type == LOCATION_HEAD)
-                        return direction == DIRECTION_DOWN ? journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset) : 0;
+                        return journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset);
                 if (j->current_location.type == LOCATION_TAIL)
-                        return direction == DIRECTION_UP ? journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset) : 0;
+                        return journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset);
                 if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
                         return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset);
                 if (j->current_location.monotonic_set) {
index 4127657ebd82c805b5a28c78cd8918ee92c20d92..877dee00ec4a35f649c1c41bd9e2dd81704b838f 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include <linux/if_arp.h>
+#include <net/if.h> /* IFF_LOOPBACK */
+#include <net/if_arp.h> /* ARPHRD_ETHER */
 
 #include "sd-dhcp-client.h"
 #include "sd-ipv4acd.h"
index 00e4e451ef3ceb695f1c1266156c9700ecdde725..788c7957d3c2dec01d2b71c6e6506737e581b006 100644 (file)
@@ -1178,7 +1178,7 @@ static int link_get_network(Link *link, Network **ret) {
         return -ENOENT;
 }
 
-static int link_reconfigure_impl(Link *link, bool force) {
+int link_reconfigure_impl(Link *link, bool force) {
         Network *network = NULL;
         NetDev *netdev = NULL;
         int r;
index 9f1cdca31272a2153b3132d8bd029d848edf0988..65b01641061cb89425f5792e1acbe76142ea6d87 100644 (file)
@@ -234,6 +234,7 @@ int link_stop_engines(Link *link, bool may_keep_dhcp);
 const char* link_state_to_string(LinkState s) _const_;
 LinkState link_state_from_string(const char *s) _pure_;
 
+int link_reconfigure_impl(Link *link, bool force);
 int link_reconfigure(Link *link, bool force);
 int link_reconfigure_after_sleep(Link *link);
 
index 4bf798a9eb01162b71dc837655a01f2882c29cb6..62cbca0cf99d20276448e52b171f55d360f0b233 100644 (file)
@@ -269,6 +269,18 @@ int manager_genl_process_nl80211_mlme(sd_netlink *genl, sd_netlink_message *mess
                 if (link->wlan_iftype == NL80211_IFTYPE_STATION && link->ssid)
                         log_link_info(link, "Connected WiFi access point: %s (%s)",
                                       link->ssid, ETHER_ADDR_TO_STR(&link->bssid));
+
+                /* Sometimes, RTM_NEWLINK message with carrier is received earlier than NL80211_CMD_CONNECT.
+                 * To make SSID= or other WiFi related settings in [Match] section work, let's try to
+                 * reconfigure the interface. */
+                if (link->ssid && link_has_carrier(link)) {
+                        r = link_reconfigure_impl(link, /* force = */ false);
+                        if (r < 0) {
+                                log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
+                                link_enter_failed(link);
+                                return 0;
+                        }
+                }
                 break;
         }
         case NL80211_CMD_DISCONNECT:
index 77f4c2ac88e2c42fb21c04daa21fe3808b8ac290..27044fadd2a877083d651725a46238ae9333dd34 100644 (file)
@@ -88,6 +88,7 @@ static int add_syscall_filters(
                 { 0,                  "sched_getparam"         },
                 { 0,                  "sched_getscheduler"     },
                 { 0,                  "sched_rr_get_interval"  },
+                { 0,                  "sched_rr_get_interval_time64" },
                 { 0,                  "sched_yield"            },
                 { 0,                  "seccomp"                },
                 { 0,                  "sendfile"               },
index 1fc81d184341723d3729a1f4fb15b524e15571e8..70a1dc941e6d75e201c91df37abac1a4890b3024 100644 (file)
@@ -164,7 +164,7 @@ int oomd_fetch_cgroup_oom_preference(OomdCGroupContext *ctx, const char *prefix)
         if (r < 0)
                 return log_debug_errno(r, "Failed to get owner/group from %s: %m", ctx->path);
 
-        if (uid == prefix_uid) {
+        if (uid == prefix_uid || uid == 0) {
                 /* Ignore most errors when reading the xattr since it is usually unset and cgroup xattrs are only used
                  * as an optional feature of systemd-oomd (and the system might not even support them). */
                 r = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, ctx->path, "user.oomd_avoid");
index 176e3a8d691226dc05f64d00616c7e2166ece24b..faa75c55788f874f4adc7576c0fae232cfe4da5e 100644 (file)
@@ -475,9 +475,9 @@ static void test_oomd_fetch_cgroup_oom_preference(void) {
 
         /* Assert that avoid/omit are not set if the cgroup and prefix are not
          * owned by the same user.*/
-        if (test_xattrs && !empty_or_root(ctx->path)) {
+        if (test_xattrs && !empty_or_root(cgroup)) {
                 ctx = oomd_cgroup_context_free(ctx);
-                assert_se(cg_set_access(SYSTEMD_CGROUP_CONTROLLER, cgroup, 65534, 0) >= 0);
+                assert_se(cg_set_access(SYSTEMD_CGROUP_CONTROLLER, cgroup, 61183, 0) >= 0);
                 assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
 
                 assert_se(oomd_fetch_cgroup_oom_preference(ctx, NULL) == 0);
index 8e3cfece89d98da62a6798401734eab5c94950eb..c4ca9840c85d811a127e739d97a02f2d080dc9c7 100644 (file)
@@ -4387,13 +4387,15 @@ static int context_write_partition_table(
 
                 log_info("Wiped block device.");
 
-                r = context_discard_range(context, 0, context->total);
-                if (r == -EOPNOTSUPP)
-                        log_info("Storage does not support discard, not discarding entire block device data.");
-                else if (r < 0)
-                        return log_error_errno(r, "Failed to discard entire block device: %m");
-                else if (r > 0)
-                        log_info("Discarded entire block device.");
+                if (arg_discard) {
+                        r = context_discard_range(context, 0, context->total);
+                        if (r == -EOPNOTSUPP)
+                                log_info("Storage does not support discard, not discarding entire block device data.");
+                        else if (r < 0)
+                                return log_error_errno(r, "Failed to discard entire block device: %m");
+                        else if (r > 0)
+                                log_info("Discarded entire block device.");
+                }
         }
 
         r = fdisk_get_partitions(context->fdisk_context, &original_table);
index be906f786cd385f958878df2f1493472b9ee2791..fbc44970148815e0076c09a2a3ca9baf5b36bf65 100644 (file)
@@ -1131,7 +1131,7 @@ static int attach_unit_file(
         (void) mkdir_parents(where, 0755);
         if (mkdir(where, 0755) < 0) {
                 if (errno != EEXIST)
-                        return -errno;
+                        return log_debug_errno(errno, "Failed to create attach directory %s: %m", where);
         } else
                 (void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, where, NULL);
 
@@ -1145,7 +1145,7 @@ static int attach_unit_file(
 
         if (mkdir(dropin_dir, 0755) < 0) {
                 if (errno != EEXIST)
-                        return -errno;
+                        return log_debug_errno(errno, "Failed to create drop-in directory %s: %m", dropin_dir);
         } else
                 (void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, dropin_dir, NULL);
 
@@ -1392,7 +1392,7 @@ int portable_attach(
                 r = attach_unit_file(&paths, image->path, image->type, extension_images,
                                      item, profile, flags, changes, n_changes);
                 if (r < 0)
-                        return r;
+                        return sd_bus_error_set_errnof(error, r, "Failed to attach unit '%s': %m", item->name);
         }
 
         /* We don't care too much for the image symlink, it's just a convenience thing, it's not necessary for proper
index 852829569ddf014988c7df0153325b4800ac2d57..4f744499aabc66293d44e564acb02d9860bca065 100644 (file)
@@ -424,7 +424,7 @@ static int dns_scope_socket(
                         return r;
         }
 
-        if (s->link) {
+        if (ifindex != 0) {
                 r = socket_set_unicast_if(fd, sa.sa.sa_family, ifindex);
                 if (r < 0)
                         return r;
index 04a4f53ed0aced288df19d799e1173d825fe37d6..8ff513fa33f08c62d9790138961d2d3a9d976185 100644 (file)
@@ -648,6 +648,11 @@ int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeature
 int dns_server_ifindex(const DnsServer *s) {
         assert(s);
 
+        /* For loopback addresses, go via the loopback interface, regardless which interface this is linked
+         * to. */
+        if (in_addr_is_localhost(s->family, &s->address))
+                return LOOPBACK_IFINDEX;
+
         /* The link ifindex always takes precedence */
         if (s->link)
                 return s->link->ifindex;
index 4d3a88c8dafcedde4275c84ba528fc82c7b035c4..4a0132ad3d8fe83f313a51fa4877b19277b879b3 100644 (file)
 #include "resolved-dnstls.h"
 #include "resolved-manager.h"
 
+static char *dnstls_error_string(int ssl_error, char *buf, size_t count) {
+        assert(buf || count == 0);
+        if (ssl_error == SSL_ERROR_SSL)
+                ERR_error_string_n(ERR_get_error(), buf, count);
+        else
+                snprintf(buf, count, "SSL_get_error()=%d", ssl_error);
+        return buf;
+}
+
+#define DNSTLS_ERROR_BUFSIZE 256
+#define DNSTLS_ERROR_STRING(error) \
+        dnstls_error_string((error), (char[DNSTLS_ERROR_BUFSIZE]){}, DNSTLS_ERROR_BUFSIZE)
+
 static int dnstls_flush_write_buffer(DnsStream *stream) {
         ssize_t ss;
 
@@ -97,26 +110,18 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
 
         if (server->server_name) {
                 r = SSL_set_tlsext_host_name(s, server->server_name);
-                if (r <= 0) {
-                        char errbuf[256];
-
-                        error = ERR_get_error();
-                        ERR_error_string_n(error, errbuf, sizeof(errbuf));
-                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set server name: %s", errbuf);
-                }
+                if (r <= 0)
+                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "Failed to set server name: %s", DNSTLS_ERROR_STRING(SSL_ERROR_SSL));
         }
 
         ERR_clear_error();
         stream->dnstls_data.handshake = SSL_do_handshake(s);
         if (stream->dnstls_data.handshake <= 0) {
                 error = SSL_get_error(s, stream->dnstls_data.handshake);
-                if (!IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) {
-                        char errbuf[256];
-
-                        ERR_error_string_n(error, errbuf, sizeof(errbuf));
+                if (!IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE))
                         return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED),
-                                               "Failed to invoke SSL_do_handshake: %s", errbuf);
-                }
+                                               "Failed to invoke SSL_do_handshake: %s", DNSTLS_ERROR_STRING(error));
         }
 
         stream->encrypted = true;
@@ -177,12 +182,8 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) {
                         } else if (error == SSL_ERROR_SYSCALL) {
                                 if (errno > 0)
                                         log_debug_errno(errno, "Failed to invoke SSL_shutdown, ignoring: %m");
-                        } else {
-                                char errbuf[256];
-
-                                ERR_error_string_n(error, errbuf, sizeof(errbuf));
-                                log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf);
-                        }
+                        } else
+                                log_debug("Failed to invoke SSL_shutdown, ignoring: %s", DNSTLS_ERROR_STRING(error));
                 }
 
                 stream->dnstls_events = 0;
@@ -206,14 +207,10 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) {
                                         return r;
 
                                 return -EAGAIN;
-                        } else {
-                                char errbuf[256];
-
-                                ERR_error_string_n(error, errbuf, sizeof(errbuf));
+                        } else
                                 return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED),
                                                        "Failed to invoke SSL_do_handshake: %s",
-                                                       errbuf);
-                        }
+                                                       DNSTLS_ERROR_STRING(error));
                 }
 
                 stream->dnstls_events = 0;
@@ -275,12 +272,8 @@ int dnstls_stream_shutdown(DnsStream *stream, int error) {
                         } else if (ssl_error == SSL_ERROR_SYSCALL) {
                                 if (errno > 0)
                                         log_debug_errno(errno, "Failed to invoke SSL_shutdown, ignoring: %m");
-                        } else {
-                                char errbuf[256];
-
-                                ERR_error_string_n(ssl_error, errbuf, sizeof(errbuf));
-                                log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf);
-                        }
+                        } else
+                                log_debug("Failed to invoke SSL_shutdown, ignoring: %s", DNSTLS_ERROR_STRING(ssl_error));
                 }
 
                 stream->dnstls_events = 0;
@@ -307,10 +300,7 @@ static ssize_t dnstls_stream_write(DnsStream *stream, const char *buf, size_t co
                         stream->dnstls_events = 0;
                         ss = 0;
                 } else {
-                        char errbuf[256];
-
-                        ERR_error_string_n(error, errbuf, sizeof(errbuf));
-                        log_debug("Failed to invoke SSL_write: %s", errbuf);
+                        log_debug("Failed to invoke SSL_write: %s", DNSTLS_ERROR_STRING(error));
                         stream->dnstls_events = 0;
                         ss = -EPIPE;
                 }
@@ -375,10 +365,7 @@ ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) {
                         stream->dnstls_events = 0;
                         ss = 0;
                 } else {
-                        char errbuf[256];
-
-                        ERR_error_string_n(error, errbuf, sizeof(errbuf));
-                        log_debug("Failed to invoke SSL_read: %s", errbuf);
+                        log_debug("Failed to invoke SSL_read: %s", DNSTLS_ERROR_STRING(error));
                         stream->dnstls_events = 0;
                         ss = -EPIPE;
                 }
index 6a34b10c044c3c403e9295d5fcaf962cacde7399..d3cfb41a12beebfd8e2167d0cf5b520274ebc73f 100644 (file)
@@ -994,6 +994,12 @@ static int boot_config_find(const BootConfig *config, const char *id) {
         if (!id)
                 return -1;
 
+        if (id[0] == '@') {
+                if (!strcaseeq(id, "@saved"))
+                        return -1;
+                id = config->entry_selected;
+        }
+
         for (size_t i = 0; i < config->n_entries; i++)
                 if (fnmatch(id, config->entries[i].id, FNM_CASEFOLD) == 0)
                         return i;
index 2989d31d3c295ec32b7136914cb9434f492e9363..7676636723566b13ac654c7b69f9b893c41af1be 100644 (file)
@@ -1010,19 +1010,13 @@ static int dissect_image(
                 log_debug("No root partition found of the native architecture, falling back to a root "
                           "partition of the secondary architecture.");
 
-                m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY];
-                zero(m->partitions[PARTITION_ROOT_SECONDARY]);
-                m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY];
-                zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
-                m->partitions[PARTITION_ROOT_VERITY_SIG] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG];
-                zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG]);
-
-                m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
-                zero(m->partitions[PARTITION_USR_SECONDARY]);
-                m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
-                zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
-                m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG];
-                zero(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
+                m->partitions[PARTITION_ROOT] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY]);
+                m->partitions[PARTITION_ROOT_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
+                m->partitions[PARTITION_ROOT_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG]);
+
+                m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY]);
+                m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
+                m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
 
                 m->partitions[PARTITION_ROOT_OTHER].found = false;
                 m->partitions[PARTITION_ROOT_OTHER_VERITY].found = false;
@@ -1044,19 +1038,13 @@ static int dissect_image(
                           "falling back to a root partition of a non-native architecture (%s).",
                           architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture));
 
-                m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_OTHER];
-                zero(m->partitions[PARTITION_ROOT_OTHER]);
-                m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_OTHER_VERITY];
-                zero(m->partitions[PARTITION_ROOT_OTHER_VERITY]);
-                m->partitions[PARTITION_ROOT_VERITY_SIG] = m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG];
-                zero(m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG]);
-
-                m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_OTHER];
-                zero(m->partitions[PARTITION_USR_OTHER]);
-                m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_OTHER_VERITY];
-                zero(m->partitions[PARTITION_USR_OTHER_VERITY]);
-                m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_OTHER_VERITY_SIG];
-                zero(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
+                m->partitions[PARTITION_ROOT] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER]);
+                m->partitions[PARTITION_ROOT_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER_VERITY]);
+                m->partitions[PARTITION_ROOT_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG]);
+
+                m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER]);
+                m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY]);
+                m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
         }
 
         /* Hmm, we found a signature partition but no Verity data? Something is off. */
@@ -1083,12 +1071,9 @@ static int dissect_image(
                           "partition of the secondary architecture.");
 
                 /* Upgrade secondary arch to primary */
-                m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
-                zero(m->partitions[PARTITION_USR_SECONDARY]);
-                m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
-                zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
-                m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG];
-                zero(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
+                m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY]);
+                m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
+                m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
 
                 m->partitions[PARTITION_USR_OTHER].found = false;
                 m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
@@ -1105,12 +1090,9 @@ static int dissect_image(
                           architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture));
 
                 /* Upgrade other arch to primary */
-                m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_OTHER];
-                zero(m->partitions[PARTITION_USR_OTHER]);
-                m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_OTHER_VERITY];
-                zero(m->partitions[PARTITION_USR_OTHER_VERITY]);
-                m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_OTHER_VERITY_SIG];
-                zero(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
+                m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER]);
+                m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY]);
+                m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
         }
 
         /* Hmm, we found a signature partition but no Verity data? Something is off. */
@@ -1327,11 +1309,11 @@ static int is_loop_device(const char *path) {
         return true;
 }
 
-static int run_fsck(const char *node, const char *fstype) {
+static int run_fsck(int node_fd, const char *fstype) {
         int r, exit_status;
         pid_t pid;
 
-        assert(node);
+        assert(node_fd >= 0);
         assert(fstype);
 
         r = fsck_exists_for_fstype(fstype);
@@ -1340,16 +1322,20 @@ static int run_fsck(const char *node, const char *fstype) {
                 return 0;
         }
         if (r == 0) {
-                log_debug("Not checking partition %s, as fsck for %s does not exist.", node, fstype);
+                log_debug("Not checking partition %s, as fsck for %s does not exist.", FORMAT_PROC_FD_PATH(node_fd), fstype);
                 return 0;
         }
 
-        r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_NULL_STDIO, &pid);
+        r = safe_fork_full(
+                        "(fsck)",
+                        &node_fd, 1, /* Leave the node fd open */
+                        FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOEXEC_OFF,
+                        &pid);
         if (r < 0)
                 return log_debug_errno(r, "Failed to fork off fsck: %m");
         if (r == 0) {
                 /* Child */
-                execl("/sbin/fsck", "/sbin/fsck", "-aT", node, NULL);
+                execl("/sbin/fsck", "/sbin/fsck", "-aT", FORMAT_PROC_FD_PATH(node_fd), NULL);
                 log_open();
                 log_debug_errno(errno, "Failed to execl() fsck: %m");
                 _exit(FSCK_OPERATIONAL_ERROR);
@@ -1439,7 +1425,7 @@ static int mount_partition(
         rw = m->rw && !(flags & DISSECT_IMAGE_MOUNT_READ_ONLY);
 
         if (FLAGS_SET(flags, DISSECT_IMAGE_FSCK) && rw) {
-                r = run_fsck(node, fstype);
+                r = run_fsck(m->mount_node_fd, fstype);
                 if (r < 0)
                         return r;
         }
index 8007b544e7a4133b17b7284c5ab8346d7634fea6..f2278c4dfa7e8a19f63c45639bcce891c61a6aa5 100644 (file)
@@ -40,6 +40,12 @@ struct DissectedPartition {
                 .architecture = _ARCHITECTURE_INVALID,                  \
                 .mount_node_fd = -1,                                    \
         })
+#define TAKE_PARTITION(p)                                       \
+        ({                                                      \
+                DissectedPartition *_pp = &(p), _p = *_pp;      \
+                *_pp = DISSECTED_PARTITION_NULL;                \
+                _p;                                             \
+        })
 
 typedef enum PartitionDesignator {
         PARTITION_ROOT,
index dfe0574aba6b16010662ade9fc0842b61320e43f..fa234c8b5fe96ddb92f52d2710f6020779c2066c 100644 (file)
@@ -165,59 +165,65 @@ static int verify_esp_udev(
 
         r = sd_device_get_devname(d, &node);
         if (r < 0)
-                return log_error_errno(r, "Failed to get device node: %m");
+                return log_device_error_errno(d, r, "Failed to get device node: %m");
 
         r = sd_device_get_property_value(d, "ID_FS_TYPE", &v);
         if (r < 0)
-                return log_error_errno(r, "Failed to get device property: %m");
+                return log_device_error_errno(d, r, "Failed to get device property: %m");
         if (!streq(v, "vfat"))
-                return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
-                                      SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
-                                      "File system \"%s\" is not FAT.", node );
+                return log_device_full_errno(d,
+                                             searching ? LOG_DEBUG : LOG_ERR,
+                                             SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
+                                             "File system \"%s\" is not FAT.", node );
 
         r = sd_device_get_property_value(d, "ID_PART_ENTRY_SCHEME", &v);
         if (r < 0)
-                return log_error_errno(r, "Failed to get device property: %m");
+                return log_device_full_errno(d,
+                                             searching && r == -ENOENT ? LOG_DEBUG : LOG_ERR,
+                                             searching && r == -ENOENT ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : r,
+                                             "Failed to get device property: %m");
         if (!streq(v, "gpt"))
-                return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
-                                      SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
-                                      "File system \"%s\" is not on a GPT partition table.", node);
+                return log_device_full_errno(d,
+                                             searching ? LOG_DEBUG : LOG_ERR,
+                                             SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
+                                             "File system \"%s\" is not on a GPT partition table.", node);
 
         r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
         if (r < 0)
-                return log_error_errno(r, "Failed to get device property: %m");
+                return log_device_error_errno(d, r, "Failed to get device property: %m");
         if (sd_id128_string_equal(v, SD_GPT_ESP) <= 0)
-                return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
-                                       SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
-                                       "File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
+                return log_device_full_errno(d,
+                                             searching ? LOG_DEBUG : LOG_ERR,
+                                             SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
+                                             "File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
 
         r = sd_device_get_property_value(d, "ID_PART_ENTRY_UUID", &v);
         if (r < 0)
-                return log_error_errno(r, "Failed to get device property: %m");
+                return log_device_error_errno(d, r, "Failed to get device property: %m");
         r = sd_id128_from_string(v, &uuid);
         if (r < 0)
-                return log_error_errno(r, "Partition \"%s\" has invalid UUID \"%s\".", node, v);
+                return log_device_error_errno(d, r, "Partition \"%s\" has invalid UUID \"%s\".", node, v);
 
         r = sd_device_get_property_value(d, "ID_PART_ENTRY_NUMBER", &v);
         if (r < 0)
-                return log_error_errno(r, "Failed to get device property: %m");
+                return log_device_error_errno(d, r, "Failed to get device property: %m");
         r = safe_atou32(v, &part);
         if (r < 0)
-                return log_error_errno(r, "Failed to parse PART_ENTRY_NUMBER field.");
+                return log_device_error_errno(d, r, "Failed to parse PART_ENTRY_NUMBER field.");
 
         r = sd_device_get_property_value(d, "ID_PART_ENTRY_OFFSET", &v);
         if (r < 0)
-                return log_error_errno(r, "Failed to get device property: %m");
+                return log_device_error_errno(d, r, "Failed to get device property: %m");
         r = safe_atou64(v, &pstart);
         if (r < 0)
-                return log_error_errno(r, "Failed to parse PART_ENTRY_OFFSET field.");
+                return log_device_error_errno(d, r, "Failed to parse PART_ENTRY_OFFSET field.");
 
         r = sd_device_get_property_value(d, "ID_PART_ENTRY_SIZE", &v);
         if (r < 0)
-                return log_error_errno(r, "Failed to get device property: %m");
+                return log_device_error_errno(d, r, "Failed to get device property: %m");
         r = safe_atou64(v, &psize);
         if (r < 0)
-                return log_error_errno(r, "Failed to parse PART_ENTRY_SIZE field.");
+                return log_device_error_errno(d, r, "Failed to parse PART_ENTRY_SIZE field.");
 
         if (ret_part)
                 *ret_part = part;
@@ -572,10 +578,11 @@ static int verify_xbootldr_blkid(
         else if (r != 0)
                 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "%s: Failed to probe file system: %m", node);
 
-        errno = 0;
         r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &type, NULL);
         if (r != 0)
-                return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "%s: Failed to probe PART_ENTRY_SCHEME: %m", node);
+                return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
+                                      searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(EIO),
+                                      "%s: Failed to probe PART_ENTRY_SCHEME: %m", node);
         if (streq(type, "gpt")) {
 
                 errno = 0;
@@ -634,11 +641,14 @@ static int verify_xbootldr_udev(
 
         r = sd_device_get_devname(d, &node);
         if (r < 0)
-                return log_error_errno(r, "Failed to get device node: %m");
+                return log_device_error_errno(d, r, "Failed to get device node: %m");
 
         r = sd_device_get_property_value(d, "ID_PART_ENTRY_SCHEME", &type);
         if (r < 0)
-                return log_device_error_errno(d, r, "Failed to query ID_PART_ENTRY_SCHEME: %m");
+                return log_device_full_errno(d,
+                                             searching && r == -ENOENT ? LOG_DEBUG : LOG_ERR,
+                                             searching && r == -ENOENT ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : r,
+                                             "Failed to query ID_PART_ENTRY_SCHEME: %m");
 
         if (streq(type, "gpt")) {
 
index 1a444841fa0870a0774548cb9f422cb69d49f0bc..4cad3551a6af518c37716e03ecec7c2729f17df4 100644 (file)
@@ -32,7 +32,6 @@ int switch_root(const char *new_root,
 
         _cleanup_free_ char *resolved_old_root_after = NULL;
         _cleanup_close_ int old_root_fd = -1;
-        bool old_root_remove;
         int r;
 
         assert(new_root);
@@ -42,12 +41,16 @@ int switch_root(const char *new_root,
                 return 0;
 
         /* Check if we shall remove the contents of the old root */
-        old_root_remove = in_initrd();
-        if (old_root_remove) {
-                old_root_fd = open("/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
-                if (old_root_fd < 0)
-                        return log_error_errno(errno, "Failed to open root directory: %m");
-        }
+        old_root_fd = open("/", O_RDONLY | O_CLOEXEC | O_DIRECTORY);
+        if (old_root_fd < 0)
+                return log_error_errno(errno, "Failed to open root directory: %m");
+        r = fd_is_temporary_fs(old_root_fd);
+        if (r < 0)
+                return log_error_errno(r, "Failed to stat root directory: %m");
+        if (r > 0)
+                log_debug("Root directory is on tmpfs, will do cleanup later.");
+        else
+                old_root_fd = safe_close(old_root_fd);
 
         /* Determine where we shall place the old root after the transition */
         r = chase_symlinks(old_root_after, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved_old_root_after, NULL);
@@ -117,9 +120,8 @@ int switch_root(const char *new_root,
                 struct stat rb;
 
                 if (fstat(old_root_fd, &rb) < 0)
-                        log_warning_errno(errno, "Failed to stat old root directory, leaving: %m");
-                else
-                        (void) rm_rf_children(TAKE_FD(old_root_fd), 0, &rb); /* takes possession of the dir fd, even on failure */
+                        return log_error_errno(errno, "Failed to stat old root directory: %m");
+                (void) rm_rf_children(TAKE_FD(old_root_fd), 0, &rb); /* takes possession of the dir fd, even on failure */
         }
 
         return 0;
index 65e8d48347959d7000c66b43c1b69b05fe04d776..8171b3e9e99fe8113f66a3df03390476a877c3c6 100644 (file)
@@ -152,8 +152,19 @@ int tpm2_context_init(const char *device, struct tpm2_context *ret) {
         if (r < 0)
                 return log_error_errno(r, "TPM2 support not installed: %m");
 
-        if (!device)
+        if (!device) {
                 device = secure_getenv("SYSTEMD_TPM2_DEVICE");
+                if (device)
+                        /* Setting the env var to an empty string forces tpm2-tss' own device picking
+                         * logic to be used. */
+                        device = empty_to_null(device);
+                else
+                        /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
+                         * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
+                         * might be used and we really don't want that, since it is a system service and that creates
+                         * various ordering issues/deadlocks during early boot. */
+                        device = "device:/dev/tpmrm0";
+        }
 
         if (device) {
                 const char *param, *driver, *fn;
@@ -163,15 +174,27 @@ int tpm2_context_init(const char *device, struct tpm2_context *ret) {
 
                 param = strchr(device, ':');
                 if (param) {
+                        /* Syntax #1: Pair of driver string and arbitrary parameter */
                         driver = strndupa_safe(device, param - device);
+                        if (isempty(driver))
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name is empty, refusing.");
+
                         param++;
-                } else {
+                } else if (path_is_absolute(device) && path_is_valid(device)) {
+                        /* Syntax #2: TPM device node */
                         driver = "device";
                         param = device;
-                }
+                } else
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid TPM2 driver string, refusing.");
+
+                log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver, param);
 
                 fn = strjoina("libtss2-tcti-", driver, ".so.0");
 
+                /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
+                if (!filename_is_valid(fn))
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver);
+
                 dl = dlopen(fn, RTLD_NOW);
                 if (!dl)
                         return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
@@ -1094,7 +1117,13 @@ static int tpm2_make_policy_session(
                                 ESYS_TR_NONE,
                                 NULL,
                                 &pubkey_tpm2,
+#if HAVE_TSS2_ESYS3
+                                /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
+                                 * hierarchy, older versions need TPM2_RH_* instead. */
+                                ESYS_TR_RH_OWNER,
+#else
                                 TPM2_RH_OWNER,
+#endif
                                 &pubkey_handle);
                 if (rc != TSS2_RC_SUCCESS) {
                         r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
index aac02cd61bcaed4eebb0f92b46058e69e33867e9..7d953534520b9b7e04e9b96aa927d948f1252355 100644 (file)
@@ -642,9 +642,46 @@ static int device_is_power_sink(sd_device *device) {
         return found_sink || !found_source;
 }
 
+static bool battery_is_discharging(sd_device *d) {
+        const char *val;
+        int r;
+
+        assert(d);
+
+        r = sd_device_get_sysattr_value(d, "scope", &val);
+        if (r < 0) {
+                if (r != -ENOENT)
+                        log_device_debug_errno(d, r, "Failed to read 'scope' sysfs attribute, ignoring: %m");
+        } else if (streq(val, "Device")) {
+                log_device_debug(d, "The power supply is a device battery, ignoring device.");
+                return false;
+        }
+
+        r = device_get_sysattr_bool(d, "present");
+        if (r < 0)
+                log_device_debug_errno(d, r, "Failed to read 'present' sysfs attribute, assuming the battery is present: %m");
+        else if (r == 0) {
+                log_device_debug(d, "The battery is not present, ignoring the power supply.");
+                return false;
+        }
+
+        /* Possible values: "Unknown", "Charging", "Discharging", "Not charging", "Full" */
+        r = sd_device_get_sysattr_value(d, "status", &val);
+        if (r < 0) {
+                log_device_debug_errno(d, r, "Failed to read 'status' sysfs attribute, assuming the battery is discharging: %m");
+                return true;
+        }
+        if (!streq(val, "Discharging")) {
+                log_device_debug(d, "The battery status is '%s', assuming the battery is not used as a power source of this machine.", val);
+                return false;
+        }
+
+        return true;
+}
+
 int on_ac_power(void) {
         _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
-        bool found_ac_online = false, found_battery = false;
+        bool found_ac_online = false, found_discharging_battery = false;
         sd_device *d;
         int r;
 
@@ -686,17 +723,10 @@ int on_ac_power(void) {
                 }
 
                 if (streq(val, "Battery")) {
-                        r = sd_device_get_sysattr_value(d, "scope", &val);
-                        if (r < 0) {
-                                if (r != -ENOENT)
-                                        log_device_debug_errno(d, r, "Failed to read 'scope' sysfs attribute, ignoring: %m");
-                        } else if (streq(val, "Device")) {
-                                log_device_debug(d, "The power supply is a device battery, ignoring device.");
-                                continue;
+                        if (battery_is_discharging(d)) {
+                                found_discharging_battery = true;
+                                log_device_debug(d, "The power supply is a battery and currently discharging.");
                         }
-
-                        found_battery = true;
-                        log_device_debug(d, "The power supply is battery.");
                         continue;
                 }
 
@@ -713,11 +743,11 @@ int on_ac_power(void) {
         if (found_ac_online) {
                 log_debug("Found at least one online non-battery power supply, system is running on AC.");
                 return true;
-        } else if (found_battery) {
-                log_debug("Found battery and no online power sources, assuming system is running from battery.");
+        } else if (found_discharging_battery) {
+                log_debug("Found at least one discharging battery and no online power sources, assuming system is running from battery.");
                 return false;
         } else {
-                log_debug("No power supply reported online and no battery, assuming system is running on AC.");
+                log_debug("No power supply reported online and no discharging battery found, assuming system is running on AC.");
                 return true;
         }
 }
index 8d3db98c0a5966e4659f0f77b86597b0d22d4acb..24c7d564b8bba62a2c680cdde5ce084f7c682e82 100644 (file)
@@ -2207,9 +2207,10 @@ int verb_show(int argc, char *argv[], void *userdata) {
 
                 if (!arg_states && !arg_types) {
                         if (show_mode == SYSTEMCTL_SHOW_PROPERTIES)
-                                r = show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
-                        else
-                                r = show_system_status(bus);
+                                /* systemctl show --all → show properties of the manager */
+                                return show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
+
+                        r = show_system_status(bus);
                         if (r < 0)
                                 return r;
 
index 86fc1d4fc0a00714fd3b61d6ce7e3ff6b16882eb..2a4dfe26dbebaeb67d880e008541af2392ab4398 100644 (file)
@@ -622,7 +622,8 @@ tests += [
 
         [files('test-journal-importer.c')],
 
-        [files('test-utmp.c')],
+        [files('test-utmp.c'),
+         [], [], [], 'ENABLE_UTMP'],
 
         [files('test-udev.c'),
          [libudevd_core,
index 784b8955778990aafba6308572ca3f63ed6f411d..18bb75715b00fe3f86745494195e154b75ce5c6f 100644 (file)
@@ -961,22 +961,34 @@ shortcut:
         return label_fix_full(fd, /* inode_path= */ NULL, /* label_path= */ path, 0);
 }
 
-static int path_open_parent_safe(const char *path) {
+static int path_open_parent_safe(const char *path, bool allow_failure) {
         _cleanup_free_ char *dn = NULL;
         int r, fd;
 
         if (!path_is_normalized(path))
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to open parent of '%s': path not normalized.", path);
+                return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
+                                      SYNTHETIC_ERRNO(EINVAL),
+                                      "Failed to open parent of '%s': path not normalized%s.",
+                                      path,
+                                      allow_failure ? ", ignoring" : "");
 
         r = path_extract_directory(path, &dn);
         if (r < 0)
-                return log_error_errno(r, "Unable to determine parent directory of '%s': %m", path);
+                return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
+                                      r,
+                                      "Unable to determine parent directory of '%s'%s: %m",
+                                      path,
+                                      allow_failure ? ", ignoring" : "");
 
-        r = chase_symlinks(dn, arg_root, CHASE_SAFE|CHASE_WARN, NULL, &fd);
+        r = chase_symlinks(dn, arg_root, allow_failure ? CHASE_SAFE : CHASE_SAFE|CHASE_WARN, NULL, &fd);
         if (r == -ENOLINK) /* Unsafe symlink: already covered by CHASE_WARN */
                 return r;
         if (r < 0)
-                return log_error_errno(r, "Failed to open path '%s': %m", dn);
+                return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
+                                      r,
+                                      "Failed to open path '%s'%s: %m",
+                                      dn,
+                                      allow_failure ? ", ignoring" : "");
 
         return fd;
 }
@@ -1431,7 +1443,7 @@ static int write_one_file(Item *i, const char *path, CreationMode creation) {
 
         /* Validate the path and keep the fd on the directory for opening the file so we're sure that it
          * can't be changed behind our back. */
-        dir_fd = path_open_parent_safe(path);
+        dir_fd = path_open_parent_safe(path, i->allow_failure);
         if (dir_fd < 0)
                 return dir_fd;
 
@@ -1481,7 +1493,7 @@ static int create_file(Item *i, const char *path) {
 
         /* Validate the path and keep the fd on the directory for opening the file so we're sure that it
          * can't be changed behind our back. */
-        dir_fd = path_open_parent_safe(path);
+        dir_fd = path_open_parent_safe(path, i->allow_failure);
         if (dir_fd < 0)
                 return dir_fd;
 
@@ -1549,7 +1561,7 @@ static int truncate_file(Item *i, const char *path) {
 
         /* Validate the path and keep the fd on the directory for opening the file so we're sure that it
          * can't be changed behind our back. */
-        dir_fd = path_open_parent_safe(path);
+        dir_fd = path_open_parent_safe(path, i->allow_failure);
         if (dir_fd < 0)
                 return dir_fd;
 
@@ -1628,7 +1640,7 @@ static int copy_files(Item *i) {
 
         /* Validate the path and use the returned directory fd for copying the target so we're sure that the
          * path can't be changed behind our back. */
-        dfd = path_open_parent_safe(i->path);
+        dfd = path_open_parent_safe(i->path, i->allow_failure);
         if (dfd < 0)
                 return dfd;
 
@@ -1664,6 +1676,7 @@ static int create_directory_or_subvolume(
                 const char *path,
                 mode_t mode,
                 bool subvol,
+                bool allow_failure,
                 struct stat *ret_st,
                 CreationMode *ret_creation) {
 
@@ -1679,7 +1692,7 @@ static int create_directory_or_subvolume(
         if (r < 0)
                 return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
 
-        pfd = path_open_parent_safe(path);
+        pfd = path_open_parent_safe(path, allow_failure);
         if (pfd < 0)
                 return pfd;
 
@@ -1720,7 +1733,11 @@ static int create_directory_or_subvolume(
 
                 /* Then look at the original error */
                 if (r < 0)
-                        return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", path);
+                        return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
+                                              r,
+                                              "Failed to create directory or subvolume \"%s\"%s: %m",
+                                              path,
+                                              allow_failure ? ", ignoring" : "");
 
                 return log_error_errno(errno, "Failed to open directory/subvolume we just created '%s': %m", path);
         }
@@ -1748,7 +1765,7 @@ static int create_directory(Item *i, const char *path) {
         assert(i);
         assert(IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY));
 
-        fd = create_directory_or_subvolume(path, i->mode, /* subvol= */ false, &st, &creation);
+        fd = create_directory_or_subvolume(path, i->mode, /* subvol= */ false, i->allow_failure, &st, &creation);
         if (fd == -EEXIST)
                 return 0;
         if (fd < 0)
@@ -1766,7 +1783,7 @@ static int create_subvolume(Item *i, const char *path) {
         assert(i);
         assert(IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA));
 
-        fd = create_directory_or_subvolume(path, i->mode, /* subvol = */ true, &st, &creation);
+        fd = create_directory_or_subvolume(path, i->mode, /* subvol = */ true, i->allow_failure, &st, &creation);
         if (fd == -EEXIST)
                 return 0;
         if (fd < 0)
@@ -1845,7 +1862,7 @@ static int create_device(Item *i, mode_t file_type) {
 
         /* Validate the path and use the returned directory fd for copying the target so we're sure that the
          * path can't be changed behind our back. */
-        dfd = path_open_parent_safe(i->path);
+        dfd = path_open_parent_safe(i->path, i->allow_failure);
         if (dfd < 0)
                 return dfd;
 
@@ -1947,7 +1964,7 @@ static int create_fifo(Item *i) {
         if (r == O_DIRECTORY)
                 return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for creating FIFO, is a directory.", i->path);
 
-        pfd = path_open_parent_safe(i->path);
+        pfd = path_open_parent_safe(i->path, i->allow_failure);
         if (pfd < 0)
                 return pfd;
 
@@ -2032,7 +2049,7 @@ static int create_symlink(Item *i) {
         if (r == O_DIRECTORY)
                 return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for creating FIFO, is a directory.", i->path);
 
-        pfd = path_open_parent_safe(i->path);
+        pfd = path_open_parent_safe(i->path, i->allow_failure);
         if (pfd < 0)
                 return pfd;
 
index 92ea43eef0590201d463fe27920916bb4d2f1a05..9f5646ffdd997a2a0eece0c3873d5b81c5b09143 100644 (file)
@@ -120,14 +120,14 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
 #if defined(SD_GPT_ROOT_NATIVE) && ENABLE_EFI
 
         _cleanup_free_ char *root_id = NULL, *root_label = NULL;
-        bool found_esp = false;
+        bool found_esp_or_xbootldr = false;
         int r;
 
         assert(pr);
 
-        /* Iterate through the partitions on this disk, and see if the
-         * EFI ESP we booted from is on it. If so, find the first root
-         * disk, and add a property indicating its partition UUID. */
+        /* Iterate through the partitions on this disk, and see if the UEFI ESP or XBOOTLDR partition we
+         * booted from is on it. If so, find the first root disk, and add a property indicating its partition
+         * UUID. */
 
         errno = 0;
         blkid_partlist pl = blkid_probe_get_partitions(pr);
@@ -157,21 +157,20 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
                 if (sd_id128_from_string(stype, &type) < 0)
                         continue;
 
-                if (sd_id128_equal(type, SD_GPT_ESP)) {
-                        sd_id128_t id, esp;
+                if (sd_id128_in_set(type, SD_GPT_ESP, SD_GPT_XBOOTLDR)) {
+                        sd_id128_t id, esp_or_xbootldr;
 
-                        /* We found an ESP, let's see if it matches
-                         * the ESP we booted from. */
+                        /* We found an ESP or XBOOTLDR, let's see if it matches the ESP/XBOOTLDR we booted from. */
 
                         if (sd_id128_from_string(sid, &id) < 0)
                                 continue;
 
-                        r = efi_loader_get_device_part_uuid(&esp);
+                        r = efi_loader_get_device_part_uuid(&esp_or_xbootldr);
                         if (r < 0)
                                 return r;
 
-                        if (sd_id128_equal(id, esp))
-                                found_esp = true;
+                        if (sd_id128_equal(id, esp_or_xbootldr))
+                                found_esp_or_xbootldr = true;
 
                 } else if (sd_id128_equal(type, SD_GPT_ROOT_NATIVE)) {
                         unsigned long long flags;
@@ -195,9 +194,9 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
                 }
         }
 
-        /* We found the ESP on this disk, and also found a root
-         * partition, nice! Let's export its UUID */
-        if (found_esp && root_id)
+        /* We found the ESP/XBOOTLDR on this disk, and also found a root partition, nice! Let's export its
+         * UUID */
+        if (found_esp_or_xbootldr && root_id)
                 udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT_UUID", root_id);
 #endif