[grub] force server download for nonstandard GRUB (Fedora 37, openSUSE Live, GeckoLinux)

* This reverts most of 3528ca773d in order to download 'core.img' from our server instead of patching it.
* Also solve the issue of downloading a custom 'core.img' for Fedora 37, that introduced
  a new 'grub_debug_is_enabled' symbol without altering their GRUB version string.
* This is accomplished by doing what the distro maintainers should have done on their
  own, by appending a custom suffix to the GRUB version string.
This commit is contained in:
Pete Batard 2022-10-06 23:39:32 +01:00
parent 8814944c35
commit fcae51a446
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
6 changed files with 48 additions and 125 deletions

View File

@ -5,35 +5,3 @@
#pragma once
#define GRUB2_PACKAGE_VERSION "2.06"
/*
* Also include the 'core.img' patch data for distros using a
* NONSTANDARD '/boot/grub2/' prefix directory (openSUSE, Gecko, ...)
* This is basically a diff of the 'core.img' generated with
* 'grub-mkimage -p/boot/grub' vs 'grub-mkimage -p/boot/grub2'
*/
// For GRUB 2.04
static const chunk_t grub_204_chunk1_src = { 0x0208, 1, { 0xce } };
static const chunk_t grub_204_chunk1_rep = { 0x0208, 1, { 0xcf } };
static const chunk_t grub_204_chunk2_src = { 0x7cf8, 6, { 0x63, 0x25, 0x7e, 0x04, 0xf6, 0x14 } };
static const chunk_t grub_204_chunk2_rep = { 0x7cf8, 7, { 0x62, 0xdb, 0x77, 0x57, 0x0c, 0x4e, 0x00 } };
// For GRUB 2.06
static const chunk_t grub_206_chunk1_src = { 0x0208, 1, { 0xcf } };
static const chunk_t grub_206_chunk1_rep = { 0x0208, 1, { 0xd0 } };
static const chunk_t grub_206_chunk2_src = { 0x95f9, 6, { 0xac, 0x1a, 0xc6, 0x4f, 0x45, 0x2c } };
static const chunk_t grub_206_chunk2_rep = { 0x95f9, 7, { 0xab, 0xe7, 0xe4, 0x0a, 0x2e, 0x38, 0x00 } };
const grub_patch_t grub_patch[2] = {
{ "2.04", {
{ &grub_204_chunk1_src, &grub_204_chunk1_rep },
{ &grub_204_chunk2_src, &grub_204_chunk2_rep },
}
},
{ "2.06", {
{ &grub_206_chunk1_src, &grub_206_chunk1_rep },
{ &grub_206_chunk2_src, &grub_206_chunk2_rep },
}
},
};

View File

