From ef345bf106fc3d975a74997f6ef1532a48f02e14 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 4 Jul 2023 18:05:30 +0100 Subject: [PATCH] [uefi] fix UEFI bootloader extraction when case doesn't match * With ISO-9660 being case sensitive, we could end up in situations where trying to extract '/efi/boot/bootx64.efi' for revocation validation would fail if the file on the image was stored as '/EFI/boot/bootx64.efi' (e.g. Debian 12). * Fox this by storing the exact UEFI bootloader path we detected during ISO scan, and using this path for file extraction. * Also add a Cancel choice to the revocation dialog and harmonize whitespaces. --- src/iso.c | 24 ++++++++++++++++++++---- src/rufus.c | 37 +++++++++++++++++-------------------- src/rufus.h | 31 ++++++++++++++++--------------- src/rufus.rc | 10 +++++----- 4 files changed, 58 insertions(+), 44 deletions(-) diff --git a/src/iso.c b/src/iso.c index 185af3f6..1b01d655 100644 --- a/src/iso.c +++ b/src/iso.c @@ -55,7 +55,6 @@ // How often should we update the progress bar (in 2K blocks) as updating // the progress bar for every block will bring extraction to a crawl #define PROGRESS_THRESHOLD 128 -#define FOUR_GIGABYTES 4294967296LL // Needed for UDF symbolic link testing #define S_IFLNK 0xA000 @@ -243,6 +242,15 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const img_report.has_bootmgr = TRUE; } if (safe_stricmp(psz_basename, bootmgr_efi_name) == 0) { + // We may extract the bootloaders for revocation validation later but + // to do so, since we're working with case sensitive file systems, we + // must store all found UEFI bootloader paths with the right case. + for (j = 0; j < ARRAYSIZE(img_report.efi_boot_path); j++) { + if (img_report.efi_boot_path[j][0] == 0) { + static_strcpy(img_report.efi_boot_path[j], psz_fullpath); + break; + } + } img_report.has_efi |= 1; img_report.has_bootmgr_efi = TRUE; } @@ -273,9 +281,17 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const // Check for the EFI boot entries if (safe_stricmp(psz_dirname, efi_dirname) == 0) { - for (i = 0; i < ARRAYSIZE(efi_bootname); i++) - if (safe_stricmp(psz_basename, efi_bootname[i]) == 0) + for (i = 0; i < ARRAYSIZE(efi_bootname); i++) { + if (safe_stricmp(psz_basename, efi_bootname[i]) == 0) { img_report.has_efi |= (2 << i); // start at 2 since "bootmgr.efi" is bit 0 + for (j = 0; j < ARRAYSIZE(img_report.efi_boot_path); j++) { + if (img_report.efi_boot_path[j][0] == 0) { + static_strcpy(img_report.efi_boot_path[j], psz_fullpath); + break; + } + } + } + } } if (psz_dirname != NULL) { @@ -312,7 +328,7 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const if (props->is_old_c32[i]) img_report.has_old_c32[i] = TRUE; } - if (file_length >= FOUR_GIGABYTES) + if (file_length >= 4 * GB) img_report.has_4GB_file = TRUE; // Compute projected size needed (NB: ISO_BLOCKSIZE = UDF_BLOCKSIZE) if (file_length != 0) diff --git a/src/rufus.c b/src/rufus.c index 7f5e70ca..7d79b564 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -1429,7 +1429,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param) const char* ldlinux = "ldlinux"; const char* syslinux = "syslinux"; const char* ldlinux_ext[3] = { "sys", "bss", "c32" }; - char tmp[MAX_PATH], tmp2[MAX_PATH], efi[MAX_PATH], c; + char tmp[MAX_PATH], tmp2[MAX_PATH], c; syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0; safe_free(grub2_buf); @@ -1449,7 +1449,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param) goto out; if ((size_check) && (img_report.projected_size > (uint64_t)SelectedDrive.DiskSize)) { // This ISO image is too big for the selected target - MessageBoxExU(hMainDialog, lmprintf(MSG_089), lmprintf(MSG_088), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid); + MessageBoxExU(hMainDialog, lmprintf(MSG_089), lmprintf(MSG_088), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid); goto out; } if (IS_DD_BOOTABLE(img_report)) { @@ -1489,14 +1489,14 @@ static DWORD WINAPI BootCheckThread(LPVOID param) if (is_windows_to_go) { if (fs_type != FS_NTFS) { // Windows To Go only works for NTFS - MessageBoxExU(hMainDialog, lmprintf(MSG_097, "Windows To Go"), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid); + MessageBoxExU(hMainDialog, lmprintf(MSG_097, "Windows To Go"), lmprintf(MSG_092), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid); goto out; } if (SelectedDrive.MediaType != FixedMedia) { if ((target_type == TT_UEFI) && (partition_type == PARTITION_STYLE_GPT) && (WindowsVersion.BuildNumber < 15000)) { // Up to Windows 10 Creators Update (1703), we were screwed, since we need access to 2 partitions at the same time. // Thankfully, the newer Windows allow mounting multiple partitions on the same REMOVABLE drive. - MessageBoxExU(hMainDialog, lmprintf(MSG_198), lmprintf(MSG_190), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid); + MessageBoxExU(hMainDialog, lmprintf(MSG_198), lmprintf(MSG_190), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid); goto out; } } @@ -1623,22 +1623,19 @@ static DWORD WINAPI BootCheckThread(LPVOID param) if (target_type == TT_UEFI) { // coverity[swapped_arguments] if (GetTempFileNameU(temp_dir, APPLICATION_NAME, 0, tmp) != 0) { - for (i = 0; i < ARRAYSIZE(efi_bootname) + 1; i++) { - if ((img_report.has_efi & (1 << i)) == 0) - continue; - if (i == 0) - static_strcpy(efi, bootmgr_efi_name); - else - static_sprintf(efi, "%s/%s", efi_dirname, efi_bootname[i - 1]); - if (ExtractISOFile(image_path, efi, tmp, FILE_ATTRIBUTE_NORMAL) == 0) { - uprintf("Warning: Failed to extract '%s' to check for UEFI revocation", efi); + // ExtractISOFile() is case sensitive, so we must use + for (i = 0; i < ARRAYSIZE(img_report.efi_boot_path) && img_report.efi_boot_path[i][0] != 0; i++) { + if (ExtractISOFile(image_path, img_report.efi_boot_path[i], tmp, FILE_ATTRIBUTE_NORMAL) == 0) { + uprintf("Warning: Failed to extract '%s' to check for UEFI revocation", img_report.efi_boot_path[i]); continue; } r = IsBootloaderRevoked(tmp); if (r > 0) { - MessageBoxExU(hMainDialog, lmprintf(MSG_339, + r = MessageBoxExU(hMainDialog, lmprintf(MSG_339, (r == 1) ? lmprintf(MSG_340) : lmprintf(MSG_341, "Error code: 0xc0000428")), - lmprintf(MSG_338), MB_ICONWARNING | MB_IS_RTL, selected_langid); + lmprintf(MSG_338), MB_OKCANCEL | MB_ICONWARNING | MB_IS_RTL, selected_langid); + if (r == IDCANCEL) + goto out; break; } } @@ -1677,7 +1674,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param) fclose(fd); } else { r = MessageBoxExU(hMainDialog, lmprintf(MSG_116, img_report.grub2_version, GRUB2_PACKAGE_VERSION), - lmprintf(MSG_115), MB_YESNOCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid); + lmprintf(MSG_115), MB_YESNOCANCEL | MB_ICONWARNING | MB_IS_RTL, selected_langid); if (r == IDCANCEL) goto out; else if (r == IDYES) { @@ -1735,7 +1732,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param) } else { PrintInfo(0, MSG_204, old_c32_name[i]); if (MessageBoxExU(hMainDialog, lmprintf(MSG_084, old_c32_name[i], old_c32_name[i]), - lmprintf(MSG_083, old_c32_name[i]), MB_YESNO|MB_ICONWARNING|MB_IS_RTL, selected_langid) == IDYES) { + lmprintf(MSG_083, old_c32_name[i]), MB_YESNO | MB_ICONWARNING | MB_IS_RTL, selected_langid) == IDYES) { static_sprintf(tmp, "%s-%s", syslinux, embedded_sl_version_str[0]); IGNORE_RETVAL(_mkdir(tmp)); static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, syslinux, embedded_sl_version_str[0], old_c32_name[i]); @@ -1775,7 +1772,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param) } else { r = MessageBoxExU(hMainDialog, lmprintf(MSG_114, img_report.sl_version_str, img_report.sl_version_ext, embedded_sl_version_str[1], embedded_sl_version_ext[1]), - lmprintf(MSG_115), MB_YESNO|MB_ICONWARNING|MB_IS_RTL, selected_langid); + lmprintf(MSG_115), MB_YESNO | MB_ICONWARNING | MB_IS_RTL, selected_langid); if (r != IDYES) goto out; for (i=0; i<2; i++) { @@ -1834,7 +1831,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param) PrintInfo(0, MSG_206, tmp); // MSG_104: "Syslinux v5.0 or later requires a '%s' file to be installed" r = MessageBoxExU(hMainDialog, lmprintf(MSG_104, "Syslinux v5.0", tmp, "Syslinux v5+", tmp), - lmprintf(MSG_103, tmp), MB_YESNOCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid); + lmprintf(MSG_103, tmp), MB_YESNOCANCEL | MB_ICONWARNING | MB_IS_RTL, selected_langid); if (r == IDCANCEL) goto out; if (r == IDYES) { @@ -1883,7 +1880,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param) static_sprintf(tmp, "grldr"); PrintInfo(0, MSG_206, tmp); r = MessageBoxExU(hMainDialog, lmprintf(MSG_104, "Grub4DOS 0.4", tmp, "Grub4DOS", tmp), - lmprintf(MSG_103, tmp), MB_YESNOCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid); + lmprintf(MSG_103, tmp), MB_YESNOCANCEL | MB_ICONWARNING | MB_IS_RTL, selected_langid); if (r == IDCANCEL) goto out; if (r == IDYES) { diff --git a/src/rufus.h b/src/rufus.h index 7bee5c06..485a409e 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -364,12 +364,28 @@ typedef struct { uint16_t revision; } winver_t; +/* We can't use the Microsoft enums as we want to have RISC-V */ +enum ArchType { + ARCH_UNKNOWN = 0, + ARCH_X86_32, + ARCH_X86_64, + ARCH_ARM_32, + ARCH_ARM_64, + ARCH_IA_64, + ARCH_RISCV_32, + ARCH_RISCV_64, + ARCH_RISCV_128, + ARCH_EBC, + ARCH_MAX +}; + typedef struct { char label[192]; // 3*64 to account for UTF-8 char usb_label[192]; // converted USB label for workaround char cfg_path[128]; // path to the ISO's isolinux.cfg char reactos_path[128]; // path to the ISO's freeldr.sys or setupldr.sys char wininst_path[MAX_WININST][64]; // path to the Windows install image(s) + char efi_boot_path[ARCH_MAX][30]; // paths of detected UEFI bootloaders char efi_img_path[128]; // path to an efi.img file uint64_t image_size; uint64_t archive_size; @@ -476,21 +492,6 @@ typedef enum TASKBAR_PROGRESS_FLAGS TASKBAR_PAUSED = 0x8 } TASKBAR_PROGRESS_FLAGS; -/* We can't use the Microsoft enums as we want to have RISC-V */ -enum ArchType { - ARCH_UNKNOWN = 0, - ARCH_X86_32, - ARCH_X86_64, - ARCH_ARM_32, - ARCH_ARM_64, - ARCH_IA_64, - ARCH_RISCV_32, - ARCH_RISCV_64, - ARCH_RISCV_128, - ARCH_EBC, - ARCH_MAX -}; - static __inline USHORT GetApplicationArch(void) { #if defined(_M_AMD64) diff --git a/src/rufus.rc b/src/rufus.rc index 0c7d1092..9cb6ccb7 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 232, 326 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 4.2.2064" +CAPTION "Rufus 4.2.2065" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -392,8 +392,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,2,2064,0 - PRODUCTVERSION 4,2,2064,0 + FILEVERSION 4,2,2065,0 + PRODUCTVERSION 4,2,2065,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -411,13 +411,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "4.2.2064" + VALUE "FileVersion", "4.2.2065" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-4.2.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "4.2.2064" + VALUE "ProductVersion", "4.2.2065" END END BLOCK "VarFileInfo"