From: Jan Janssen Date: Wed, 16 Feb 2022 11:28:20 +0000 (+0100) Subject: boot: Fix integer format specifiers X-Git-Tag: v251-rc2~126^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ec4106afa0672f12f2a79cd4619767c07985e1d8;p=thirdparty%2Fsystemd.git boot: Fix integer format specifiers gnu-efi only knows two sizes for formatting integers: 32bit without a length prefix and 64bit with 'l' prefix. Provide a PRI-style format specifier for (U)INTN so that Print() can read the right amount of bytes instead of printing garbage or worse. --- diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 96e56a78391..ca43f007398 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -493,7 +493,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) { Print(L" secure boot: %s (%s)\n", yes_no(IN_SET(secure, SECURE_BOOT_USER, SECURE_BOOT_DEPLOYED)), secure_boot_mode_to_string(secure)); ps_bool(L" shim: %s\n", shim_loaded()); ps_bool(L" TPM: %s\n", tpm_present()); - Print(L" console mode: %d/%d (%lux%lu @%ux%u)\n", ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - 1LL, x_max, y_max, screen_width, screen_height); + Print(L" console mode: %d/%ld (%" PRIuN L"x%" PRIuN L" @%ux%u)\n", ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - INT64_C(1), x_max, y_max, screen_width, screen_height); if (!ps_continue()) return; @@ -506,7 +506,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) { case TIMEOUT_MENU_HIDDEN: Print(L" timeout: menu-hidden\n"); break; default: - Print(L" timeout: %lu s\n", config->timeout_sec_config); + Print(L" timeout: %u s\n", config->timeout_sec_config); } switch (config->timeout_sec_efivar) { @@ -517,7 +517,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) { case TIMEOUT_MENU_HIDDEN: Print(L" timeout (EFI var): menu-hidden\n"); break; default: - Print(L" timeout (EFI var): %lu s\n", config->timeout_sec_efivar); + Print(L" timeout (EFI var): %u s\n", config->timeout_sec_efivar); } ps_string(L" default: %s\n", config->entry_default_config); @@ -552,7 +552,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) { for (UINTN i = 0; i < config->entry_count; i++) { ConfigEntry *entry = config->entries[i]; - Print(L" config entry: %lu/%lu\n", i + 1, config->entry_count); + Print(L" config entry: %" PRIuN L"/%" PRIuN L"\n", i + 1, config->entry_count); ps_string(L" id: %s\n", entry->id); ps_string(L" title: %s\n", entry->title); ps_string(L" title show: %s\n", streq_ptr(entry->title, entry->title_show) ? NULL : entry->title_show); @@ -568,7 +568,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) { ps_bool(L"counting boots: %s\n", entry->tries_left != UINTN_MAX); if (entry->tries_left != UINTN_MAX) { - Print(L" tries: %lu done, %lu left\n", entry->tries_done, entry->tries_left); + Print(L" tries: %" PRIuN L" done, %" PRIuN L" left\n", entry->tries_done, entry->tries_left); Print(L" current path: %s\\%s\n", entry->path, entry->current_name); Print(L" next path: %s\\%s\n", entry->path, entry->next_name); } @@ -920,10 +920,14 @@ static BOOLEAN menu_run( break; case KEYPRESS(0, 0, 'v'): - status = xpool_print(L"systemd-boot " GIT_VERSION " (" EFI_MACHINE_TYPE_NAME "), " - L"UEFI Specification %d.%02d, Vendor %s %d.%02d", - ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff, - ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + status = xpool_print( + L"systemd-boot " GIT_VERSION L" (" EFI_MACHINE_TYPE_NAME L"), " + L"UEFI Specification %u.%02u, Vendor %s %u.%02u", + ST->Hdr.Revision >> 16, + ST->Hdr.Revision & 0xffff, + ST->FirmwareVendor, + ST->FirmwareRevision >> 16, + ST->FirmwareRevision & 0xffff); break; case KEYPRESS(0, 0, 'p'): @@ -1362,7 +1366,7 @@ good: prefix = xstrdup(file); prefix[i] = 0; - entry->next_name = xpool_print(L"%s+%u-%u%s", prefix, next_left, next_done, suffix ?: L""); + entry->next_name = xpool_print(L"%s+%" PRIuN L"-%" PRIuN L"%s", prefix, next_left, next_done, suffix ?: L""); } static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) { @@ -2074,7 +2078,7 @@ static EFI_STATUS boot_windows_bitlocker(void) { CHAR16 name[sizeof(L"Boot0000")]; UINTN buf_size; - SPrint(name, sizeof(name), L"Boot%04x", boot_order[i]); + SPrint(name, sizeof(name), L"Boot%04x", (UINT32) boot_order[i]); err = efivar_get_raw(EFI_GLOBAL_GUID, name, &buf, &buf_size); if (EFI_ERROR(err)) continue; @@ -2458,10 +2462,10 @@ static void export_variables( efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec); efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, 0); - infostr = xpool_print(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + infostr = xpool_print(L"%s %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", infostr, 0); - typestr = xpool_print(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); + typestr = xpool_print(L"UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); efivar_set(LOADER_GUID, L"LoaderFirmwareType", typestr, 0); (void) efivar_set_uint64_le(LOADER_GUID, L"LoaderFeatures", loader_features, 0); diff --git a/src/boot/efi/drivers.c b/src/boot/efi/drivers.c index 376745f5298..2ff87261dab 100644 --- a/src/boot/efi/drivers.c +++ b/src/boot/efi/drivers.c @@ -71,7 +71,7 @@ static EFI_STATUS reconnect(void) { if (err == EFI_NOT_FOUND) /* No drivers for this handle */ continue; if (EFI_ERROR(err)) - log_error_status_stall(err, L"Failed to reconnect handle %u, ignoring: %r", i, err); + log_error_status_stall(err, L"Failed to reconnect handle %" PRIuN L", ignoring: %r", i, err); } return EFI_SUCCESS; diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 73d06de7f11..40f615b2b36 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -131,14 +131,14 @@ static void export_variables(EFI_LOADED_IMAGE *loaded_image) { /* if LoaderFirmwareInfo is not set, let's set it */ if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) { _cleanup_freepool_ CHAR16 *s = NULL; - s = xpool_print(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + s = xpool_print(L"%s %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", s, 0); } /* ditto for LoaderFirmwareType */ if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) { _cleanup_freepool_ CHAR16 *s = NULL; - s = xpool_print(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); + s = xpool_print(L"UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); efivar_set(LOADER_GUID, L"LoaderFirmwareType", s, 0); } diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c index e6250207f68..169add8680e 100644 --- a/src/boot/efi/util.c +++ b/src/boot/efi/util.c @@ -57,7 +57,10 @@ EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UI assert(vendor); assert(name); - SPrint(str, ELEMENTSOF(str), L"%u", i); + /* Note that SPrint has no native sized length specifier and will always use ValueToString() + * regardless of what sign we tell it to use. Therefore, UINTN_MAX will come out as -1 on + * 64bit machines. */ + ValueToString(str, FALSE, i); return efivar_set(vendor, name, str, flags); } @@ -236,7 +239,8 @@ void efivar_set_time_usec(const EFI_GUID *vendor, const CHAR16 *name, UINT64 use if (usec == 0) return; - SPrint(str, ELEMENTSOF(str), L"%ld", usec); + /* See comment on ValueToString in efivar_set_uint_string(). */ + ValueToString(str, FALSE, usec); efivar_set(vendor, name, str, 0); } diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h index 93dd2da566f..c45374a08eb 100644 --- a/src/boot/efi/util.h +++ b/src/boot/efi/util.h @@ -17,6 +17,20 @@ #define UINT64_MAX ((UINT64) -1) #endif +/* gnu-efi format specifiers for integers are fixed to either 64bit with 'l' and 32bit without a size prefix. + * We rely on %u/%d/%x to format regular ints, so ensure the size is what we expect. At the same time, we also + * need specifiers for (U)INTN which are native (pointer) sized. */ +assert_cc(sizeof(int) == sizeof(UINT32)); +#if __SIZEOF_POINTER__ == 4 +# define PRIuN L"u" +# define PRIiN L"d" +#elif __SIZEOF_POINTER__ == 8 +# define PRIuN L"lu" +# define PRIiN L"ld" +#else +# error "Unexpected pointer size" +#endif + #define xnew_alloc(type, n, alloc) \ ({ \ UINTN _alloc_size; \ @@ -146,7 +160,7 @@ void debug_break(void); extern UINT8 _text, _data; /* Report the relocated position of text and data sections so that a debugger * can attach to us. See debug-sd-boot.sh for how this can be done. */ -# define debug_hook(identity) Print(identity L"@0x%x,0x%x\n", &_text, &_data) +# define debug_hook(identity) Print(identity L"@0x%lx,0x%lx\n", POINTER_TO_PHYSICAL_ADDRESS(&_text), POINTER_TO_PHYSICAL_ADDRESS(&_data)) #else # define debug_hook(identity) #endif