@ -21,18 +21,20 @@
#pragma once
/*
* NB: Table data was generated from the files/ directory on the server with:
* find . -not -name "*.txt" -not -name "*.sig" -not -name "*.sh" -not -name "*pre*" -type f -print0 | xargs -0 sha256sum | sort | uniq -w 64 | awk -F '' '{ printf " "; for(i=1; i<=64; i+=2) {printf "0x%s%s, ", $i,$(i+1);}} {print "// " substr($0,69)}'
* NB: Table data was generated from the https://github.com/pbatard/rufus-web/tree/gh-pages/files/
* directory using the https://github.com/pbatard/rufus-web/blob/gh-pages/files/gendb.sh script.
*/
static uint8_t sha256db[] = {
0x01, 0x21, 0x98, 0x20, 0xd9, 0x1c, 0x28, 0x7b, 0x35, 0x28, 0x06, 0xf1, 0xb6, 0xa8, 0x0d, 0x4a, 0x8a, 0xf4, 0x5c, 0xf5, 0x04, 0x83, 0xed, 0x6b, 0xe0, 0xc6, 0x0e, 0x7a, 0x66, 0x9c, 0x67, 0x87, // syslinux-6.04/pre2/ldlinux.bss
0x11, 0x0c, 0x50, 0x1b, 0xfa, 0x9e, 0x72, 0xa8, 0x8c, 0xdb, 0xb8, 0xba, 0x11, 0xe1, 0xf0, 0x76, 0x1a, 0xec, 0x28, 0xbf, 0x04, 0x44, 0x67, 0xff, 0x38, 0x2c, 0x06, 0x95, 0xd5, 0x1f, 0x8a, 0x83, // grub-2.04-nonstandard/core.img
0x12, 0xbd, 0x22, 0xd2, 0xb3, 0x69, 0x56, 0x0f, 0x89, 0xb8, 0x50, 0x7e, 0x7e, 0x74, 0xeb, 0xc5, 0xea, 0x44, 0x91, 0x48, 0x75, 0xf0, 0xa4, 0xcb, 0x1e, 0xa6, 0xfb, 0x4e, 0xc9, 0x89, 0x58, 0x17, // syslinux-6.03/pre6/ldlinux.sys
0x15, 0x5f, 0x36, 0x7b, 0xb1, 0x30, 0xfe, 0x05, 0x5c, 0x79, 0x9f, 0x88, 0xb3, 0xc0, 0xc1, 0xa0, 0x0a, 0x18, 0x05, 0x78, 0x22, 0x69, 0xcf, 0x7e, 0x54, 0xaa, 0x61, 0xbd, 0xe3, 0x8e, 0x05, 0x92, // syslinux-6.03/pre3/ldlinux.bss
0x1c, 0xb7, 0x8b, 0x98, 0xbc, 0xd6, 0x76, 0x7b, 0x01, 0x44, 0xf5, 0x00, 0xaf, 0x81, 0xef, 0x4f, 0x3c, 0x54, 0xea, 0xaf, 0xe3, 0xc9, 0x4e, 0x1f, 0xd6, 0x24, 0x68, 0x41, 0x4e, 0x98, 0x92, 0x25, // syslinux-6.03/pre20/ldlinux.bss
0x1c, 0xc6, 0x32, 0x21, 0xfd, 0xf4, 0x46, 0xfc, 0xda, 0xc6, 0xc0, 0x56, 0x35, 0x79, 0x54, 0xc1, 0x5b, 0x61, 0x75, 0xca, 0x1b, 0xc2, 0xa4, 0x9f, 0x85, 0x52, 0xec, 0xca, 0x28, 0xac, 0x3e, 0x51, // syslinux-6.02/ldlinux.bss
0x22, 0x96, 0x82, 0xac, 0x61, 0xb8, 0x8b, 0x11, 0x25, 0xfc, 0xd7, 0xe6, 0x9f, 0x4e, 0x7f, 0x46, 0x7f, 0x68, 0xc5, 0x14, 0x9e, 0xb9, 0x37, 0x1a, 0x98, 0xd8, 0xf2, 0x78, 0x41, 0x40, 0xad, 0x88, // syslinux-5.00/ldlinux.sys
0x25, 0xd1, 0x38, 0xf3, 0x8b, 0x17, 0x35, 0x79, 0x3e, 0xee, 0x89, 0x19, 0xa3, 0xa0, 0xe5, 0xc9, 0x97, 0x9d, 0x2f, 0xac, 0xc0, 0xb5, 0x70, 0x74, 0x24, 0xe8, 0x04, 0x98, 0x1d, 0x25, 0xf9, 0xc9, // syslinux-6.03/pre10/ldlinux.sys
0x28, 0xf8, 0x1d, 0xd8, 0x72, 0x0e, 0x6e, 0xfd, 0xc5, 0x30, 0x44, 0xf6, 0xf9, 0xa6, 0xc2, 0x8b, 0x6b, 0x89, 0x54, 0x23, 0xfb, 0x4c, 0xbc, 0x2d, 0xa2, 0xfb, 0xd6, 0x29, 0x70, 0xd6, 0xd1, 0xd6, // grub-2.06-nonstandard/core.img
0x29, 0xcd, 0xfc, 0x24, 0x0d, 0x08, 0xe4, 0xd6, 0x42, 0x0d, 0x1f, 0x05, 0x7a, 0x0e, 0xb0, 0xb1, 0x07, 0x88, 0x91, 0x65, 0xa8, 0xeb, 0x16, 0x3c, 0x31, 0x72, 0xaa, 0xfc, 0xee, 0x02, 0xac, 0xdd, // grub-2.06~rc1/core.img
0x2b, 0x07, 0x20, 0x67, 0xf9, 0xcd, 0x6e, 0x8c, 0x62, 0xe7, 0x82, 0xdc, 0x4a, 0xe2, 0x3b, 0x19, 0x2d, 0xe6, 0x28, 0xe7, 0x67, 0x0c, 0x84, 0x68, 0xed, 0x38, 0x0d, 0x36, 0x4a, 0xa7, 0x0b, 0xf1, // grub-2.06/core.img
0x2b, 0x31, 0x7b, 0x12, 0xab, 0xff, 0x49, 0x66, 0x48, 0x78, 0xdf, 0xe0, 0xb5, 0x00, 0xb8, 0x50, 0x0f, 0x93, 0xf1, 0xd5, 0xe4, 0xd5, 0x28, 0x45, 0x95, 0xcc, 0x2c, 0x15, 0x6c, 0x74, 0x4f, 0x79, // grub-2.02~beta3/core.img
@ -71,6 +73,7 @@ static uint8_t sha256db[] = {
0x6a, 0xbc, 0xdc, 0x80, 0x3a, 0x30, 0x85, 0xea, 0x5f, 0x9d, 0xa1, 0xb4, 0x3e, 0xdb, 0x2e, 0xad, 0xa2, 0x75, 0x36, 0x0d, 0xb8, 0x11, 0xc9, 0xac, 0xf5, 0x9a, 0x55, 0x5f, 0x67, 0x7b, 0x2d, 0x8b, // syslinux-6.03/pre12/ldlinux.bss
0x73, 0xb6, 0x27, 0x67, 0xa1, 0x62, 0x00, 0xb9, 0xaf, 0x19, 0x3a, 0x7d, 0x5c, 0x94, 0xe9, 0xc2, 0x94, 0xc6, 0xdb, 0xb6, 0xd5, 0xb1, 0x7c, 0x15, 0x03, 0x8c, 0x9f, 0x31, 0x73, 0xc9, 0xa7, 0xbc, // syslinux-6.04/ldlinux.sys
0x75, 0x6f, 0x89, 0x25, 0x23, 0xc6, 0x8d, 0x27, 0x32, 0x28, 0x8b, 0x5a, 0xd4, 0x2d, 0x7d, 0xc7, 0x4e, 0xa7, 0xa7, 0x08, 0x9b, 0x04, 0x2b, 0x12, 0x5f, 0x5d, 0x74, 0x7f, 0xf3, 0x20, 0xa0, 0x77, // syslinux-4.07/vesamenu.c32
0x76, 0xd1, 0x2b, 0x17, 0xfd, 0x05, 0xd3, 0x10, 0xb0, 0x5d, 0x00, 0xa8, 0x38, 0x77, 0x06, 0xc5, 0xce, 0x35, 0xd4, 0xb0, 0x50, 0xf2, 0x23, 0x9d, 0x15, 0xd3, 0xc9, 0xac, 0x92, 0xc5, 0xdd, 0xbc, // grub-2.06-fedora-nonstandard/core.img
0x77, 0x9a, 0x5e, 0xbd, 0x69, 0xd3, 0x28, 0x5e, 0xb9, 0xed, 0x4a, 0xc7, 0xc0, 0x4d, 0x2d, 0x15, 0xcb, 0xa1, 0x8a, 0x1f, 0x97, 0xc7, 0xc4, 0xbe, 0x62, 0x48, 0x93, 0xa9, 0xe1, 0xb0, 0x89, 0x2e, // syslinux-6.03/pre9/ldlinux.sys
0x78, 0x64, 0x8e, 0xf0, 0xc5, 0x00, 0x41, 0x75, 0xb9, 0xa8, 0xea, 0x33, 0x30, 0x14, 0xea, 0x02, 0xc9, 0x17, 0xf8, 0x23, 0xe7, 0x7a, 0x3e, 0xc9, 0xac, 0xd9, 0xd2, 0x2b, 0x46, 0x02, 0xf3, 0x6d, // syslinux-6.03/pre13/ldlinux.sys
0x7d, 0xa9, 0xc5, 0x21, 0x76, 0xb8, 0xaf, 0x01, 0x64, 0xea, 0x39, 0x21, 0x22, 0x44, 0xb1, 0x0a, 0xa0, 0xc7, 0x97, 0xe7, 0x65, 0xbb, 0x6b, 0x92, 0x69, 0xb5, 0x8b, 0xc9, 0xe5, 0x0a, 0x9f, 0x18, // syslinux-5.01/ldlinux.bss

View File

@ -74,7 +74,6 @@ extern uint32_t dur_mins, dur_secs;
extern uint32_t wim_nb_files, wim_proc_files, wim_extra_files;
extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, fast_zeroing, enable_file_indexing;
extern BOOL write_as_image, use_vds, write_as_esp, is_vds_available;
extern const grub_patch_t grub_patch[2];
uint8_t *grub2_buf = NULL, *sec_buf = NULL;
long grub2_len;
@ -911,8 +910,8 @@ static BOOL WriteSBR(HANDLE hPhysicalDrive)
{
// TODO: Do we need anything special for 4K sectors?
DWORD size, max_size, br_size = 0x200;
int i, j, r, sub_type = boot_type;
uint8_t *buf = NULL, *patched = NULL;
int r, sub_type = boot_type;
uint8_t *buf = NULL;
FAKE_FD fake_fd = { 0 };
FILE* fp = (FILE*)&fake_fd;
@ -955,32 +954,6 @@ static BOOL WriteSBR(HANDLE hPhysicalDrive)
return FALSE;
}
}
// TODO: Compute the projected increase in size instead of harcoding it
if (img_report.has_grub2 == 2 && ((patched = malloc(size + 16)) != NULL)) {
memcpy(patched, buf, size);
// Patch GRUB for nonstandard prefix directory
for (i = 0; i < ARRAYSIZE(grub_patch); i++) {
if (strcmp(img_report.grub2_version, grub_patch[i].version) == 0) {
for (j = 0; j < ARRAYSIZE(grub_patch[i].patch); j++) {
if (memcmp(&patched[grub_patch[i].patch[j].src->offset], grub_patch[i].patch[j].src->data,
grub_patch[i].patch[j].src->size) != 0) {
uprintf("ERROR: Did not find expected source data for GRUB patch");
free(patched);
return FALSE;
}
memcpy(&patched[grub_patch[i].patch[j].rep->offset], grub_patch[i].patch[j].rep->data,
grub_patch[i].patch[j].rep->size);
if (grub_patch[i].patch[j].rep->size > grub_patch[i].patch[j].src->size)
size += grub_patch[i].patch[j].rep->size - grub_patch[i].patch[j].src->size;
}
safe_free(grub2_buf);
grub2_buf = patched;
buf = grub2_buf;
uprintf("Patched Grub 2.0 SBR for NONSTANDARD prefix");
break;
}
}
}
break;
case BT_MAX:
uprintf("Writing protective message SBR");

View File

@ -82,7 +82,6 @@ RUFUS_IMG_REPORT img_report;
int64_t iso_blocking_status = -1;
extern BOOL preserve_timestamps, enable_ntfs_compression;
extern char* archive_path;
extern const grub_patch_t grub_patch[2];
BOOL enable_iso = TRUE, enable_joliet = TRUE, enable_rockridge = TRUE, has_ldlinux_c32;
#define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0)
static const char* psz_extract_dir;
@ -851,16 +850,18 @@ void GetGrubVersion(char* buf, size_t buf_size)
// not having it mention GNU anywhere. See:
// https://src.fedoraproject.org/rpms/grub2/blob/rawhide/f/0024-Don-t-say-GNU-Linux-in-generated-menus.patch
const char* grub_version_str[] = { "GRUB version %s", "GRUB version %s" };
const char* grub_debug_is_enabled_str = "grub_debug_is_enabled";
char *p, unauthorized[] = {'<', '>', ':', '|', '*', '?', '\\', '/'};
size_t i, j;
BOOL has_grub_debug_is_enabled = FALSE;
for (i = 0; i < buf_size; i++) {
for (j = 0; j < ARRAYSIZE(grub_version_str); j++) {
if (memcmp(&buf[i], grub_version_str[j], strlen(grub_version_str[j]) + 1) == 0) {
if (memcmp(&buf[i], grub_version_str[j], strlen(grub_version_str[j]) + 1) == 0)
static_strcpy(img_report.grub2_version, &buf[i + strlen(grub_version_str[j]) + 1]);
break;
}
}
if (memcmp(&buf[i], grub_debug_is_enabled_str, strlen(grub_debug_is_enabled_str)) == 0)
has_grub_debug_is_enabled = TRUE;
}
// Sanitize the string
for (p = &img_report.grub2_version[0]; *p; p++) {
@ -873,6 +874,35 @@ void GetGrubVersion(char* buf, size_t buf_size)
// But seriously, these guys should know better than "security" through obscurity...
if (img_report.grub2_version[0] == '0')
img_report.grub2_version[0] = 0;
// For some obscure reason, openSUSE have decided that their Live images should
// use /boot/grub2/ as their prefix directory instead of the standard /boot/grub/
// This creates a MAJOR issue because the prefix directory is hardcoded in
// 'core.img', and Rufus must install a 'core.img', that is not provided by the
// ISO, for the USB to boot (since even trying to pick the one from ISOHybrid
// does usually not guarantees the presence of the FAT driver which is mandatory
// for ISO boot).
// Therefore, when *someone* uses a nonstandard GRUB prefix directory, our base
// 'core.img' can't work with their image, since it isn't able to load modules
// like 'normal.mod', that are required to access the configuration files. Oh and
// you can forget about direct editing the prefix string inside 'core.img' since
// GRUB are forcing LZMA compression for BIOS payloads. And it gets even better,
// because even if you're trying to be smart and use GRUB's earlyconfig features
// to do something like:
// if [ -e /boot/grub2/i386-pc/normal.mod ]; then set prefix = ...
// you still must embed 'configfile.mod' and 'normal.mod' in 'core.img' in order
// to do that, which ends up tripling the file size...
// Also, as mentioned above, Fedora have started applying *BREAKING* patches
// willy-nilly, without bothering to alter the GRUB version string.
// Soooo, since the universe is conspiring against us and since we have already
// have a facility for it, we'll use it to dowload the relevant 'core.img' by
// appending a missing version suffix as needed...
if (img_report.grub2_version[0] != 0) {
if (has_grub_debug_is_enabled)
strcat(img_report.grub2_version, "-fedora");
if (img_report.has_grub2 > 1)
strcat(img_report.grub2_version, "-nonstandard");
}
}
BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
@ -1120,41 +1150,7 @@ out:
DeleteFileU(path);
}
if (img_report.grub2_version[0] != 0) {
// (Insert "Why is it always you three" meme, with Fedora, Manjaro and openSUSE)
// For some obscure reason, openSUSE have decided that their Live images should
// use /boot/grub2/ as their prefix directory instead of the standard /boot/grub/
// This creates a MAJOR issue because the prefix directory is hardcoded in
// 'core.img', and Rufus must install a 'core.img', that is not provided by the
// ISO, for the USB to boot (since even trying to pick the one from ISOHybrid
// does usually not guarantees the presence of the FAT driver which is mandatory
// for ISO boot).
// Therefore, when *someone* uses a nonstandard GRUB prefix directory, our base
// 'core.img' can't work with their image, since it isn't able to load modules
// like 'normal.mod', that are required to access the configuration files. Oh and
// you can forget about direct editing the prefix string inside 'core.img' since
// GRUB are forcing LZMA compression for BIOS payloads. And it gets even better,
// because even if you're trying to be smart and use GRUB's earlyconfig features
// to do something like:
// if [ -e /boot/grub2/i386-pc/normal.mod ]; then set prefix = ...
// you still must embed 'configfile.mod' and 'normal.mod' in 'core.img' in order
// to do that, which ends up tripling the file size...
// Soooo, since the universe is conspiring against us and in order to cut a long
// story short about developers making annoying decisions, we'll take advantage
// of the fact that the LZMA replacement section for the 2.04 and 2.06 'core.img'
// when using '/boot/grub2' as a prefix is very small and always located at the
// very end the file to patch the damn thing and get on with our life!
uprintf(" Detected Grub version: %s%s", img_report.grub2_version,
img_report.has_grub2 > 1 ? " with NONSTANDARD prefix" : "");
if (img_report.has_grub2 > 1) {
for (k = 0; k < ARRAYSIZE(grub_patch); k++) {
if (strcmp(img_report.grub2_version, grub_patch[k].version) == 0)
break;
}
if (k >= ARRAYSIZE(grub_patch)) {
uprintf(" • Don't have a prefix patch for this version => DROPPED!");
img_report.has_grub2 = 0;
}
}
uprintf(" Detected Grub version: %s", img_report.grub2_version);
} else {
uprintf(" Could not detect Grub version");
img_report.has_grub2 = 0;

View File

@ -398,7 +398,7 @@ typedef struct {
uint16_t sl_version; // Syslinux/Isolinux version
char sl_version_str[12];
char sl_version_ext[32];
char grub2_version[32];
char grub2_version[64];
} RUFUS_IMG_REPORT;
/* Isolate the Syslinux version numbers */
@ -693,23 +693,6 @@ extern void StrArrayClear(StrArray* arr);
extern void StrArrayDestroy(StrArray* arr);
#define IsStrArrayEmpty(arr) (arr.Index == 0)
/* Patch structs for GRUB */
typedef struct {
const uint32_t offset;
const uint32_t size;
const uint8_t data[];
} chunk_t;
typedef struct {
const chunk_t* src;
const chunk_t* rep;
} patch_t;
typedef struct {
const char* version;
const patch_t patch[2];
} grub_patch_t;
/*
* typedefs for the function prototypes. Use the something like:
* PF_DECL(FormatEx);

View File

@ -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 3.21.1937"
CAPTION "Rufus 3.21.1938"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -395,8 +395,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,21,1937,0
PRODUCTVERSION 3,21,1937,0
FILEVERSION 3,21,1938,0
PRODUCTVERSION 3,21,1938,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -414,13 +414,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.21.1937"
VALUE "FileVersion", "3.21.1938"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2022 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-3.21.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.21.1937"
VALUE "ProductVersion", "3.21.1938"
END
END
BLOCK "VarFileInfo"