diff --git a/0175-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch b/0175-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch new file mode 100644 index 0000000..5728f26 --- /dev/null +++ b/0175-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch @@ -0,0 +1,315 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Sat, 8 May 2021 02:27:58 +0200 +Subject: [PATCH] appendedsig/x509: Also handle the Extended Key Usage + extension + +Red Hat certificates have both Key Usage and Extended Key Usage extensions +present, but the appended signatures x509 parser doesn't handle the latter +and so buils due finding an unrecognised critical extension: + +Error loading initial key: +../../grub-core/commands/appendedsig/x509.c:780:Unhandled critical x509 extension with OID 2.5.29.37 + +Fix this by also parsing the Extended Key Usage extension and handle it by +verifying that the certificate has a single purpose, that is code signing. + +Signed-off-by: Javier Martinez Canillas +Signed-off-by: Daniel Axtens +--- + grub-core/commands/appendedsig/x509.c | 94 ++++++++++++++++++++++++++++++- + grub-core/tests/appended_signature_test.c | 29 +++++++++- + grub-core/tests/appended_signatures.h | 81 ++++++++++++++++++++++++++ + 3 files changed, 201 insertions(+), 3 deletions(-) + +diff --git a/grub-core/commands/appendedsig/x509.c b/grub-core/commands/appendedsig/x509.c +index 2b38b3670a..42ec65c54a 100644 +--- a/grub-core/commands/appendedsig/x509.c ++++ b/grub-core/commands/appendedsig/x509.c +@@ -47,6 +47,12 @@ const char *keyUsage_oid = "2.5.29.15"; + */ + const char *basicConstraints_oid = "2.5.29.19"; + ++/* ++ * RFC 5280 4.2.1.12 Extended Key Usage ++ */ ++const char *extendedKeyUsage_oid = "2.5.29.37"; ++const char *codeSigningUsage_oid = "1.3.6.1.5.5.7.3.3"; ++ + /* + * RFC 3279 2.3.1 + * +@@ -637,6 +643,77 @@ cleanup: + return err; + } + ++/* ++ * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId ++ * ++ * KeyPurposeId ::= OBJECT IDENTIFIER ++ */ ++static grub_err_t ++verify_extended_key_usage (grub_uint8_t * value, int value_size) ++{ ++ asn1_node extendedasn; ++ int result, count; ++ grub_err_t err = GRUB_ERR_NONE; ++ char usage[MAX_OID_LEN]; ++ int usage_size = sizeof (usage); ++ ++ result = ++ asn1_create_element (_gnutls_pkix_asn, "PKIX1.ExtKeyUsageSyntax", ++ &extendedasn); ++ if (result != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not create ASN.1 structure for Extended Key Usage"); ++ } ++ ++ result = asn1_der_decoding2 (&extendedasn, value, &value_size, ++ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error parsing DER for Extended Key Usage: %s", ++ asn1_error); ++ goto cleanup; ++ } ++ ++ /* ++ * If EKUs are present, there must be exactly 1 and it must be a ++ * codeSigning usage. ++ */ ++ result = asn1_number_of_elements(extendedasn, "", &count); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error counting number of Extended Key Usages: %s", ++ asn1_strerror (result)); ++ goto cleanup; ++ } ++ ++ result = asn1_read_value (extendedasn, "?1", usage, &usage_size); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading Extended Key Usage: %s", ++ asn1_strerror (result)); ++ goto cleanup; ++ } ++ ++ if (grub_strncmp (codeSigningUsage_oid, usage, usage_size) != 0) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Unexpected Extended Key Usage OID, got: %s", ++ usage); ++ goto cleanup; ++ } ++ ++cleanup: ++ asn1_delete_structure (&extendedasn); ++ return err; ++} + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension +@@ -660,7 +737,7 @@ verify_extensions (asn1_node cert) + { + int result; + int ext, num_extensions = 0; +- int usage_present = 0, constraints_present = 0; ++ int usage_present = 0, constraints_present = 0, extended_usage_present = 0; + char *oid_path, *critical_path, *value_path; + char extnID[MAX_OID_LEN]; + int extnID_size; +@@ -754,6 +831,15 @@ verify_extensions (asn1_node cert) + } + constraints_present++; + } ++ else if (grub_strncmp (extendedKeyUsage_oid, extnID, extnID_size) == 0) ++ { ++ err = verify_extended_key_usage (value, value_size); ++ if (err != GRUB_ERR_NONE) ++ { ++ goto cleanup_value; ++ } ++ extended_usage_present++; ++ } + else if (grub_strncmp ("TRUE", critical, critical_size) == 0) + { + /* +@@ -785,6 +871,12 @@ verify_extensions (asn1_node cert) + "Unexpected number of basic constraints extensions - expected 1, got %d", + constraints_present); + } ++ if (extended_usage_present > 1) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Unexpected number of Extended Key Usage extensions - expected 0 or 1, got %d", ++ extended_usage_present); ++ } + return GRUB_ERR_NONE; + + cleanup_value: +diff --git a/grub-core/tests/appended_signature_test.c b/grub-core/tests/appended_signature_test.c +index 88a485200d..dbba061662 100644 +--- a/grub-core/tests/appended_signature_test.c ++++ b/grub-core/tests/appended_signature_test.c +@@ -111,6 +111,22 @@ static struct grub_procfs_entry certificate_printable_der_entry = { + .get_contents = get_certificate_printable_der + }; + ++static char * ++get_certificate_eku_der (grub_size_t * sz) ++{ ++ char *ret; ++ *sz = certificate_eku_der_len; ++ ret = grub_malloc (*sz); ++ if (ret) ++ grub_memcpy (ret, certificate_eku_der, *sz); ++ return ret; ++} ++ ++static struct grub_procfs_entry certificate_eku_der_entry = { ++ .name = "certificate_eku.der", ++ .get_contents = get_certificate_eku_der ++}; ++ + + static void + do_verify (const char *f, int is_valid) +@@ -149,6 +165,7 @@ appended_signature_test (void) + char *trust_args2[] = { (char *) "(proc)/certificate2.der", NULL }; + char *trust_args_printable[] = { (char *) "(proc)/certificate_printable.der", + NULL }; ++ char *trust_args_eku[] = { (char *) "(proc)/certificate_eku.der", NULL }; + char *distrust_args[] = { (char *) "1", NULL }; + char *distrust2_args[] = { (char *) "2", NULL }; + grub_err_t err; +@@ -157,6 +174,7 @@ appended_signature_test (void) + grub_procfs_register ("certificate2.der", &certificate2_der_entry); + grub_procfs_register ("certificate_printable.der", + &certificate_printable_der_entry); ++ grub_procfs_register ("certificate_eku.der", &certificate_eku_der_entry); + + cmd_trust = grub_command_find ("trust_certificate"); + if (!cmd_trust) +@@ -266,16 +284,23 @@ appended_signature_test (void) + + /* + * Lastly, check a certificate that uses printableString rather than +- * utf8String loads properly. ++ * utf8String loads properly, and that a certificate with an appropriate ++ * extended key usage loads. + */ + err = (cmd_trust->func) (cmd_trust, 1, trust_args_printable); + grub_test_assert (err == GRUB_ERR_NONE, +- "distrusting printable certificate failed: %d: %s", ++ "trusting printable certificate failed: %d: %s", ++ grub_errno, grub_errmsg); ++ ++ err = (cmd_trust->func) (cmd_trust, 1, trust_args_eku); ++ grub_test_assert (err == GRUB_ERR_NONE, ++ "trusting certificate with extended key usage failed: %d: %s", + grub_errno, grub_errmsg); + + grub_procfs_unregister (&certificate_der_entry); + grub_procfs_unregister (&certificate2_der_entry); + grub_procfs_unregister (&certificate_printable_der_entry); ++ grub_procfs_unregister (&certificate_eku_der_entry); + } + + GRUB_FUNCTIONAL_TEST (appended_signature_test, appended_signature_test); +diff --git a/grub-core/tests/appended_signatures.h b/grub-core/tests/appended_signatures.h +index aa3dc6278e..2e5ebd7d8b 100644 +--- a/grub-core/tests/appended_signatures.h ++++ b/grub-core/tests/appended_signatures.h +@@ -555,3 +555,84 @@ unsigned char certificate_printable_der[] = { + 0xd2 + }; + unsigned int certificate_printable_der_len = 829; ++ ++unsigned char certificate_eku_der[] = { ++ 0x30, 0x82, 0x03, 0x90, 0x30, 0x82, 0x02, 0x78, 0xa0, 0x03, 0x02, 0x01, ++ 0x02, 0x02, 0x09, 0x00, 0xd3, 0x9c, 0x41, 0x33, 0xdd, 0x6b, 0x5f, 0x45, ++ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, ++ 0x0b, 0x05, 0x00, 0x30, 0x47, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, ++ 0x04, 0x03, 0x0c, 0x18, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, ++ 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, ++ 0x43, 0x41, 0x20, 0x36, 0x31, 0x22, 0x30, 0x20, 0x06, 0x09, 0x2a, 0x86, ++ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x13, 0x73, 0x65, 0x63, ++ 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, 0x64, 0x68, 0x61, 0x74, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, ++ 0x31, 0x35, 0x31, 0x34, 0x30, 0x30, 0x34, 0x34, 0x5a, 0x17, 0x0d, 0x33, ++ 0x38, 0x30, 0x31, 0x31, 0x37, 0x31, 0x34, 0x30, 0x30, 0x34, 0x34, 0x5a, ++ 0x30, 0x4e, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, ++ 0x1f, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, 0x53, 0x65, 0x63, ++ 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x53, 0x69, 0x67, ++ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x36, 0x30, 0x32, 0x31, 0x22, 0x30, 0x20, ++ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, ++ 0x13, 0x73, 0x65, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, ++ 0x64, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, ++ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, ++ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, ++ 0x02, 0x82, 0x01, 0x01, 0x00, 0xaa, 0x6f, 0xbb, 0x92, 0x77, 0xd7, 0x15, ++ 0xef, 0x88, 0x80, 0x88, 0xc0, 0xe7, 0x89, 0xeb, 0x35, 0x76, 0xf4, 0x85, ++ 0x05, 0x0f, 0x19, 0xe4, 0x5f, 0x25, 0xdd, 0xc1, 0xa2, 0xe5, 0x5c, 0x06, ++ 0xfb, 0xf1, 0x06, 0xb5, 0x65, 0x45, 0xcb, 0xbd, 0x19, 0x33, 0x54, 0xb5, ++ 0x1a, 0xcd, 0xe4, 0xa8, 0x35, 0x2a, 0xfe, 0x9c, 0x53, 0xf4, 0xc6, 0x76, ++ 0xdb, 0x1f, 0x8a, 0xd4, 0x7b, 0x18, 0x11, 0xaf, 0xa3, 0x90, 0xd4, 0xdd, ++ 0x4d, 0xd5, 0x42, 0xcc, 0x14, 0x9a, 0x64, 0x6b, 0xc0, 0x7f, 0xaa, 0x1c, ++ 0x94, 0x47, 0x4d, 0x79, 0xbd, 0x57, 0x9a, 0xbf, 0x99, 0x4e, 0x96, 0xa9, ++ 0x31, 0x2c, 0xa9, 0xe7, 0x14, 0x65, 0x86, 0xc8, 0xac, 0x79, 0x5e, 0x78, ++ 0xa4, 0x3c, 0x00, 0x24, 0xd3, 0xf7, 0xe1, 0xf5, 0x12, 0xad, 0xa0, 0x29, ++ 0xe5, 0xfe, 0x80, 0xae, 0xf8, 0xaa, 0x60, 0x36, 0xe7, 0xe8, 0x94, 0xcb, ++ 0xe9, 0xd1, 0xcc, 0x0b, 0x4d, 0xf7, 0xde, 0xeb, 0x52, 0xd2, 0x73, 0x09, ++ 0x28, 0xdf, 0x48, 0x99, 0x53, 0x9f, 0xc5, 0x9a, 0xd4, 0x36, 0xa3, 0xc6, ++ 0x5e, 0x8d, 0xbe, 0xd5, 0xdc, 0x76, 0xb4, 0x74, 0xb8, 0x26, 0x18, 0x27, ++ 0xfb, 0xf2, 0xfb, 0xd0, 0x9b, 0x3d, 0x7f, 0x10, 0xe2, 0xab, 0x44, 0xc7, ++ 0x88, 0x7f, 0xb4, 0x3d, 0x3e, 0xa3, 0xff, 0x6d, 0x06, 0x4b, 0x3e, 0x55, ++ 0xb2, 0x84, 0xf4, 0xad, 0x54, 0x88, 0x81, 0xc3, 0x9c, 0xf8, 0xb6, 0x68, ++ 0x96, 0x38, 0x8b, 0xcd, 0x90, 0x6d, 0x25, 0x4b, 0xbf, 0x0c, 0x44, 0x90, ++ 0xa5, 0x5b, 0x98, 0xd0, 0x40, 0x2f, 0xbb, 0x0d, 0xa8, 0x4b, 0x8a, 0x62, ++ 0x82, 0x46, 0x46, 0x18, 0x38, 0xae, 0x82, 0x07, 0xd0, 0xb4, 0x2f, 0x16, ++ 0x79, 0x55, 0x9f, 0x1b, 0xc5, 0x08, 0x6d, 0x85, 0xdf, 0x3f, 0xa9, 0x9b, ++ 0x4b, 0xc6, 0x28, 0xd3, 0x58, 0x72, 0x3d, 0x37, 0x11, 0x02, 0x03, 0x01, ++ 0x00, 0x01, 0xa3, 0x78, 0x30, 0x76, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, ++ 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, ++ 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, ++ 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, ++ 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, ++ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x6c, ++ 0xe4, 0x6c, 0x27, 0xaa, 0xcd, 0x0d, 0x4b, 0x74, 0x21, 0xa4, 0xf6, 0x5f, ++ 0x87, 0xb5, 0x31, 0xfe, 0x10, 0xbb, 0xa7, 0x30, 0x1f, 0x06, 0x03, 0x55, ++ 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xe8, 0x6a, 0x1c, 0xab, ++ 0x2c, 0x48, 0xf9, 0x60, 0x36, 0xa2, 0xf0, 0x7b, 0x8e, 0xd2, 0x9d, 0xb4, ++ 0x2a, 0x28, 0x98, 0xc8, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, ++ 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, ++ 0x55, 0x34, 0xe2, 0xfa, 0xf6, 0x89, 0x86, 0xad, 0x92, 0x21, 0xec, 0xb9, ++ 0x54, 0x0e, 0x18, 0x47, 0x0d, 0x1b, 0xa7, 0x58, 0xad, 0x69, 0xe4, 0xef, ++ 0x3b, 0xe6, 0x8d, 0xdd, 0xda, 0x0c, 0x45, 0xf6, 0xe8, 0x96, 0xa4, 0x29, ++ 0x0f, 0xbb, 0xcf, 0x16, 0xae, 0x93, 0xd0, 0xcb, 0x2a, 0x26, 0x1a, 0x7b, ++ 0xfc, 0x51, 0x22, 0x76, 0x98, 0x31, 0xa7, 0x0f, 0x29, 0x35, 0x79, 0xbf, ++ 0xe2, 0x4f, 0x0f, 0x14, 0xf5, 0x1f, 0xcb, 0xbf, 0x87, 0x65, 0x13, 0x32, ++ 0xa3, 0x19, 0x4a, 0xd1, 0x3f, 0x45, 0xd4, 0x4b, 0xe2, 0x00, 0x26, 0xa9, ++ 0x3e, 0xd7, 0xa5, 0x37, 0x9f, 0xf5, 0xad, 0x61, 0xe2, 0x40, 0xa9, 0x74, ++ 0x24, 0x53, 0xf2, 0x78, 0xeb, 0x10, 0x9b, 0x2c, 0x27, 0x88, 0x46, 0xcb, ++ 0xe4, 0x60, 0xca, 0xf5, 0x06, 0x24, 0x40, 0x2a, 0x97, 0x3a, 0xcc, 0xd0, ++ 0x81, 0xb1, 0x15, 0xa3, 0x4f, 0xd0, 0x2b, 0x4f, 0xca, 0x6e, 0xaa, 0x24, ++ 0x31, 0xb3, 0xac, 0xa6, 0x75, 0x05, 0xfe, 0x8a, 0xf4, 0x41, 0xc4, 0x06, ++ 0x8a, 0xc7, 0x0a, 0x83, 0x4e, 0x49, 0xd4, 0x3f, 0x83, 0x50, 0xec, 0x57, ++ 0x04, 0x97, 0x14, 0x49, 0xf5, 0xe1, 0xb1, 0x7a, 0x9c, 0x09, 0x4f, 0x61, ++ 0x87, 0xc3, 0x97, 0x22, 0x17, 0xc2, 0xeb, 0xcc, 0x32, 0x81, 0x31, 0x21, ++ 0x3f, 0x10, 0x57, 0x5b, 0x43, 0xbe, 0xcd, 0x68, 0x82, 0xbe, 0xe5, 0xc1, ++ 0x65, 0x94, 0x7e, 0xc2, 0x34, 0x76, 0x2b, 0xcf, 0x89, 0x3c, 0x2b, 0x81, ++ 0x23, 0x72, 0x95, 0xcf, 0xc9, 0x67, 0x19, 0x2a, 0xd5, 0x5c, 0xca, 0xa3, ++ 0x46, 0xbd, 0x48, 0x06, 0x0b, 0xa6, 0xa3, 0x96, 0x50, 0x28, 0xc7, 0x7e, ++ 0xcf, 0x62, 0xf2, 0xfa, 0xc4, 0xf2, 0x53, 0xe3, 0xc9, 0xe8, 0x2e, 0xdd, ++ 0x29, 0x37, 0x07, 0x47, 0xff, 0xff, 0x8a, 0x32, 0xbd, 0xa2, 0xb7, 0x21, ++ 0x89, 0xa0, 0x55, 0xf7 ++}; ++unsigned int certificate_eku_der_len = 916; diff --git a/0175-ieee1275-claim-more-memory.patch b/0175-ieee1275-claim-more-memory.patch deleted file mode 100644 index 6ec319b..0000000 --- a/0175-ieee1275-claim-more-memory.patch +++ /dev/null @@ -1,252 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Wed, 15 Apr 2020 23:28:29 +1000 -Subject: [PATCH] ieee1275: claim more memory - -On powerpc-ieee1275, we are running out of memory trying to verify -anything. This is because: - - - we have to load an entire file into memory to verify it. This is - extremely difficult to change with appended signatures. - - We only have 32MB of heap. - - Distro kernels are now often around 30MB. - -So we want to claim more memory from OpenFirmware for our heap. - -There are some complications: - - - The grub mm code isn't the only thing that will make claims on - memory from OpenFirmware: - - * PFW/SLOF will have claimed some for their own use. - - * The ieee1275 loader will try to find other bits of memory that we - haven't claimed to place the kernel and initrd when we go to boot. - - * Once we load Linux, it will also try to claim memory. It claims - memory without any reference to /memory/available, it just starts - at min(top of RMO, 768MB) and works down. So we need to avoid this - area. See arch/powerpc/kernel/prom_init.c as of v5.11. - - - The smallest amount of memory a ppc64 KVM guest can have is 256MB. - It doesn't work with distro kernels but can work with custom kernels. - We should maintain support for that. (ppc32 can boot with even less, - and we shouldn't break that either.) - - - Even if a VM has more memory, the memory OpenFirmware makes available - as Real Memory Area can be restricted. A freshly created LPAR on a - PowerVM machine is likely to have only 256MB available to OpenFirmware - even if it has many gigabytes of memory allocated. - -EFI systems will attempt to allocate 1/4th of the available memory, -clamped to between 1M and 1600M. That seems like a good sort of -approach, we just need to figure out if 1/4 is the right fraction -for us. - -We don't know in advance how big the kernel and initrd are going to be, -which makes figuring out how much memory we can take a bit tricky. - -To figure out how much memory we should leave unused, I looked at: - - - an Ubuntu 20.04.1 ppc64le pseries KVM guest: - vmlinux: ~30MB - initrd: ~50MB - - - a RHEL8.2 ppc64le pseries KVM guest: - vmlinux: ~30MB - initrd: ~30MB - -Ubuntu VMs struggle to boot with just 256MB under SLOF. -RHEL likewise has a higher minimum supported memory figure. -So lets first consider a distro kernel and 512MB of addressible memory. -(This is the default case for anything booting under PFW.) Say we lose -131MB to PFW (based on some tests). This leaves us 381MB. 1/4 of 381MB -is ~95MB. That should be enough to verify a 30MB vmlinux and should -leave plenty of space to load Linux and the initrd. - -If we consider 256MB of RMA under PFW, we have just 125MB remaining. 1/4 -of that is a smidge under 32MB, which gives us very poor odds of verifying -a distro-sized kernel. However, if we need 80MB just to put the kernel -and initrd in memory, we can't claim any more than 45MB anyway. So 1/4 -will do. We'll come back to this later. - -grub is always built as a 32-bit binary, even if it's loading a ppc64 -kernel. So we can't address memory beyond 4GB. This gives a natural cap -of 1GB for powerpc-ieee1275. - -Also apply this 1/4 approach to i386-ieee1275, but keep the 32MB cap. - -make check still works for both i386 and powerpc and I've booted -powerpc grub with this change under SLOF and PFW. - -Signed-off-by: Daniel Axtens ---- - grub-core/kern/ieee1275/init.c | 81 +++++++++++++++++++++++++++++++++--------- - docs/grub-dev.texi | 6 ++-- - 2 files changed, 69 insertions(+), 18 deletions(-) - -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index 0dcd114ce5..c61d91a028 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -46,11 +46,12 @@ - #endif - #include - --/* The maximum heap size we're going to claim */ -+/* The maximum heap size we're going to claim. Not used by sparc. -+ We allocate 1/4 of the available memory under 4G, up to this limit. */ - #ifdef __i386__ - #define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024) --#else --#define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024) -+#else // __powerpc__ -+#define HEAP_MAX_SIZE (unsigned long) (1 * 1024 * 1024 * 1024) - #endif - - extern char _end[]; -@@ -147,16 +148,45 @@ grub_claim_heap (void) - + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); - } - #else --/* Helper for grub_claim_heap. */ -+/* Helper for grub_claim_heap on powerpc. */ -+static int -+heap_size (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, -+ void *data) -+{ -+ grub_uint32_t total = *(grub_uint32_t *)data; -+ -+ if (type != GRUB_MEMORY_AVAILABLE) -+ return 0; -+ -+ /* Do not consider memory beyond 4GB */ -+ if (addr > 0xffffffffUL) -+ return 0; -+ -+ if (addr + len > 0xffffffffUL) -+ len = 0xffffffffUL - addr; -+ -+ total += len; -+ *(grub_uint32_t *)data = total; -+ -+ return 0; -+} -+ - static int - heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - void *data) - { -- unsigned long *total = data; -+ grub_uint32_t total = *(grub_uint32_t *)data; - - if (type != GRUB_MEMORY_AVAILABLE) - return 0; - -+ /* Do not consider memory beyond 4GB */ -+ if (addr > 0xffffffffUL) -+ return 0; -+ -+ if (addr + len > 0xffffffffUL) -+ len = 0xffffffffUL - addr; -+ - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) - { - if (addr + len <= 0x180000) -@@ -170,10 +200,6 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - } - len -= 1; /* Required for some firmware. */ - -- /* Never exceed HEAP_MAX_SIZE */ -- if (*total + len > HEAP_MAX_SIZE) -- len = HEAP_MAX_SIZE - *total; -- - /* In theory, firmware should already prevent this from happening by not - listing our own image in /memory/available. The check below is intended - as a safeguard in case that doesn't happen. However, it doesn't protect -@@ -185,6 +211,18 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - len = 0; - } - -+ /* If this block contains 0x30000000 (768MB), do not claim below that. -+ Linux likes to claim memory at min(RMO top, 768MB) and works down -+ without reference to /memory/available. */ -+ if ((addr < 0x30000000) && ((addr + len) > 0x30000000)) -+ { -+ len = len - (0x30000000 - addr); -+ addr = 0x30000000; -+ } -+ -+ if (len > total) -+ len = total; -+ - if (len) - { - grub_err_t err; -@@ -193,10 +231,12 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - if (err) - return err; - grub_mm_init_region ((void *) (grub_addr_t) addr, len); -+ total -= len; - } - -- *total += len; -- if (*total >= HEAP_MAX_SIZE) -+ *(grub_uint32_t *)data = total; -+ -+ if (total == 0) - return 1; - - return 0; -@@ -205,13 +245,22 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - static void - grub_claim_heap (void) - { -- unsigned long total = 0; -+ grub_uint32_t total = 0; - - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) -- heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN, -- 1, &total); -- else -- grub_machine_mmap_iterate (heap_init, &total); -+ { -+ heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN, -+ 1, &total); -+ return; -+ } -+ -+ grub_machine_mmap_iterate (heap_size, &total); -+ -+ total = total / 4; -+ if (total > HEAP_MAX_SIZE) -+ total = HEAP_MAX_SIZE; -+ -+ grub_machine_mmap_iterate (heap_init, &total); - } - #endif - -diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi -index 19f708ee66..90083772c8 100644 ---- a/docs/grub-dev.texi -+++ b/docs/grub-dev.texi -@@ -1047,7 +1047,9 @@ space is limited to 4GiB. GRUB allocates pages from EFI for its heap, at most - 1.6 GiB. - - On i386-ieee1275 and powerpc-ieee1275 GRUB uses same stack as IEEE1275. --It allocates at most 32MiB for its heap. -+ -+On i386-ieee1275, GRUB allocates at most 32MiB for its heap. On -+powerpc-ieee1275, GRUB allocates up to 1GiB. - - On sparc64-ieee1275 stack is 256KiB and heap is 2MiB. - -@@ -1075,7 +1077,7 @@ In short: - @item i386-qemu @tab 60 KiB @tab < 4 GiB - @item *-efi @tab ? @tab < 1.6 GiB - @item i386-ieee1275 @tab ? @tab < 32 MiB --@item powerpc-ieee1275 @tab ? @tab < 32 MiB -+@item powerpc-ieee1275 @tab ? @tab < 1 GiB - @item sparc64-ieee1275 @tab 256KiB @tab 2 MiB - @item arm-uboot @tab 256KiB @tab 2 MiB - @item mips(el)-qemu_mips @tab 2MiB @tab 253 MiB diff --git a/0176-ieee1275-ofdisk-retry-on-open-failure.patch b/0176-ieee1275-ofdisk-retry-on-open-failure.patch new file mode 100644 index 0000000..9149773 --- /dev/null +++ b/0176-ieee1275-ofdisk-retry-on-open-failure.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Diego Domingos +Date: Wed, 10 Mar 2021 14:17:52 -0500 +Subject: [PATCH] ieee1275/ofdisk: retry on open failure + +This patch aims to make grub more robust when booting from SAN/Multipath disks. + +If a path is failing intermittently so grub will retry the OPEN and READ the +disk (grub_ieee1275_open and grub_ieee1275_read) until the total amount of times +specified in MAX_RETRIES. + +Signed-off-by: Diego Domingos +--- + grub-core/disk/ieee1275/ofdisk.c | 25 ++++++++++++++++++++----- + include/grub/ieee1275/ofdisk.h | 8 ++++++++ + 2 files changed, 28 insertions(+), 5 deletions(-) + +diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c +index ea7f78ac7d..55346849d3 100644 +--- a/grub-core/disk/ieee1275/ofdisk.c ++++ b/grub-core/disk/ieee1275/ofdisk.c +@@ -225,7 +225,9 @@ dev_iterate (const struct grub_ieee1275_devalias *alias) + char *buf, *bufptr; + unsigned i; + +- if (grub_ieee1275_open (alias->path, &ihandle)) ++ ++ RETRY_IEEE1275_OFDISK_OPEN(alias->path, &ihandle) ++ if (! ihandle) + return; + + /* This method doesn't need memory allocation for the table. Open +@@ -305,7 +307,9 @@ dev_iterate (const struct grub_ieee1275_devalias *alias) + return; + } + +- if (grub_ieee1275_open (alias->path, &ihandle)) ++ RETRY_IEEE1275_OFDISK_OPEN(alias->path, &ihandle); ++ ++ if (! ihandle) + { + grub_free (buf); + grub_free (table); +@@ -495,7 +499,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) + last_ihandle = 0; + last_devpath = NULL; + +- grub_ieee1275_open (op->open_path, &last_ihandle); ++ RETRY_IEEE1275_OFDISK_OPEN(op->open_path, &last_ihandle); + if (! last_ihandle) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + last_devpath = op->open_path; +@@ -571,7 +575,7 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) + last_ihandle = 0; + last_devpath = NULL; + +- grub_ieee1275_open (disk->data, &last_ihandle); ++ RETRY_IEEE1275_OFDISK_OPEN(disk->data, &last_ihandle); + if (! last_ihandle) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + last_devpath = disk->data; +@@ -598,12 +602,23 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + return err; + grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, + &actual); +- if (actual != (grub_ssize_t) (size << disk->log_sector_size)) ++ int i = 0; ++ while(actual != (grub_ssize_t) (size << disk->log_sector_size)){ ++ if (i>MAX_RETRIES){ + return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " + "from `%s'"), + (unsigned long long) sector, + disk->name); ++ } ++ last_devpath = NULL; ++ err = grub_ofdisk_prepare (disk, sector); ++ if (err) ++ return err; + ++ grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, ++ &actual); ++ i++; ++ } + return 0; + } + +diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h +index 2f69e3f191..7d2d540930 100644 +--- a/include/grub/ieee1275/ofdisk.h ++++ b/include/grub/ieee1275/ofdisk.h +@@ -22,4 +22,12 @@ + extern void grub_ofdisk_init (void); + extern void grub_ofdisk_fini (void); + ++#define MAX_RETRIES 20 ++ ++ ++#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) unsigned retry_i=0;for(retry_i=0; retry_i < MAX_RETRIES; retry_i++){ \ ++ if(!grub_ieee1275_open(device, last_ihandle)) \ ++ break; \ ++ grub_dprintf("ofdisk","Opening disk %s failed. Retrying...\n",device); } ++ + #endif /* ! GRUB_INIT_HEADER */ diff --git a/0176-ieee1275-request-memory-with-ibm-client-architecture.patch b/0176-ieee1275-request-memory-with-ibm-client-architecture.patch deleted file mode 100644 index 4f3ab90..0000000 --- a/0176-ieee1275-request-memory-with-ibm-client-architecture.patch +++ /dev/null @@ -1,268 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 16 Apr 2021 11:48:46 +1000 -Subject: [PATCH] ieee1275: request memory with ibm,client-architecture-support - -On PowerVM, the first time we boot a Linux partition, we may only get -256MB of real memory area, even if the partition has more memory. - -This isn't really enough. Fortunately, the Power Architecture Platform -Reference (PAPR) defines a method we can call to ask for more memory. -This is part of the broad and powerful ibm,client-architecture-support -(CAS) method. - -CAS can do an enormous amount of things on a PAPR platform: as well as -asking for memory, you can set the supported processor level, the interrupt -controller, hash vs radix mmu, and so on. We want to touch as little of -this as possible because we don't want to step on the toes of the future OS. - -If: - - - we are running under what we think is PowerVM (compatible property of / - begins with "IBM"), and - - - the full amount of RMA is less than 512MB (as determined by the reg - property of /memory) - -then call CAS as follows: (refer to the Linux on Power Architecture -Reference, LoPAR, which is public, at B.5.2.3): - - - Use the "any" PVR value and supply 2 option vectors. - - - Set option vector 1 (PowerPC Server Processor Architecture Level) - to "ignore". - - - Set option vector 2 with default or Linux-like options, including a - min-rma-size of 512MB. - -This will cause a CAS reboot and the partition will restart with 512MB -of RMA. Grub will notice the 512MB and not call CAS again. - -(A partition can be configured with only 256MB of memory, which would -mean this request couldn't be satisfied, but PFW refuses to load with -only 256MB of memory, so it's a bit moot. SLOF will run fine with 256MB, -but we will never call CAS under qemu/SLOF because /compatible won't -begin with "IBM".) - -One of the first things Linux does while still running under OpenFirmware -is to call CAS with a much fuller set of options (including asking for -512MB of memory). This includes a much more restrictive set of PVR values -and processor support levels, and this will induce another reboot. On this -reboot grub will again notice the higher RMA, and not call CAS. We will get -to Linux, Linux will call CAS but because the values are now set for Linux -this will not induce another CAS reboot and we will finally boot. - -On all subsequent boots, everything will be configured with 512MB of RMA -and all the settings Linux likes, so there will be no further CAS reboots. - -(phyp is super sticky with the RMA size - it persists even on cold boots. -So if you've ever booted Linux in a partition, you'll probably never have -grub call CAS. It'll only ever fire the first time a partition loads grub, -or if you deliberately lower the amount of memory your partition has below -512MB.) - -Signed-off-by: Daniel Axtens ---- - grub-core/kern/ieee1275/cmain.c | 3 + - grub-core/kern/ieee1275/init.c | 144 ++++++++++++++++++++++++++++++++++++++- - include/grub/ieee1275/ieee1275.h | 8 ++- - 3 files changed, 152 insertions(+), 3 deletions(-) - -diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c -index 04df9d2c66..6435628ec5 100644 ---- a/grub-core/kern/ieee1275/cmain.c -+++ b/grub-core/kern/ieee1275/cmain.c -@@ -127,6 +127,9 @@ grub_ieee1275_find_options (void) - break; - } - } -+ -+ if (grub_strncmp (tmp, "IBM,", 4) == 0) -+ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY); - } - - if (is_smartfirmware) -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index c61d91a028..9704715c83 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -242,6 +242,135 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - return 0; - } - -+/* How much memory does OF believe it has? (regardless of whether -+ it's accessible or not) */ -+static grub_err_t -+grub_ieee1275_total_mem (grub_uint64_t *total) -+{ -+ grub_ieee1275_phandle_t root; -+ grub_ieee1275_phandle_t memory; -+ grub_uint32_t reg[4]; -+ grub_ssize_t reg_size; -+ grub_uint32_t address_cells = 1; -+ grub_uint32_t size_cells = 1; -+ grub_uint64_t size; -+ -+ /* If we fail to get to the end, report 0. */ -+ *total = 0; -+ -+ /* Determine the format of each entry in `reg'. */ -+ grub_ieee1275_finddevice ("/", &root); -+ grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells, -+ sizeof address_cells, 0); -+ grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells, -+ sizeof size_cells, 0); -+ -+ if (size_cells > address_cells) -+ address_cells = size_cells; -+ -+ /* Load `/memory/reg'. */ -+ if (grub_ieee1275_finddevice ("/memory", &memory)) -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, -+ "couldn't find /memory node"); -+ if (grub_ieee1275_get_integer_property (memory, "reg", reg, -+ sizeof reg, ®_size)) -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, -+ "couldn't examine /memory/reg property"); -+ if (reg_size < 0 || (grub_size_t) reg_size > sizeof (reg)) -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, -+ "/memory response buffer exceeded"); -+ -+ if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS)) -+ { -+ address_cells = 1; -+ size_cells = 1; -+ } -+ -+ /* Decode only the size */ -+ size = reg[address_cells]; -+ if (size_cells == 2) -+ size = (size << 32) | reg[address_cells + 1]; -+ -+ *total = size; -+ -+ return grub_errno; -+} -+ -+/* Based on linux - arch/powerpc/kernel/prom_init.c */ -+struct option_vector2 { -+ grub_uint8_t byte1; -+ grub_uint16_t reserved; -+ grub_uint32_t real_base; -+ grub_uint32_t real_size; -+ grub_uint32_t virt_base; -+ grub_uint32_t virt_size; -+ grub_uint32_t load_base; -+ grub_uint32_t min_rma; -+ grub_uint32_t min_load; -+ grub_uint8_t min_rma_percent; -+ grub_uint8_t max_pft_size; -+} __attribute__((packed)); -+ -+struct pvr_entry { -+ grub_uint32_t mask; -+ grub_uint32_t entry; -+}; -+ -+struct cas_vector { -+ struct { -+ struct pvr_entry terminal; -+ } pvr_list; -+ grub_uint8_t num_vecs; -+ grub_uint8_t vec1_size; -+ grub_uint8_t vec1; -+ grub_uint8_t vec2_size; -+ struct option_vector2 vec2; -+} __attribute__((packed)); -+ -+/* Call ibm,client-architecture-support to try to get more RMA. -+ We ask for 512MB which should be enough to verify a distro kernel. -+ We ignore most errors: if we don't succeed we'll proceed with whatever -+ memory we have. */ -+static void -+grub_ieee1275_ibm_cas (void) -+{ -+ int rc; -+ grub_ieee1275_ihandle_t root; -+ struct cas_args { -+ struct grub_ieee1275_common_hdr common; -+ grub_ieee1275_cell_t method; -+ grub_ieee1275_ihandle_t ihandle; -+ grub_ieee1275_cell_t cas_addr; -+ grub_ieee1275_cell_t result; -+ } args; -+ struct cas_vector vector = { -+ .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ -+ .num_vecs = 2 - 1, -+ .vec1_size = 0, -+ .vec1 = 0x80, /* ignore */ -+ .vec2_size = 1 + sizeof(struct option_vector2) - 2, -+ .vec2 = { -+ 0, 0, -1, -1, -1, -1, -1, 512, -1, 0, 48 -+ }, -+ }; -+ -+ INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); -+ args.method = (grub_ieee1275_cell_t)"ibm,client-architecture-support"; -+ rc = grub_ieee1275_open("/", &root); -+ if (rc) { -+ grub_error (GRUB_ERR_IO, "could not open root when trying to call CAS"); -+ return; -+ } -+ args.ihandle = root; -+ args.cas_addr = (grub_ieee1275_cell_t)&vector; -+ -+ grub_printf("Calling ibm,client-architecture-support..."); -+ IEEE1275_CALL_ENTRY_FN (&args); -+ grub_printf("done\n"); -+ -+ grub_ieee1275_close(root); -+} -+ - static void - grub_claim_heap (void) - { -@@ -249,11 +378,22 @@ grub_claim_heap (void) - - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) - { -- heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN, -- 1, &total); -+ heap_init (GRUB_IEEE1275_STATIC_HEAP_START, -+ GRUB_IEEE1275_STATIC_HEAP_LEN, 1, &total); - return; - } - -+ if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY)) -+ { -+ grub_uint64_t rma_size; -+ grub_err_t err; -+ -+ err = grub_ieee1275_total_mem (&rma_size); -+ /* if we have an error, don't call CAS, just hope for the best */ -+ if (!err && rma_size < (512 * 1024 * 1024)) -+ grub_ieee1275_ibm_cas(); -+ } -+ - grub_machine_mmap_iterate (heap_size, &total); - - total = total / 4; -diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h -index b5a1d49bbc..e0a6c2ce1e 100644 ---- a/include/grub/ieee1275/ieee1275.h -+++ b/include/grub/ieee1275/ieee1275.h -@@ -149,7 +149,13 @@ enum grub_ieee1275_flag - - GRUB_IEEE1275_FLAG_RAW_DEVNAMES, - -- GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT -+ GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT, -+ -+ /* On PFW, the first time we boot a Linux partition, we may only get 256MB -+ of real memory area, even if the partition has more memory. Set this flag -+ if we think we're running under PFW. Then, if this flag is set, and the -+ RMA is only 256MB in size, try asking for more with CAS. */ -+ GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY, - }; - - extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag); diff --git a/0177-Allow-chainloading-EFI-apps-from-loop-mounts.patch b/0177-Allow-chainloading-EFI-apps-from-loop-mounts.patch new file mode 100644 index 0000000..c3101e1 --- /dev/null +++ b/0177-Allow-chainloading-EFI-apps-from-loop-mounts.patch @@ -0,0 +1,138 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Fri, 11 Jun 2021 13:51:20 +0200 +Subject: [PATCH] Allow chainloading EFI apps from loop mounts. + +Signed-off-by: Dimitri John Ledkov +Signed-off-by: Robbie Harwood +--- + grub-core/disk/loopback.c | 9 +-------- + grub-core/loader/efi/chainloader.c | 23 +++++++++++++++++++++++ + include/grub/loopback.h | 30 ++++++++++++++++++++++++++++++ + 3 files changed, 54 insertions(+), 8 deletions(-) + create mode 100644 include/grub/loopback.h + +diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c +index 41bebd14fe..99f47924ec 100644 +--- a/grub-core/disk/loopback.c ++++ b/grub-core/disk/loopback.c +@@ -21,20 +21,13 @@ + #include + #include + #include ++#include + #include + #include + #include + + GRUB_MOD_LICENSE ("GPLv3+"); + +-struct grub_loopback +-{ +- char *devname; +- grub_file_t file; +- struct grub_loopback *next; +- unsigned long id; +-}; +- + static struct grub_loopback *loopback_list; + static unsigned long last_id = 0; + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index d41e8ea14a..3af6b12292 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -901,6 +902,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_efi_status_t status; + grub_efi_boot_services_t *b; + grub_device_t dev = 0; ++ grub_device_t orig_dev = 0; + grub_efi_device_path_t *dp = 0; + char *filename; + void *boot_image = 0; +@@ -958,6 +960,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + if (! dev) + goto fail; + ++ /* if device is loopback, use underlying dev */ ++ if (dev->disk->dev->id == GRUB_DISK_DEVICE_LOOPBACK_ID) ++ { ++ struct grub_loopback *d; ++ orig_dev = dev; ++ d = dev->disk->data; ++ dev = d->file->device; ++ } ++ + if (dev->disk) + dev_handle = grub_efidisk_get_device_handle (dev->disk); + else if (dev->net && dev->net->server) +@@ -1065,6 +1076,12 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + } + #endif + ++ if (orig_dev) ++ { ++ dev = orig_dev; ++ orig_dev = 0; ++ } ++ + rc = grub_linuxefi_secure_validate((void *)(unsigned long)address, fsize); + grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc); + if (rc > 0) +@@ -1087,6 +1104,12 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + // -1 fall-through to fail + + fail: ++ if (orig_dev) ++ { ++ dev = orig_dev; ++ orig_dev = 0; ++ } ++ + if (dev) + grub_device_close (dev); + +diff --git a/include/grub/loopback.h b/include/grub/loopback.h +new file mode 100644 +index 0000000000..3b9a9e32e8 +--- /dev/null ++++ b/include/grub/loopback.h +@@ -0,0 +1,30 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2019 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_LOOPBACK_HEADER ++#define GRUB_LOOPBACK_HEADER 1 ++ ++struct grub_loopback ++{ ++ char *devname; ++ grub_file_t file; ++ struct grub_loopback *next; ++ unsigned long id; ++}; ++ ++#endif /* ! GRUB_LOOPBACK_HEADER */ diff --git a/0177-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch b/0177-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch deleted file mode 100644 index 5728f26..0000000 --- a/0177-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Sat, 8 May 2021 02:27:58 +0200 -Subject: [PATCH] appendedsig/x509: Also handle the Extended Key Usage - extension - -Red Hat certificates have both Key Usage and Extended Key Usage extensions -present, but the appended signatures x509 parser doesn't handle the latter -and so buils due finding an unrecognised critical extension: - -Error loading initial key: -../../grub-core/commands/appendedsig/x509.c:780:Unhandled critical x509 extension with OID 2.5.29.37 - -Fix this by also parsing the Extended Key Usage extension and handle it by -verifying that the certificate has a single purpose, that is code signing. - -Signed-off-by: Javier Martinez Canillas -Signed-off-by: Daniel Axtens ---- - grub-core/commands/appendedsig/x509.c | 94 ++++++++++++++++++++++++++++++- - grub-core/tests/appended_signature_test.c | 29 +++++++++- - grub-core/tests/appended_signatures.h | 81 ++++++++++++++++++++++++++ - 3 files changed, 201 insertions(+), 3 deletions(-) - -diff --git a/grub-core/commands/appendedsig/x509.c b/grub-core/commands/appendedsig/x509.c -index 2b38b3670a..42ec65c54a 100644 ---- a/grub-core/commands/appendedsig/x509.c -+++ b/grub-core/commands/appendedsig/x509.c -@@ -47,6 +47,12 @@ const char *keyUsage_oid = "2.5.29.15"; - */ - const char *basicConstraints_oid = "2.5.29.19"; - -+/* -+ * RFC 5280 4.2.1.12 Extended Key Usage -+ */ -+const char *extendedKeyUsage_oid = "2.5.29.37"; -+const char *codeSigningUsage_oid = "1.3.6.1.5.5.7.3.3"; -+ - /* - * RFC 3279 2.3.1 - * -@@ -637,6 +643,77 @@ cleanup: - return err; - } - -+/* -+ * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId -+ * -+ * KeyPurposeId ::= OBJECT IDENTIFIER -+ */ -+static grub_err_t -+verify_extended_key_usage (grub_uint8_t * value, int value_size) -+{ -+ asn1_node extendedasn; -+ int result, count; -+ grub_err_t err = GRUB_ERR_NONE; -+ char usage[MAX_OID_LEN]; -+ int usage_size = sizeof (usage); -+ -+ result = -+ asn1_create_element (_gnutls_pkix_asn, "PKIX1.ExtKeyUsageSyntax", -+ &extendedasn); -+ if (result != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not create ASN.1 structure for Extended Key Usage"); -+ } -+ -+ result = asn1_der_decoding2 (&extendedasn, value, &value_size, -+ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error parsing DER for Extended Key Usage: %s", -+ asn1_error); -+ goto cleanup; -+ } -+ -+ /* -+ * If EKUs are present, there must be exactly 1 and it must be a -+ * codeSigning usage. -+ */ -+ result = asn1_number_of_elements(extendedasn, "", &count); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error counting number of Extended Key Usages: %s", -+ asn1_strerror (result)); -+ goto cleanup; -+ } -+ -+ result = asn1_read_value (extendedasn, "?1", usage, &usage_size); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading Extended Key Usage: %s", -+ asn1_strerror (result)); -+ goto cleanup; -+ } -+ -+ if (grub_strncmp (codeSigningUsage_oid, usage, usage_size) != 0) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Unexpected Extended Key Usage OID, got: %s", -+ usage); -+ goto cleanup; -+ } -+ -+cleanup: -+ asn1_delete_structure (&extendedasn); -+ return err; -+} - - /* - * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension -@@ -660,7 +737,7 @@ verify_extensions (asn1_node cert) - { - int result; - int ext, num_extensions = 0; -- int usage_present = 0, constraints_present = 0; -+ int usage_present = 0, constraints_present = 0, extended_usage_present = 0; - char *oid_path, *critical_path, *value_path; - char extnID[MAX_OID_LEN]; - int extnID_size; -@@ -754,6 +831,15 @@ verify_extensions (asn1_node cert) - } - constraints_present++; - } -+ else if (grub_strncmp (extendedKeyUsage_oid, extnID, extnID_size) == 0) -+ { -+ err = verify_extended_key_usage (value, value_size); -+ if (err != GRUB_ERR_NONE) -+ { -+ goto cleanup_value; -+ } -+ extended_usage_present++; -+ } - else if (grub_strncmp ("TRUE", critical, critical_size) == 0) - { - /* -@@ -785,6 +871,12 @@ verify_extensions (asn1_node cert) - "Unexpected number of basic constraints extensions - expected 1, got %d", - constraints_present); - } -+ if (extended_usage_present > 1) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Unexpected number of Extended Key Usage extensions - expected 0 or 1, got %d", -+ extended_usage_present); -+ } - return GRUB_ERR_NONE; - - cleanup_value: -diff --git a/grub-core/tests/appended_signature_test.c b/grub-core/tests/appended_signature_test.c -index 88a485200d..dbba061662 100644 ---- a/grub-core/tests/appended_signature_test.c -+++ b/grub-core/tests/appended_signature_test.c -@@ -111,6 +111,22 @@ static struct grub_procfs_entry certificate_printable_der_entry = { - .get_contents = get_certificate_printable_der - }; - -+static char * -+get_certificate_eku_der (grub_size_t * sz) -+{ -+ char *ret; -+ *sz = certificate_eku_der_len; -+ ret = grub_malloc (*sz); -+ if (ret) -+ grub_memcpy (ret, certificate_eku_der, *sz); -+ return ret; -+} -+ -+static struct grub_procfs_entry certificate_eku_der_entry = { -+ .name = "certificate_eku.der", -+ .get_contents = get_certificate_eku_der -+}; -+ - - static void - do_verify (const char *f, int is_valid) -@@ -149,6 +165,7 @@ appended_signature_test (void) - char *trust_args2[] = { (char *) "(proc)/certificate2.der", NULL }; - char *trust_args_printable[] = { (char *) "(proc)/certificate_printable.der", - NULL }; -+ char *trust_args_eku[] = { (char *) "(proc)/certificate_eku.der", NULL }; - char *distrust_args[] = { (char *) "1", NULL }; - char *distrust2_args[] = { (char *) "2", NULL }; - grub_err_t err; -@@ -157,6 +174,7 @@ appended_signature_test (void) - grub_procfs_register ("certificate2.der", &certificate2_der_entry); - grub_procfs_register ("certificate_printable.der", - &certificate_printable_der_entry); -+ grub_procfs_register ("certificate_eku.der", &certificate_eku_der_entry); - - cmd_trust = grub_command_find ("trust_certificate"); - if (!cmd_trust) -@@ -266,16 +284,23 @@ appended_signature_test (void) - - /* - * Lastly, check a certificate that uses printableString rather than -- * utf8String loads properly. -+ * utf8String loads properly, and that a certificate with an appropriate -+ * extended key usage loads. - */ - err = (cmd_trust->func) (cmd_trust, 1, trust_args_printable); - grub_test_assert (err == GRUB_ERR_NONE, -- "distrusting printable certificate failed: %d: %s", -+ "trusting printable certificate failed: %d: %s", -+ grub_errno, grub_errmsg); -+ -+ err = (cmd_trust->func) (cmd_trust, 1, trust_args_eku); -+ grub_test_assert (err == GRUB_ERR_NONE, -+ "trusting certificate with extended key usage failed: %d: %s", - grub_errno, grub_errmsg); - - grub_procfs_unregister (&certificate_der_entry); - grub_procfs_unregister (&certificate2_der_entry); - grub_procfs_unregister (&certificate_printable_der_entry); -+ grub_procfs_unregister (&certificate_eku_der_entry); - } - - GRUB_FUNCTIONAL_TEST (appended_signature_test, appended_signature_test); -diff --git a/grub-core/tests/appended_signatures.h b/grub-core/tests/appended_signatures.h -index aa3dc6278e..2e5ebd7d8b 100644 ---- a/grub-core/tests/appended_signatures.h -+++ b/grub-core/tests/appended_signatures.h -@@ -555,3 +555,84 @@ unsigned char certificate_printable_der[] = { - 0xd2 - }; - unsigned int certificate_printable_der_len = 829; -+ -+unsigned char certificate_eku_der[] = { -+ 0x30, 0x82, 0x03, 0x90, 0x30, 0x82, 0x02, 0x78, 0xa0, 0x03, 0x02, 0x01, -+ 0x02, 0x02, 0x09, 0x00, 0xd3, 0x9c, 0x41, 0x33, 0xdd, 0x6b, 0x5f, 0x45, -+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, -+ 0x0b, 0x05, 0x00, 0x30, 0x47, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, -+ 0x04, 0x03, 0x0c, 0x18, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, -+ 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, -+ 0x43, 0x41, 0x20, 0x36, 0x31, 0x22, 0x30, 0x20, 0x06, 0x09, 0x2a, 0x86, -+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x13, 0x73, 0x65, 0x63, -+ 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, 0x64, 0x68, 0x61, 0x74, -+ 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, -+ 0x31, 0x35, 0x31, 0x34, 0x30, 0x30, 0x34, 0x34, 0x5a, 0x17, 0x0d, 0x33, -+ 0x38, 0x30, 0x31, 0x31, 0x37, 0x31, 0x34, 0x30, 0x30, 0x34, 0x34, 0x5a, -+ 0x30, 0x4e, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, -+ 0x1f, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, 0x53, 0x65, 0x63, -+ 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x53, 0x69, 0x67, -+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x36, 0x30, 0x32, 0x31, 0x22, 0x30, 0x20, -+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, -+ 0x13, 0x73, 0x65, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, -+ 0x64, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, -+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, -+ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, -+ 0x02, 0x82, 0x01, 0x01, 0x00, 0xaa, 0x6f, 0xbb, 0x92, 0x77, 0xd7, 0x15, -+ 0xef, 0x88, 0x80, 0x88, 0xc0, 0xe7, 0x89, 0xeb, 0x35, 0x76, 0xf4, 0x85, -+ 0x05, 0x0f, 0x19, 0xe4, 0x5f, 0x25, 0xdd, 0xc1, 0xa2, 0xe5, 0x5c, 0x06, -+ 0xfb, 0xf1, 0x06, 0xb5, 0x65, 0x45, 0xcb, 0xbd, 0x19, 0x33, 0x54, 0xb5, -+ 0x1a, 0xcd, 0xe4, 0xa8, 0x35, 0x2a, 0xfe, 0x9c, 0x53, 0xf4, 0xc6, 0x76, -+ 0xdb, 0x1f, 0x8a, 0xd4, 0x7b, 0x18, 0x11, 0xaf, 0xa3, 0x90, 0xd4, 0xdd, -+ 0x4d, 0xd5, 0x42, 0xcc, 0x14, 0x9a, 0x64, 0x6b, 0xc0, 0x7f, 0xaa, 0x1c, -+ 0x94, 0x47, 0x4d, 0x79, 0xbd, 0x57, 0x9a, 0xbf, 0x99, 0x4e, 0x96, 0xa9, -+ 0x31, 0x2c, 0xa9, 0xe7, 0x14, 0x65, 0x86, 0xc8, 0xac, 0x79, 0x5e, 0x78, -+ 0xa4, 0x3c, 0x00, 0x24, 0xd3, 0xf7, 0xe1, 0xf5, 0x12, 0xad, 0xa0, 0x29, -+ 0xe5, 0xfe, 0x80, 0xae, 0xf8, 0xaa, 0x60, 0x36, 0xe7, 0xe8, 0x94, 0xcb, -+ 0xe9, 0xd1, 0xcc, 0x0b, 0x4d, 0xf7, 0xde, 0xeb, 0x52, 0xd2, 0x73, 0x09, -+ 0x28, 0xdf, 0x48, 0x99, 0x53, 0x9f, 0xc5, 0x9a, 0xd4, 0x36, 0xa3, 0xc6, -+ 0x5e, 0x8d, 0xbe, 0xd5, 0xdc, 0x76, 0xb4, 0x74, 0xb8, 0x26, 0x18, 0x27, -+ 0xfb, 0xf2, 0xfb, 0xd0, 0x9b, 0x3d, 0x7f, 0x10, 0xe2, 0xab, 0x44, 0xc7, -+ 0x88, 0x7f, 0xb4, 0x3d, 0x3e, 0xa3, 0xff, 0x6d, 0x06, 0x4b, 0x3e, 0x55, -+ 0xb2, 0x84, 0xf4, 0xad, 0x54, 0x88, 0x81, 0xc3, 0x9c, 0xf8, 0xb6, 0x68, -+ 0x96, 0x38, 0x8b, 0xcd, 0x90, 0x6d, 0x25, 0x4b, 0xbf, 0x0c, 0x44, 0x90, -+ 0xa5, 0x5b, 0x98, 0xd0, 0x40, 0x2f, 0xbb, 0x0d, 0xa8, 0x4b, 0x8a, 0x62, -+ 0x82, 0x46, 0x46, 0x18, 0x38, 0xae, 0x82, 0x07, 0xd0, 0xb4, 0x2f, 0x16, -+ 0x79, 0x55, 0x9f, 0x1b, 0xc5, 0x08, 0x6d, 0x85, 0xdf, 0x3f, 0xa9, 0x9b, -+ 0x4b, 0xc6, 0x28, 0xd3, 0x58, 0x72, 0x3d, 0x37, 0x11, 0x02, 0x03, 0x01, -+ 0x00, 0x01, 0xa3, 0x78, 0x30, 0x76, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, -+ 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, -+ 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, -+ 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, -+ 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, -+ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x6c, -+ 0xe4, 0x6c, 0x27, 0xaa, 0xcd, 0x0d, 0x4b, 0x74, 0x21, 0xa4, 0xf6, 0x5f, -+ 0x87, 0xb5, 0x31, 0xfe, 0x10, 0xbb, 0xa7, 0x30, 0x1f, 0x06, 0x03, 0x55, -+ 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xe8, 0x6a, 0x1c, 0xab, -+ 0x2c, 0x48, 0xf9, 0x60, 0x36, 0xa2, 0xf0, 0x7b, 0x8e, 0xd2, 0x9d, 0xb4, -+ 0x2a, 0x28, 0x98, 0xc8, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, -+ 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, -+ 0x55, 0x34, 0xe2, 0xfa, 0xf6, 0x89, 0x86, 0xad, 0x92, 0x21, 0xec, 0xb9, -+ 0x54, 0x0e, 0x18, 0x47, 0x0d, 0x1b, 0xa7, 0x58, 0xad, 0x69, 0xe4, 0xef, -+ 0x3b, 0xe6, 0x8d, 0xdd, 0xda, 0x0c, 0x45, 0xf6, 0xe8, 0x96, 0xa4, 0x29, -+ 0x0f, 0xbb, 0xcf, 0x16, 0xae, 0x93, 0xd0, 0xcb, 0x2a, 0x26, 0x1a, 0x7b, -+ 0xfc, 0x51, 0x22, 0x76, 0x98, 0x31, 0xa7, 0x0f, 0x29, 0x35, 0x79, 0xbf, -+ 0xe2, 0x4f, 0x0f, 0x14, 0xf5, 0x1f, 0xcb, 0xbf, 0x87, 0x65, 0x13, 0x32, -+ 0xa3, 0x19, 0x4a, 0xd1, 0x3f, 0x45, 0xd4, 0x4b, 0xe2, 0x00, 0x26, 0xa9, -+ 0x3e, 0xd7, 0xa5, 0x37, 0x9f, 0xf5, 0xad, 0x61, 0xe2, 0x40, 0xa9, 0x74, -+ 0x24, 0x53, 0xf2, 0x78, 0xeb, 0x10, 0x9b, 0x2c, 0x27, 0x88, 0x46, 0xcb, -+ 0xe4, 0x60, 0xca, 0xf5, 0x06, 0x24, 0x40, 0x2a, 0x97, 0x3a, 0xcc, 0xd0, -+ 0x81, 0xb1, 0x15, 0xa3, 0x4f, 0xd0, 0x2b, 0x4f, 0xca, 0x6e, 0xaa, 0x24, -+ 0x31, 0xb3, 0xac, 0xa6, 0x75, 0x05, 0xfe, 0x8a, 0xf4, 0x41, 0xc4, 0x06, -+ 0x8a, 0xc7, 0x0a, 0x83, 0x4e, 0x49, 0xd4, 0x3f, 0x83, 0x50, 0xec, 0x57, -+ 0x04, 0x97, 0x14, 0x49, 0xf5, 0xe1, 0xb1, 0x7a, 0x9c, 0x09, 0x4f, 0x61, -+ 0x87, 0xc3, 0x97, 0x22, 0x17, 0xc2, 0xeb, 0xcc, 0x32, 0x81, 0x31, 0x21, -+ 0x3f, 0x10, 0x57, 0x5b, 0x43, 0xbe, 0xcd, 0x68, 0x82, 0xbe, 0xe5, 0xc1, -+ 0x65, 0x94, 0x7e, 0xc2, 0x34, 0x76, 0x2b, 0xcf, 0x89, 0x3c, 0x2b, 0x81, -+ 0x23, 0x72, 0x95, 0xcf, 0xc9, 0x67, 0x19, 0x2a, 0xd5, 0x5c, 0xca, 0xa3, -+ 0x46, 0xbd, 0x48, 0x06, 0x0b, 0xa6, 0xa3, 0x96, 0x50, 0x28, 0xc7, 0x7e, -+ 0xcf, 0x62, 0xf2, 0xfa, 0xc4, 0xf2, 0x53, 0xe3, 0xc9, 0xe8, 0x2e, 0xdd, -+ 0x29, 0x37, 0x07, 0x47, 0xff, 0xff, 0x8a, 0x32, 0xbd, 0xa2, 0xb7, 0x21, -+ 0x89, 0xa0, 0x55, 0xf7 -+}; -+unsigned int certificate_eku_der_len = 916; diff --git a/0178-efinet-Add-DHCP-proxy-support.patch b/0178-efinet-Add-DHCP-proxy-support.patch new file mode 100644 index 0000000..eed2dbb --- /dev/null +++ b/0178-efinet-Add-DHCP-proxy-support.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ian Page Hands +Date: Tue, 8 Jun 2021 13:48:56 -0400 +Subject: [PATCH] efinet: Add DHCP proxy support + +If a proxyDHCP configuration is used, the server name, server IP and boot +file values should be taken from the DHCP proxy offer instead of the DHCP +server ack packet. Currently that case is not handled, add support for it. + +Signed-off-by: Ian Page Hands +Signed-off-by: Robbie Harwood +--- + grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index e11d759f19..1a24f38a21 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -850,10 +850,31 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + else + { + grub_dprintf ("efinet", "using ipv4 and dhcp\n"); ++ ++ struct grub_net_bootp_packet *dhcp_ack = &pxe_mode->dhcp_ack; ++ ++ if (pxe_mode->proxy_offer_received) ++ { ++ grub_dprintf ("efinet", "proxy offer receive"); ++ struct grub_net_bootp_packet *proxy_offer = &pxe_mode->proxy_offer; ++ ++ if (proxy_offer && dhcp_ack->boot_file[0] == '\0') ++ { ++ grub_dprintf ("efinet", "setting values from proxy offer"); ++ /* Here we got a proxy offer and the dhcp_ack has a nil boot_file ++ * Copy the proxy DHCP offer details into the bootp_packet we are ++ * sending forward as they are the deatils we need. ++ */ ++ *dhcp_ack->server_name = *proxy_offer->server_name; ++ *dhcp_ack->boot_file = *proxy_offer->boot_file; ++ dhcp_ack->server_ip = proxy_offer->server_ip; ++ } ++ } ++ + grub_net_configure_by_dhcp_ack (card->name, card, 0, + (struct grub_net_bootp_packet *) +- packet_buf, +- packet_bufsz, ++ &pxe_mode->dhcp_ack, ++ sizeof (pxe_mode->dhcp_ack), + 1, device, path); + grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); + } diff --git a/0178-ieee1275-ofdisk-retry-on-open-failure.patch b/0178-ieee1275-ofdisk-retry-on-open-failure.patch deleted file mode 100644 index 9149773..0000000 --- a/0178-ieee1275-ofdisk-retry-on-open-failure.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Diego Domingos -Date: Wed, 10 Mar 2021 14:17:52 -0500 -Subject: [PATCH] ieee1275/ofdisk: retry on open failure - -This patch aims to make grub more robust when booting from SAN/Multipath disks. - -If a path is failing intermittently so grub will retry the OPEN and READ the -disk (grub_ieee1275_open and grub_ieee1275_read) until the total amount of times -specified in MAX_RETRIES. - -Signed-off-by: Diego Domingos ---- - grub-core/disk/ieee1275/ofdisk.c | 25 ++++++++++++++++++++----- - include/grub/ieee1275/ofdisk.h | 8 ++++++++ - 2 files changed, 28 insertions(+), 5 deletions(-) - -diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c -index ea7f78ac7d..55346849d3 100644 ---- a/grub-core/disk/ieee1275/ofdisk.c -+++ b/grub-core/disk/ieee1275/ofdisk.c -@@ -225,7 +225,9 @@ dev_iterate (const struct grub_ieee1275_devalias *alias) - char *buf, *bufptr; - unsigned i; - -- if (grub_ieee1275_open (alias->path, &ihandle)) -+ -+ RETRY_IEEE1275_OFDISK_OPEN(alias->path, &ihandle) -+ if (! ihandle) - return; - - /* This method doesn't need memory allocation for the table. Open -@@ -305,7 +307,9 @@ dev_iterate (const struct grub_ieee1275_devalias *alias) - return; - } - -- if (grub_ieee1275_open (alias->path, &ihandle)) -+ RETRY_IEEE1275_OFDISK_OPEN(alias->path, &ihandle); -+ -+ if (! ihandle) - { - grub_free (buf); - grub_free (table); -@@ -495,7 +499,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) - last_ihandle = 0; - last_devpath = NULL; - -- grub_ieee1275_open (op->open_path, &last_ihandle); -+ RETRY_IEEE1275_OFDISK_OPEN(op->open_path, &last_ihandle); - if (! last_ihandle) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - last_devpath = op->open_path; -@@ -571,7 +575,7 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) - last_ihandle = 0; - last_devpath = NULL; - -- grub_ieee1275_open (disk->data, &last_ihandle); -+ RETRY_IEEE1275_OFDISK_OPEN(disk->data, &last_ihandle); - if (! last_ihandle) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - last_devpath = disk->data; -@@ -598,12 +602,23 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, - return err; - grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, - &actual); -- if (actual != (grub_ssize_t) (size << disk->log_sector_size)) -+ int i = 0; -+ while(actual != (grub_ssize_t) (size << disk->log_sector_size)){ -+ if (i>MAX_RETRIES){ - return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " - "from `%s'"), - (unsigned long long) sector, - disk->name); -+ } -+ last_devpath = NULL; -+ err = grub_ofdisk_prepare (disk, sector); -+ if (err) -+ return err; - -+ grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, -+ &actual); -+ i++; -+ } - return 0; - } - -diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h -index 2f69e3f191..7d2d540930 100644 ---- a/include/grub/ieee1275/ofdisk.h -+++ b/include/grub/ieee1275/ofdisk.h -@@ -22,4 +22,12 @@ - extern void grub_ofdisk_init (void); - extern void grub_ofdisk_fini (void); - -+#define MAX_RETRIES 20 -+ -+ -+#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) unsigned retry_i=0;for(retry_i=0; retry_i < MAX_RETRIES; retry_i++){ \ -+ if(!grub_ieee1275_open(device, last_ihandle)) \ -+ break; \ -+ grub_dprintf("ofdisk","Opening disk %s failed. Retrying...\n",device); } -+ - #endif /* ! GRUB_INIT_HEADER */ diff --git a/0179-Allow-chainloading-EFI-apps-from-loop-mounts.patch b/0179-Allow-chainloading-EFI-apps-from-loop-mounts.patch deleted file mode 100644 index c3101e1..0000000 --- a/0179-Allow-chainloading-EFI-apps-from-loop-mounts.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dimitri John Ledkov -Date: Fri, 11 Jun 2021 13:51:20 +0200 -Subject: [PATCH] Allow chainloading EFI apps from loop mounts. - -Signed-off-by: Dimitri John Ledkov -Signed-off-by: Robbie Harwood ---- - grub-core/disk/loopback.c | 9 +-------- - grub-core/loader/efi/chainloader.c | 23 +++++++++++++++++++++++ - include/grub/loopback.h | 30 ++++++++++++++++++++++++++++++ - 3 files changed, 54 insertions(+), 8 deletions(-) - create mode 100644 include/grub/loopback.h - -diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c -index 41bebd14fe..99f47924ec 100644 ---- a/grub-core/disk/loopback.c -+++ b/grub-core/disk/loopback.c -@@ -21,20 +21,13 @@ - #include - #include - #include -+#include - #include - #include - #include - - GRUB_MOD_LICENSE ("GPLv3+"); - --struct grub_loopback --{ -- char *devname; -- grub_file_t file; -- struct grub_loopback *next; -- unsigned long id; --}; -- - static struct grub_loopback *loopback_list; - static unsigned long last_id = 0; - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index d41e8ea14a..3af6b12292 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -901,6 +902,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_efi_status_t status; - grub_efi_boot_services_t *b; - grub_device_t dev = 0; -+ grub_device_t orig_dev = 0; - grub_efi_device_path_t *dp = 0; - char *filename; - void *boot_image = 0; -@@ -958,6 +960,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - if (! dev) - goto fail; - -+ /* if device is loopback, use underlying dev */ -+ if (dev->disk->dev->id == GRUB_DISK_DEVICE_LOOPBACK_ID) -+ { -+ struct grub_loopback *d; -+ orig_dev = dev; -+ d = dev->disk->data; -+ dev = d->file->device; -+ } -+ - if (dev->disk) - dev_handle = grub_efidisk_get_device_handle (dev->disk); - else if (dev->net && dev->net->server) -@@ -1065,6 +1076,12 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -+ if (orig_dev) -+ { -+ dev = orig_dev; -+ orig_dev = 0; -+ } -+ - rc = grub_linuxefi_secure_validate((void *)(unsigned long)address, fsize); - grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc); - if (rc > 0) -@@ -1087,6 +1104,12 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - // -1 fall-through to fail - - fail: -+ if (orig_dev) -+ { -+ dev = orig_dev; -+ orig_dev = 0; -+ } -+ - if (dev) - grub_device_close (dev); - -diff --git a/include/grub/loopback.h b/include/grub/loopback.h -new file mode 100644 -index 0000000000..3b9a9e32e8 ---- /dev/null -+++ b/include/grub/loopback.h -@@ -0,0 +1,30 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2019 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_LOOPBACK_HEADER -+#define GRUB_LOOPBACK_HEADER 1 -+ -+struct grub_loopback -+{ -+ char *devname; -+ grub_file_t file; -+ struct grub_loopback *next; -+ unsigned long id; -+}; -+ -+#endif /* ! GRUB_LOOPBACK_HEADER */ diff --git a/0179-fs-ext2-Ignore-checksum-seed-incompat-feature.patch b/0179-fs-ext2-Ignore-checksum-seed-incompat-feature.patch new file mode 100644 index 0000000..3d7c641 --- /dev/null +++ b/0179-fs-ext2-Ignore-checksum-seed-incompat-feature.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Fri, 11 Jun 2021 00:01:29 +0200 +Subject: [PATCH] fs/ext2: Ignore checksum seed incompat feature + +This incompat feature is used to denote that the filesystem stored its +metadata checksum seed in the superblock. This is used to allow tune2fs +to change the UUID on a mounted metadata_csum filesystem without having +to rewrite all the disk metadata. + +But GRUB doesn't use the metadata checksum in anyway, so can just ignore +this feature if is enabled. This is consistent with GRUB filesystem code +in general which just does a best effort to access the filesystem's data. + +It may be removed from the ignored list in the future if supports to do +metadata checksumming verification is added to the read-only FS driver. + +Suggested-by: Eric Sandeen +Suggested-by: Lukas Czerner +Signed-off-by: Javier Martinez Canillas +--- + grub-core/fs/ext2.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c +index e7dd78e663..731d346f88 100644 +--- a/grub-core/fs/ext2.c ++++ b/grub-core/fs/ext2.c +@@ -103,6 +103,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 + #define EXT4_FEATURE_INCOMPAT_MMP 0x0100 + #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 ++#define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000 + #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 + + /* The set of back-incompatible features this driver DOES support. Add (OR) +@@ -123,9 +124,16 @@ GRUB_MOD_LICENSE ("GPLv3+"); + * mmp: Not really back-incompatible - was added as such to + * avoid multiple read-write mounts. Safe to ignore for this + * RO driver. ++ * checksum seed: Not really back-incompatible - was added to allow tools ++ * such as tune2fs to change the UUID on a mounted metadata ++ * checksummed filesystem. Safe to ignore for now since the ++ * driver doesn't support checksum verification. But it must ++ * be removed from this list if that support is added later. ++ * + */ + #define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \ +- | EXT4_FEATURE_INCOMPAT_MMP) ++ | EXT4_FEATURE_INCOMPAT_MMP \ ++ | EXT4_FEATURE_INCOMPAT_CSUM_SEED) + + + #define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U diff --git a/0180-Don-t-update-the-cmdline-when-generating-legacy-menu.patch b/0180-Don-t-update-the-cmdline-when-generating-legacy-menu.patch new file mode 100644 index 0000000..b2783d1 --- /dev/null +++ b/0180-Don-t-update-the-cmdline-when-generating-legacy-menu.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Thu, 17 Jun 2021 14:31:42 +0200 +Subject: [PATCH] Don't update the cmdline when generating legacy menuentry + commands + +On OPAL ppc64le machines with an old petitboot version that doesn't have +support to parse BLS snippets, the grub2-mkconfig script is executed to +generate menuentry commands from the BLS snippets. + +In this case, the script is executed with the --no-grubenv-update option +that indicates that no side effects should happen when running the script. + +But the options field in the BLS snippets are updated regardless, only do +the update if --no-grubenv-update was not used. + +Signed-off-by: Javier Martinez Canillas +--- + util/grub.d/10_linux.in | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index e490e1a43a..865af3d6c4 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -256,7 +256,9 @@ if [ -z "\${kernelopts}" ]; then + fi + EOF + +- update_bls_cmdline ++ if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then ++ update_bls_cmdline ++ fi + + if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then + populate_menu diff --git a/0180-efinet-Add-DHCP-proxy-support.patch b/0180-efinet-Add-DHCP-proxy-support.patch deleted file mode 100644 index eed2dbb..0000000 --- a/0180-efinet-Add-DHCP-proxy-support.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ian Page Hands -Date: Tue, 8 Jun 2021 13:48:56 -0400 -Subject: [PATCH] efinet: Add DHCP proxy support - -If a proxyDHCP configuration is used, the server name, server IP and boot -file values should be taken from the DHCP proxy offer instead of the DHCP -server ack packet. Currently that case is not handled, add support for it. - -Signed-off-by: Ian Page Hands -Signed-off-by: Robbie Harwood ---- - grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++-- - 1 file changed, 23 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c -index e11d759f19..1a24f38a21 100644 ---- a/grub-core/net/drivers/efi/efinet.c -+++ b/grub-core/net/drivers/efi/efinet.c -@@ -850,10 +850,31 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - else - { - grub_dprintf ("efinet", "using ipv4 and dhcp\n"); -+ -+ struct grub_net_bootp_packet *dhcp_ack = &pxe_mode->dhcp_ack; -+ -+ if (pxe_mode->proxy_offer_received) -+ { -+ grub_dprintf ("efinet", "proxy offer receive"); -+ struct grub_net_bootp_packet *proxy_offer = &pxe_mode->proxy_offer; -+ -+ if (proxy_offer && dhcp_ack->boot_file[0] == '\0') -+ { -+ grub_dprintf ("efinet", "setting values from proxy offer"); -+ /* Here we got a proxy offer and the dhcp_ack has a nil boot_file -+ * Copy the proxy DHCP offer details into the bootp_packet we are -+ * sending forward as they are the deatils we need. -+ */ -+ *dhcp_ack->server_name = *proxy_offer->server_name; -+ *dhcp_ack->boot_file = *proxy_offer->boot_file; -+ dhcp_ack->server_ip = proxy_offer->server_ip; -+ } -+ } -+ - grub_net_configure_by_dhcp_ack (card->name, card, 0, - (struct grub_net_bootp_packet *) -- packet_buf, -- packet_bufsz, -+ &pxe_mode->dhcp_ack, -+ sizeof (pxe_mode->dhcp_ack), - 1, device, path); - grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); - } diff --git a/0181-Suppress-gettext-error-message.patch b/0181-Suppress-gettext-error-message.patch new file mode 100644 index 0000000..64b219a --- /dev/null +++ b/0181-Suppress-gettext-error-message.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 29 Jun 2021 13:17:42 +0200 +Subject: [PATCH] Suppress gettext error message + +Colin Watson's patch from comment #11 on the upstream bug: +https://savannah.gnu.org/bugs/?35880#comment11 + +Resolves: rhbz#1592124 + +Signed-off-by: Paulo Flabiano Smorigo +--- + grub-core/gettext/gettext.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c +index 4d02e62c10..7ec81ca0b4 100644 +--- a/grub-core/gettext/gettext.c ++++ b/grub-core/gettext/gettext.c +@@ -424,6 +424,13 @@ grub_gettext_init_ext (struct grub_gettext_context *ctx, + grub_free (lang); + } + ++ /* If no translations are available, fall back to untranslated text. */ ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ return 0; ++ } ++ + if (locale[0] == 'e' && locale[1] == 'n' + && (locale[2] == '\0' || locale[2] == '_')) + grub_errno = err = GRUB_ERR_NONE; diff --git a/0181-fs-ext2-Ignore-checksum-seed-incompat-feature.patch b/0181-fs-ext2-Ignore-checksum-seed-incompat-feature.patch deleted file mode 100644 index 3d7c641..0000000 --- a/0181-fs-ext2-Ignore-checksum-seed-incompat-feature.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Fri, 11 Jun 2021 00:01:29 +0200 -Subject: [PATCH] fs/ext2: Ignore checksum seed incompat feature - -This incompat feature is used to denote that the filesystem stored its -metadata checksum seed in the superblock. This is used to allow tune2fs -to change the UUID on a mounted metadata_csum filesystem without having -to rewrite all the disk metadata. - -But GRUB doesn't use the metadata checksum in anyway, so can just ignore -this feature if is enabled. This is consistent with GRUB filesystem code -in general which just does a best effort to access the filesystem's data. - -It may be removed from the ignored list in the future if supports to do -metadata checksumming verification is added to the read-only FS driver. - -Suggested-by: Eric Sandeen -Suggested-by: Lukas Czerner -Signed-off-by: Javier Martinez Canillas ---- - grub-core/fs/ext2.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c -index e7dd78e663..731d346f88 100644 ---- a/grub-core/fs/ext2.c -+++ b/grub-core/fs/ext2.c -@@ -103,6 +103,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); - #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 - #define EXT4_FEATURE_INCOMPAT_MMP 0x0100 - #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 -+#define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000 - #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 - - /* The set of back-incompatible features this driver DOES support. Add (OR) -@@ -123,9 +124,16 @@ GRUB_MOD_LICENSE ("GPLv3+"); - * mmp: Not really back-incompatible - was added as such to - * avoid multiple read-write mounts. Safe to ignore for this - * RO driver. -+ * checksum seed: Not really back-incompatible - was added to allow tools -+ * such as tune2fs to change the UUID on a mounted metadata -+ * checksummed filesystem. Safe to ignore for now since the -+ * driver doesn't support checksum verification. But it must -+ * be removed from this list if that support is added later. -+ * - */ - #define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \ -- | EXT4_FEATURE_INCOMPAT_MMP) -+ | EXT4_FEATURE_INCOMPAT_MMP \ -+ | EXT4_FEATURE_INCOMPAT_CSUM_SEED) - - - #define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U diff --git a/0182-Don-t-update-the-cmdline-when-generating-legacy-menu.patch b/0182-Don-t-update-the-cmdline-when-generating-legacy-menu.patch deleted file mode 100644 index b2783d1..0000000 --- a/0182-Don-t-update-the-cmdline-when-generating-legacy-menu.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Thu, 17 Jun 2021 14:31:42 +0200 -Subject: [PATCH] Don't update the cmdline when generating legacy menuentry - commands - -On OPAL ppc64le machines with an old petitboot version that doesn't have -support to parse BLS snippets, the grub2-mkconfig script is executed to -generate menuentry commands from the BLS snippets. - -In this case, the script is executed with the --no-grubenv-update option -that indicates that no side effects should happen when running the script. - -But the options field in the BLS snippets are updated regardless, only do -the update if --no-grubenv-update was not used. - -Signed-off-by: Javier Martinez Canillas ---- - util/grub.d/10_linux.in | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index e490e1a43a..865af3d6c4 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -256,7 +256,9 @@ if [ -z "\${kernelopts}" ]; then - fi - EOF - -- update_bls_cmdline -+ if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then -+ update_bls_cmdline -+ fi - - if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then - populate_menu diff --git a/0182-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch b/0182-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch new file mode 100644 index 0000000..b5d5e5c --- /dev/null +++ b/0182-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Mon, 5 Jul 2021 18:24:22 +0200 +Subject: [PATCH] grub-set-password: Always use /boot/grub2/user.cfg as + password default + +The GRUB configuration file is always placed in /boot/grub2/ now, even for +EFI. But the tool is still creating the user.cfg in the ESP and not there. + +Resolves: rhbz#1955294 + +Signed-off-by: Javier Martinez Canillas +--- + util/grub-set-password.in | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/util/grub-set-password.in b/util/grub-set-password.in +index c0b5ebbfdc..d8005e5a14 100644 +--- a/util/grub-set-password.in ++++ b/util/grub-set-password.in +@@ -1,11 +1,6 @@ + #!/bin/sh -e + +-EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g') +-if [ -d /sys/firmware/efi/efivars/ ]; then +- grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` +-else +- grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` +-fi ++grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` + + PACKAGE_VERSION="@PACKAGE_VERSION@" + PACKAGE_NAME="@PACKAGE_NAME@" +@@ -116,8 +111,6 @@ if [ -z "${MYPASS}" ]; then + exit 1 + fi + +-# on the ESP, these will fail to set the permissions, but it's okay because +-# the directory is protected. + install -m 0600 /dev/null "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : + chmod 0600 "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : + echo "GRUB2_PASSWORD=${MYPASS}" > "${OUTPUT_PATH}/user.cfg" diff --git a/0183-Suppress-gettext-error-message.patch b/0183-Suppress-gettext-error-message.patch deleted file mode 100644 index 64b219a..0000000 --- a/0183-Suppress-gettext-error-message.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paulo Flabiano Smorigo -Date: Tue, 29 Jun 2021 13:17:42 +0200 -Subject: [PATCH] Suppress gettext error message - -Colin Watson's patch from comment #11 on the upstream bug: -https://savannah.gnu.org/bugs/?35880#comment11 - -Resolves: rhbz#1592124 - -Signed-off-by: Paulo Flabiano Smorigo ---- - grub-core/gettext/gettext.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c -index 4d02e62c10..7ec81ca0b4 100644 ---- a/grub-core/gettext/gettext.c -+++ b/grub-core/gettext/gettext.c -@@ -424,6 +424,13 @@ grub_gettext_init_ext (struct grub_gettext_context *ctx, - grub_free (lang); - } - -+ /* If no translations are available, fall back to untranslated text. */ -+ if (err == GRUB_ERR_FILE_NOT_FOUND) -+ { -+ grub_errno = GRUB_ERR_NONE; -+ return 0; -+ } -+ - if (locale[0] == 'e' && locale[1] == 'n' - && (locale[2] == '\0' || locale[2] == '_')) - grub_errno = err = GRUB_ERR_NONE; diff --git a/0183-templates-Check-for-EFI-at-runtime-instead-of-config.patch b/0183-templates-Check-for-EFI-at-runtime-instead-of-config.patch new file mode 100644 index 0000000..265b967 --- /dev/null +++ b/0183-templates-Check-for-EFI-at-runtime-instead-of-config.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 6 Jul 2021 00:38:40 +0200 +Subject: [PATCH] templates: Check for EFI at runtime instead of config + generation time + +The 30_uefi-firmware template checks if an OsIndicationsSupported UEFI var +exists and EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit is set, to decide whether +a "fwsetup" menu entry would be added or not to the GRUB menu. + +But this has the problem that it will only work if the configuration file +was created on an UEFI machine that supports booting to a firmware UI. + +This for example doesn't support creating GRUB config files when executing +on systems that support both UEFI and legacy BIOS booting. Since creating +the config file from legacy BIOS wouldn't allow to access the firmware UI. + +To prevent this, make the template to unconditionally create the grub.cfg +snippet but check at runtime if was booted through UEFI to decide if this +entry should be added. That way it won't be added when booting with BIOS. + +There's no need to check if EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit is set, +since that's already done by the "fwsetup" command when is executed. + +Resolves: rhbz#1823864 + +Signed-off-by: Javier Martinez Canillas +--- + util/grub.d/30_uefi-firmware.in | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +diff --git a/util/grub.d/30_uefi-firmware.in b/util/grub.d/30_uefi-firmware.in +index d344d3883d..b6041b55e2 100644 +--- a/util/grub.d/30_uefi-firmware.in ++++ b/util/grub.d/30_uefi-firmware.in +@@ -26,19 +26,14 @@ export TEXTDOMAINDIR="@localedir@" + + . "$pkgdatadir/grub-mkconfig_lib" + +-EFI_VARS_DIR=/sys/firmware/efi/efivars +-EFI_GLOBAL_VARIABLE=8be4df61-93ca-11d2-aa0d-00e098032b8c +-OS_INDICATIONS="$EFI_VARS_DIR/OsIndicationsSupported-$EFI_GLOBAL_VARIABLE" ++LABEL="UEFI Firmware Settings" + +-if [ -e "$OS_INDICATIONS" ] && \ +- [ "$(( $(printf 0x%x \'"$(cat $OS_INDICATIONS | cut -b5)"\') & 1 ))" = 1 ]; then +- LABEL="UEFI Firmware Settings" ++gettext_printf "Adding boot menu entry for UEFI Firmware Settings ...\n" >&2 + +- gettext_printf "Adding boot menu entry for UEFI Firmware Settings ...\n" >&2 +- +- cat << EOF +-menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' { +- fwsetup +-} +-EOF ++cat << EOF ++if [ "\$grub_platform" = "efi" ]; then ++ menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' { ++ fwsetup ++ } + fi ++EOF diff --git a/0184-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch b/0184-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch new file mode 100644 index 0000000..3b1a219 --- /dev/null +++ b/0184-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 6 Jul 2021 01:10:18 +0200 +Subject: [PATCH] efi: Print an error if boot to firmware setup is not + supported + +The "fwsetup" command is only registered if the firmware supports booting +to the firmware setup UI. But it could be possible that the GRUB config +already contains a "fwsetup" entry, because it was generated in a machine +that has support for this feature. + +To prevent users getting a "can't find command `fwsetup`" error if it is +not supported by the firmware, let's just always register the command but +print a more accurate message if the firmware doesn't support this option. + +Resolves: rhbz#1823864 + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/commands/efi/efifwsetup.c | 43 ++++++++++++++++++++----------------- + 1 file changed, 23 insertions(+), 20 deletions(-) + +diff --git a/grub-core/commands/efi/efifwsetup.c b/grub-core/commands/efi/efifwsetup.c +index eaca032838..328c45e82e 100644 +--- a/grub-core/commands/efi/efifwsetup.c ++++ b/grub-core/commands/efi/efifwsetup.c +@@ -27,6 +27,25 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + ++static grub_efi_boolean_t ++efifwsetup_is_supported (void) ++{ ++ grub_efi_uint64_t *os_indications_supported = NULL; ++ grub_size_t oi_size = 0; ++ grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; ++ ++ grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size, ++ (void **) &os_indications_supported); ++ ++ if (!os_indications_supported) ++ return 0; ++ ++ if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) ++ return 1; ++ ++ return 0; ++} ++ + static grub_err_t + grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), +@@ -38,6 +57,10 @@ grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), + grub_size_t oi_size; + grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; + ++ if (!efifwsetup_is_supported ()) ++ return grub_error (GRUB_ERR_INVALID_COMMAND, ++ N_("Reboot to firmware setup is not supported")); ++ + grub_efi_get_variable ("OsIndications", &global, &oi_size, + (void **) &old_os_indications); + +@@ -56,28 +79,8 @@ grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), + + static grub_command_t cmd = NULL; + +-static grub_efi_boolean_t +-efifwsetup_is_supported (void) +-{ +- grub_efi_uint64_t *os_indications_supported = NULL; +- grub_size_t oi_size = 0; +- grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; +- +- grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size, +- (void **) &os_indications_supported); +- +- if (!os_indications_supported) +- return 0; +- +- if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) +- return 1; +- +- return 0; +-} +- + GRUB_MOD_INIT (efifwsetup) + { +- if (efifwsetup_is_supported ()) + cmd = grub_register_command ("fwsetup", grub_cmd_fwsetup, NULL, + N_("Reboot into firmware setup menu.")); + diff --git a/0184-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch b/0184-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch deleted file mode 100644 index b5d5e5c..0000000 --- a/0184-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Mon, 5 Jul 2021 18:24:22 +0200 -Subject: [PATCH] grub-set-password: Always use /boot/grub2/user.cfg as - password default - -The GRUB configuration file is always placed in /boot/grub2/ now, even for -EFI. But the tool is still creating the user.cfg in the ESP and not there. - -Resolves: rhbz#1955294 - -Signed-off-by: Javier Martinez Canillas ---- - util/grub-set-password.in | 9 +-------- - 1 file changed, 1 insertion(+), 8 deletions(-) - -diff --git a/util/grub-set-password.in b/util/grub-set-password.in -index c0b5ebbfdc..d8005e5a14 100644 ---- a/util/grub-set-password.in -+++ b/util/grub-set-password.in -@@ -1,11 +1,6 @@ - #!/bin/sh -e - --EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g') --if [ -d /sys/firmware/efi/efivars/ ]; then -- grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` --else -- grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` --fi -+grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` - - PACKAGE_VERSION="@PACKAGE_VERSION@" - PACKAGE_NAME="@PACKAGE_NAME@" -@@ -116,8 +111,6 @@ if [ -z "${MYPASS}" ]; then - exit 1 - fi - --# on the ESP, these will fail to set the permissions, but it's okay because --# the directory is protected. - install -m 0600 /dev/null "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : - chmod 0600 "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : - echo "GRUB2_PASSWORD=${MYPASS}" > "${OUTPUT_PATH}/user.cfg" diff --git a/0185-arm64-Fix-EFI-loader-kernel-image-allocation.patch b/0185-arm64-Fix-EFI-loader-kernel-image-allocation.patch new file mode 100644 index 0000000..cc5458c --- /dev/null +++ b/0185-arm64-Fix-EFI-loader-kernel-image-allocation.patch @@ -0,0 +1,218 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt +Date: Mon, 2 Aug 2021 23:10:01 +1000 +Subject: [PATCH] arm64: Fix EFI loader kernel image allocation + +We are currently allocating just enough memory for the file size, +which means that the kernel BSS is in limbo (and not even zeroed). + +We are also not honoring the alignment specified in the image +PE header. + +This makes us use the PE optional header in which the kernel puts the +actual size it needs, including BSS, and make sure we clear it, and +honors the specified alignment for the image. + +Signed-off-by: Benjamin Herrenschmidt +[pjones: arm: check for the PE magic for the compiled arch] +Signed-off-by: Peter Jones +Signed-off-by: Robbie Harwood +--- + grub-core/loader/arm64/linux.c | 100 +++++++++++++++++++++++++++-------------- + include/grub/arm/linux.h | 1 + + include/grub/arm64/linux.h | 1 + + 3 files changed, 68 insertions(+), 34 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 47f8cf0d84..f18d90bd74 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -41,6 +41,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; + static int loaded; + ++static void *kernel_alloc_addr; ++static grub_uint32_t kernel_alloc_pages; + static void *kernel_addr; + static grub_uint64_t kernel_size; + static grub_uint32_t handover_offset; +@@ -204,9 +206,8 @@ grub_linux_unload (void) + GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start)); + initrd_start = initrd_end = 0; + grub_free (linux_args); +- if (kernel_addr) +- grub_efi_free_pages ((grub_addr_t) kernel_addr, +- GRUB_EFI_BYTES_TO_PAGES (kernel_size)); ++ if (kernel_alloc_addr) ++ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages); + grub_fdt_unload (); + return GRUB_ERR_NONE; + } +@@ -311,14 +312,35 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + return grub_errno; + } + ++static grub_err_t ++parse_pe_header (void *kernel, grub_uint64_t *total_size, ++ grub_uint32_t *entry_offset, ++ grub_uint32_t *alignment) ++{ ++ struct linux_arch_kernel_header *lh = kernel; ++ struct grub_armxx_linux_pe_header *pe; ++ ++ pe = (void *)((unsigned long)kernel + lh->hdr_offset); ++ ++ if (pe->opt.magic != GRUB_PE32_PEXX_MAGIC) ++ return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic"); ++ ++ *total_size = pe->opt.image_size; ++ *entry_offset = pe->opt.entry_addr; ++ *alignment = pe->opt.section_alignment; ++ ++ return GRUB_ERR_NONE; ++} ++ + static grub_err_t + grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { + grub_file_t file = 0; +- struct linux_arch_kernel_header lh; +- struct grub_armxx_linux_pe_header *pe; + grub_err_t err; ++ grub_off_t filelen; ++ grub_uint32_t align; ++ void *kernel = NULL; + int rc; + + grub_dl_ref (my_mod); +@@ -333,40 +355,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + if (!file) + goto fail; + +- kernel_size = grub_file_size (file); +- +- if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) +- return grub_errno; +- +- if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE) +- goto fail; +- +- grub_loader_unset(); +- +- grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size); +- kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size)); +- grub_dprintf ("linux", "kernel numpages: %lld\n", +- (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size)); +- if (!kernel_addr) ++ filelen = grub_file_size (file); ++ kernel = grub_malloc(filelen); ++ if (!kernel) + { +- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel load buffer")); + goto fail; + } + +- grub_file_seek (file, 0); +- if (grub_file_read (file, kernel_addr, kernel_size) +- < (grub_int64_t) kernel_size) ++ if (grub_file_read (file, kernel, filelen) < (grub_ssize_t)filelen) + { +- if (!grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); ++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), ++ argv[0]); + goto fail; + } + +- grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); +- + if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) + { +- rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); ++ rc = grub_linuxefi_secure_validate (kernel, filelen); + if (rc <= 0) + { + grub_error (GRUB_ERR_INVALID_COMMAND, +@@ -375,8 +381,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + } + +- pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); +- handover_offset = pe->opt.entry_addr; ++ if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) ++ goto fail; ++ if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) ++ goto fail; ++ grub_dprintf ("linux", "kernel mem size : %lld\n", (long long) kernel_size); ++ grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); ++ grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); ++ ++ grub_loader_unset(); ++ ++ kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); ++ kernel_alloc_addr = grub_efi_allocate_any_pages (kernel_alloc_pages); ++ grub_dprintf ("linux", "kernel numpages: %d\n", kernel_alloc_pages); ++ if (!kernel_alloc_addr) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align); ++ ++ grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); ++ grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size)); ++ if (kernel_size > filelen) ++ grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen); ++ grub_free(kernel); ++ kernel = NULL; + + cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); + linux_args = grub_malloc (cmdline_size); +@@ -400,6 +430,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + + fail: ++ if (kernel) ++ grub_free (kernel); ++ + if (file) + grub_file_close (file); + +@@ -412,9 +445,8 @@ fail: + if (linux_args && !loaded) + grub_free (linux_args); + +- if (kernel_addr && !loaded) +- grub_efi_free_pages ((grub_addr_t) kernel_addr, +- GRUB_EFI_BYTES_TO_PAGES (kernel_size)); ++ if (kernel_alloc_addr && !loaded) ++ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages); + + return grub_errno; + } +diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h +index b582f67f66..966a5074f5 100644 +--- a/include/grub/arm/linux.h ++++ b/include/grub/arm/linux.h +@@ -44,6 +44,7 @@ struct grub_arm_linux_pe_header + + #if defined(__arm__) + # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM_MAGIC_SIGNATURE ++# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE32_MAGIC + # define linux_arch_kernel_header linux_arm_kernel_header + # define grub_armxx_linux_pe_header grub_arm_linux_pe_header + #endif +diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h +index ea030312df..422bf2bf24 100644 +--- a/include/grub/arm64/linux.h ++++ b/include/grub/arm64/linux.h +@@ -48,6 +48,7 @@ struct grub_arm64_linux_pe_header + + #if defined(__aarch64__) + # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE ++# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE64_MAGIC + # define linux_arch_kernel_header linux_arm64_kernel_header + # define grub_armxx_linux_pe_header grub_arm64_linux_pe_header + #endif diff --git a/0185-templates-Check-for-EFI-at-runtime-instead-of-config.patch b/0185-templates-Check-for-EFI-at-runtime-instead-of-config.patch deleted file mode 100644 index 265b967..0000000 --- a/0185-templates-Check-for-EFI-at-runtime-instead-of-config.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 6 Jul 2021 00:38:40 +0200 -Subject: [PATCH] templates: Check for EFI at runtime instead of config - generation time - -The 30_uefi-firmware template checks if an OsIndicationsSupported UEFI var -exists and EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit is set, to decide whether -a "fwsetup" menu entry would be added or not to the GRUB menu. - -But this has the problem that it will only work if the configuration file -was created on an UEFI machine that supports booting to a firmware UI. - -This for example doesn't support creating GRUB config files when executing -on systems that support both UEFI and legacy BIOS booting. Since creating -the config file from legacy BIOS wouldn't allow to access the firmware UI. - -To prevent this, make the template to unconditionally create the grub.cfg -snippet but check at runtime if was booted through UEFI to decide if this -entry should be added. That way it won't be added when booting with BIOS. - -There's no need to check if EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit is set, -since that's already done by the "fwsetup" command when is executed. - -Resolves: rhbz#1823864 - -Signed-off-by: Javier Martinez Canillas ---- - util/grub.d/30_uefi-firmware.in | 21 ++++++++------------- - 1 file changed, 8 insertions(+), 13 deletions(-) - -diff --git a/util/grub.d/30_uefi-firmware.in b/util/grub.d/30_uefi-firmware.in -index d344d3883d..b6041b55e2 100644 ---- a/util/grub.d/30_uefi-firmware.in -+++ b/util/grub.d/30_uefi-firmware.in -@@ -26,19 +26,14 @@ export TEXTDOMAINDIR="@localedir@" - - . "$pkgdatadir/grub-mkconfig_lib" - --EFI_VARS_DIR=/sys/firmware/efi/efivars --EFI_GLOBAL_VARIABLE=8be4df61-93ca-11d2-aa0d-00e098032b8c --OS_INDICATIONS="$EFI_VARS_DIR/OsIndicationsSupported-$EFI_GLOBAL_VARIABLE" -+LABEL="UEFI Firmware Settings" - --if [ -e "$OS_INDICATIONS" ] && \ -- [ "$(( $(printf 0x%x \'"$(cat $OS_INDICATIONS | cut -b5)"\') & 1 ))" = 1 ]; then -- LABEL="UEFI Firmware Settings" -+gettext_printf "Adding boot menu entry for UEFI Firmware Settings ...\n" >&2 - -- gettext_printf "Adding boot menu entry for UEFI Firmware Settings ...\n" >&2 -- -- cat << EOF --menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' { -- fwsetup --} --EOF -+cat << EOF -+if [ "\$grub_platform" = "efi" ]; then -+ menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' { -+ fwsetup -+ } - fi -+EOF diff --git a/0186-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch b/0186-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch deleted file mode 100644 index 3b1a219..0000000 --- a/0186-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 6 Jul 2021 01:10:18 +0200 -Subject: [PATCH] efi: Print an error if boot to firmware setup is not - supported - -The "fwsetup" command is only registered if the firmware supports booting -to the firmware setup UI. But it could be possible that the GRUB config -already contains a "fwsetup" entry, because it was generated in a machine -that has support for this feature. - -To prevent users getting a "can't find command `fwsetup`" error if it is -not supported by the firmware, let's just always register the command but -print a more accurate message if the firmware doesn't support this option. - -Resolves: rhbz#1823864 - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/commands/efi/efifwsetup.c | 43 ++++++++++++++++++++----------------- - 1 file changed, 23 insertions(+), 20 deletions(-) - -diff --git a/grub-core/commands/efi/efifwsetup.c b/grub-core/commands/efi/efifwsetup.c -index eaca032838..328c45e82e 100644 ---- a/grub-core/commands/efi/efifwsetup.c -+++ b/grub-core/commands/efi/efifwsetup.c -@@ -27,6 +27,25 @@ - - GRUB_MOD_LICENSE ("GPLv3+"); - -+static grub_efi_boolean_t -+efifwsetup_is_supported (void) -+{ -+ grub_efi_uint64_t *os_indications_supported = NULL; -+ grub_size_t oi_size = 0; -+ grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; -+ -+ grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size, -+ (void **) &os_indications_supported); -+ -+ if (!os_indications_supported) -+ return 0; -+ -+ if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) -+ return 1; -+ -+ return 0; -+} -+ - static grub_err_t - grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), -@@ -38,6 +57,10 @@ grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), - grub_size_t oi_size; - grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; - -+ if (!efifwsetup_is_supported ()) -+ return grub_error (GRUB_ERR_INVALID_COMMAND, -+ N_("Reboot to firmware setup is not supported")); -+ - grub_efi_get_variable ("OsIndications", &global, &oi_size, - (void **) &old_os_indications); - -@@ -56,28 +79,8 @@ grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), - - static grub_command_t cmd = NULL; - --static grub_efi_boolean_t --efifwsetup_is_supported (void) --{ -- grub_efi_uint64_t *os_indications_supported = NULL; -- grub_size_t oi_size = 0; -- grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; -- -- grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size, -- (void **) &os_indications_supported); -- -- if (!os_indications_supported) -- return 0; -- -- if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) -- return 1; -- -- return 0; --} -- - GRUB_MOD_INIT (efifwsetup) - { -- if (efifwsetup_is_supported ()) - cmd = grub_register_command ("fwsetup", grub_cmd_fwsetup, NULL, - N_("Reboot into firmware setup menu.")); - diff --git a/0186-normal-main-Discover-the-device-to-read-the-config-f.patch b/0186-normal-main-Discover-the-device-to-read-the-config-f.patch new file mode 100644 index 0000000..2c9ca3a --- /dev/null +++ b/0186-normal-main-Discover-the-device-to-read-the-config-f.patch @@ -0,0 +1,123 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Mon, 30 Aug 2021 12:31:18 +0200 +Subject: [PATCH] normal/main: Discover the device to read the config from as a + fallback + +The GRUB core.img is generated locally, when this is done the grub2-probe +tool figures out the device and partition that needs to be read to parse +the GRUB configuration file. + +But in some cases the core.img can't be generated on the host and instead +has to be done at package build time. For example, if needs to get signed +with a key that's only available on the package building infrastructure. + +If that's the case, the prefix variable won't have a device and partition +but only a directory path. So there's no way for GRUB to know from which +device has to read the configuration file. + +To allow GRUB to continue working on that scenario, fallback to iterating +over all the available devices, if reading the config failed when using +the prefix and fw_path variables. + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/normal/main.c | 58 +++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 51 insertions(+), 7 deletions(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 7de9e4c36d..8f5fd81003 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -337,18 +337,13 @@ grub_enter_normal_mode (const char *config) + } + + static grub_err_t +-grub_try_normal (const char *variable) ++grub_try_normal_prefix (const char *prefix) + { + char *config; +- const char *prefix; + grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; + const char *net_search_cfg; + int disable_net_search = 0; + +- prefix = grub_env_get (variable); +- if (!prefix) +- return GRUB_ERR_FILE_NOT_FOUND; +- + net_search_cfg = grub_env_get ("feature_net_search_cfg"); + if (net_search_cfg && net_search_cfg[0] == 'n') + disable_net_search = 1; +@@ -362,7 +357,7 @@ grub_try_normal (const char *variable) + config = grub_malloc (config_len); + + if (! config) +- return GRUB_ERR_FILE_NOT_FOUND; ++ return err; + + grub_snprintf (config, config_len, "%s/grub.cfg", prefix); + err = grub_net_search_config_file (config); +@@ -391,6 +386,53 @@ grub_try_normal (const char *variable) + return err; + } + ++static int ++grub_try_normal_dev (const char *name, void *data) ++{ ++ grub_err_t err; ++ const char *prefix = grub_xasprintf ("(%s)%s", name, (char *)data); ++ ++ if (!prefix) ++ return 0; ++ ++ err = grub_try_normal_prefix (prefix); ++ if (err == GRUB_ERR_NONE) ++ return 1; ++ ++ return 0; ++} ++ ++static grub_err_t ++grub_try_normal_discover (void) ++{ ++ char *prefix = grub_env_get ("prefix"); ++ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; ++ ++ if (!prefix) ++ return err; ++ ++ if (grub_device_iterate (grub_try_normal_dev, (void *)prefix)) ++ return GRUB_ERR_NONE; ++ ++ return err; ++} ++ ++static grub_err_t ++grub_try_normal (const char *variable) ++{ ++ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; ++ const char *prefix; ++ ++ if (!variable) ++ return err; ++ ++ prefix = grub_env_get (variable); ++ if (!prefix) ++ return err; ++ ++ return grub_try_normal_prefix (prefix); ++} ++ + /* Enter normal mode from rescue mode. */ + static grub_err_t + grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), +@@ -405,6 +447,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + err = grub_try_normal ("fw_path"); + if (err == GRUB_ERR_FILE_NOT_FOUND) + err = grub_try_normal ("prefix"); ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ err = grub_try_normal_discover (); + if (err == GRUB_ERR_FILE_NOT_FOUND) + grub_enter_normal_mode (0); + } diff --git a/0187-arm64-Fix-EFI-loader-kernel-image-allocation.patch b/0187-arm64-Fix-EFI-loader-kernel-image-allocation.patch deleted file mode 100644 index cc5458c..0000000 --- a/0187-arm64-Fix-EFI-loader-kernel-image-allocation.patch +++ /dev/null @@ -1,218 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Herrenschmidt -Date: Mon, 2 Aug 2021 23:10:01 +1000 -Subject: [PATCH] arm64: Fix EFI loader kernel image allocation - -We are currently allocating just enough memory for the file size, -which means that the kernel BSS is in limbo (and not even zeroed). - -We are also not honoring the alignment specified in the image -PE header. - -This makes us use the PE optional header in which the kernel puts the -actual size it needs, including BSS, and make sure we clear it, and -honors the specified alignment for the image. - -Signed-off-by: Benjamin Herrenschmidt -[pjones: arm: check for the PE magic for the compiled arch] -Signed-off-by: Peter Jones -Signed-off-by: Robbie Harwood ---- - grub-core/loader/arm64/linux.c | 100 +++++++++++++++++++++++++++-------------- - include/grub/arm/linux.h | 1 + - include/grub/arm64/linux.h | 1 + - 3 files changed, 68 insertions(+), 34 deletions(-) - -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index 47f8cf0d84..f18d90bd74 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -41,6 +41,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); - static grub_dl_t my_mod; - static int loaded; - -+static void *kernel_alloc_addr; -+static grub_uint32_t kernel_alloc_pages; - static void *kernel_addr; - static grub_uint64_t kernel_size; - static grub_uint32_t handover_offset; -@@ -204,9 +206,8 @@ grub_linux_unload (void) - GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start)); - initrd_start = initrd_end = 0; - grub_free (linux_args); -- if (kernel_addr) -- grub_efi_free_pages ((grub_addr_t) kernel_addr, -- GRUB_EFI_BYTES_TO_PAGES (kernel_size)); -+ if (kernel_alloc_addr) -+ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages); - grub_fdt_unload (); - return GRUB_ERR_NONE; - } -@@ -311,14 +312,35 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - return grub_errno; - } - -+static grub_err_t -+parse_pe_header (void *kernel, grub_uint64_t *total_size, -+ grub_uint32_t *entry_offset, -+ grub_uint32_t *alignment) -+{ -+ struct linux_arch_kernel_header *lh = kernel; -+ struct grub_armxx_linux_pe_header *pe; -+ -+ pe = (void *)((unsigned long)kernel + lh->hdr_offset); -+ -+ if (pe->opt.magic != GRUB_PE32_PEXX_MAGIC) -+ return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic"); -+ -+ *total_size = pe->opt.image_size; -+ *entry_offset = pe->opt.entry_addr; -+ *alignment = pe->opt.section_alignment; -+ -+ return GRUB_ERR_NONE; -+} -+ - static grub_err_t - grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) - { - grub_file_t file = 0; -- struct linux_arch_kernel_header lh; -- struct grub_armxx_linux_pe_header *pe; - grub_err_t err; -+ grub_off_t filelen; -+ grub_uint32_t align; -+ void *kernel = NULL; - int rc; - - grub_dl_ref (my_mod); -@@ -333,40 +355,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - if (!file) - goto fail; - -- kernel_size = grub_file_size (file); -- -- if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) -- return grub_errno; -- -- if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE) -- goto fail; -- -- grub_loader_unset(); -- -- grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size); -- kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size)); -- grub_dprintf ("linux", "kernel numpages: %lld\n", -- (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size)); -- if (!kernel_addr) -+ filelen = grub_file_size (file); -+ kernel = grub_malloc(filelen); -+ if (!kernel) - { -- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel load buffer")); - goto fail; - } - -- grub_file_seek (file, 0); -- if (grub_file_read (file, kernel_addr, kernel_size) -- < (grub_int64_t) kernel_size) -+ if (grub_file_read (file, kernel, filelen) < (grub_ssize_t)filelen) - { -- if (!grub_errno) -- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); -+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), -+ argv[0]); - goto fail; - } - -- grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); -- - if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) - { -- rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); -+ rc = grub_linuxefi_secure_validate (kernel, filelen); - if (rc <= 0) - { - grub_error (GRUB_ERR_INVALID_COMMAND, -@@ -375,8 +381,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - } - -- pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); -- handover_offset = pe->opt.entry_addr; -+ if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) -+ goto fail; -+ if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) -+ goto fail; -+ grub_dprintf ("linux", "kernel mem size : %lld\n", (long long) kernel_size); -+ grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); -+ grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); -+ -+ grub_loader_unset(); -+ -+ kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); -+ kernel_alloc_addr = grub_efi_allocate_any_pages (kernel_alloc_pages); -+ grub_dprintf ("linux", "kernel numpages: %d\n", kernel_alloc_pages); -+ if (!kernel_alloc_addr) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -+ goto fail; -+ } -+ kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align); -+ -+ grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); -+ grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size)); -+ if (kernel_size > filelen) -+ grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen); -+ grub_free(kernel); -+ kernel = NULL; - - cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); - linux_args = grub_malloc (cmdline_size); -@@ -400,6 +430,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - - fail: -+ if (kernel) -+ grub_free (kernel); -+ - if (file) - grub_file_close (file); - -@@ -412,9 +445,8 @@ fail: - if (linux_args && !loaded) - grub_free (linux_args); - -- if (kernel_addr && !loaded) -- grub_efi_free_pages ((grub_addr_t) kernel_addr, -- GRUB_EFI_BYTES_TO_PAGES (kernel_size)); -+ if (kernel_alloc_addr && !loaded) -+ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages); - - return grub_errno; - } -diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h -index b582f67f66..966a5074f5 100644 ---- a/include/grub/arm/linux.h -+++ b/include/grub/arm/linux.h -@@ -44,6 +44,7 @@ struct grub_arm_linux_pe_header - - #if defined(__arm__) - # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM_MAGIC_SIGNATURE -+# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE32_MAGIC - # define linux_arch_kernel_header linux_arm_kernel_header - # define grub_armxx_linux_pe_header grub_arm_linux_pe_header - #endif -diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h -index ea030312df..422bf2bf24 100644 ---- a/include/grub/arm64/linux.h -+++ b/include/grub/arm64/linux.h -@@ -48,6 +48,7 @@ struct grub_arm64_linux_pe_header - - #if defined(__aarch64__) - # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE -+# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE64_MAGIC - # define linux_arch_kernel_header linux_arm64_kernel_header - # define grub_armxx_linux_pe_header grub_arm64_linux_pe_header - #endif diff --git a/0187-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch b/0187-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch new file mode 100644 index 0000000..b9bc140 --- /dev/null +++ b/0187-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 19 Jul 2021 14:35:55 +1000 +Subject: [PATCH] powerpc: adjust setting of prefix for signed binary case + +On RHEL-signed powerpc grub, we sign a grub with -p /grub2 and expect +that there's a boot partition. + +Unfortunately grub_set_prefix_and_root tries to convert this to +($fwdevice)/grub2. This ends up being (ieee1275/disk)/grub2 and that +falls apart pretty quickly - there's no file-system on ieee1275/disk, +and it makes the search routine try things like +(ieee1275/disk,msdos2)(ieee1275/disk)/grub2 which also doesn't work. + +Detect if we would be about to create (ieee1275/disk)/path and don't: +preserve a prefix of /path instead and hope the search later finds us. + +Related: rhbz#1899864 + +Signed-off-by: Daniel Axtens +[rharwood@redhat.com: squash in fixup commit] +Signed-off-by: Robbie Harwood +--- + grub-core/kern/main.c | 49 ++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 44 insertions(+), 5 deletions(-) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index b573be6650..3fc3401472 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -216,13 +216,52 @@ grub_set_prefix_and_root (void) + if (device) + { + char *prefix_set; +- +- prefix_set = grub_xasprintf ("(%s)%s", device, path ? : ""); +- if (prefix_set) ++ ++#ifdef __powerpc__ ++ /* We have to be careful here on powerpc-ieee1275 + signed grub. We ++ will have signed something with a prefix that doesn't have a device ++ because we cannot know in advance what partition we're on. ++ ++ We will have had !device earlier, so we will have set device=fwdevice ++ However, we want to make sure we do not end up setting prefix to be ++ ($fwdevice)/path, because we will then end up trying to boot or search ++ based on a prefix of (ieee1275/disk)/path, which will not work because ++ it's missing a partition. ++ ++ Also: ++ - You can end up with a device with an FS directly on it, without ++ a partition, e.g. ieee1275/cdrom. ++ ++ - powerpc-ieee1275 + grub-install sets e.g. prefix=(,gpt2)/path, ++ which will have now been extended to device=$fwdisk,partition ++ and path=/path ++ ++ - PowerVM will give us device names like ++ ieee1275//vdevice/v-scsi@3000006c/disk@8100000000000000 ++ and we don't want to try to encode some sort of truth table about ++ what sorts of paths represent disks with partition tables and those ++ without partition tables. ++ ++ So we act unless there is a comma in the device, which would indicate ++ a partition has already been specified. ++ ++ (If we only have a path, the code in normal to discover config files ++ will try both without partitions and then with any partitions so we ++ will cover both CDs and HDs.) ++ */ ++ if (grub_strchr (device, ',') == NULL) ++ grub_env_set ("prefix", path); ++ else ++#endif + { +- grub_env_set ("prefix", prefix_set); +- grub_free (prefix_set); ++ prefix_set = grub_xasprintf ("(%s)%s", device, path ? : ""); ++ if (prefix_set) ++ { ++ grub_env_set ("prefix", prefix_set); ++ grub_free (prefix_set); ++ } + } ++ + grub_env_set ("root", device); + } + diff --git a/0188-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch b/0188-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch new file mode 100644 index 0000000..7fc40f1 --- /dev/null +++ b/0188-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch @@ -0,0 +1,118 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Erwan Velu +Date: Wed, 25 Aug 2021 15:31:52 +0200 +Subject: [PATCH] fs/xfs: Fix unreadable filesystem with v4 superblock + +The commit 8b1e5d193 (fs/xfs: Add bigtime incompat feature support) +introduced the bigtime support by adding some features in v3 inodes. +This change extended grub_xfs_inode struct by 76 bytes but also changed +the computation of XFS_V2_INODE_SIZE and XFS_V3_INODE_SIZE. Prior this +commit, XFS_V2_INODE_SIZE was 100 bytes. After the commit it's 84 bytes +XFS_V2_INODE_SIZE becomes 16 bytes too small. + +As a result, the data structures aren't properly aligned and the GRUB +generates "attempt to read or write outside of partition" errors when +trying to read the XFS filesystem: + + GNU GRUB version 2.11 + .... + grub> set debug=efi,gpt,xfs + grub> insmod part_gpt + grub> ls (hd0,gpt1)/ + partmap/gpt.c:93: Read a valid GPT header + partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125 + fs/xfs.c:931: Reading sb + fs/xfs.c:270: Validating superblock + fs/xfs.c:295: XFS v4 superblock detected + fs/xfs.c:962: Reading root ino 128 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (739521961424144223) - 344365866970255880, 3840 + error: attempt to read or write outside of partition. + +This commit change the XFS_V2_INODE_SIZE computation by subtracting 76 +bytes instead of 92 bytes from the actual size of grub_xfs_inode struct. +This 76 bytes value comes from added members: + 20 grub_uint8_t unused5 + 1 grub_uint64_t flags2 + 48 grub_uint8_t unused6 + +This patch explicitly splits the v2 and v3 parts of the structure. +The unused4 is still ending of the v2 structures and the v3 starts +at unused5. Thanks to this we will avoid future corruptions of v2 +or v3 inodes. + +The XFS_V2_INODE_SIZE is returning to its expected size and the +filesystem is back to a readable state: + + GNU GRUB version 2.11 + .... + grub> set debug=efi,gpt,xfs + grub> insmod part_gpt + grub> ls (hd0,gpt1)/ + partmap/gpt.c:93: Read a valid GPT header + partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125 + fs/xfs.c:931: Reading sb + fs/xfs.c:270: Validating superblock + fs/xfs.c:295: XFS v4 superblock detected + fs/xfs.c:962: Reading root ino 128 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:931: Reading sb + fs/xfs.c:270: Validating superblock + fs/xfs.c:295: XFS v4 superblock detected + fs/xfs.c:962: Reading root ino 128 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (131) - 64, 768 + efi/ fs/xfs.c:515: Reading inode (3145856) - 1464904, 0 + grub2/ fs/xfs.c:515: Reading inode (132) - 64, 1024 + grub/ fs/xfs.c:515: Reading inode (139) - 64, 2816 + grub> + +Fixes: 8b1e5d193 (fs/xfs: Add bigtime incompat feature support) + +Signed-off-by: Erwan Velu +Tested-by: Carlos Maiolino +Reviewed-by: Daniel Kiper +(cherry picked from commit a4b495520e4dc41a896a8b916a64eda9970c50ea) +--- + grub-core/fs/xfs.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 0f524c3a8a..e3816d1ec4 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -192,6 +192,11 @@ struct grub_xfs_time_legacy + grub_uint32_t nanosec; + } GRUB_PACKED; + ++/* ++ * The struct grub_xfs_inode layout was taken from the ++ * struct xfs_dinode_core which is described here: ++ * https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf ++ */ + struct grub_xfs_inode + { + grub_uint8_t magic[2]; +@@ -208,14 +213,15 @@ struct grub_xfs_inode + grub_uint32_t nextents; + grub_uint16_t unused3; + grub_uint8_t fork_offset; +- grub_uint8_t unused4[37]; ++ grub_uint8_t unused4[17]; /* Last member of inode v2. */ ++ grub_uint8_t unused5[20]; /* First member of inode v3. */ + grub_uint64_t flags2; +- grub_uint8_t unused5[48]; ++ grub_uint8_t unused6[48]; /* Last member of inode v3. */ + } GRUB_PACKED; + + #define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode) +-/* Size of struct grub_xfs_inode until fork_offset (included). */ +-#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 92) ++/* Size of struct grub_xfs_inode v2, up to unused4 member included. */ ++#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76) + + struct grub_xfs_dirblock_tail + { diff --git a/0188-normal-main-Discover-the-device-to-read-the-config-f.patch b/0188-normal-main-Discover-the-device-to-read-the-config-f.patch deleted file mode 100644 index 2c9ca3a..0000000 --- a/0188-normal-main-Discover-the-device-to-read-the-config-f.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Mon, 30 Aug 2021 12:31:18 +0200 -Subject: [PATCH] normal/main: Discover the device to read the config from as a - fallback - -The GRUB core.img is generated locally, when this is done the grub2-probe -tool figures out the device and partition that needs to be read to parse -the GRUB configuration file. - -But in some cases the core.img can't be generated on the host and instead -has to be done at package build time. For example, if needs to get signed -with a key that's only available on the package building infrastructure. - -If that's the case, the prefix variable won't have a device and partition -but only a directory path. So there's no way for GRUB to know from which -device has to read the configuration file. - -To allow GRUB to continue working on that scenario, fallback to iterating -over all the available devices, if reading the config failed when using -the prefix and fw_path variables. - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/normal/main.c | 58 +++++++++++++++++++++++++++++++++++++++++++------ - 1 file changed, 51 insertions(+), 7 deletions(-) - -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index 7de9e4c36d..8f5fd81003 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -337,18 +337,13 @@ grub_enter_normal_mode (const char *config) - } - - static grub_err_t --grub_try_normal (const char *variable) -+grub_try_normal_prefix (const char *prefix) - { - char *config; -- const char *prefix; - grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; - const char *net_search_cfg; - int disable_net_search = 0; - -- prefix = grub_env_get (variable); -- if (!prefix) -- return GRUB_ERR_FILE_NOT_FOUND; -- - net_search_cfg = grub_env_get ("feature_net_search_cfg"); - if (net_search_cfg && net_search_cfg[0] == 'n') - disable_net_search = 1; -@@ -362,7 +357,7 @@ grub_try_normal (const char *variable) - config = grub_malloc (config_len); - - if (! config) -- return GRUB_ERR_FILE_NOT_FOUND; -+ return err; - - grub_snprintf (config, config_len, "%s/grub.cfg", prefix); - err = grub_net_search_config_file (config); -@@ -391,6 +386,53 @@ grub_try_normal (const char *variable) - return err; - } - -+static int -+grub_try_normal_dev (const char *name, void *data) -+{ -+ grub_err_t err; -+ const char *prefix = grub_xasprintf ("(%s)%s", name, (char *)data); -+ -+ if (!prefix) -+ return 0; -+ -+ err = grub_try_normal_prefix (prefix); -+ if (err == GRUB_ERR_NONE) -+ return 1; -+ -+ return 0; -+} -+ -+static grub_err_t -+grub_try_normal_discover (void) -+{ -+ char *prefix = grub_env_get ("prefix"); -+ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; -+ -+ if (!prefix) -+ return err; -+ -+ if (grub_device_iterate (grub_try_normal_dev, (void *)prefix)) -+ return GRUB_ERR_NONE; -+ -+ return err; -+} -+ -+static grub_err_t -+grub_try_normal (const char *variable) -+{ -+ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; -+ const char *prefix; -+ -+ if (!variable) -+ return err; -+ -+ prefix = grub_env_get (variable); -+ if (!prefix) -+ return err; -+ -+ return grub_try_normal_prefix (prefix); -+} -+ - /* Enter normal mode from rescue mode. */ - static grub_err_t - grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), -@@ -405,6 +447,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), - err = grub_try_normal ("fw_path"); - if (err == GRUB_ERR_FILE_NOT_FOUND) - err = grub_try_normal ("prefix"); -+ if (err == GRUB_ERR_FILE_NOT_FOUND) -+ err = grub_try_normal_discover (); - if (err == GRUB_ERR_FILE_NOT_FOUND) - grub_enter_normal_mode (0); - } diff --git a/0189-Print-module-name-on-license-check-failure.patch b/0189-Print-module-name-on-license-check-failure.patch new file mode 100644 index 0000000..5c30859 --- /dev/null +++ b/0189-Print-module-name-on-license-check-failure.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 12 Oct 2021 12:34:23 -0400 +Subject: [PATCH] Print module name on license check failure + +At the very least, this will make it easier to track down the problem +module - or, if something else has gone wrong, provide more information +for debugging. + +Signed-off-by: Robbie Harwood +--- + grub-core/kern/dl.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index 9557254035..f304494574 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -528,14 +528,16 @@ grub_dl_find_section_index (Elf_Ehdr *e, const char *name) + Be sure to understand your license obligations. + */ + static grub_err_t +-grub_dl_check_license (Elf_Ehdr *e) ++grub_dl_check_license (grub_dl_t mod, Elf_Ehdr *e) + { + Elf_Shdr *s = grub_dl_find_section (e, ".module_license"); + if (s && (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0 + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0)) + return GRUB_ERR_NONE; +- return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license"); ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "incompatible license in module %s: %s", mod->name, ++ (char *) e + s->sh_offset); + } + + static grub_err_t +@@ -743,8 +745,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) + constitutes linking) and GRUB core being licensed under GPLv3+. + Be sure to understand your license obligations. + */ +- if (grub_dl_check_license (e) +- || grub_dl_resolve_name (mod, e) ++ if (grub_dl_resolve_name (mod, e) ++ || grub_dl_check_license (mod, e) + || grub_dl_resolve_dependencies (mod, e) + || grub_dl_load_segments (mod, e) + || grub_dl_resolve_symbols (mod, e) diff --git a/0189-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch b/0189-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch deleted file mode 100644 index b9bc140..0000000 --- a/0189-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 19 Jul 2021 14:35:55 +1000 -Subject: [PATCH] powerpc: adjust setting of prefix for signed binary case - -On RHEL-signed powerpc grub, we sign a grub with -p /grub2 and expect -that there's a boot partition. - -Unfortunately grub_set_prefix_and_root tries to convert this to -($fwdevice)/grub2. This ends up being (ieee1275/disk)/grub2 and that -falls apart pretty quickly - there's no file-system on ieee1275/disk, -and it makes the search routine try things like -(ieee1275/disk,msdos2)(ieee1275/disk)/grub2 which also doesn't work. - -Detect if we would be about to create (ieee1275/disk)/path and don't: -preserve a prefix of /path instead and hope the search later finds us. - -Related: rhbz#1899864 - -Signed-off-by: Daniel Axtens -[rharwood@redhat.com: squash in fixup commit] -Signed-off-by: Robbie Harwood ---- - grub-core/kern/main.c | 49 ++++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 44 insertions(+), 5 deletions(-) - -diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index b573be6650..3fc3401472 100644 ---- a/grub-core/kern/main.c -+++ b/grub-core/kern/main.c -@@ -216,13 +216,52 @@ grub_set_prefix_and_root (void) - if (device) - { - char *prefix_set; -- -- prefix_set = grub_xasprintf ("(%s)%s", device, path ? : ""); -- if (prefix_set) -+ -+#ifdef __powerpc__ -+ /* We have to be careful here on powerpc-ieee1275 + signed grub. We -+ will have signed something with a prefix that doesn't have a device -+ because we cannot know in advance what partition we're on. -+ -+ We will have had !device earlier, so we will have set device=fwdevice -+ However, we want to make sure we do not end up setting prefix to be -+ ($fwdevice)/path, because we will then end up trying to boot or search -+ based on a prefix of (ieee1275/disk)/path, which will not work because -+ it's missing a partition. -+ -+ Also: -+ - You can end up with a device with an FS directly on it, without -+ a partition, e.g. ieee1275/cdrom. -+ -+ - powerpc-ieee1275 + grub-install sets e.g. prefix=(,gpt2)/path, -+ which will have now been extended to device=$fwdisk,partition -+ and path=/path -+ -+ - PowerVM will give us device names like -+ ieee1275//vdevice/v-scsi@3000006c/disk@8100000000000000 -+ and we don't want to try to encode some sort of truth table about -+ what sorts of paths represent disks with partition tables and those -+ without partition tables. -+ -+ So we act unless there is a comma in the device, which would indicate -+ a partition has already been specified. -+ -+ (If we only have a path, the code in normal to discover config files -+ will try both without partitions and then with any partitions so we -+ will cover both CDs and HDs.) -+ */ -+ if (grub_strchr (device, ',') == NULL) -+ grub_env_set ("prefix", path); -+ else -+#endif - { -- grub_env_set ("prefix", prefix_set); -- grub_free (prefix_set); -+ prefix_set = grub_xasprintf ("(%s)%s", device, path ? : ""); -+ if (prefix_set) -+ { -+ grub_env_set ("prefix", prefix_set); -+ grub_free (prefix_set); -+ } - } -+ - grub_env_set ("root", device); - } - diff --git a/0190-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch b/0190-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch deleted file mode 100644 index 7fc40f1..0000000 --- a/0190-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Erwan Velu -Date: Wed, 25 Aug 2021 15:31:52 +0200 -Subject: [PATCH] fs/xfs: Fix unreadable filesystem with v4 superblock - -The commit 8b1e5d193 (fs/xfs: Add bigtime incompat feature support) -introduced the bigtime support by adding some features in v3 inodes. -This change extended grub_xfs_inode struct by 76 bytes but also changed -the computation of XFS_V2_INODE_SIZE and XFS_V3_INODE_SIZE. Prior this -commit, XFS_V2_INODE_SIZE was 100 bytes. After the commit it's 84 bytes -XFS_V2_INODE_SIZE becomes 16 bytes too small. - -As a result, the data structures aren't properly aligned and the GRUB -generates "attempt to read or write outside of partition" errors when -trying to read the XFS filesystem: - - GNU GRUB version 2.11 - .... - grub> set debug=efi,gpt,xfs - grub> insmod part_gpt - grub> ls (hd0,gpt1)/ - partmap/gpt.c:93: Read a valid GPT header - partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125 - fs/xfs.c:931: Reading sb - fs/xfs.c:270: Validating superblock - fs/xfs.c:295: XFS v4 superblock detected - fs/xfs.c:962: Reading root ino 128 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:515: Reading inode (739521961424144223) - 344365866970255880, 3840 - error: attempt to read or write outside of partition. - -This commit change the XFS_V2_INODE_SIZE computation by subtracting 76 -bytes instead of 92 bytes from the actual size of grub_xfs_inode struct. -This 76 bytes value comes from added members: - 20 grub_uint8_t unused5 - 1 grub_uint64_t flags2 - 48 grub_uint8_t unused6 - -This patch explicitly splits the v2 and v3 parts of the structure. -The unused4 is still ending of the v2 structures and the v3 starts -at unused5. Thanks to this we will avoid future corruptions of v2 -or v3 inodes. - -The XFS_V2_INODE_SIZE is returning to its expected size and the -filesystem is back to a readable state: - - GNU GRUB version 2.11 - .... - grub> set debug=efi,gpt,xfs - grub> insmod part_gpt - grub> ls (hd0,gpt1)/ - partmap/gpt.c:93: Read a valid GPT header - partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125 - fs/xfs.c:931: Reading sb - fs/xfs.c:270: Validating superblock - fs/xfs.c:295: XFS v4 superblock detected - fs/xfs.c:962: Reading root ino 128 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:931: Reading sb - fs/xfs.c:270: Validating superblock - fs/xfs.c:295: XFS v4 superblock detected - fs/xfs.c:962: Reading root ino 128 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:515: Reading inode (131) - 64, 768 - efi/ fs/xfs.c:515: Reading inode (3145856) - 1464904, 0 - grub2/ fs/xfs.c:515: Reading inode (132) - 64, 1024 - grub/ fs/xfs.c:515: Reading inode (139) - 64, 2816 - grub> - -Fixes: 8b1e5d193 (fs/xfs: Add bigtime incompat feature support) - -Signed-off-by: Erwan Velu -Tested-by: Carlos Maiolino -Reviewed-by: Daniel Kiper -(cherry picked from commit a4b495520e4dc41a896a8b916a64eda9970c50ea) ---- - grub-core/fs/xfs.c | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - -diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c -index 0f524c3a8a..e3816d1ec4 100644 ---- a/grub-core/fs/xfs.c -+++ b/grub-core/fs/xfs.c -@@ -192,6 +192,11 @@ struct grub_xfs_time_legacy - grub_uint32_t nanosec; - } GRUB_PACKED; - -+/* -+ * The struct grub_xfs_inode layout was taken from the -+ * struct xfs_dinode_core which is described here: -+ * https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf -+ */ - struct grub_xfs_inode - { - grub_uint8_t magic[2]; -@@ -208,14 +213,15 @@ struct grub_xfs_inode - grub_uint32_t nextents; - grub_uint16_t unused3; - grub_uint8_t fork_offset; -- grub_uint8_t unused4[37]; -+ grub_uint8_t unused4[17]; /* Last member of inode v2. */ -+ grub_uint8_t unused5[20]; /* First member of inode v3. */ - grub_uint64_t flags2; -- grub_uint8_t unused5[48]; -+ grub_uint8_t unused6[48]; /* Last member of inode v3. */ - } GRUB_PACKED; - - #define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode) --/* Size of struct grub_xfs_inode until fork_offset (included). */ --#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 92) -+/* Size of struct grub_xfs_inode v2, up to unused4 member included. */ -+#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76) - - struct grub_xfs_dirblock_tail - { diff --git a/0190-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch b/0190-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch new file mode 100644 index 0000000..216418b --- /dev/null +++ b/0190-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Fri, 22 Oct 2021 09:53:15 +1100 +Subject: [PATCH] powerpc-ieee1275: load grub at 4MB, not 2MB + +This was first reported under PFW but reproduces under SLOF. + + - The core.elf was 2126152 = 0x207148 bytes in size with the following + program headers (per readelf): + +Entry point 0x200000 +There are 4 program headers, starting at offset 52 + +Program Headers: + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + LOAD 0x000160 0x00200000 0x00200000 0x21f98 0x2971c RWE 0x8 + GNU_STACK 0x0220f8 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4 + LOAD 0x0220f8 0x00232000 0x00232000 0x1e4e50 0x1e4e50 RWE 0x4 + NOTE 0x206f48 0x00000000 0x00000000 0x00200 0x00000 R 0x4 + + - SLOF places the ELF file at 0x4000 (after the reserved space for + interrupt handlers etc.) upwards. The image was 2126152 = 0x207148 + bytes in size, so it runs from 0x4000 - 0x20b148. We'll call 0x4000 the + load address. + +0x0 0x4000 0x20b148 + |----------|--------------| + | reserved | ELF contents | + + - SLOF then copies the first LOAD program header (for .text). That runs + for 0x21f98 bytes. It runs from + (load addr + 0x160) to (load addr + 0x160 + 0x21f98) + = 0x4160 to 0x260f8 + and we copy it to 0x200000 to 0x221f98. This overwrites the end of the + image: + +0x0 0x4000 0x200000 0x221f98 + |----------|------------|---------------| + | reserved | ELF cont.. | .text section | + + - SLOF zeros the bss up to PhysAddr + MemSize = 0x22971c + +0x0 0x4000 0x200000 0x221f98 0x22971c + |----------|------------|---------------|--------| + | reserved | ELF cont.. | .text section | bss 0s | + + - SLOF then goes to fulfil the next LOAD header (for mods), which is + for 0x1e4e50 bytes. We copy from + (load addr + 0x220f8) to (load addr + 0x220f8 + 0x1e4e50) + = 0x260f8 to 0x20af48 + and we copy it to 0x232000 to 0x416e50: + +0x0 0x4000 0x200000 0x221f98 0x22971c + |----------|------------|---------------|--------| + | reserved | ELF cont.. | .text section | bss 0s | + |-------------| + | copied area | + 0x260f8 0x20af48 + + This goes poorly: + +0x0 0x4000 0x200000 0x221f98 0x22971c 0x232000 0x40bf08 0x416e50 + |----------|------------|---------------|--------|-----|-----------|-------------| + | reserved | ELF cont.. | .text section | bss 0s | pad | some mods | .text start | + +This matches the observations on the running system - 0x40bf08 was where +the contents of memory no longer matched the contents of the ELF file. + +This was reported as a license verification failure on SLOF as the +last module's .module_license section fell past where the corruption +began. + +Signed-off-by: Daniel Axtens +[rharwood@redhat.com: trim very detailed commit message] +Signed-off-by: Robbie Harwood +--- + grub-core/Makefile.core.def | 2 +- + include/grub/offsets.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 4a57de975e..08ac0fb15f 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -89,7 +89,7 @@ kernel = { + i386_xen_pvh_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x100000'; + + mips_loongson_ldflags = '-Wl,-Ttext,0x80200000'; +- powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; ++ powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x400000'; + sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; + mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)'; + mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; +diff --git a/include/grub/offsets.h b/include/grub/offsets.h +index 871e1cd4c3..69211aa798 100644 +--- a/include/grub/offsets.h ++++ b/include/grub/offsets.h +@@ -63,7 +63,7 @@ + #define GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR 0x4400 + + #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4 +-#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x200000 ++#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x400000 + + #define GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR 0x80200000 + diff --git a/0191-Print-module-name-on-license-check-failure.patch b/0191-Print-module-name-on-license-check-failure.patch deleted file mode 100644 index 5c30859..0000000 --- a/0191-Print-module-name-on-license-check-failure.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Tue, 12 Oct 2021 12:34:23 -0400 -Subject: [PATCH] Print module name on license check failure - -At the very least, this will make it easier to track down the problem -module - or, if something else has gone wrong, provide more information -for debugging. - -Signed-off-by: Robbie Harwood ---- - grub-core/kern/dl.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index 9557254035..f304494574 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -528,14 +528,16 @@ grub_dl_find_section_index (Elf_Ehdr *e, const char *name) - Be sure to understand your license obligations. - */ - static grub_err_t --grub_dl_check_license (Elf_Ehdr *e) -+grub_dl_check_license (grub_dl_t mod, Elf_Ehdr *e) - { - Elf_Shdr *s = grub_dl_find_section (e, ".module_license"); - if (s && (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 - || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0 - || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0)) - return GRUB_ERR_NONE; -- return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license"); -+ return grub_error (GRUB_ERR_BAD_MODULE, -+ "incompatible license in module %s: %s", mod->name, -+ (char *) e + s->sh_offset); - } - - static grub_err_t -@@ -743,8 +745,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) - constitutes linking) and GRUB core being licensed under GPLv3+. - Be sure to understand your license obligations. - */ -- if (grub_dl_check_license (e) -- || grub_dl_resolve_name (mod, e) -+ if (grub_dl_resolve_name (mod, e) -+ || grub_dl_check_license (mod, e) - || grub_dl_resolve_dependencies (mod, e) - || grub_dl_load_segments (mod, e) - || grub_dl_resolve_symbols (mod, e) diff --git a/0191-grub-mkconfig-restore-umask-for-grub.cfg.patch b/0191-grub-mkconfig-restore-umask-for-grub.cfg.patch new file mode 100644 index 0000000..76b73f5 --- /dev/null +++ b/0191-grub-mkconfig-restore-umask-for-grub.cfg.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang via Grub-devel +Date: Fri, 3 Dec 2021 16:13:28 +0800 +Subject: [PATCH] grub-mkconfig: restore umask for grub.cfg + +Since commit: + + ab2e53c8a grub-mkconfig: Honor a symlink when generating configuration +by grub-mkconfig + +has inadvertently discarded umask for creating grub.cfg in the process +of grub-mkconfig. The resulting wrong permission (0644) would allow +unprivileged users to read grub's configuration file content. This +presents a low confidentiality risk as grub.cfg may contain non-secured +plain-text passwords. + +This patch restores the missing umask and set the file mode of creation +to 0600 preventing unprivileged access. + +Fixes: CVE-2021-3981 + +Signed-off-by: Michael Chang +--- + util/grub-mkconfig.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index f55339a3f6..520a672cd2 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -311,7 +311,9 @@ and /etc/grub.d/* files or please file a bug report with + exit 1 + else + # none of the children aborted with error, install the new grub.cfg ++ oldumask=$(umask); umask 077 + cat ${grub_cfg}.new > ${grub_cfg} ++ umask $oldumask + rm -f ${grub_cfg}.new + fi + fi diff --git a/0192-fs-btrfs-Use-full-btrfs-bootloader-area.patch b/0192-fs-btrfs-Use-full-btrfs-bootloader-area.patch new file mode 100644 index 0000000..3f7198f --- /dev/null +++ b/0192-fs-btrfs-Use-full-btrfs-bootloader-area.patch @@ -0,0 +1,160 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 13 Dec 2021 14:25:49 +0800 +Subject: [PATCH] fs/btrfs: Use full btrfs bootloader area + +Up to now GRUB can only embed to the first 64 KiB before primary +superblock of btrfs, effectively limiting the GRUB core size. That +could consequently pose restrictions to feature enablement like +advanced zstd compression. + +This patch attempts to utilize full unused area reserved by btrfs for +the bootloader outlined in the document [1]: + + The first 1MiB on each device is unused with the exception of primary + superblock that is on the offset 64KiB and spans 4KiB. + +Apart from that, adjacent sectors to superblock and first block group +are not used for embedding in case of overflow and logged access to +adjacent sectors could be useful for tracing it up. + +This patch has been tested to provide out of the box support for btrfs +zstd compression with which GRUB has been installed to the partition. + +[1] https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT + +Signed-off-by: Michael Chang +Reviewed-by: Daniel Kiper +(cherry picked from commit b0f06a81c6f31b6fa20be67a96b6683bba8210c9) +--- + grub-core/fs/btrfs.c | 90 ++++++++++++++++++++++++++++++++++++++++++++-------- + include/grub/disk.h | 2 ++ + 2 files changed, 79 insertions(+), 13 deletions(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 4cc86e9b79..07c0ff874b 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -2476,6 +2476,33 @@ grub_btrfs_label (grub_device_t device, char **label) + } + + #ifdef GRUB_UTIL ++ ++struct embed_region { ++ unsigned int start; ++ unsigned int secs; ++}; ++ ++/* ++ * https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT ++ * The first 1 MiB on each device is unused with the exception of primary ++ * superblock that is on the offset 64 KiB and spans 4 KiB. ++ */ ++ ++static const struct { ++ struct embed_region available; ++ struct embed_region used[6]; ++} btrfs_head = { ++ .available = {0, GRUB_DISK_KiB_TO_SECTORS (1024)}, /* The first 1 MiB. */ ++ .used = { ++ {0, 1}, /* boot.S. */ ++ {GRUB_DISK_KiB_TO_SECTORS (64) - 1, 1}, /* Overflow guard. */ ++ {GRUB_DISK_KiB_TO_SECTORS (64), GRUB_DISK_KiB_TO_SECTORS (4)}, /* 4 KiB superblock. */ ++ {GRUB_DISK_KiB_TO_SECTORS (68), 1}, /* Overflow guard. */ ++ {GRUB_DISK_KiB_TO_SECTORS (1024) - 1, 1}, /* Overflow guard. */ ++ {0, 0} /* Array terminator. */ ++ } ++}; ++ + static grub_err_t + grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), + unsigned int *nsectors, +@@ -2483,25 +2510,62 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors) + { +- unsigned i; ++ unsigned int i, j, n = 0; ++ const struct embed_region *u; ++ grub_disk_addr_t *map; + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "BtrFS currently supports only PC-BIOS embedding"); + +- if (64 * 2 - 1 < *nsectors) +- return grub_error (GRUB_ERR_OUT_OF_RANGE, +- N_("your core.img is unusually large. " +- "It won't fit in the embedding area")); +- +- *nsectors = 64 * 2 - 1; +- if (*nsectors > max_nsectors) +- *nsectors = max_nsectors; +- *sectors = grub_calloc (*nsectors, sizeof (**sectors)); +- if (!*sectors) ++ map = grub_calloc (btrfs_head.available.secs, sizeof (*map)); ++ if (map == NULL) + return grub_errno; +- for (i = 0; i < *nsectors; i++) +- (*sectors)[i] = i + 1; ++ ++ /* ++ * Populating the map array so that it can be used to index if a disk ++ * address is available to embed: ++ * - 0: available, ++ * - 1: unavailable. ++ */ ++ for (u = btrfs_head.used; u->secs; ++u) ++ { ++ unsigned int end = u->start + u->secs; ++ ++ if (end > btrfs_head.available.secs) ++ end = btrfs_head.available.secs; ++ for (i = u->start; i < end; ++i) ++ map[i] = 1; ++ } ++ ++ /* Adding up n until it matches total size of available embedding area. */ ++ for (i = 0; i < btrfs_head.available.secs; ++i) ++ if (map[i] == 0) ++ n++; ++ ++ if (n < *nsectors) ++ { ++ grub_free (map); ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, ++ N_("your core.img is unusually large. " ++ "It won't fit in the embedding area")); ++ } ++ ++ if (n > max_nsectors) ++ n = max_nsectors; ++ ++ /* ++ * Populating the array so that it can used to index disk block address for ++ * an image file's offset to be embedded on disk (the unit is in sectors): ++ * - i: The disk block address relative to btrfs_head.available.start, ++ * - j: The offset in image file. ++ */ ++ for (i = 0, j = 0; i < btrfs_head.available.secs && j < n; ++i) ++ if (map[i] == 0) ++ map[j++] = btrfs_head.available.start + i; ++ ++ *nsectors = n; ++ *sectors = map; + + return GRUB_ERR_NONE; + } +diff --git a/include/grub/disk.h b/include/grub/disk.h +index f95aca929a..06210a7049 100644 +--- a/include/grub/disk.h ++++ b/include/grub/disk.h +@@ -182,6 +182,8 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t; + /* Return value of grub_disk_native_sectors() in case disk size is unknown. */ + #define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL + ++#define GRUB_DISK_KiB_TO_SECTORS(x) ((x) << (10 - GRUB_DISK_SECTOR_BITS)) ++ + /* Convert sector number from one sector size to another. */ + static inline grub_disk_addr_t + grub_convert_sector (grub_disk_addr_t sector, diff --git a/0192-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch b/0192-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch deleted file mode 100644 index 216418b..0000000 --- a/0192-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 22 Oct 2021 09:53:15 +1100 -Subject: [PATCH] powerpc-ieee1275: load grub at 4MB, not 2MB - -This was first reported under PFW but reproduces under SLOF. - - - The core.elf was 2126152 = 0x207148 bytes in size with the following - program headers (per readelf): - -Entry point 0x200000 -There are 4 program headers, starting at offset 52 - -Program Headers: - Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align - LOAD 0x000160 0x00200000 0x00200000 0x21f98 0x2971c RWE 0x8 - GNU_STACK 0x0220f8 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4 - LOAD 0x0220f8 0x00232000 0x00232000 0x1e4e50 0x1e4e50 RWE 0x4 - NOTE 0x206f48 0x00000000 0x00000000 0x00200 0x00000 R 0x4 - - - SLOF places the ELF file at 0x4000 (after the reserved space for - interrupt handlers etc.) upwards. The image was 2126152 = 0x207148 - bytes in size, so it runs from 0x4000 - 0x20b148. We'll call 0x4000 the - load address. - -0x0 0x4000 0x20b148 - |----------|--------------| - | reserved | ELF contents | - - - SLOF then copies the first LOAD program header (for .text). That runs - for 0x21f98 bytes. It runs from - (load addr + 0x160) to (load addr + 0x160 + 0x21f98) - = 0x4160 to 0x260f8 - and we copy it to 0x200000 to 0x221f98. This overwrites the end of the - image: - -0x0 0x4000 0x200000 0x221f98 - |----------|------------|---------------| - | reserved | ELF cont.. | .text section | - - - SLOF zeros the bss up to PhysAddr + MemSize = 0x22971c - -0x0 0x4000 0x200000 0x221f98 0x22971c - |----------|------------|---------------|--------| - | reserved | ELF cont.. | .text section | bss 0s | - - - SLOF then goes to fulfil the next LOAD header (for mods), which is - for 0x1e4e50 bytes. We copy from - (load addr + 0x220f8) to (load addr + 0x220f8 + 0x1e4e50) - = 0x260f8 to 0x20af48 - and we copy it to 0x232000 to 0x416e50: - -0x0 0x4000 0x200000 0x221f98 0x22971c - |----------|------------|---------------|--------| - | reserved | ELF cont.. | .text section | bss 0s | - |-------------| - | copied area | - 0x260f8 0x20af48 - - This goes poorly: - -0x0 0x4000 0x200000 0x221f98 0x22971c 0x232000 0x40bf08 0x416e50 - |----------|------------|---------------|--------|-----|-----------|-------------| - | reserved | ELF cont.. | .text section | bss 0s | pad | some mods | .text start | - -This matches the observations on the running system - 0x40bf08 was where -the contents of memory no longer matched the contents of the ELF file. - -This was reported as a license verification failure on SLOF as the -last module's .module_license section fell past where the corruption -began. - -Signed-off-by: Daniel Axtens -[rharwood@redhat.com: trim very detailed commit message] -Signed-off-by: Robbie Harwood ---- - grub-core/Makefile.core.def | 2 +- - include/grub/offsets.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 4a57de975e..08ac0fb15f 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -89,7 +89,7 @@ kernel = { - i386_xen_pvh_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x100000'; - - mips_loongson_ldflags = '-Wl,-Ttext,0x80200000'; -- powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; -+ powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x400000'; - sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; - mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)'; - mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; -diff --git a/include/grub/offsets.h b/include/grub/offsets.h -index 871e1cd4c3..69211aa798 100644 ---- a/include/grub/offsets.h -+++ b/include/grub/offsets.h -@@ -63,7 +63,7 @@ - #define GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR 0x4400 - - #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4 --#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x200000 -+#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x400000 - - #define GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR 0x80200000 - diff --git a/0193-Add-Fedora-location-of-DejaVu-SANS-font.patch b/0193-Add-Fedora-location-of-DejaVu-SANS-font.patch new file mode 100644 index 0000000..070fc24 --- /dev/null +++ b/0193-Add-Fedora-location-of-DejaVu-SANS-font.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: fluteze +Date: Sat, 27 Nov 2021 10:54:44 -0600 +Subject: [PATCH] Add Fedora location of DejaVu SANS font + +In Fedora 35, and possibly earlier, grub would fail to configure with a +complaint about DejaVu being "not found" even though it was installed. +The DejaVu sans font search path is updated to reflect the +distribution's current install path. + +Signed-off-by: Erik Edwards +[rharwood@redhat.com: slight commit message edits] +Signed-off-by: Robbie Harwood +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index ab0d326f00..40c4338bce 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1784,7 +1784,7 @@ fi + + if test x"$starfield_excuse" = x; then + for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do +- for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype; do ++ for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype /usr/share/fonts/dejavu-sans-fonts; do + if test -f "$dir/DejaVuSans.$ext"; then + DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext" + break 2 diff --git a/0193-grub-mkconfig-restore-umask-for-grub.cfg.patch b/0193-grub-mkconfig-restore-umask-for-grub.cfg.patch deleted file mode 100644 index 76b73f5..0000000 --- a/0193-grub-mkconfig-restore-umask-for-grub.cfg.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang via Grub-devel -Date: Fri, 3 Dec 2021 16:13:28 +0800 -Subject: [PATCH] grub-mkconfig: restore umask for grub.cfg - -Since commit: - - ab2e53c8a grub-mkconfig: Honor a symlink when generating configuration -by grub-mkconfig - -has inadvertently discarded umask for creating grub.cfg in the process -of grub-mkconfig. The resulting wrong permission (0644) would allow -unprivileged users to read grub's configuration file content. This -presents a low confidentiality risk as grub.cfg may contain non-secured -plain-text passwords. - -This patch restores the missing umask and set the file mode of creation -to 0600 preventing unprivileged access. - -Fixes: CVE-2021-3981 - -Signed-off-by: Michael Chang ---- - util/grub-mkconfig.in | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in -index f55339a3f6..520a672cd2 100644 ---- a/util/grub-mkconfig.in -+++ b/util/grub-mkconfig.in -@@ -311,7 +311,9 @@ and /etc/grub.d/* files or please file a bug report with - exit 1 - else - # none of the children aborted with error, install the new grub.cfg -+ oldumask=$(umask); umask 077 - cat ${grub_cfg}.new > ${grub_cfg} -+ umask $oldumask - rm -f ${grub_cfg}.new - fi - fi diff --git a/0194-fs-btrfs-Use-full-btrfs-bootloader-area.patch b/0194-fs-btrfs-Use-full-btrfs-bootloader-area.patch deleted file mode 100644 index 3f7198f..0000000 --- a/0194-fs-btrfs-Use-full-btrfs-bootloader-area.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Mon, 13 Dec 2021 14:25:49 +0800 -Subject: [PATCH] fs/btrfs: Use full btrfs bootloader area - -Up to now GRUB can only embed to the first 64 KiB before primary -superblock of btrfs, effectively limiting the GRUB core size. That -could consequently pose restrictions to feature enablement like -advanced zstd compression. - -This patch attempts to utilize full unused area reserved by btrfs for -the bootloader outlined in the document [1]: - - The first 1MiB on each device is unused with the exception of primary - superblock that is on the offset 64KiB and spans 4KiB. - -Apart from that, adjacent sectors to superblock and first block group -are not used for embedding in case of overflow and logged access to -adjacent sectors could be useful for tracing it up. - -This patch has been tested to provide out of the box support for btrfs -zstd compression with which GRUB has been installed to the partition. - -[1] https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT - -Signed-off-by: Michael Chang -Reviewed-by: Daniel Kiper -(cherry picked from commit b0f06a81c6f31b6fa20be67a96b6683bba8210c9) ---- - grub-core/fs/btrfs.c | 90 ++++++++++++++++++++++++++++++++++++++++++++-------- - include/grub/disk.h | 2 ++ - 2 files changed, 79 insertions(+), 13 deletions(-) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index 4cc86e9b79..07c0ff874b 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -2476,6 +2476,33 @@ grub_btrfs_label (grub_device_t device, char **label) - } - - #ifdef GRUB_UTIL -+ -+struct embed_region { -+ unsigned int start; -+ unsigned int secs; -+}; -+ -+/* -+ * https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT -+ * The first 1 MiB on each device is unused with the exception of primary -+ * superblock that is on the offset 64 KiB and spans 4 KiB. -+ */ -+ -+static const struct { -+ struct embed_region available; -+ struct embed_region used[6]; -+} btrfs_head = { -+ .available = {0, GRUB_DISK_KiB_TO_SECTORS (1024)}, /* The first 1 MiB. */ -+ .used = { -+ {0, 1}, /* boot.S. */ -+ {GRUB_DISK_KiB_TO_SECTORS (64) - 1, 1}, /* Overflow guard. */ -+ {GRUB_DISK_KiB_TO_SECTORS (64), GRUB_DISK_KiB_TO_SECTORS (4)}, /* 4 KiB superblock. */ -+ {GRUB_DISK_KiB_TO_SECTORS (68), 1}, /* Overflow guard. */ -+ {GRUB_DISK_KiB_TO_SECTORS (1024) - 1, 1}, /* Overflow guard. */ -+ {0, 0} /* Array terminator. */ -+ } -+}; -+ - static grub_err_t - grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), - unsigned int *nsectors, -@@ -2483,25 +2510,62 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), - grub_embed_type_t embed_type, - grub_disk_addr_t **sectors) - { -- unsigned i; -+ unsigned int i, j, n = 0; -+ const struct embed_region *u; -+ grub_disk_addr_t *map; - - if (embed_type != GRUB_EMBED_PCBIOS) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "BtrFS currently supports only PC-BIOS embedding"); - -- if (64 * 2 - 1 < *nsectors) -- return grub_error (GRUB_ERR_OUT_OF_RANGE, -- N_("your core.img is unusually large. " -- "It won't fit in the embedding area")); -- -- *nsectors = 64 * 2 - 1; -- if (*nsectors > max_nsectors) -- *nsectors = max_nsectors; -- *sectors = grub_calloc (*nsectors, sizeof (**sectors)); -- if (!*sectors) -+ map = grub_calloc (btrfs_head.available.secs, sizeof (*map)); -+ if (map == NULL) - return grub_errno; -- for (i = 0; i < *nsectors; i++) -- (*sectors)[i] = i + 1; -+ -+ /* -+ * Populating the map array so that it can be used to index if a disk -+ * address is available to embed: -+ * - 0: available, -+ * - 1: unavailable. -+ */ -+ for (u = btrfs_head.used; u->secs; ++u) -+ { -+ unsigned int end = u->start + u->secs; -+ -+ if (end > btrfs_head.available.secs) -+ end = btrfs_head.available.secs; -+ for (i = u->start; i < end; ++i) -+ map[i] = 1; -+ } -+ -+ /* Adding up n until it matches total size of available embedding area. */ -+ for (i = 0; i < btrfs_head.available.secs; ++i) -+ if (map[i] == 0) -+ n++; -+ -+ if (n < *nsectors) -+ { -+ grub_free (map); -+ return grub_error (GRUB_ERR_OUT_OF_RANGE, -+ N_("your core.img is unusually large. " -+ "It won't fit in the embedding area")); -+ } -+ -+ if (n > max_nsectors) -+ n = max_nsectors; -+ -+ /* -+ * Populating the array so that it can used to index disk block address for -+ * an image file's offset to be embedded on disk (the unit is in sectors): -+ * - i: The disk block address relative to btrfs_head.available.start, -+ * - j: The offset in image file. -+ */ -+ for (i = 0, j = 0; i < btrfs_head.available.secs && j < n; ++i) -+ if (map[i] == 0) -+ map[j++] = btrfs_head.available.start + i; -+ -+ *nsectors = n; -+ *sectors = map; - - return GRUB_ERR_NONE; - } -diff --git a/include/grub/disk.h b/include/grub/disk.h -index f95aca929a..06210a7049 100644 ---- a/include/grub/disk.h -+++ b/include/grub/disk.h -@@ -182,6 +182,8 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t; - /* Return value of grub_disk_native_sectors() in case disk size is unknown. */ - #define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL - -+#define GRUB_DISK_KiB_TO_SECTORS(x) ((x) << (10 - GRUB_DISK_SECTOR_BITS)) -+ - /* Convert sector number from one sector size to another. */ - static inline grub_disk_addr_t - grub_convert_sector (grub_disk_addr_t sector, diff --git a/0194-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch b/0194-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch new file mode 100644 index 0000000..200cd51 --- /dev/null +++ b/0194-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 11:30:32 +0100 +Subject: [PATCH] normal/menu: Don't show "Booting `%s'" msg when auto-booting + with TIMEOUT_STYLE_HIDDEN + +When the user has asked the menu code to be hidden/quiet and the current +entry is being autobooted because the timeout has expired don't show +the "Booting `%s'" msg. + +This is necessary to let flicker-free boots really be flicker free, +otherwise the "Booting `%s'" msg will kick the EFI fb into text mode +and show the msg, breaking the flicker-free experience. + +Signed-off-by: Hans de Goede +--- + grub-core/normal/menu.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c +index ec0c92bade..c8516a5a08 100644 +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -606,13 +606,15 @@ print_countdown (struct grub_term_coordinate *pos, int n) + entry to be executed is a result of an automatic default selection because + of the timeout. */ + static int +-run_menu (grub_menu_t menu, int nested, int *auto_boot) ++run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot) + { + grub_uint64_t saved_time; + int default_entry, current_entry; + int timeout; + enum timeout_style timeout_style; + ++ *notify_boot = 1; ++ + default_entry = get_entry_number (menu, "default"); + + /* If DEFAULT_ENTRY is not within the menu entries, fall back to +@@ -687,6 +689,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) + if (timeout == 0) + { + *auto_boot = 1; ++ *notify_boot = timeout_style != TIMEOUT_STYLE_HIDDEN; + return default_entry; + } + +@@ -840,12 +843,16 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) + + /* Callback invoked immediately before a menu entry is executed. */ + static void +-notify_booting (grub_menu_entry_t entry, +- void *userdata __attribute__((unused))) ++notify_booting (grub_menu_entry_t entry, void *userdata) + { +- grub_printf (" "); +- grub_printf_ (N_("Booting `%s'"), entry->title); +- grub_printf ("\n\n"); ++ int *notify_boot = userdata; ++ ++ if (*notify_boot) ++ { ++ grub_printf (" "); ++ grub_printf_ (N_("Booting `%s'"), entry->title); ++ grub_printf ("\n\n"); ++ } + } + + /* Callback invoked when a default menu entry executed because of a timeout +@@ -893,8 +900,9 @@ show_menu (grub_menu_t menu, int nested, int autobooted) + int boot_entry; + grub_menu_entry_t e; + int auto_boot; ++ int notify_boot; + +- boot_entry = run_menu (menu, nested, &auto_boot); ++ boot_entry = run_menu (menu, nested, &auto_boot, ¬ify_boot); + if (boot_entry < 0) + break; + +@@ -906,7 +914,7 @@ show_menu (grub_menu_t menu, int nested, int autobooted) + + if (auto_boot) + grub_menu_execute_with_fallback (menu, e, autobooted, +- &execution_callback, 0); ++ &execution_callback, ¬ify_boot); + else + grub_menu_execute_entry (e, 0); + if (autobooted) diff --git a/0195-Add-Fedora-location-of-DejaVu-SANS-font.patch b/0195-Add-Fedora-location-of-DejaVu-SANS-font.patch deleted file mode 100644 index 070fc24..0000000 --- a/0195-Add-Fedora-location-of-DejaVu-SANS-font.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: fluteze -Date: Sat, 27 Nov 2021 10:54:44 -0600 -Subject: [PATCH] Add Fedora location of DejaVu SANS font - -In Fedora 35, and possibly earlier, grub would fail to configure with a -complaint about DejaVu being "not found" even though it was installed. -The DejaVu sans font search path is updated to reflect the -distribution's current install path. - -Signed-off-by: Erik Edwards -[rharwood@redhat.com: slight commit message edits] -Signed-off-by: Robbie Harwood ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index ab0d326f00..40c4338bce 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1784,7 +1784,7 @@ fi - - if test x"$starfield_excuse" = x; then - for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do -- for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype; do -+ for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype /usr/share/fonts/dejavu-sans-fonts; do - if test -f "$dir/DejaVuSans.$ext"; then - DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext" - break 2 diff --git a/0195-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch b/0195-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch new file mode 100644 index 0000000..0f99c22 --- /dev/null +++ b/0195-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 11:30:33 +0100 +Subject: [PATCH] EFI: suppress the "Welcome to GRUB!" message in EFI builds + +Grub EFI builds are now often used in combination with flicker-free +boot, but this breaks with upstream grub because the "Welcome to GRUB!" +message will kick the EFI fb into text mode and show the msg, +breaking the flicker-free experience. + +EFI systems are so fast, that when the menu or the countdown are enabled +the message will be immediately overwritten, so in these cases not +printing the message does not matter. + +And in case when the timeout_style is set to TIMEOUT_STYLE_HIDDEN, +the user has asked grub to be quiet (for example to allow flickfree +boot) annd thus the message should not be printed. + +Signed-off-by: Hans de Goede +--- + grub-core/kern/main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index 3fc3401472..993b8a8598 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -317,10 +317,13 @@ grub_main (void) + + grub_boot_time ("After machine init."); + ++ /* This breaks flicker-free boot on EFI systems, so disable it there. */ ++#ifndef GRUB_MACHINE_EFI + /* Hello. */ + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + grub_printf ("Welcome to GRUB!\n\n"); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); ++#endif + + /* Init verifiers API. */ + grub_verifiers_init (); diff --git a/0196-EFI-console-Do-not-set-colorstate-until-the-first-te.patch b/0196-EFI-console-Do-not-set-colorstate-until-the-first-te.patch new file mode 100644 index 0000000..ade6aae --- /dev/null +++ b/0196-EFI-console-Do-not-set-colorstate-until-the-first-te.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 12:43:48 +0100 +Subject: [PATCH] EFI: console: Do not set colorstate until the first text + output + +GRUB_MOD_INIT(normal) does an unconditional: + +grub_env_set ("color_normal", "light-gray/black"); + +which triggers a grub_term_setcolorstate() call. The original version +of the "efi/console: Do not set text-mode until we actually need it" patch: +https://lists.gnu.org/archive/html/grub-devel/2018-03/msg00125.html + +Protected against this by caching the requested state in +grub_console_setcolorstate () and then only applying it when the first +text output actually happens. During refactoring to move the +grub_console_setcolorstate () up higher in the grub-core/term/efi/console.c +file the code to cache the color-state + bail early was accidentally +dropped. + +Restore the cache the color-state + bail early behavior from the original. + +Cc: Javier Martinez Canillas +Fixes: 2d7c3abd871f ("efi/console: Do not set text-mode until we actually need it") +Signed-off-by: Hans de Goede +--- + grub-core/term/efi/console.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c +index 2f1ae85ba7..c44b2ac318 100644 +--- a/grub-core/term/efi/console.c ++++ b/grub-core/term/efi/console.c +@@ -82,6 +82,16 @@ grub_console_setcolorstate (struct grub_term_output *term + { + grub_efi_simple_text_output_interface_t *o; + ++ if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE) ++ { ++ /* ++ * Cache colorstate changes before the first text-output, this avoids ++ * "color_normal" environment writes causing a switch to textmode. ++ */ ++ text_colorstate = state; ++ return; ++ } ++ + if (grub_efi_is_finished) + return; + diff --git a/0196-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch b/0196-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch deleted file mode 100644 index 200cd51..0000000 --- a/0196-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Fri, 28 Jan 2022 11:30:32 +0100 -Subject: [PATCH] normal/menu: Don't show "Booting `%s'" msg when auto-booting - with TIMEOUT_STYLE_HIDDEN - -When the user has asked the menu code to be hidden/quiet and the current -entry is being autobooted because the timeout has expired don't show -the "Booting `%s'" msg. - -This is necessary to let flicker-free boots really be flicker free, -otherwise the "Booting `%s'" msg will kick the EFI fb into text mode -and show the msg, breaking the flicker-free experience. - -Signed-off-by: Hans de Goede ---- - grub-core/normal/menu.c | 24 ++++++++++++++++-------- - 1 file changed, 16 insertions(+), 8 deletions(-) - -diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c -index ec0c92bade..c8516a5a08 100644 ---- a/grub-core/normal/menu.c -+++ b/grub-core/normal/menu.c -@@ -606,13 +606,15 @@ print_countdown (struct grub_term_coordinate *pos, int n) - entry to be executed is a result of an automatic default selection because - of the timeout. */ - static int --run_menu (grub_menu_t menu, int nested, int *auto_boot) -+run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot) - { - grub_uint64_t saved_time; - int default_entry, current_entry; - int timeout; - enum timeout_style timeout_style; - -+ *notify_boot = 1; -+ - default_entry = get_entry_number (menu, "default"); - - /* If DEFAULT_ENTRY is not within the menu entries, fall back to -@@ -687,6 +689,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) - if (timeout == 0) - { - *auto_boot = 1; -+ *notify_boot = timeout_style != TIMEOUT_STYLE_HIDDEN; - return default_entry; - } - -@@ -840,12 +843,16 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) - - /* Callback invoked immediately before a menu entry is executed. */ - static void --notify_booting (grub_menu_entry_t entry, -- void *userdata __attribute__((unused))) -+notify_booting (grub_menu_entry_t entry, void *userdata) - { -- grub_printf (" "); -- grub_printf_ (N_("Booting `%s'"), entry->title); -- grub_printf ("\n\n"); -+ int *notify_boot = userdata; -+ -+ if (*notify_boot) -+ { -+ grub_printf (" "); -+ grub_printf_ (N_("Booting `%s'"), entry->title); -+ grub_printf ("\n\n"); -+ } - } - - /* Callback invoked when a default menu entry executed because of a timeout -@@ -893,8 +900,9 @@ show_menu (grub_menu_t menu, int nested, int autobooted) - int boot_entry; - grub_menu_entry_t e; - int auto_boot; -+ int notify_boot; - -- boot_entry = run_menu (menu, nested, &auto_boot); -+ boot_entry = run_menu (menu, nested, &auto_boot, ¬ify_boot); - if (boot_entry < 0) - break; - -@@ -906,7 +914,7 @@ show_menu (grub_menu_t menu, int nested, int autobooted) - - if (auto_boot) - grub_menu_execute_with_fallback (menu, e, autobooted, -- &execution_callback, 0); -+ &execution_callback, ¬ify_boot); - else - grub_menu_execute_entry (e, 0); - if (autobooted) diff --git a/0197-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch b/0197-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch new file mode 100644 index 0000000..5fab5db --- /dev/null +++ b/0197-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 12:43:49 +0100 +Subject: [PATCH] EFI: console: Do not set cursor until the first text output + +To allow flickerfree boot the EFI console code does not call +grub_efi_set_text_mode (1) until some text is actually output. + +Depending on if the output text is because of an error loading +e.g. the .cfg file; or because of showing the menu the cursor needs +to be on or off when the first text is shown. + +So far the cursor was hardcoded to being on, but this is causing +drawing artifacts + slow drawing of the menu as reported here: +https://bugzilla.redhat.com/show_bug.cgi?id=1946969 + +Handle the cursorstate in the same way as the colorstate to fix this, +when no text has been output yet, just cache the cursorstate and +then use the last set value when the first text is output. + +Fixes: 2d7c3abd871f ("efi/console: Do not set text-mode until we actually need it") +Signed-off-by: Hans de Goede +--- + grub-core/term/efi/console.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c +index c44b2ac318..a3622e4fe5 100644 +--- a/grub-core/term/efi/console.c ++++ b/grub-core/term/efi/console.c +@@ -31,7 +31,15 @@ typedef enum { + } + grub_text_mode; + ++typedef enum { ++ GRUB_CURSOR_MODE_UNDEFINED = -1, ++ GRUB_CURSOR_MODE_OFF = 0, ++ GRUB_CURSUR_MODE_ON ++} ++grub_cursor_mode; ++ + static grub_text_mode text_mode = GRUB_TEXT_MODE_UNDEFINED; ++static grub_cursor_mode cursor_mode = GRUB_CURSOR_MODE_UNDEFINED; + static grub_term_color_state text_colorstate = GRUB_TERM_COLOR_UNDEFINED; + + static grub_uint32_t +@@ -119,8 +127,12 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)), + { + grub_efi_simple_text_output_interface_t *o; + +- if (grub_efi_is_finished) +- return; ++ if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE) ++ { ++ /* Cache cursor changes before the first text-output */ ++ cursor_mode = on; ++ return; ++ } + + o = grub_efi_system_table->con_out; + efi_call_2 (o->enable_cursor, o, on); +@@ -143,7 +155,8 @@ grub_prepare_for_text_output (struct grub_term_output *term) + return GRUB_ERR_BAD_DEVICE; + } + +- grub_console_setcursor (term, 1); ++ if (cursor_mode != GRUB_CURSOR_MODE_UNDEFINED) ++ grub_console_setcursor (term, cursor_mode); + if (text_colorstate != GRUB_TERM_COLOR_UNDEFINED) + grub_console_setcolorstate (term, text_colorstate); + text_mode = GRUB_TEXT_MODE_AVAILABLE; diff --git a/0197-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch b/0197-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch deleted file mode 100644 index 0f99c22..0000000 --- a/0197-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Fri, 28 Jan 2022 11:30:33 +0100 -Subject: [PATCH] EFI: suppress the "Welcome to GRUB!" message in EFI builds - -Grub EFI builds are now often used in combination with flicker-free -boot, but this breaks with upstream grub because the "Welcome to GRUB!" -message will kick the EFI fb into text mode and show the msg, -breaking the flicker-free experience. - -EFI systems are so fast, that when the menu or the countdown are enabled -the message will be immediately overwritten, so in these cases not -printing the message does not matter. - -And in case when the timeout_style is set to TIMEOUT_STYLE_HIDDEN, -the user has asked grub to be quiet (for example to allow flickfree -boot) annd thus the message should not be printed. - -Signed-off-by: Hans de Goede ---- - grub-core/kern/main.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index 3fc3401472..993b8a8598 100644 ---- a/grub-core/kern/main.c -+++ b/grub-core/kern/main.c -@@ -317,10 +317,13 @@ grub_main (void) - - grub_boot_time ("After machine init."); - -+ /* This breaks flicker-free boot on EFI systems, so disable it there. */ -+#ifndef GRUB_MACHINE_EFI - /* Hello. */ - grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); - grub_printf ("Welcome to GRUB!\n\n"); - grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); -+#endif - - /* Init verifiers API. */ - grub_verifiers_init (); diff --git a/0198-EFI-console-Do-not-set-colorstate-until-the-first-te.patch b/0198-EFI-console-Do-not-set-colorstate-until-the-first-te.patch deleted file mode 100644 index ade6aae..0000000 --- a/0198-EFI-console-Do-not-set-colorstate-until-the-first-te.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Fri, 28 Jan 2022 12:43:48 +0100 -Subject: [PATCH] EFI: console: Do not set colorstate until the first text - output - -GRUB_MOD_INIT(normal) does an unconditional: - -grub_env_set ("color_normal", "light-gray/black"); - -which triggers a grub_term_setcolorstate() call. The original version -of the "efi/console: Do not set text-mode until we actually need it" patch: -https://lists.gnu.org/archive/html/grub-devel/2018-03/msg00125.html - -Protected against this by caching the requested state in -grub_console_setcolorstate () and then only applying it when the first -text output actually happens. During refactoring to move the -grub_console_setcolorstate () up higher in the grub-core/term/efi/console.c -file the code to cache the color-state + bail early was accidentally -dropped. - -Restore the cache the color-state + bail early behavior from the original. - -Cc: Javier Martinez Canillas -Fixes: 2d7c3abd871f ("efi/console: Do not set text-mode until we actually need it") -Signed-off-by: Hans de Goede ---- - grub-core/term/efi/console.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c -index 2f1ae85ba7..c44b2ac318 100644 ---- a/grub-core/term/efi/console.c -+++ b/grub-core/term/efi/console.c -@@ -82,6 +82,16 @@ grub_console_setcolorstate (struct grub_term_output *term - { - grub_efi_simple_text_output_interface_t *o; - -+ if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE) -+ { -+ /* -+ * Cache colorstate changes before the first text-output, this avoids -+ * "color_normal" environment writes causing a switch to textmode. -+ */ -+ text_colorstate = state; -+ return; -+ } -+ - if (grub_efi_is_finished) - return; - diff --git a/0198-Use-visual-indentation-in-config.h.in.patch b/0198-Use-visual-indentation-in-config.h.in.patch new file mode 100644 index 0000000..978eb07 --- /dev/null +++ b/0198-Use-visual-indentation-in-config.h.in.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 15 Dec 2021 15:46:13 -0500 +Subject: [PATCH] Use visual indentation in config.h.in + +Signed-off-by: Robbie Harwood +(cherry picked from commit de8051f34de0aa55c921a510974e5bb27e39c17b) +[rharwood: GRUB_RPM_CONFIG presence] +--- + config.h.in | 58 +++++++++++++++++++++++++++++----------------------------- + 1 file changed, 29 insertions(+), 29 deletions(-) + +diff --git a/config.h.in b/config.h.in +index c80e3e0aba..f2ed0066ec 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -23,47 +23,47 @@ + #define MINILZO_CFG_SKIP_LZO1X_DECOMPRESS 1 + + #if defined (GRUB_BUILD) +-#undef ENABLE_NLS +-#define BUILD_SIZEOF_LONG @BUILD_SIZEOF_LONG@ +-#define BUILD_SIZEOF_VOID_P @BUILD_SIZEOF_VOID_P@ +-#if defined __APPLE__ +-# if defined __BIG_ENDIAN__ +-# define BUILD_WORDS_BIGENDIAN 1 +-# else +-# define BUILD_WORDS_BIGENDIAN 0 +-# endif +-#else +-#define BUILD_WORDS_BIGENDIAN @BUILD_WORDS_BIGENDIAN@ +-#endif ++# undef ENABLE_NLS ++# define BUILD_SIZEOF_LONG @BUILD_SIZEOF_LONG@ ++# define BUILD_SIZEOF_VOID_P @BUILD_SIZEOF_VOID_P@ ++# if defined __APPLE__ ++# if defined __BIG_ENDIAN__ ++# define BUILD_WORDS_BIGENDIAN 1 ++# else ++# define BUILD_WORDS_BIGENDIAN 0 ++# endif ++# else /* !defined __APPLE__ */ ++# define BUILD_WORDS_BIGENDIAN @BUILD_WORDS_BIGENDIAN@ ++# endif /* !defined __APPLE__ */ + #elif defined (GRUB_UTIL) || !defined (GRUB_MACHINE) +-#include +-#else +-#define HAVE_FONT_SOURCE @HAVE_FONT_SOURCE@ ++# include ++#else /* !defined GRUB_UTIL && defined GRUB_MACHINE */ ++# define HAVE_FONT_SOURCE @HAVE_FONT_SOURCE@ + /* Define if C symbols get an underscore after compilation. */ +-#define HAVE_ASM_USCORE @HAVE_ASM_USCORE@ ++# define HAVE_ASM_USCORE @HAVE_ASM_USCORE@ + /* Define it to one of __bss_start, edata and _edata. */ +-#define BSS_START_SYMBOL @BSS_START_SYMBOL@ ++# define BSS_START_SYMBOL @BSS_START_SYMBOL@ + /* Define it to either end or _end. */ +-#define END_SYMBOL @END_SYMBOL@ ++# define END_SYMBOL @END_SYMBOL@ + /* Name of package. */ +-#define PACKAGE "@PACKAGE@" ++# define PACKAGE "@PACKAGE@" + /* Version number of package. */ +-#define VERSION "@VERSION@" ++# define VERSION "@VERSION@" + /* Define to the full name and version of this package. */ +-#define PACKAGE_STRING "@PACKAGE_STRING@" ++# define PACKAGE_STRING "@PACKAGE_STRING@" + /* Define to the version of this package. */ +-#define PACKAGE_VERSION "@PACKAGE_VERSION@" ++# define PACKAGE_VERSION "@PACKAGE_VERSION@" + /* Define to the full name of this package. */ +-#define PACKAGE_NAME "@PACKAGE_NAME@" ++# define PACKAGE_NAME "@PACKAGE_NAME@" + /* Define to the address where bug reports for this package should be sent. */ +-#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" ++# define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +-#define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" +-#define GRUB_PLATFORM "@GRUB_PLATFORM@" +-#define GRUB_RPM_VERSION "@GRUB_RPM_VERSION@" ++# define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" ++# define GRUB_PLATFORM "@GRUB_PLATFORM@" ++# define GRUB_RPM_VERSION "@GRUB_RPM_VERSION@" + +-#define RE_ENABLE_I18N 1 ++# define RE_ENABLE_I18N 1 + +-#define _GNU_SOURCE 1 ++# define _GNU_SOURCE 1 + + #endif diff --git a/0199-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch b/0199-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch deleted file mode 100644 index 5fab5db..0000000 --- a/0199-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Fri, 28 Jan 2022 12:43:49 +0100 -Subject: [PATCH] EFI: console: Do not set cursor until the first text output - -To allow flickerfree boot the EFI console code does not call -grub_efi_set_text_mode (1) until some text is actually output. - -Depending on if the output text is because of an error loading -e.g. the .cfg file; or because of showing the menu the cursor needs -to be on or off when the first text is shown. - -So far the cursor was hardcoded to being on, but this is causing -drawing artifacts + slow drawing of the menu as reported here: -https://bugzilla.redhat.com/show_bug.cgi?id=1946969 - -Handle the cursorstate in the same way as the colorstate to fix this, -when no text has been output yet, just cache the cursorstate and -then use the last set value when the first text is output. - -Fixes: 2d7c3abd871f ("efi/console: Do not set text-mode until we actually need it") -Signed-off-by: Hans de Goede ---- - grub-core/term/efi/console.c | 19 ++++++++++++++++--- - 1 file changed, 16 insertions(+), 3 deletions(-) - -diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c -index c44b2ac318..a3622e4fe5 100644 ---- a/grub-core/term/efi/console.c -+++ b/grub-core/term/efi/console.c -@@ -31,7 +31,15 @@ typedef enum { - } - grub_text_mode; - -+typedef enum { -+ GRUB_CURSOR_MODE_UNDEFINED = -1, -+ GRUB_CURSOR_MODE_OFF = 0, -+ GRUB_CURSUR_MODE_ON -+} -+grub_cursor_mode; -+ - static grub_text_mode text_mode = GRUB_TEXT_MODE_UNDEFINED; -+static grub_cursor_mode cursor_mode = GRUB_CURSOR_MODE_UNDEFINED; - static grub_term_color_state text_colorstate = GRUB_TERM_COLOR_UNDEFINED; - - static grub_uint32_t -@@ -119,8 +127,12 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)), - { - grub_efi_simple_text_output_interface_t *o; - -- if (grub_efi_is_finished) -- return; -+ if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE) -+ { -+ /* Cache cursor changes before the first text-output */ -+ cursor_mode = on; -+ return; -+ } - - o = grub_efi_system_table->con_out; - efi_call_2 (o->enable_cursor, o, on); -@@ -143,7 +155,8 @@ grub_prepare_for_text_output (struct grub_term_output *term) - return GRUB_ERR_BAD_DEVICE; - } - -- grub_console_setcursor (term, 1); -+ if (cursor_mode != GRUB_CURSOR_MODE_UNDEFINED) -+ grub_console_setcursor (term, cursor_mode); - if (text_colorstate != GRUB_TERM_COLOR_UNDEFINED) - grub_console_setcolorstate (term, text_colorstate); - text_mode = GRUB_TEXT_MODE_AVAILABLE; diff --git a/0199-Where-present-ensure-config-util.h-precedes-config.h.patch b/0199-Where-present-ensure-config-util.h-precedes-config.h.patch new file mode 100644 index 0000000..22c2d9c --- /dev/null +++ b/0199-Where-present-ensure-config-util.h-precedes-config.h.patch @@ -0,0 +1,275 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 22 Feb 2022 16:57:54 -0500 +Subject: [PATCH] Where present, ensure config-util.h precedes config.h + +gnulib defines go in config-util.h, and we need to know whether to +provide duplicates in config.h or not. + +Signed-off-by: Robbie Harwood +(cherry picked from commit 46e82b28e1a75703d0424c7e13d009171310c6cd) +[rharwood: gensymlist isn't part of tarballs] +--- + grub-core/disk/host.c | 2 +- + grub-core/kern/emu/argp_common.c | 2 +- + grub-core/kern/emu/main.c | 2 +- + grub-core/osdep/aros/config.c | 2 +- + grub-core/osdep/basic/emunet.c | 2 +- + grub-core/osdep/basic/init.c | 2 +- + grub-core/osdep/haiku/getroot.c | 2 +- + grub-core/osdep/linux/emunet.c | 2 +- + grub-core/osdep/unix/config.c | 2 +- + grub-core/osdep/unix/cputime.c | 2 +- + grub-core/osdep/unix/dl.c | 2 +- + grub-core/osdep/unix/emuconsole.c | 2 +- + grub-core/osdep/unix/getroot.c | 2 +- + grub-core/osdep/windows/config.c | 2 +- + grub-core/osdep/windows/cputime.c | 2 +- + grub-core/osdep/windows/dl.c | 2 +- + grub-core/osdep/windows/emuconsole.c | 2 +- + grub-core/osdep/windows/init.c | 2 +- + 18 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c +index c151d225df..f34529f86a 100644 +--- a/grub-core/disk/host.c ++++ b/grub-core/disk/host.c +@@ -20,8 +20,8 @@ + /* When using the disk, make a reference to this module. Otherwise + the user will end up with a useless module :-). */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/kern/emu/argp_common.c b/grub-core/kern/emu/argp_common.c +index 1668858703..8cb4608c3d 100644 +--- a/grub-core/kern/emu/argp_common.c ++++ b/grub-core/kern/emu/argp_common.c +@@ -17,8 +17,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #pragma GCC diagnostic ignored "-Wmissing-prototypes" + #pragma GCC diagnostic ignored "-Wmissing-declarations" +diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c +index 55ea5a11cc..12277c34d2 100644 +--- a/grub-core/kern/emu/main.c ++++ b/grub-core/kern/emu/main.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/aros/config.c b/grub-core/osdep/aros/config.c +index c82d0ea8e7..55f5728efc 100644 +--- a/grub-core/osdep/aros/config.c ++++ b/grub-core/osdep/aros/config.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/basic/emunet.c b/grub-core/osdep/basic/emunet.c +index 6362e5cfbb..dbfd316d61 100644 +--- a/grub-core/osdep/basic/emunet.c ++++ b/grub-core/osdep/basic/emunet.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/basic/init.c b/grub-core/osdep/basic/init.c +index c54c710dbc..b104c7e162 100644 +--- a/grub-core/osdep/basic/init.c ++++ b/grub-core/osdep/basic/init.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/haiku/getroot.c b/grub-core/osdep/haiku/getroot.c +index 4e123c0903..927a1ebc94 100644 +--- a/grub-core/osdep/haiku/getroot.c ++++ b/grub-core/osdep/haiku/getroot.c +@@ -1,5 +1,5 @@ +-#include + #include ++#include + #include + #include + #include +diff --git a/grub-core/osdep/linux/emunet.c b/grub-core/osdep/linux/emunet.c +index 19b188f09e..d5a6417355 100644 +--- a/grub-core/osdep/linux/emunet.c ++++ b/grub-core/osdep/linux/emunet.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c +index 46a881530c..0ce0e309ac 100644 +--- a/grub-core/osdep/unix/config.c ++++ b/grub-core/osdep/unix/config.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/unix/cputime.c b/grub-core/osdep/unix/cputime.c +index cff359a3b9..fb6ff55a1a 100644 +--- a/grub-core/osdep/unix/cputime.c ++++ b/grub-core/osdep/unix/cputime.c +@@ -1,5 +1,5 @@ +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/unix/dl.c b/grub-core/osdep/unix/dl.c +index 562b101a28..99b189bc1c 100644 +--- a/grub-core/osdep/unix/dl.c ++++ b/grub-core/osdep/unix/dl.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/unix/emuconsole.c b/grub-core/osdep/unix/emuconsole.c +index 7308798efe..cac159424d 100644 +--- a/grub-core/osdep/unix/emuconsole.c ++++ b/grub-core/osdep/unix/emuconsole.c +@@ -17,8 +17,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c +index 46d7116c6e..4f436284ce 100644 +--- a/grub-core/osdep/unix/getroot.c ++++ b/grub-core/osdep/unix/getroot.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/windows/config.c b/grub-core/osdep/windows/config.c +index 928ab1a49b..2bb8a2fd88 100644 +--- a/grub-core/osdep/windows/config.c ++++ b/grub-core/osdep/windows/config.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/windows/cputime.c b/grub-core/osdep/windows/cputime.c +index 3568aa2d35..5d06d79dd5 100644 +--- a/grub-core/osdep/windows/cputime.c ++++ b/grub-core/osdep/windows/cputime.c +@@ -1,5 +1,5 @@ +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/windows/dl.c b/grub-core/osdep/windows/dl.c +index eec6a24ad7..8eab7057e4 100644 +--- a/grub-core/osdep/windows/dl.c ++++ b/grub-core/osdep/windows/dl.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/windows/emuconsole.c b/grub-core/osdep/windows/emuconsole.c +index 4fb3693cc0..17a44de469 100644 +--- a/grub-core/osdep/windows/emuconsole.c ++++ b/grub-core/osdep/windows/emuconsole.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/windows/init.c b/grub-core/osdep/windows/init.c +index 6297de6326..51a9647dde 100644 +--- a/grub-core/osdep/windows/init.c ++++ b/grub-core/osdep/windows/init.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + #include + #include + #include diff --git a/0200-Drop-gnulib-fix-base64.patch.patch b/0200-Drop-gnulib-fix-base64.patch.patch new file mode 100644 index 0000000..054e476 --- /dev/null +++ b/0200-Drop-gnulib-fix-base64.patch.patch @@ -0,0 +1,140 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 28 Oct 2021 15:07:50 -0400 +Subject: [PATCH] Drop gnulib fix-base64.patch + +Originally added in 9fbdec2f6b4fa8b549daa4d49134d1fe89d95ef9 and +subsequently modified in 552c9fd08122a3036c724ce96dfe68aa2f75705f, +fix-base64.patch handled two problems we have using gnulib, which are +exerciesd by the base64 module but not directly caused by it. + +First, grub2 defines its own bool type, while gnulib expects the +equivalent of stdbool.h to be present. Rather than patching gnulib, +instead use gnulib's stdbool module to provide a bool type if needed. +(Suggested by Simon Josefsson.) + +Second, our config.h doesn't always inherit config-util.h, which is +where gnulib-related options like _GL_ATTRIBUTE_CONST end up. +fix-base64.h worked around this by defining the attribute away, but this +workaround is better placed in config.h itself, not a gnulib patch. + +Signed-off-by: Robbie Harwood +(cherry picked from commit 54fd1c3301dd15f6b6212c12887265e8a6cbc076) +--- + grub-core/lib/posix_wrap/sys/types.h | 7 +++---- + grub-core/lib/xzembed/xz.h | 5 +---- + bootstrap.conf | 3 ++- + conf/Makefile.extra-dist | 1 - + config.h.in | 4 ++++ + grub-core/lib/gnulib-patches/fix-base64.patch | 21 --------------------- + 6 files changed, 10 insertions(+), 31 deletions(-) + delete mode 100644 grub-core/lib/gnulib-patches/fix-base64.patch + +diff --git a/grub-core/lib/posix_wrap/sys/types.h b/grub-core/lib/posix_wrap/sys/types.h +index f63412c8da..2f3e865495 100644 +--- a/grub-core/lib/posix_wrap/sys/types.h ++++ b/grub-core/lib/posix_wrap/sys/types.h +@@ -23,11 +23,10 @@ + + #include + ++/* Provided by gnulib if not present. */ ++#include ++ + typedef grub_ssize_t ssize_t; +-#ifndef GRUB_POSIX_BOOL_DEFINED +-typedef enum { false = 0, true = 1 } bool; +-#define GRUB_POSIX_BOOL_DEFINED 1 +-#endif + + typedef grub_uint8_t uint8_t; + typedef grub_uint16_t uint16_t; +diff --git a/grub-core/lib/xzembed/xz.h b/grub-core/lib/xzembed/xz.h +index f7b32d8003..d1417039aa 100644 +--- a/grub-core/lib/xzembed/xz.h ++++ b/grub-core/lib/xzembed/xz.h +@@ -29,10 +29,7 @@ + #include + #include + #include +- +-#ifndef GRUB_POSIX_BOOL_DEFINED +-typedef enum { false = 0, true = 1 } bool; +-#endif ++#include + + /** + * enum xz_ret - Return codes +diff --git a/bootstrap.conf b/bootstrap.conf +index 52d4af44be..645e3a459c 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -35,6 +35,7 @@ gnulib_modules=" + realloc-gnu + regex + save-cwd ++ stdbool + " + + gnulib_tool_option_extras="\ +@@ -79,7 +80,7 @@ cp -a INSTALL INSTALL.grub + + bootstrap_post_import_hook () { + set -e +- for patchname in fix-base64 fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ ++ for patchname in fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ + fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width no-abort; do + patch -d grub-core/lib/gnulib -p2 \ + < "grub-core/lib/gnulib-patches/$patchname.patch" +diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist +index ad235de7fc..f4791dc6ca 100644 +--- a/conf/Makefile.extra-dist ++++ b/conf/Makefile.extra-dist +@@ -31,7 +31,6 @@ EXTRA_DIST += grub-core/gensymlist.sh + EXTRA_DIST += grub-core/genemuinit.sh + EXTRA_DIST += grub-core/genemuinitheader.sh + +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-base64.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-state-deref.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch +diff --git a/config.h.in b/config.h.in +index f2ed0066ec..9c7b4afaaa 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -66,4 +66,8 @@ + + # define _GNU_SOURCE 1 + ++# ifndef _GL_INLINE_HEADER_BEGIN ++# define _GL_ATTRIBUTE_CONST __attribute__ ((const)) ++# endif /* !_GL_INLINE_HEADER_BEGIN */ ++ + #endif +diff --git a/grub-core/lib/gnulib-patches/fix-base64.patch b/grub-core/lib/gnulib-patches/fix-base64.patch +deleted file mode 100644 +index 985db12797..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-base64.patch ++++ /dev/null +@@ -1,21 +0,0 @@ +-diff --git a/lib/base64.h b/lib/base64.h +-index 9cd0183b8..185a2afa1 100644 +---- a/lib/base64.h +-+++ b/lib/base64.h +-@@ -21,8 +21,14 @@ +- /* Get size_t. */ +- # include +- +--/* Get bool. */ +--# include +-+#ifndef GRUB_POSIX_BOOL_DEFINED +-+typedef enum { false = 0, true = 1 } bool; +-+#define GRUB_POSIX_BOOL_DEFINED 1 +-+#endif +-+ +-+#ifndef _GL_ATTRIBUTE_CONST +-+# define _GL_ATTRIBUTE_CONST /* empty */ +-+#endif +- +- # ifdef __cplusplus +- extern "C" { diff --git a/0200-Use-visual-indentation-in-config.h.in.patch b/0200-Use-visual-indentation-in-config.h.in.patch deleted file mode 100644 index 978eb07..0000000 --- a/0200-Use-visual-indentation-in-config.h.in.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Wed, 15 Dec 2021 15:46:13 -0500 -Subject: [PATCH] Use visual indentation in config.h.in - -Signed-off-by: Robbie Harwood -(cherry picked from commit de8051f34de0aa55c921a510974e5bb27e39c17b) -[rharwood: GRUB_RPM_CONFIG presence] ---- - config.h.in | 58 +++++++++++++++++++++++++++++----------------------------- - 1 file changed, 29 insertions(+), 29 deletions(-) - -diff --git a/config.h.in b/config.h.in -index c80e3e0aba..f2ed0066ec 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -23,47 +23,47 @@ - #define MINILZO_CFG_SKIP_LZO1X_DECOMPRESS 1 - - #if defined (GRUB_BUILD) --#undef ENABLE_NLS --#define BUILD_SIZEOF_LONG @BUILD_SIZEOF_LONG@ --#define BUILD_SIZEOF_VOID_P @BUILD_SIZEOF_VOID_P@ --#if defined __APPLE__ --# if defined __BIG_ENDIAN__ --# define BUILD_WORDS_BIGENDIAN 1 --# else --# define BUILD_WORDS_BIGENDIAN 0 --# endif --#else --#define BUILD_WORDS_BIGENDIAN @BUILD_WORDS_BIGENDIAN@ --#endif -+# undef ENABLE_NLS -+# define BUILD_SIZEOF_LONG @BUILD_SIZEOF_LONG@ -+# define BUILD_SIZEOF_VOID_P @BUILD_SIZEOF_VOID_P@ -+# if defined __APPLE__ -+# if defined __BIG_ENDIAN__ -+# define BUILD_WORDS_BIGENDIAN 1 -+# else -+# define BUILD_WORDS_BIGENDIAN 0 -+# endif -+# else /* !defined __APPLE__ */ -+# define BUILD_WORDS_BIGENDIAN @BUILD_WORDS_BIGENDIAN@ -+# endif /* !defined __APPLE__ */ - #elif defined (GRUB_UTIL) || !defined (GRUB_MACHINE) --#include --#else --#define HAVE_FONT_SOURCE @HAVE_FONT_SOURCE@ -+# include -+#else /* !defined GRUB_UTIL && defined GRUB_MACHINE */ -+# define HAVE_FONT_SOURCE @HAVE_FONT_SOURCE@ - /* Define if C symbols get an underscore after compilation. */ --#define HAVE_ASM_USCORE @HAVE_ASM_USCORE@ -+# define HAVE_ASM_USCORE @HAVE_ASM_USCORE@ - /* Define it to one of __bss_start, edata and _edata. */ --#define BSS_START_SYMBOL @BSS_START_SYMBOL@ -+# define BSS_START_SYMBOL @BSS_START_SYMBOL@ - /* Define it to either end or _end. */ --#define END_SYMBOL @END_SYMBOL@ -+# define END_SYMBOL @END_SYMBOL@ - /* Name of package. */ --#define PACKAGE "@PACKAGE@" -+# define PACKAGE "@PACKAGE@" - /* Version number of package. */ --#define VERSION "@VERSION@" -+# define VERSION "@VERSION@" - /* Define to the full name and version of this package. */ --#define PACKAGE_STRING "@PACKAGE_STRING@" -+# define PACKAGE_STRING "@PACKAGE_STRING@" - /* Define to the version of this package. */ --#define PACKAGE_VERSION "@PACKAGE_VERSION@" -+# define PACKAGE_VERSION "@PACKAGE_VERSION@" - /* Define to the full name of this package. */ --#define PACKAGE_NAME "@PACKAGE_NAME@" -+# define PACKAGE_NAME "@PACKAGE_NAME@" - /* Define to the address where bug reports for this package should be sent. */ --#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" -+# define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" - --#define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" --#define GRUB_PLATFORM "@GRUB_PLATFORM@" --#define GRUB_RPM_VERSION "@GRUB_RPM_VERSION@" -+# define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" -+# define GRUB_PLATFORM "@GRUB_PLATFORM@" -+# define GRUB_RPM_VERSION "@GRUB_RPM_VERSION@" - --#define RE_ENABLE_I18N 1 -+# define RE_ENABLE_I18N 1 - --#define _GNU_SOURCE 1 -+# define _GNU_SOURCE 1 - - #endif diff --git a/0201-Drop-gnulib-no-abort.patch.patch b/0201-Drop-gnulib-no-abort.patch.patch new file mode 100644 index 0000000..a12789f --- /dev/null +++ b/0201-Drop-gnulib-no-abort.patch.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 5 Jan 2022 16:42:11 -0500 +Subject: [PATCH] Drop gnulib no-abort.patch + +Originally added in db7337a3d353a817ffe9eb4a3702120527100be9, this +patched out all relevant invocations of abort() in gnulib. While it was +not documented why at the time, testing suggests that there's no abort() +implementation available for gnulib to use. + +gnulib's position is that the use of abort() is correct here, since it +happens when input violates a "shall" from POSIX. Additionally, the +code in question is probably not reachable. Since abort() is more +friendly to user-space, they prefer to make no change, so we can just +carry a define instead. (Suggested by Paul Eggert.) + +Signed-off-by: Robbie Harwood +(cherry picked from commit 5137c8eb3ec11c3217acea1a93a3f88f3fa4cbca) +--- + bootstrap.conf | 2 +- + conf/Makefile.extra-dist | 1 - + config.h.in | 3 +++ + grub-core/lib/gnulib-patches/no-abort.patch | 26 -------------------------- + 4 files changed, 4 insertions(+), 28 deletions(-) + delete mode 100644 grub-core/lib/gnulib-patches/no-abort.patch + +diff --git a/bootstrap.conf b/bootstrap.conf +index 645e3a459c..71ce943c7d 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -81,7 +81,7 @@ cp -a INSTALL INSTALL.grub + bootstrap_post_import_hook () { + set -e + for patchname in fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ +- fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width no-abort; do ++ fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width; do + patch -d grub-core/lib/gnulib -p2 \ + < "grub-core/lib/gnulib-patches/$patchname.patch" + done +diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist +index f4791dc6ca..5eef708338 100644 +--- a/conf/Makefile.extra-dist ++++ b/conf/Makefile.extra-dist +@@ -38,7 +38,6 @@ EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/no-abort.patch + + EXTRA_DIST += grub-core/lib/libgcrypt + EXTRA_DIST += grub-core/lib/libgcrypt-grub/mpi/generic +diff --git a/config.h.in b/config.h.in +index 9c7b4afaaa..c3134309c6 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -68,6 +68,9 @@ + + # ifndef _GL_INLINE_HEADER_BEGIN + # define _GL_ATTRIBUTE_CONST __attribute__ ((const)) ++ ++/* We don't have an abort() for gnulib to call in regexp. */ ++# define abort __builtin_unreachable + # endif /* !_GL_INLINE_HEADER_BEGIN */ + + #endif +diff --git a/grub-core/lib/gnulib-patches/no-abort.patch b/grub-core/lib/gnulib-patches/no-abort.patch +deleted file mode 100644 +index e469c4762e..0000000000 +--- a/grub-core/lib/gnulib-patches/no-abort.patch ++++ /dev/null +@@ -1,26 +0,0 @@ +-diff --git a/lib/regcomp.c b/lib/regcomp.c +-index cc85f35ac..de45ebb5c 100644 +---- a/lib/regcomp.c +-+++ b/lib/regcomp.c +-@@ -528,9 +528,9 @@ regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, +- to this routine. If we are given anything else, or if other regex +- code generates an invalid error code, then the program has a bug. +- Dump core so we can fix it. */ +-- abort (); +-- +-- msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); +-+ msg = gettext ("unknown regexp error"); +-+ else +-+ msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); +- +- msg_size = strlen (msg) + 1; /* Includes the null. */ +- +-@@ -1136,7 +1136,7 @@ optimize_utf8 (re_dfa_t *dfa) +- } +- break; +- default: +-- abort (); +-+ break; +- } +- +- if (mb_chars || has_period) diff --git a/0201-Where-present-ensure-config-util.h-precedes-config.h.patch b/0201-Where-present-ensure-config-util.h-precedes-config.h.patch deleted file mode 100644 index 22c2d9c..0000000 --- a/0201-Where-present-ensure-config-util.h-precedes-config.h.patch +++ /dev/null @@ -1,275 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Tue, 22 Feb 2022 16:57:54 -0500 -Subject: [PATCH] Where present, ensure config-util.h precedes config.h - -gnulib defines go in config-util.h, and we need to know whether to -provide duplicates in config.h or not. - -Signed-off-by: Robbie Harwood -(cherry picked from commit 46e82b28e1a75703d0424c7e13d009171310c6cd) -[rharwood: gensymlist isn't part of tarballs] ---- - grub-core/disk/host.c | 2 +- - grub-core/kern/emu/argp_common.c | 2 +- - grub-core/kern/emu/main.c | 2 +- - grub-core/osdep/aros/config.c | 2 +- - grub-core/osdep/basic/emunet.c | 2 +- - grub-core/osdep/basic/init.c | 2 +- - grub-core/osdep/haiku/getroot.c | 2 +- - grub-core/osdep/linux/emunet.c | 2 +- - grub-core/osdep/unix/config.c | 2 +- - grub-core/osdep/unix/cputime.c | 2 +- - grub-core/osdep/unix/dl.c | 2 +- - grub-core/osdep/unix/emuconsole.c | 2 +- - grub-core/osdep/unix/getroot.c | 2 +- - grub-core/osdep/windows/config.c | 2 +- - grub-core/osdep/windows/cputime.c | 2 +- - grub-core/osdep/windows/dl.c | 2 +- - grub-core/osdep/windows/emuconsole.c | 2 +- - grub-core/osdep/windows/init.c | 2 +- - 18 files changed, 18 insertions(+), 18 deletions(-) - -diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c -index c151d225df..f34529f86a 100644 ---- a/grub-core/disk/host.c -+++ b/grub-core/disk/host.c -@@ -20,8 +20,8 @@ - /* When using the disk, make a reference to this module. Otherwise - the user will end up with a useless module :-). */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/kern/emu/argp_common.c b/grub-core/kern/emu/argp_common.c -index 1668858703..8cb4608c3d 100644 ---- a/grub-core/kern/emu/argp_common.c -+++ b/grub-core/kern/emu/argp_common.c -@@ -17,8 +17,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #pragma GCC diagnostic ignored "-Wmissing-prototypes" - #pragma GCC diagnostic ignored "-Wmissing-declarations" -diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c -index 55ea5a11cc..12277c34d2 100644 ---- a/grub-core/kern/emu/main.c -+++ b/grub-core/kern/emu/main.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/aros/config.c b/grub-core/osdep/aros/config.c -index c82d0ea8e7..55f5728efc 100644 ---- a/grub-core/osdep/aros/config.c -+++ b/grub-core/osdep/aros/config.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/basic/emunet.c b/grub-core/osdep/basic/emunet.c -index 6362e5cfbb..dbfd316d61 100644 ---- a/grub-core/osdep/basic/emunet.c -+++ b/grub-core/osdep/basic/emunet.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/basic/init.c b/grub-core/osdep/basic/init.c -index c54c710dbc..b104c7e162 100644 ---- a/grub-core/osdep/basic/init.c -+++ b/grub-core/osdep/basic/init.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/haiku/getroot.c b/grub-core/osdep/haiku/getroot.c -index 4e123c0903..927a1ebc94 100644 ---- a/grub-core/osdep/haiku/getroot.c -+++ b/grub-core/osdep/haiku/getroot.c -@@ -1,5 +1,5 @@ --#include - #include -+#include - #include - #include - #include -diff --git a/grub-core/osdep/linux/emunet.c b/grub-core/osdep/linux/emunet.c -index 19b188f09e..d5a6417355 100644 ---- a/grub-core/osdep/linux/emunet.c -+++ b/grub-core/osdep/linux/emunet.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c -index 46a881530c..0ce0e309ac 100644 ---- a/grub-core/osdep/unix/config.c -+++ b/grub-core/osdep/unix/config.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/unix/cputime.c b/grub-core/osdep/unix/cputime.c -index cff359a3b9..fb6ff55a1a 100644 ---- a/grub-core/osdep/unix/cputime.c -+++ b/grub-core/osdep/unix/cputime.c -@@ -1,5 +1,5 @@ --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/unix/dl.c b/grub-core/osdep/unix/dl.c -index 562b101a28..99b189bc1c 100644 ---- a/grub-core/osdep/unix/dl.c -+++ b/grub-core/osdep/unix/dl.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/unix/emuconsole.c b/grub-core/osdep/unix/emuconsole.c -index 7308798efe..cac159424d 100644 ---- a/grub-core/osdep/unix/emuconsole.c -+++ b/grub-core/osdep/unix/emuconsole.c -@@ -17,8 +17,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c -index 46d7116c6e..4f436284ce 100644 ---- a/grub-core/osdep/unix/getroot.c -+++ b/grub-core/osdep/unix/getroot.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/windows/config.c b/grub-core/osdep/windows/config.c -index 928ab1a49b..2bb8a2fd88 100644 ---- a/grub-core/osdep/windows/config.c -+++ b/grub-core/osdep/windows/config.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/windows/cputime.c b/grub-core/osdep/windows/cputime.c -index 3568aa2d35..5d06d79dd5 100644 ---- a/grub-core/osdep/windows/cputime.c -+++ b/grub-core/osdep/windows/cputime.c -@@ -1,5 +1,5 @@ --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/windows/dl.c b/grub-core/osdep/windows/dl.c -index eec6a24ad7..8eab7057e4 100644 ---- a/grub-core/osdep/windows/dl.c -+++ b/grub-core/osdep/windows/dl.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/windows/emuconsole.c b/grub-core/osdep/windows/emuconsole.c -index 4fb3693cc0..17a44de469 100644 ---- a/grub-core/osdep/windows/emuconsole.c -+++ b/grub-core/osdep/windows/emuconsole.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - - #include - #include -diff --git a/grub-core/osdep/windows/init.c b/grub-core/osdep/windows/init.c -index 6297de6326..51a9647dde 100644 ---- a/grub-core/osdep/windows/init.c -+++ b/grub-core/osdep/windows/init.c -@@ -16,8 +16,8 @@ - * along with GRUB. If not, see . - */ - --#include - #include -+#include - #include - #include - #include diff --git a/0202-Drop-gnulib-fix-base64.patch.patch b/0202-Drop-gnulib-fix-base64.patch.patch deleted file mode 100644 index 054e476..0000000 --- a/0202-Drop-gnulib-fix-base64.patch.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Thu, 28 Oct 2021 15:07:50 -0400 -Subject: [PATCH] Drop gnulib fix-base64.patch - -Originally added in 9fbdec2f6b4fa8b549daa4d49134d1fe89d95ef9 and -subsequently modified in 552c9fd08122a3036c724ce96dfe68aa2f75705f, -fix-base64.patch handled two problems we have using gnulib, which are -exerciesd by the base64 module but not directly caused by it. - -First, grub2 defines its own bool type, while gnulib expects the -equivalent of stdbool.h to be present. Rather than patching gnulib, -instead use gnulib's stdbool module to provide a bool type if needed. -(Suggested by Simon Josefsson.) - -Second, our config.h doesn't always inherit config-util.h, which is -where gnulib-related options like _GL_ATTRIBUTE_CONST end up. -fix-base64.h worked around this by defining the attribute away, but this -workaround is better placed in config.h itself, not a gnulib patch. - -Signed-off-by: Robbie Harwood -(cherry picked from commit 54fd1c3301dd15f6b6212c12887265e8a6cbc076) ---- - grub-core/lib/posix_wrap/sys/types.h | 7 +++---- - grub-core/lib/xzembed/xz.h | 5 +---- - bootstrap.conf | 3 ++- - conf/Makefile.extra-dist | 1 - - config.h.in | 4 ++++ - grub-core/lib/gnulib-patches/fix-base64.patch | 21 --------------------- - 6 files changed, 10 insertions(+), 31 deletions(-) - delete mode 100644 grub-core/lib/gnulib-patches/fix-base64.patch - -diff --git a/grub-core/lib/posix_wrap/sys/types.h b/grub-core/lib/posix_wrap/sys/types.h -index f63412c8da..2f3e865495 100644 ---- a/grub-core/lib/posix_wrap/sys/types.h -+++ b/grub-core/lib/posix_wrap/sys/types.h -@@ -23,11 +23,10 @@ - - #include - -+/* Provided by gnulib if not present. */ -+#include -+ - typedef grub_ssize_t ssize_t; --#ifndef GRUB_POSIX_BOOL_DEFINED --typedef enum { false = 0, true = 1 } bool; --#define GRUB_POSIX_BOOL_DEFINED 1 --#endif - - typedef grub_uint8_t uint8_t; - typedef grub_uint16_t uint16_t; -diff --git a/grub-core/lib/xzembed/xz.h b/grub-core/lib/xzembed/xz.h -index f7b32d8003..d1417039aa 100644 ---- a/grub-core/lib/xzembed/xz.h -+++ b/grub-core/lib/xzembed/xz.h -@@ -29,10 +29,7 @@ - #include - #include - #include -- --#ifndef GRUB_POSIX_BOOL_DEFINED --typedef enum { false = 0, true = 1 } bool; --#endif -+#include - - /** - * enum xz_ret - Return codes -diff --git a/bootstrap.conf b/bootstrap.conf -index 52d4af44be..645e3a459c 100644 ---- a/bootstrap.conf -+++ b/bootstrap.conf -@@ -35,6 +35,7 @@ gnulib_modules=" - realloc-gnu - regex - save-cwd -+ stdbool - " - - gnulib_tool_option_extras="\ -@@ -79,7 +80,7 @@ cp -a INSTALL INSTALL.grub - - bootstrap_post_import_hook () { - set -e -- for patchname in fix-base64 fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ -+ for patchname in fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ - fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width no-abort; do - patch -d grub-core/lib/gnulib -p2 \ - < "grub-core/lib/gnulib-patches/$patchname.patch" -diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist -index ad235de7fc..f4791dc6ca 100644 ---- a/conf/Makefile.extra-dist -+++ b/conf/Makefile.extra-dist -@@ -31,7 +31,6 @@ EXTRA_DIST += grub-core/gensymlist.sh - EXTRA_DIST += grub-core/genemuinit.sh - EXTRA_DIST += grub-core/genemuinitheader.sh - --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-base64.patch - EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch - EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-state-deref.patch - EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch -diff --git a/config.h.in b/config.h.in -index f2ed0066ec..9c7b4afaaa 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -66,4 +66,8 @@ - - # define _GNU_SOURCE 1 - -+# ifndef _GL_INLINE_HEADER_BEGIN -+# define _GL_ATTRIBUTE_CONST __attribute__ ((const)) -+# endif /* !_GL_INLINE_HEADER_BEGIN */ -+ - #endif -diff --git a/grub-core/lib/gnulib-patches/fix-base64.patch b/grub-core/lib/gnulib-patches/fix-base64.patch -deleted file mode 100644 -index 985db12797..0000000000 ---- a/grub-core/lib/gnulib-patches/fix-base64.patch -+++ /dev/null -@@ -1,21 +0,0 @@ --diff --git a/lib/base64.h b/lib/base64.h --index 9cd0183b8..185a2afa1 100644 ----- a/lib/base64.h --+++ b/lib/base64.h --@@ -21,8 +21,14 @@ -- /* Get size_t. */ -- # include -- ---/* Get bool. */ ---# include --+#ifndef GRUB_POSIX_BOOL_DEFINED --+typedef enum { false = 0, true = 1 } bool; --+#define GRUB_POSIX_BOOL_DEFINED 1 --+#endif --+ --+#ifndef _GL_ATTRIBUTE_CONST --+# define _GL_ATTRIBUTE_CONST /* empty */ --+#endif -- -- # ifdef __cplusplus -- extern "C" { diff --git a/0202-Update-gnulib-version-and-drop-most-gnulib-patches.patch b/0202-Update-gnulib-version-and-drop-most-gnulib-patches.patch new file mode 100644 index 0000000..c2c50f1 --- /dev/null +++ b/0202-Update-gnulib-version-and-drop-most-gnulib-patches.patch @@ -0,0 +1,832 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 15 Dec 2021 15:07:50 -0500 +Subject: [PATCH] Update gnulib version and drop most gnulib patches + +In addition to the changes carried in our gnulib patches, several +Coverity and code hygiene fixes that were previously downstream are also +included in this 3-year gnulib increment. + +Unfortunately, fix-width.patch is retained. + +Bump minimum autoconf version from 2.63 to 2.64 and automake from 1.11 +to 1.14, as required by gnulib. + +Sync bootstrap script itself with gnulib. + +Update regexp module for new dynarray dependency. + +Fix various new warnings. + +Signed-off-by: Robbie Harwood +(cherry picked from commit deb18ff931c3133c2aa536a92bd92e50d6615303) +[rharwood: backport around requirements in INSTALL] +--- + configure.ac | 2 +- + grub-core/Makefile.core.def | 3 + + grub-core/disk/luks2.c | 4 +- + grub-core/lib/posix_wrap/limits.h | 6 +- + include/grub/compiler.h | 4 +- + include/grub/list.h | 2 +- + INSTALL | 2 +- + bootstrap | 291 ++++++++++++--------- + bootstrap.conf | 22 +- + conf/Makefile.extra-dist | 6 - + config.h.in | 68 +++++ + grub-core/lib/gnulib-patches/fix-null-deref.patch | 13 - + .../lib/gnulib-patches/fix-null-state-deref.patch | 12 - + .../gnulib-patches/fix-regcomp-uninit-token.patch | 15 -- + .../gnulib-patches/fix-regexec-null-deref.patch | 12 - + .../lib/gnulib-patches/fix-uninit-structure.patch | 11 - + .../lib/gnulib-patches/fix-unused-value.patch | 14 - + 17 files changed, 262 insertions(+), 225 deletions(-) + delete mode 100644 grub-core/lib/gnulib-patches/fix-null-deref.patch + delete mode 100644 grub-core/lib/gnulib-patches/fix-null-state-deref.patch + delete mode 100644 grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch + delete mode 100644 grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch + delete mode 100644 grub-core/lib/gnulib-patches/fix-uninit-structure.patch + delete mode 100644 grub-core/lib/gnulib-patches/fix-unused-value.patch + +diff --git a/configure.ac b/configure.ac +index 40c4338bce..79f45ef1e1 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -49,7 +49,7 @@ AC_CANONICAL_TARGET + program_prefix="${save_program_prefix}" + + AM_INIT_AUTOMAKE([1.11]) +-AC_PREREQ(2.63) ++AC_PREREQ(2.64) + AC_CONFIG_SRCDIR([include/grub/dl.h]) + AC_CONFIG_HEADER([config-util.h]) + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 08ac0fb15f..ec1ec5083b 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -762,6 +762,9 @@ module = { + name = regexp; + common = commands/regexp.c; + common = commands/wildcard.c; ++ common = lib/gnulib/malloc/dynarray_finalize.c; ++ common = lib/gnulib/malloc/dynarray_emplace_enlarge.c; ++ common = lib/gnulib/malloc/dynarray_resize.c; + common = lib/gnulib/regex.c; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; +diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c +index 371a53b837..c917a5f91e 100644 +--- a/grub-core/disk/luks2.c ++++ b/grub-core/disk/luks2.c +@@ -389,7 +389,7 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key, + { + grub_uint8_t candidate_digest[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN], salt[GRUB_CRYPTODISK_MAX_KEYLEN]; +- grub_size_t saltlen = sizeof (salt), digestlen = sizeof (digest); ++ idx_t saltlen = sizeof (salt), digestlen = sizeof (digest); + const gcry_md_spec_t *hash; + gcry_err_code_t gcry_ret; + +@@ -428,7 +428,7 @@ luks2_decrypt_key (grub_uint8_t *out_key, + grub_uint8_t area_key[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t *split_key = NULL; +- grub_size_t saltlen = sizeof (salt); ++ idx_t saltlen = sizeof (salt); + char cipher[32], *p; + const gcry_md_spec_t *hash; + gcry_err_code_t gcry_ret; +diff --git a/grub-core/lib/posix_wrap/limits.h b/grub-core/lib/posix_wrap/limits.h +index 591dbf3289..4be7b40806 100644 +--- a/grub-core/lib/posix_wrap/limits.h ++++ b/grub-core/lib/posix_wrap/limits.h +@@ -25,7 +25,11 @@ + #define USHRT_MAX GRUB_USHRT_MAX + #define UINT_MAX GRUB_UINT_MAX + #define ULONG_MAX GRUB_ULONG_MAX +-#define SIZE_MAX GRUB_SIZE_MAX ++ ++/* gnulib also defines this type */ ++#ifndef SIZE_MAX ++# define SIZE_MAX GRUB_SIZE_MAX ++#endif + + #define SCHAR_MIN GRUB_SCHAR_MIN + #define SCHAR_MAX GRUB_SCHAR_MAX +diff --git a/include/grub/compiler.h b/include/grub/compiler.h +index ebafec6895..441a9eca07 100644 +--- a/include/grub/compiler.h ++++ b/include/grub/compiler.h +@@ -30,10 +30,10 @@ + + /* Does this compiler support compile-time error attributes? */ + #if GNUC_PREREQ(4,3) +-# define ATTRIBUTE_ERROR(msg) \ ++# define GRUB_ATTRIBUTE_ERROR(msg) \ + __attribute__ ((__error__ (msg))) + #else +-# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn)) ++# define GRUB_ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn)) + #endif + + #if GNUC_PREREQ(4,4) +diff --git a/include/grub/list.h b/include/grub/list.h +index b13acb9624..21f4b4b44a 100644 +--- a/include/grub/list.h ++++ b/include/grub/list.h +@@ -40,7 +40,7 @@ void EXPORT_FUNC(grub_list_remove) (grub_list_t item); + + static inline void * + grub_bad_type_cast_real (int line, const char *file) +- ATTRIBUTE_ERROR ("bad type cast between incompatible grub types"); ++ GRUB_ATTRIBUTE_ERROR ("bad type cast between incompatible grub types"); + + static inline void * + grub_bad_type_cast_real (int line, const char *file) +diff --git a/INSTALL b/INSTALL +index 79a0af7d93..ee9f536f76 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -42,7 +42,7 @@ If you use a development snapshot or want to hack on GRUB you may + need the following. + + * Python 2.6 or later +-* Autoconf 2.63 or later ++* Autoconf 2.64 or later + * Automake 1.11 or later + + Prerequisites for make-check: +diff --git a/bootstrap b/bootstrap +index 5b08e7e2d4..dc2238f4ad 100755 +--- a/bootstrap ++++ b/bootstrap +@@ -1,10 +1,10 @@ + #! /bin/sh + # Print a version string. +-scriptversion=2019-01-04.17; # UTC ++scriptversion=2022-01-26.05; # UTC + + # Bootstrap this package from checked-out sources. + +-# Copyright (C) 2003-2019 Free Software Foundation, Inc. ++# Copyright (C) 2003-2022 Free Software Foundation, Inc. + + # This program is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -47,7 +47,7 @@ PERL="${PERL-perl}" + + me=$0 + +-default_gnulib_url=git://git.sv.gnu.org/gnulib ++default_gnulib_url=https://git.savannah.gnu.org/git/gnulib.git + + usage() { + cat </dev/null) ++if test -z "$package"; then ++ package=$(sed -n "$extract_package_name" configure.ac) \ ++ || die 'cannot find package name in configure.ac' ++fi + gnulib_name=lib$package + + build_aux=build-aux +@@ -290,6 +313,116 @@ find_tool () + eval "export $find_tool_envvar" + } + ++# Strip blank and comment lines to leave significant entries. ++gitignore_entries() { ++ sed '/^#/d; /^$/d' "$@" ++} ++ ++# If $STR is not already on a line by itself in $FILE, insert it at the start. ++# Entries are inserted at the start of the ignore list to ensure existing ++# entries starting with ! are not overridden. Such entries support ++# whitelisting exceptions after a more generic blacklist pattern. ++insert_if_absent() { ++ file=$1 ++ str=$2 ++ test -f $file || touch $file ++ test -r $file || die "Error: failed to read ignore file: $file" ++ duplicate_entries=$(gitignore_entries $file | sort | uniq -d) ++ if [ "$duplicate_entries" ] ; then ++ die "Error: Duplicate entries in $file: " $duplicate_entries ++ fi ++ linesold=$(gitignore_entries $file | wc -l) ++ linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l) ++ if [ $linesold != $linesnew ] ; then ++ { echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \ ++ || die "insert_if_absent $file $str: failed" ++ fi ++} ++ ++# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with ++# insert_if_absent. ++insert_vc_ignore() { ++ vc_ignore_file="$1" ++ pattern="$2" ++ case $vc_ignore_file in ++ *.gitignore) ++ # A .gitignore entry that does not start with '/' applies ++ # recursively to subdirectories, so prepend '/' to every ++ # .gitignore entry. ++ pattern=$(echo "$pattern" | sed s,^,/,);; ++ esac ++ insert_if_absent "$vc_ignore_file" "$pattern" ++} ++ ++symlink_to_dir() ++{ ++ src=$1/$2 ++ dst=${3-$2} ++ ++ test -f "$src" && { ++ ++ # If the destination directory doesn't exist, create it. ++ # This is required at least for "lib/uniwidth/cjk.h". ++ dst_dir=$(dirname "$dst") ++ if ! test -d "$dst_dir"; then ++ mkdir -p "$dst_dir" ++ ++ # If we've just created a directory like lib/uniwidth, ++ # tell version control system(s) it's ignorable. ++ # FIXME: for now, this does only one level ++ parent=$(dirname "$dst_dir") ++ for dot_ig in x $vc_ignore; do ++ test $dot_ig = x && continue ++ ig=$parent/$dot_ig ++ insert_vc_ignore $ig "${dst_dir##*/}" ++ done ++ fi ++ ++ if $copy; then ++ { ++ test ! -h "$dst" || { ++ echo "$me: rm -f $dst" && ++ rm -f "$dst" ++ } ++ } && ++ test -f "$dst" && ++ cmp -s "$src" "$dst" || { ++ echo "$me: cp -fp $src $dst" && ++ cp -fp "$src" "$dst" ++ } ++ else ++ # Leave any existing symlink alone, if it already points to the source, ++ # so that broken build tools that care about symlink times ++ # aren't confused into doing unnecessary builds. Conversely, if the ++ # existing symlink's timestamp is older than the source, make it afresh, ++ # so that broken tools aren't confused into skipping needed builds. See ++ # . ++ test -h "$dst" && ++ src_ls=$(ls -diL "$src" 2>/dev/null) && set $src_ls && src_i=$1 && ++ dst_ls=$(ls -diL "$dst" 2>/dev/null) && set $dst_ls && dst_i=$1 && ++ test "$src_i" = "$dst_i" && ++ both_ls=$(ls -dt "$src" "$dst") && ++ test "X$both_ls" = "X$dst$nl$src" || { ++ dot_dots= ++ case $src in ++ /*) ;; ++ *) ++ case /$dst/ in ++ *//* | */../* | */./* | /*/*/*/*/*/) ++ die "invalid symlink calculation: $src -> $dst";; ++ /*/*/*/*/) dot_dots=../../../;; ++ /*/*/*/) dot_dots=../../;; ++ /*/*/) dot_dots=../;; ++ esac;; ++ esac ++ ++ echo "$me: ln -fs $dot_dots$src $dst" && ++ ln -fs "$dot_dots$src" "$dst" ++ } ++ fi ++ } ++} ++ + # Override the default configuration, if necessary. + # Make sure that bootstrap.conf is sourced from the current directory + # if we were invoked as "sh bootstrap". +@@ -320,6 +453,12 @@ do + --help) + usage + exit;; ++ --version) ++ set -e ++ echo "bootstrap $scriptversion" ++ echo "$copyright" ++ exit 0 ++ ;; + --gnulib-srcdir=*) + GNULIB_SRCDIR=${option#--gnulib-srcdir=};; + --skip-po) +@@ -335,7 +474,7 @@ do + --no-git) + use_git=false;; + *) +- die "$option: unknown option";; ++ bootstrap_option_hook $option || die "$option: unknown option";; + esac + done + +@@ -346,47 +485,6 @@ if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then + die "Bootstrapping from a non-checked-out distribution is risky." + fi + +-# Strip blank and comment lines to leave significant entries. +-gitignore_entries() { +- sed '/^#/d; /^$/d' "$@" +-} +- +-# If $STR is not already on a line by itself in $FILE, insert it at the start. +-# Entries are inserted at the start of the ignore list to ensure existing +-# entries starting with ! are not overridden. Such entries support +-# whitelisting exceptions after a more generic blacklist pattern. +-insert_if_absent() { +- file=$1 +- str=$2 +- test -f $file || touch $file +- test -r $file || die "Error: failed to read ignore file: $file" +- duplicate_entries=$(gitignore_entries $file | sort | uniq -d) +- if [ "$duplicate_entries" ] ; then +- die "Error: Duplicate entries in $file: " $duplicate_entries +- fi +- linesold=$(gitignore_entries $file | wc -l) +- linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l) +- if [ $linesold != $linesnew ] ; then +- { echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \ +- || die "insert_if_absent $file $str: failed" +- fi +-} +- +-# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with +-# insert_if_absent. +-insert_vc_ignore() { +- vc_ignore_file="$1" +- pattern="$2" +- case $vc_ignore_file in +- *.gitignore) +- # A .gitignore entry that does not start with '/' applies +- # recursively to subdirectories, so prepend '/' to every +- # .gitignore entry. +- pattern=$(echo "$pattern" | sed s,^,/,);; +- esac +- insert_if_absent "$vc_ignore_file" "$pattern" +-} +- + # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac. + found_aux_dir=no + grep '^[ ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \ +@@ -665,9 +763,25 @@ if $use_gnulib; then + shallow= + if test -z "$GNULIB_REVISION"; then + git clone -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2' ++ git clone $shallow ${GNULIB_URL:-$default_gnulib_url} "$gnulib_path" \ ++ || cleanup_gnulib ++ else ++ git fetch -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2' ++ mkdir -p "$gnulib_path" ++ # Only want a shallow checkout of $GNULIB_REVISION, but git does not ++ # support cloning by commit hash. So attempt a shallow fetch by commit ++ # hash to minimize the amount of data downloaded and changes needed to ++ # be processed, which can drastically reduce download and processing ++ # time for checkout. If the fetch by commit fails, a shallow fetch can ++ # not be performed because we do not know what the depth of the commit ++ # is without fetching all commits. So fallback to fetching all commits. ++ git -C "$gnulib_path" init ++ git -C "$gnulib_path" remote add origin ${GNULIB_URL:-$default_gnulib_url} ++ git -C "$gnulib_path" fetch $shallow origin "$GNULIB_REVISION" \ ++ || git -C "$gnulib_path" fetch origin \ ++ || cleanup_gnulib ++ git -C "$gnulib_path" reset --hard FETCH_HEAD + fi +- git clone $shallow ${GNULIB_URL:-$default_gnulib_url} "$gnulib_path" \ +- || cleanup_gnulib + + trap - 1 2 13 15 + fi +@@ -784,75 +898,6 @@ case $SKIP_PO in + fi;; + esac + +-symlink_to_dir() +-{ +- src=$1/$2 +- dst=${3-$2} +- +- test -f "$src" && { +- +- # If the destination directory doesn't exist, create it. +- # This is required at least for "lib/uniwidth/cjk.h". +- dst_dir=$(dirname "$dst") +- if ! test -d "$dst_dir"; then +- mkdir -p "$dst_dir" +- +- # If we've just created a directory like lib/uniwidth, +- # tell version control system(s) it's ignorable. +- # FIXME: for now, this does only one level +- parent=$(dirname "$dst_dir") +- for dot_ig in x $vc_ignore; do +- test $dot_ig = x && continue +- ig=$parent/$dot_ig +- insert_vc_ignore $ig "${dst_dir##*/}" +- done +- fi +- +- if $copy; then +- { +- test ! -h "$dst" || { +- echo "$me: rm -f $dst" && +- rm -f "$dst" +- } +- } && +- test -f "$dst" && +- cmp -s "$src" "$dst" || { +- echo "$me: cp -fp $src $dst" && +- cp -fp "$src" "$dst" +- } +- else +- # Leave any existing symlink alone, if it already points to the source, +- # so that broken build tools that care about symlink times +- # aren't confused into doing unnecessary builds. Conversely, if the +- # existing symlink's timestamp is older than the source, make it afresh, +- # so that broken tools aren't confused into skipping needed builds. See +- # . +- test -h "$dst" && +- src_ls=$(ls -diL "$src" 2>/dev/null) && set $src_ls && src_i=$1 && +- dst_ls=$(ls -diL "$dst" 2>/dev/null) && set $dst_ls && dst_i=$1 && +- test "$src_i" = "$dst_i" && +- both_ls=$(ls -dt "$src" "$dst") && +- test "X$both_ls" = "X$dst$nl$src" || { +- dot_dots= +- case $src in +- /*) ;; +- *) +- case /$dst/ in +- *//* | */../* | */./* | /*/*/*/*/*/) +- die "invalid symlink calculation: $src -> $dst";; +- /*/*/*/*/) dot_dots=../../../;; +- /*/*/*/) dot_dots=../../;; +- /*/*/) dot_dots=../;; +- esac;; +- esac +- +- echo "$me: ln -fs $dot_dots$src $dst" && +- ln -fs "$dot_dots$src" "$dst" +- } +- fi +- } +-} +- + version_controlled_file() { + parent=$1 + file=$2 +@@ -970,7 +1015,7 @@ bootstrap_post_import_hook \ + # Uninitialized submodules are listed with an initial dash. + if $use_git && git submodule | grep '^-' >/dev/null; then + die "some git submodules are not initialized. " \ +- "Run 'git submodule init' and bootstrap again." ++ "Run 'git submodule update --init' and bootstrap again." + fi + + # Remove any dangling symlink matching "*.m4" or "*.[ch]" in some +@@ -1064,7 +1109,7 @@ bootstrap_epilogue + + echo "$0: done. Now you can run './configure'." + +-# Local variables: ++# Local Variables: + # eval: (add-hook 'before-save-hook 'time-stamp) + # time-stamp-start: "scriptversion=" + # time-stamp-format: "%:y-%02m-%02d.%02H" +diff --git a/bootstrap.conf b/bootstrap.conf +index 71ce943c7d..e4e5f3750a 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -1,6 +1,6 @@ + # Bootstrap configuration. + +-# Copyright (C) 2006-2019 Free Software Foundation, Inc. ++# Copyright (C) 2006-2022 Free Software Foundation, Inc. + + # This program is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -16,11 +16,10 @@ + # along with this program. If not, see . + + +-GNULIB_REVISION=d271f868a8df9bbec29049d01e056481b7a1a263 ++GNULIB_REVISION=9f48fb992a3d7e96610c4ce8be969cff2d61a01b + + # gnulib modules used by this package. +-# mbswidth is used by gnulib-fix-width.diff's changes to argp rather than +-# directly. ++# mbswidth is used by fix-width.diff's changes to argp rather than directly. + gnulib_modules=" + argp + base64 +@@ -67,8 +66,8 @@ SKIP_PO=t + + # Build prerequisites + buildreq="\ +-autoconf 2.63 +-automake 1.11 ++autoconf 2.64 ++automake 1.14 + gettext 0.18.3 + git 1.5.5 + tar - +@@ -80,11 +79,12 @@ cp -a INSTALL INSTALL.grub + + bootstrap_post_import_hook () { + set -e +- for patchname in fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ +- fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width; do +- patch -d grub-core/lib/gnulib -p2 \ +- < "grub-core/lib/gnulib-patches/$patchname.patch" +- done ++ ++ # Instead of patching our gnulib and therefore maintaining a fork, submit ++ # changes to gnulib and update the hash above when they've merged. Do not ++ # add new patches here. ++ patch -d grub-core/lib/gnulib -p2 < grub-core/lib/gnulib-patches/fix-width.patch ++ + for patchname in \ + 0001-Support-POTFILES-shell \ + 0002-Handle-gettext_printf-shell-function \ +diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist +index 5eef708338..26ac8765e3 100644 +--- a/conf/Makefile.extra-dist ++++ b/conf/Makefile.extra-dist +@@ -31,12 +31,6 @@ EXTRA_DIST += grub-core/gensymlist.sh + EXTRA_DIST += grub-core/genemuinit.sh + EXTRA_DIST += grub-core/genemuinitheader.sh + +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-state-deref.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch + + EXTRA_DIST += grub-core/lib/libgcrypt +diff --git a/config.h.in b/config.h.in +index c3134309c6..512d1bbe13 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -67,10 +67,78 @@ + # define _GNU_SOURCE 1 + + # ifndef _GL_INLINE_HEADER_BEGIN ++/* gnulib gets configured against the host, not the target, and the rest of ++ * our buildsystem works around that. This is difficult to avoid as gnulib's ++ * detection requires a more capable system than our target. Instead, we ++ * reach in and set values appropriately - intentionally setting more than the ++ * bare minimum. If, when updating gnulib, something breaks, there's probably ++ * a change needed here or in grub-core/Makefile.core.def. */ ++# define SIZE_MAX ((size_t) -1) ++# define _GL_ATTRIBUTE_ALLOC_SIZE(args) \ ++ __attribute__ ((__alloc_size__ args)) ++# define _GL_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__)) ++# define _GL_ATTRIBUTE_ARTIFICIAL __attribute__ ((__artificial__)) ++# define _GL_ATTRIBUTE_COLD __attribute__ ((cold)) + # define _GL_ATTRIBUTE_CONST __attribute__ ((const)) ++# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute ((__malloc__ (f, i))) ++# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1) ++# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__)) ++# define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__error__ (msg))) ++# define _GL_ATTRIBUTE_EXTERNALLY_VISIBLE \ ++ __attribute__ ((externally_visible)) ++# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) ++# define _GL_ATTRIBUTE_LEAF __attribute__ ((__leaf__)) ++# define _GL_ATTRIBUTE_MALLOC __attribute__ ((malloc)) ++# define _GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_UNUSED ++# define _GL_ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__)) ++# define _GL_ATTRIBUTE_NODISCARD __attribute__ ((__warn_unused_result__)) ++# define _GL_ATTRIBUTE_NOINLINE __attribute__ ((__noinline__)) ++# define _GL_ATTRIBUTE_NONNULL(args) __attribute__ ((__nonnull__ args)) ++# define _GL_ATTRIBUTE_NONSTRING __attribute__ ((__nonstring__)) ++# define _GL_ATTRIBUTE_PACKED __attribute__ ((__packed__)) ++# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) ++# define _GL_ATTRIBUTE_RETURNS_NONNULL \ ++ __attribute__ ((__returns_nonnull__)) ++# define _GL_ATTRIBUTE_SENTINEL(pos) __attribute__ ((__sentinel__ pos)) ++# define _GL_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) ++# define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__warning__ (msg))) ++# define _GL_CMP(n1, n2) (((n1) > (n2)) - ((n1) < (n2))) ++# define _GL_GNUC_PREREQ GNUC_PREREQ ++# define _GL_INLINE inline ++# define _GL_UNUSED_LABEL _GL_ATTRIBUTE_UNUSED ++ ++/* We can't use __has_attribute for these because gcc-5.1 is too old for ++ * that. Everything above is present in that version, though. */ ++# if __GNUC__ >= 7 ++# define _GL_ATTRIBUTE_FALLTHROUGH __attribute__ ((fallthrough)) ++# else ++# define _GL_ATTRIBUTE_FALLTHROUGH /* empty */ ++# endif ++ ++# ifndef ASM_FILE ++typedef __INT_FAST32_TYPE__ int_fast32_t; ++typedef __UINT_FAST32_TYPE__ uint_fast32_t; ++# endif ++ ++/* Ensure ialloc nests static/non-static inline properly. */ ++# define IALLOC_INLINE static inline ++ ++/* gnulib uses these for blocking out warnings they can't/won't fix. gnulib ++ * also makes the decision about whether to provide a declaration for ++ * reallocarray() at compile-time, so this is a convenient place to override - ++ * it's used by the ialloc module, which is used by base64. */ ++# define _GL_INLINE_HEADER_BEGIN _Pragma ("GCC diagnostic push") \ ++ void * \ ++ reallocarray (void *ptr, unsigned int nmemb, unsigned int size); ++# define _GL_INLINE_HEADER_END _Pragma ("GCC diagnostic pop") + + /* We don't have an abort() for gnulib to call in regexp. */ + # define abort __builtin_unreachable + # endif /* !_GL_INLINE_HEADER_BEGIN */ + ++/* gnulib doesn't build cleanly with older compilers. */ ++# if __GNUC__ < 11 ++_Pragma ("GCC diagnostic ignored \"-Wtype-limits\"") ++# endif ++ + #endif +diff --git a/grub-core/lib/gnulib-patches/fix-null-deref.patch b/grub-core/lib/gnulib-patches/fix-null-deref.patch +deleted file mode 100644 +index 8fafa153a4..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-null-deref.patch ++++ /dev/null +@@ -1,13 +0,0 @@ +-diff --git a/lib/argp-parse.c b/lib/argp-parse.c +-index 6dec57310..900adad54 100644 +---- a/lib/argp-parse.c +-+++ b/lib/argp-parse.c +-@@ -940,7 +940,7 @@ weak_alias (__argp_parse, argp_parse) +- void * +- __argp_input (const struct argp *argp, const struct argp_state *state) +- { +-- if (state) +-+ if (state && state->pstate) +- { +- struct group *group; +- struct parser *parser = state->pstate; +diff --git a/grub-core/lib/gnulib-patches/fix-null-state-deref.patch b/grub-core/lib/gnulib-patches/fix-null-state-deref.patch +deleted file mode 100644 +index 813ec09c8a..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-null-state-deref.patch ++++ /dev/null +@@ -1,12 +0,0 @@ +---- a/lib/argp-help.c 2020-10-28 14:32:19.189215988 +0000 +-+++ b/lib/argp-help.c 2020-10-28 14:38:21.204673940 +0000 +-@@ -145,7 +145,8 @@ +- if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin) +- { +- __argp_failure (state, 0, 0, +-- dgettext (state->root_argp->argp_domain, +-+ dgettext (state == NULL ? NULL +-+ : state->root_argp->argp_domain, +- "\ +- ARGP_HELP_FMT: %s value is less than or equal to %s"), +- "rmargin", up->name); +diff --git a/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch b/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch +deleted file mode 100644 +index 02e06315df..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch ++++ /dev/null +@@ -1,15 +0,0 @@ +---- a/lib/regcomp.c 2020-11-24 17:06:08.159223858 +0000 +-+++ b/lib/regcomp.c 2020-11-24 17:06:15.630253923 +0000 +-@@ -3808,11 +3808,7 @@ +- create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, +- re_token_type_t type) +- { +-- re_token_t t; +--#if defined GCC_LINT || defined lint +-- memset (&t, 0, sizeof t); +--#endif +-- t.type = type; +-+ re_token_t t = { .type = type }; +- return create_token_tree (dfa, left, right, &t); +- } +- +diff --git a/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch b/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch +deleted file mode 100644 +index db6dac9c9e..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch ++++ /dev/null +@@ -1,12 +0,0 @@ +---- a/lib/regexec.c 2020-10-21 14:25:35.310195912 +0000 +-+++ b/lib/regexec.c 2020-11-05 10:55:09.621542984 +0000 +-@@ -1692,6 +1692,9 @@ +- { +- Idx top = mctx->state_log_top; +- +-+ if (mctx->state_log == NULL) +-+ return REG_NOERROR; +-+ +- if ((next_state_log_idx >= mctx->input.bufs_len +- && mctx->input.bufs_len < mctx->input.len) +- || (next_state_log_idx >= mctx->input.valid_len +diff --git a/grub-core/lib/gnulib-patches/fix-uninit-structure.patch b/grub-core/lib/gnulib-patches/fix-uninit-structure.patch +deleted file mode 100644 +index 7b4d9f67af..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-uninit-structure.patch ++++ /dev/null +@@ -1,11 +0,0 @@ +---- a/lib/regcomp.c 2020-10-22 13:49:06.770168928 +0000 +-+++ b/lib/regcomp.c 2020-10-22 13:50:37.026528298 +0000 +-@@ -3662,7 +3662,7 @@ +- Idx alloc = 0; +- #endif /* not RE_ENABLE_I18N */ +- reg_errcode_t ret; +-- re_token_t br_token; +-+ re_token_t br_token = {0}; +- bin_tree_t *tree; +- +- sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); +diff --git a/grub-core/lib/gnulib-patches/fix-unused-value.patch b/grub-core/lib/gnulib-patches/fix-unused-value.patch +deleted file mode 100644 +index ba51f1bf22..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-unused-value.patch ++++ /dev/null +@@ -1,14 +0,0 @@ +---- a/lib/regexec.c 2020-10-21 14:25:35.310195912 +0000 +-+++ b/lib/regexec.c 2020-10-21 14:32:07.961765604 +0000 +-@@ -828,7 +828,11 @@ +- break; +- if (__glibc_unlikely (err != REG_NOMATCH)) +- goto free_return; +-+#ifdef DEBUG +-+ /* Only used for assertion below when DEBUG is set, otherwise +-+ it will be over-written when we loop around. */ +- match_last = -1; +-+#endif +- } +- else +- break; /* We found a match. */ diff --git a/0203-Drop-gnulib-no-abort.patch.patch b/0203-Drop-gnulib-no-abort.patch.patch deleted file mode 100644 index a12789f..0000000 --- a/0203-Drop-gnulib-no-abort.patch.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Wed, 5 Jan 2022 16:42:11 -0500 -Subject: [PATCH] Drop gnulib no-abort.patch - -Originally added in db7337a3d353a817ffe9eb4a3702120527100be9, this -patched out all relevant invocations of abort() in gnulib. While it was -not documented why at the time, testing suggests that there's no abort() -implementation available for gnulib to use. - -gnulib's position is that the use of abort() is correct here, since it -happens when input violates a "shall" from POSIX. Additionally, the -code in question is probably not reachable. Since abort() is more -friendly to user-space, they prefer to make no change, so we can just -carry a define instead. (Suggested by Paul Eggert.) - -Signed-off-by: Robbie Harwood -(cherry picked from commit 5137c8eb3ec11c3217acea1a93a3f88f3fa4cbca) ---- - bootstrap.conf | 2 +- - conf/Makefile.extra-dist | 1 - - config.h.in | 3 +++ - grub-core/lib/gnulib-patches/no-abort.patch | 26 -------------------------- - 4 files changed, 4 insertions(+), 28 deletions(-) - delete mode 100644 grub-core/lib/gnulib-patches/no-abort.patch - -diff --git a/bootstrap.conf b/bootstrap.conf -index 645e3a459c..71ce943c7d 100644 ---- a/bootstrap.conf -+++ b/bootstrap.conf -@@ -81,7 +81,7 @@ cp -a INSTALL INSTALL.grub - bootstrap_post_import_hook () { - set -e - for patchname in fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ -- fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width no-abort; do -+ fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width; do - patch -d grub-core/lib/gnulib -p2 \ - < "grub-core/lib/gnulib-patches/$patchname.patch" - done -diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist -index f4791dc6ca..5eef708338 100644 ---- a/conf/Makefile.extra-dist -+++ b/conf/Makefile.extra-dist -@@ -38,7 +38,6 @@ EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch - EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch - EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch - EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/no-abort.patch - - EXTRA_DIST += grub-core/lib/libgcrypt - EXTRA_DIST += grub-core/lib/libgcrypt-grub/mpi/generic -diff --git a/config.h.in b/config.h.in -index 9c7b4afaaa..c3134309c6 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -68,6 +68,9 @@ - - # ifndef _GL_INLINE_HEADER_BEGIN - # define _GL_ATTRIBUTE_CONST __attribute__ ((const)) -+ -+/* We don't have an abort() for gnulib to call in regexp. */ -+# define abort __builtin_unreachable - # endif /* !_GL_INLINE_HEADER_BEGIN */ - - #endif -diff --git a/grub-core/lib/gnulib-patches/no-abort.patch b/grub-core/lib/gnulib-patches/no-abort.patch -deleted file mode 100644 -index e469c4762e..0000000000 ---- a/grub-core/lib/gnulib-patches/no-abort.patch -+++ /dev/null -@@ -1,26 +0,0 @@ --diff --git a/lib/regcomp.c b/lib/regcomp.c --index cc85f35ac..de45ebb5c 100644 ----- a/lib/regcomp.c --+++ b/lib/regcomp.c --@@ -528,9 +528,9 @@ regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, -- to this routine. If we are given anything else, or if other regex -- code generates an invalid error code, then the program has a bug. -- Dump core so we can fix it. */ --- abort (); --- --- msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); --+ msg = gettext ("unknown regexp error"); --+ else --+ msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); -- -- msg_size = strlen (msg) + 1; /* Includes the null. */ -- --@@ -1136,7 +1136,7 @@ optimize_utf8 (re_dfa_t *dfa) -- } -- break; -- default: --- abort (); --+ break; -- } -- -- if (mb_chars || has_period) diff --git a/0203-commands-search-Fix-bug-stopping-iteration-when-no-f.patch b/0203-commands-search-Fix-bug-stopping-iteration-when-no-f.patch new file mode 100644 index 0000000..4f7feb9 --- /dev/null +++ b/0203-commands-search-Fix-bug-stopping-iteration-when-no-f.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Tue, 8 Feb 2022 08:39:10 +0100 +Subject: [PATCH] commands/search: Fix bug stopping iteration when --no-floppy + is used +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When using --no-floppy and a floppy was encountered, iterate_device() +was returning 1, causing the iteration to stop instead of continuing. + +Signed-off-by: Renaud Métrich +Reviewed-by: Daniel Kiper +(cherry picked from commit 68ba54c2298604146be83cae144dafd1cfd1fe2d) +Signed-off-by: Robbie Harwood +--- + grub-core/commands/search.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c +index ed090b3af8..51656e361c 100644 +--- a/grub-core/commands/search.c ++++ b/grub-core/commands/search.c +@@ -64,7 +64,7 @@ iterate_device (const char *name, void *data) + /* Skip floppy drives when requested. */ + if (ctx->no_floppy && + name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') +- return 1; ++ return 0; + + #ifdef DO_SEARCH_FS_UUID + #define compare_fn grub_strcasecmp diff --git a/0204-Update-gnulib-version-and-drop-most-gnulib-patches.patch b/0204-Update-gnulib-version-and-drop-most-gnulib-patches.patch deleted file mode 100644 index c2c50f1..0000000 --- a/0204-Update-gnulib-version-and-drop-most-gnulib-patches.patch +++ /dev/null @@ -1,832 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Wed, 15 Dec 2021 15:07:50 -0500 -Subject: [PATCH] Update gnulib version and drop most gnulib patches - -In addition to the changes carried in our gnulib patches, several -Coverity and code hygiene fixes that were previously downstream are also -included in this 3-year gnulib increment. - -Unfortunately, fix-width.patch is retained. - -Bump minimum autoconf version from 2.63 to 2.64 and automake from 1.11 -to 1.14, as required by gnulib. - -Sync bootstrap script itself with gnulib. - -Update regexp module for new dynarray dependency. - -Fix various new warnings. - -Signed-off-by: Robbie Harwood -(cherry picked from commit deb18ff931c3133c2aa536a92bd92e50d6615303) -[rharwood: backport around requirements in INSTALL] ---- - configure.ac | 2 +- - grub-core/Makefile.core.def | 3 + - grub-core/disk/luks2.c | 4 +- - grub-core/lib/posix_wrap/limits.h | 6 +- - include/grub/compiler.h | 4 +- - include/grub/list.h | 2 +- - INSTALL | 2 +- - bootstrap | 291 ++++++++++++--------- - bootstrap.conf | 22 +- - conf/Makefile.extra-dist | 6 - - config.h.in | 68 +++++ - grub-core/lib/gnulib-patches/fix-null-deref.patch | 13 - - .../lib/gnulib-patches/fix-null-state-deref.patch | 12 - - .../gnulib-patches/fix-regcomp-uninit-token.patch | 15 -- - .../gnulib-patches/fix-regexec-null-deref.patch | 12 - - .../lib/gnulib-patches/fix-uninit-structure.patch | 11 - - .../lib/gnulib-patches/fix-unused-value.patch | 14 - - 17 files changed, 262 insertions(+), 225 deletions(-) - delete mode 100644 grub-core/lib/gnulib-patches/fix-null-deref.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-null-state-deref.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-uninit-structure.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-unused-value.patch - -diff --git a/configure.ac b/configure.ac -index 40c4338bce..79f45ef1e1 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -49,7 +49,7 @@ AC_CANONICAL_TARGET - program_prefix="${save_program_prefix}" - - AM_INIT_AUTOMAKE([1.11]) --AC_PREREQ(2.63) -+AC_PREREQ(2.64) - AC_CONFIG_SRCDIR([include/grub/dl.h]) - AC_CONFIG_HEADER([config-util.h]) - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 08ac0fb15f..ec1ec5083b 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -762,6 +762,9 @@ module = { - name = regexp; - common = commands/regexp.c; - common = commands/wildcard.c; -+ common = lib/gnulib/malloc/dynarray_finalize.c; -+ common = lib/gnulib/malloc/dynarray_emplace_enlarge.c; -+ common = lib/gnulib/malloc/dynarray_resize.c; - common = lib/gnulib/regex.c; - cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; - cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; -diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c -index 371a53b837..c917a5f91e 100644 ---- a/grub-core/disk/luks2.c -+++ b/grub-core/disk/luks2.c -@@ -389,7 +389,7 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key, - { - grub_uint8_t candidate_digest[GRUB_CRYPTODISK_MAX_KEYLEN]; - grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN], salt[GRUB_CRYPTODISK_MAX_KEYLEN]; -- grub_size_t saltlen = sizeof (salt), digestlen = sizeof (digest); -+ idx_t saltlen = sizeof (salt), digestlen = sizeof (digest); - const gcry_md_spec_t *hash; - gcry_err_code_t gcry_ret; - -@@ -428,7 +428,7 @@ luks2_decrypt_key (grub_uint8_t *out_key, - grub_uint8_t area_key[GRUB_CRYPTODISK_MAX_KEYLEN]; - grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN]; - grub_uint8_t *split_key = NULL; -- grub_size_t saltlen = sizeof (salt); -+ idx_t saltlen = sizeof (salt); - char cipher[32], *p; - const gcry_md_spec_t *hash; - gcry_err_code_t gcry_ret; -diff --git a/grub-core/lib/posix_wrap/limits.h b/grub-core/lib/posix_wrap/limits.h -index 591dbf3289..4be7b40806 100644 ---- a/grub-core/lib/posix_wrap/limits.h -+++ b/grub-core/lib/posix_wrap/limits.h -@@ -25,7 +25,11 @@ - #define USHRT_MAX GRUB_USHRT_MAX - #define UINT_MAX GRUB_UINT_MAX - #define ULONG_MAX GRUB_ULONG_MAX --#define SIZE_MAX GRUB_SIZE_MAX -+ -+/* gnulib also defines this type */ -+#ifndef SIZE_MAX -+# define SIZE_MAX GRUB_SIZE_MAX -+#endif - - #define SCHAR_MIN GRUB_SCHAR_MIN - #define SCHAR_MAX GRUB_SCHAR_MAX -diff --git a/include/grub/compiler.h b/include/grub/compiler.h -index ebafec6895..441a9eca07 100644 ---- a/include/grub/compiler.h -+++ b/include/grub/compiler.h -@@ -30,10 +30,10 @@ - - /* Does this compiler support compile-time error attributes? */ - #if GNUC_PREREQ(4,3) --# define ATTRIBUTE_ERROR(msg) \ -+# define GRUB_ATTRIBUTE_ERROR(msg) \ - __attribute__ ((__error__ (msg))) - #else --# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn)) -+# define GRUB_ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn)) - #endif - - #if GNUC_PREREQ(4,4) -diff --git a/include/grub/list.h b/include/grub/list.h -index b13acb9624..21f4b4b44a 100644 ---- a/include/grub/list.h -+++ b/include/grub/list.h -@@ -40,7 +40,7 @@ void EXPORT_FUNC(grub_list_remove) (grub_list_t item); - - static inline void * - grub_bad_type_cast_real (int line, const char *file) -- ATTRIBUTE_ERROR ("bad type cast between incompatible grub types"); -+ GRUB_ATTRIBUTE_ERROR ("bad type cast between incompatible grub types"); - - static inline void * - grub_bad_type_cast_real (int line, const char *file) -diff --git a/INSTALL b/INSTALL -index 79a0af7d93..ee9f536f76 100644 ---- a/INSTALL -+++ b/INSTALL -@@ -42,7 +42,7 @@ If you use a development snapshot or want to hack on GRUB you may - need the following. - - * Python 2.6 or later --* Autoconf 2.63 or later -+* Autoconf 2.64 or later - * Automake 1.11 or later - - Prerequisites for make-check: -diff --git a/bootstrap b/bootstrap -index 5b08e7e2d4..dc2238f4ad 100755 ---- a/bootstrap -+++ b/bootstrap -@@ -1,10 +1,10 @@ - #! /bin/sh - # Print a version string. --scriptversion=2019-01-04.17; # UTC -+scriptversion=2022-01-26.05; # UTC - - # Bootstrap this package from checked-out sources. - --# Copyright (C) 2003-2019 Free Software Foundation, Inc. -+# Copyright (C) 2003-2022 Free Software Foundation, Inc. - - # This program is free software: you can redistribute it and/or modify - # it under the terms of the GNU General Public License as published by -@@ -47,7 +47,7 @@ PERL="${PERL-perl}" - - me=$0 - --default_gnulib_url=git://git.sv.gnu.org/gnulib -+default_gnulib_url=https://git.savannah.gnu.org/git/gnulib.git - - usage() { - cat </dev/null) -+if test -z "$package"; then -+ package=$(sed -n "$extract_package_name" configure.ac) \ -+ || die 'cannot find package name in configure.ac' -+fi - gnulib_name=lib$package - - build_aux=build-aux -@@ -290,6 +313,116 @@ find_tool () - eval "export $find_tool_envvar" - } - -+# Strip blank and comment lines to leave significant entries. -+gitignore_entries() { -+ sed '/^#/d; /^$/d' "$@" -+} -+ -+# If $STR is not already on a line by itself in $FILE, insert it at the start. -+# Entries are inserted at the start of the ignore list to ensure existing -+# entries starting with ! are not overridden. Such entries support -+# whitelisting exceptions after a more generic blacklist pattern. -+insert_if_absent() { -+ file=$1 -+ str=$2 -+ test -f $file || touch $file -+ test -r $file || die "Error: failed to read ignore file: $file" -+ duplicate_entries=$(gitignore_entries $file | sort | uniq -d) -+ if [ "$duplicate_entries" ] ; then -+ die "Error: Duplicate entries in $file: " $duplicate_entries -+ fi -+ linesold=$(gitignore_entries $file | wc -l) -+ linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l) -+ if [ $linesold != $linesnew ] ; then -+ { echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \ -+ || die "insert_if_absent $file $str: failed" -+ fi -+} -+ -+# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with -+# insert_if_absent. -+insert_vc_ignore() { -+ vc_ignore_file="$1" -+ pattern="$2" -+ case $vc_ignore_file in -+ *.gitignore) -+ # A .gitignore entry that does not start with '/' applies -+ # recursively to subdirectories, so prepend '/' to every -+ # .gitignore entry. -+ pattern=$(echo "$pattern" | sed s,^,/,);; -+ esac -+ insert_if_absent "$vc_ignore_file" "$pattern" -+} -+ -+symlink_to_dir() -+{ -+ src=$1/$2 -+ dst=${3-$2} -+ -+ test -f "$src" && { -+ -+ # If the destination directory doesn't exist, create it. -+ # This is required at least for "lib/uniwidth/cjk.h". -+ dst_dir=$(dirname "$dst") -+ if ! test -d "$dst_dir"; then -+ mkdir -p "$dst_dir" -+ -+ # If we've just created a directory like lib/uniwidth, -+ # tell version control system(s) it's ignorable. -+ # FIXME: for now, this does only one level -+ parent=$(dirname "$dst_dir") -+ for dot_ig in x $vc_ignore; do -+ test $dot_ig = x && continue -+ ig=$parent/$dot_ig -+ insert_vc_ignore $ig "${dst_dir##*/}" -+ done -+ fi -+ -+ if $copy; then -+ { -+ test ! -h "$dst" || { -+ echo "$me: rm -f $dst" && -+ rm -f "$dst" -+ } -+ } && -+ test -f "$dst" && -+ cmp -s "$src" "$dst" || { -+ echo "$me: cp -fp $src $dst" && -+ cp -fp "$src" "$dst" -+ } -+ else -+ # Leave any existing symlink alone, if it already points to the source, -+ # so that broken build tools that care about symlink times -+ # aren't confused into doing unnecessary builds. Conversely, if the -+ # existing symlink's timestamp is older than the source, make it afresh, -+ # so that broken tools aren't confused into skipping needed builds. See -+ # . -+ test -h "$dst" && -+ src_ls=$(ls -diL "$src" 2>/dev/null) && set $src_ls && src_i=$1 && -+ dst_ls=$(ls -diL "$dst" 2>/dev/null) && set $dst_ls && dst_i=$1 && -+ test "$src_i" = "$dst_i" && -+ both_ls=$(ls -dt "$src" "$dst") && -+ test "X$both_ls" = "X$dst$nl$src" || { -+ dot_dots= -+ case $src in -+ /*) ;; -+ *) -+ case /$dst/ in -+ *//* | */../* | */./* | /*/*/*/*/*/) -+ die "invalid symlink calculation: $src -> $dst";; -+ /*/*/*/*/) dot_dots=../../../;; -+ /*/*/*/) dot_dots=../../;; -+ /*/*/) dot_dots=../;; -+ esac;; -+ esac -+ -+ echo "$me: ln -fs $dot_dots$src $dst" && -+ ln -fs "$dot_dots$src" "$dst" -+ } -+ fi -+ } -+} -+ - # Override the default configuration, if necessary. - # Make sure that bootstrap.conf is sourced from the current directory - # if we were invoked as "sh bootstrap". -@@ -320,6 +453,12 @@ do - --help) - usage - exit;; -+ --version) -+ set -e -+ echo "bootstrap $scriptversion" -+ echo "$copyright" -+ exit 0 -+ ;; - --gnulib-srcdir=*) - GNULIB_SRCDIR=${option#--gnulib-srcdir=};; - --skip-po) -@@ -335,7 +474,7 @@ do - --no-git) - use_git=false;; - *) -- die "$option: unknown option";; -+ bootstrap_option_hook $option || die "$option: unknown option";; - esac - done - -@@ -346,47 +485,6 @@ if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then - die "Bootstrapping from a non-checked-out distribution is risky." - fi - --# Strip blank and comment lines to leave significant entries. --gitignore_entries() { -- sed '/^#/d; /^$/d' "$@" --} -- --# If $STR is not already on a line by itself in $FILE, insert it at the start. --# Entries are inserted at the start of the ignore list to ensure existing --# entries starting with ! are not overridden. Such entries support --# whitelisting exceptions after a more generic blacklist pattern. --insert_if_absent() { -- file=$1 -- str=$2 -- test -f $file || touch $file -- test -r $file || die "Error: failed to read ignore file: $file" -- duplicate_entries=$(gitignore_entries $file | sort | uniq -d) -- if [ "$duplicate_entries" ] ; then -- die "Error: Duplicate entries in $file: " $duplicate_entries -- fi -- linesold=$(gitignore_entries $file | wc -l) -- linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l) -- if [ $linesold != $linesnew ] ; then -- { echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \ -- || die "insert_if_absent $file $str: failed" -- fi --} -- --# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with --# insert_if_absent. --insert_vc_ignore() { -- vc_ignore_file="$1" -- pattern="$2" -- case $vc_ignore_file in -- *.gitignore) -- # A .gitignore entry that does not start with '/' applies -- # recursively to subdirectories, so prepend '/' to every -- # .gitignore entry. -- pattern=$(echo "$pattern" | sed s,^,/,);; -- esac -- insert_if_absent "$vc_ignore_file" "$pattern" --} -- - # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac. - found_aux_dir=no - grep '^[ ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \ -@@ -665,9 +763,25 @@ if $use_gnulib; then - shallow= - if test -z "$GNULIB_REVISION"; then - git clone -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2' -+ git clone $shallow ${GNULIB_URL:-$default_gnulib_url} "$gnulib_path" \ -+ || cleanup_gnulib -+ else -+ git fetch -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2' -+ mkdir -p "$gnulib_path" -+ # Only want a shallow checkout of $GNULIB_REVISION, but git does not -+ # support cloning by commit hash. So attempt a shallow fetch by commit -+ # hash to minimize the amount of data downloaded and changes needed to -+ # be processed, which can drastically reduce download and processing -+ # time for checkout. If the fetch by commit fails, a shallow fetch can -+ # not be performed because we do not know what the depth of the commit -+ # is without fetching all commits. So fallback to fetching all commits. -+ git -C "$gnulib_path" init -+ git -C "$gnulib_path" remote add origin ${GNULIB_URL:-$default_gnulib_url} -+ git -C "$gnulib_path" fetch $shallow origin "$GNULIB_REVISION" \ -+ || git -C "$gnulib_path" fetch origin \ -+ || cleanup_gnulib -+ git -C "$gnulib_path" reset --hard FETCH_HEAD - fi -- git clone $shallow ${GNULIB_URL:-$default_gnulib_url} "$gnulib_path" \ -- || cleanup_gnulib - - trap - 1 2 13 15 - fi -@@ -784,75 +898,6 @@ case $SKIP_PO in - fi;; - esac - --symlink_to_dir() --{ -- src=$1/$2 -- dst=${3-$2} -- -- test -f "$src" && { -- -- # If the destination directory doesn't exist, create it. -- # This is required at least for "lib/uniwidth/cjk.h". -- dst_dir=$(dirname "$dst") -- if ! test -d "$dst_dir"; then -- mkdir -p "$dst_dir" -- -- # If we've just created a directory like lib/uniwidth, -- # tell version control system(s) it's ignorable. -- # FIXME: for now, this does only one level -- parent=$(dirname "$dst_dir") -- for dot_ig in x $vc_ignore; do -- test $dot_ig = x && continue -- ig=$parent/$dot_ig -- insert_vc_ignore $ig "${dst_dir##*/}" -- done -- fi -- -- if $copy; then -- { -- test ! -h "$dst" || { -- echo "$me: rm -f $dst" && -- rm -f "$dst" -- } -- } && -- test -f "$dst" && -- cmp -s "$src" "$dst" || { -- echo "$me: cp -fp $src $dst" && -- cp -fp "$src" "$dst" -- } -- else -- # Leave any existing symlink alone, if it already points to the source, -- # so that broken build tools that care about symlink times -- # aren't confused into doing unnecessary builds. Conversely, if the -- # existing symlink's timestamp is older than the source, make it afresh, -- # so that broken tools aren't confused into skipping needed builds. See -- # . -- test -h "$dst" && -- src_ls=$(ls -diL "$src" 2>/dev/null) && set $src_ls && src_i=$1 && -- dst_ls=$(ls -diL "$dst" 2>/dev/null) && set $dst_ls && dst_i=$1 && -- test "$src_i" = "$dst_i" && -- both_ls=$(ls -dt "$src" "$dst") && -- test "X$both_ls" = "X$dst$nl$src" || { -- dot_dots= -- case $src in -- /*) ;; -- *) -- case /$dst/ in -- *//* | */../* | */./* | /*/*/*/*/*/) -- die "invalid symlink calculation: $src -> $dst";; -- /*/*/*/*/) dot_dots=../../../;; -- /*/*/*/) dot_dots=../../;; -- /*/*/) dot_dots=../;; -- esac;; -- esac -- -- echo "$me: ln -fs $dot_dots$src $dst" && -- ln -fs "$dot_dots$src" "$dst" -- } -- fi -- } --} -- - version_controlled_file() { - parent=$1 - file=$2 -@@ -970,7 +1015,7 @@ bootstrap_post_import_hook \ - # Uninitialized submodules are listed with an initial dash. - if $use_git && git submodule | grep '^-' >/dev/null; then - die "some git submodules are not initialized. " \ -- "Run 'git submodule init' and bootstrap again." -+ "Run 'git submodule update --init' and bootstrap again." - fi - - # Remove any dangling symlink matching "*.m4" or "*.[ch]" in some -@@ -1064,7 +1109,7 @@ bootstrap_epilogue - - echo "$0: done. Now you can run './configure'." - --# Local variables: -+# Local Variables: - # eval: (add-hook 'before-save-hook 'time-stamp) - # time-stamp-start: "scriptversion=" - # time-stamp-format: "%:y-%02m-%02d.%02H" -diff --git a/bootstrap.conf b/bootstrap.conf -index 71ce943c7d..e4e5f3750a 100644 ---- a/bootstrap.conf -+++ b/bootstrap.conf -@@ -1,6 +1,6 @@ - # Bootstrap configuration. - --# Copyright (C) 2006-2019 Free Software Foundation, Inc. -+# Copyright (C) 2006-2022 Free Software Foundation, Inc. - - # This program is free software: you can redistribute it and/or modify - # it under the terms of the GNU General Public License as published by -@@ -16,11 +16,10 @@ - # along with this program. If not, see . - - --GNULIB_REVISION=d271f868a8df9bbec29049d01e056481b7a1a263 -+GNULIB_REVISION=9f48fb992a3d7e96610c4ce8be969cff2d61a01b - - # gnulib modules used by this package. --# mbswidth is used by gnulib-fix-width.diff's changes to argp rather than --# directly. -+# mbswidth is used by fix-width.diff's changes to argp rather than directly. - gnulib_modules=" - argp - base64 -@@ -67,8 +66,8 @@ SKIP_PO=t - - # Build prerequisites - buildreq="\ --autoconf 2.63 --automake 1.11 -+autoconf 2.64 -+automake 1.14 - gettext 0.18.3 - git 1.5.5 - tar - -@@ -80,11 +79,12 @@ cp -a INSTALL INSTALL.grub - - bootstrap_post_import_hook () { - set -e -- for patchname in fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ -- fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width; do -- patch -d grub-core/lib/gnulib -p2 \ -- < "grub-core/lib/gnulib-patches/$patchname.patch" -- done -+ -+ # Instead of patching our gnulib and therefore maintaining a fork, submit -+ # changes to gnulib and update the hash above when they've merged. Do not -+ # add new patches here. -+ patch -d grub-core/lib/gnulib -p2 < grub-core/lib/gnulib-patches/fix-width.patch -+ - for patchname in \ - 0001-Support-POTFILES-shell \ - 0002-Handle-gettext_printf-shell-function \ -diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist -index 5eef708338..26ac8765e3 100644 ---- a/conf/Makefile.extra-dist -+++ b/conf/Makefile.extra-dist -@@ -31,12 +31,6 @@ EXTRA_DIST += grub-core/gensymlist.sh - EXTRA_DIST += grub-core/genemuinit.sh - EXTRA_DIST += grub-core/genemuinitheader.sh - --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-state-deref.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch - EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch - - EXTRA_DIST += grub-core/lib/libgcrypt -diff --git a/config.h.in b/config.h.in -index c3134309c6..512d1bbe13 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -67,10 +67,78 @@ - # define _GNU_SOURCE 1 - - # ifndef _GL_INLINE_HEADER_BEGIN -+/* gnulib gets configured against the host, not the target, and the rest of -+ * our buildsystem works around that. This is difficult to avoid as gnulib's -+ * detection requires a more capable system than our target. Instead, we -+ * reach in and set values appropriately - intentionally setting more than the -+ * bare minimum. If, when updating gnulib, something breaks, there's probably -+ * a change needed here or in grub-core/Makefile.core.def. */ -+# define SIZE_MAX ((size_t) -1) -+# define _GL_ATTRIBUTE_ALLOC_SIZE(args) \ -+ __attribute__ ((__alloc_size__ args)) -+# define _GL_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__)) -+# define _GL_ATTRIBUTE_ARTIFICIAL __attribute__ ((__artificial__)) -+# define _GL_ATTRIBUTE_COLD __attribute__ ((cold)) - # define _GL_ATTRIBUTE_CONST __attribute__ ((const)) -+# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute ((__malloc__ (f, i))) -+# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1) -+# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__)) -+# define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__error__ (msg))) -+# define _GL_ATTRIBUTE_EXTERNALLY_VISIBLE \ -+ __attribute__ ((externally_visible)) -+# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) -+# define _GL_ATTRIBUTE_LEAF __attribute__ ((__leaf__)) -+# define _GL_ATTRIBUTE_MALLOC __attribute__ ((malloc)) -+# define _GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_UNUSED -+# define _GL_ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__)) -+# define _GL_ATTRIBUTE_NODISCARD __attribute__ ((__warn_unused_result__)) -+# define _GL_ATTRIBUTE_NOINLINE __attribute__ ((__noinline__)) -+# define _GL_ATTRIBUTE_NONNULL(args) __attribute__ ((__nonnull__ args)) -+# define _GL_ATTRIBUTE_NONSTRING __attribute__ ((__nonstring__)) -+# define _GL_ATTRIBUTE_PACKED __attribute__ ((__packed__)) -+# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) -+# define _GL_ATTRIBUTE_RETURNS_NONNULL \ -+ __attribute__ ((__returns_nonnull__)) -+# define _GL_ATTRIBUTE_SENTINEL(pos) __attribute__ ((__sentinel__ pos)) -+# define _GL_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -+# define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__warning__ (msg))) -+# define _GL_CMP(n1, n2) (((n1) > (n2)) - ((n1) < (n2))) -+# define _GL_GNUC_PREREQ GNUC_PREREQ -+# define _GL_INLINE inline -+# define _GL_UNUSED_LABEL _GL_ATTRIBUTE_UNUSED -+ -+/* We can't use __has_attribute for these because gcc-5.1 is too old for -+ * that. Everything above is present in that version, though. */ -+# if __GNUC__ >= 7 -+# define _GL_ATTRIBUTE_FALLTHROUGH __attribute__ ((fallthrough)) -+# else -+# define _GL_ATTRIBUTE_FALLTHROUGH /* empty */ -+# endif -+ -+# ifndef ASM_FILE -+typedef __INT_FAST32_TYPE__ int_fast32_t; -+typedef __UINT_FAST32_TYPE__ uint_fast32_t; -+# endif -+ -+/* Ensure ialloc nests static/non-static inline properly. */ -+# define IALLOC_INLINE static inline -+ -+/* gnulib uses these for blocking out warnings they can't/won't fix. gnulib -+ * also makes the decision about whether to provide a declaration for -+ * reallocarray() at compile-time, so this is a convenient place to override - -+ * it's used by the ialloc module, which is used by base64. */ -+# define _GL_INLINE_HEADER_BEGIN _Pragma ("GCC diagnostic push") \ -+ void * \ -+ reallocarray (void *ptr, unsigned int nmemb, unsigned int size); -+# define _GL_INLINE_HEADER_END _Pragma ("GCC diagnostic pop") - - /* We don't have an abort() for gnulib to call in regexp. */ - # define abort __builtin_unreachable - # endif /* !_GL_INLINE_HEADER_BEGIN */ - -+/* gnulib doesn't build cleanly with older compilers. */ -+# if __GNUC__ < 11 -+_Pragma ("GCC diagnostic ignored \"-Wtype-limits\"") -+# endif -+ - #endif -diff --git a/grub-core/lib/gnulib-patches/fix-null-deref.patch b/grub-core/lib/gnulib-patches/fix-null-deref.patch -deleted file mode 100644 -index 8fafa153a4..0000000000 ---- a/grub-core/lib/gnulib-patches/fix-null-deref.patch -+++ /dev/null -@@ -1,13 +0,0 @@ --diff --git a/lib/argp-parse.c b/lib/argp-parse.c --index 6dec57310..900adad54 100644 ----- a/lib/argp-parse.c --+++ b/lib/argp-parse.c --@@ -940,7 +940,7 @@ weak_alias (__argp_parse, argp_parse) -- void * -- __argp_input (const struct argp *argp, const struct argp_state *state) -- { --- if (state) --+ if (state && state->pstate) -- { -- struct group *group; -- struct parser *parser = state->pstate; -diff --git a/grub-core/lib/gnulib-patches/fix-null-state-deref.patch b/grub-core/lib/gnulib-patches/fix-null-state-deref.patch -deleted file mode 100644 -index 813ec09c8a..0000000000 ---- a/grub-core/lib/gnulib-patches/fix-null-state-deref.patch -+++ /dev/null -@@ -1,12 +0,0 @@ ----- a/lib/argp-help.c 2020-10-28 14:32:19.189215988 +0000 --+++ b/lib/argp-help.c 2020-10-28 14:38:21.204673940 +0000 --@@ -145,7 +145,8 @@ -- if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin) -- { -- __argp_failure (state, 0, 0, --- dgettext (state->root_argp->argp_domain, --+ dgettext (state == NULL ? NULL --+ : state->root_argp->argp_domain, -- "\ -- ARGP_HELP_FMT: %s value is less than or equal to %s"), -- "rmargin", up->name); -diff --git a/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch b/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch -deleted file mode 100644 -index 02e06315df..0000000000 ---- a/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch -+++ /dev/null -@@ -1,15 +0,0 @@ ----- a/lib/regcomp.c 2020-11-24 17:06:08.159223858 +0000 --+++ b/lib/regcomp.c 2020-11-24 17:06:15.630253923 +0000 --@@ -3808,11 +3808,7 @@ -- create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, -- re_token_type_t type) -- { --- re_token_t t; ---#if defined GCC_LINT || defined lint --- memset (&t, 0, sizeof t); ---#endif --- t.type = type; --+ re_token_t t = { .type = type }; -- return create_token_tree (dfa, left, right, &t); -- } -- -diff --git a/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch b/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch -deleted file mode 100644 -index db6dac9c9e..0000000000 ---- a/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch -+++ /dev/null -@@ -1,12 +0,0 @@ ----- a/lib/regexec.c 2020-10-21 14:25:35.310195912 +0000 --+++ b/lib/regexec.c 2020-11-05 10:55:09.621542984 +0000 --@@ -1692,6 +1692,9 @@ -- { -- Idx top = mctx->state_log_top; -- --+ if (mctx->state_log == NULL) --+ return REG_NOERROR; --+ -- if ((next_state_log_idx >= mctx->input.bufs_len -- && mctx->input.bufs_len < mctx->input.len) -- || (next_state_log_idx >= mctx->input.valid_len -diff --git a/grub-core/lib/gnulib-patches/fix-uninit-structure.patch b/grub-core/lib/gnulib-patches/fix-uninit-structure.patch -deleted file mode 100644 -index 7b4d9f67af..0000000000 ---- a/grub-core/lib/gnulib-patches/fix-uninit-structure.patch -+++ /dev/null -@@ -1,11 +0,0 @@ ----- a/lib/regcomp.c 2020-10-22 13:49:06.770168928 +0000 --+++ b/lib/regcomp.c 2020-10-22 13:50:37.026528298 +0000 --@@ -3662,7 +3662,7 @@ -- Idx alloc = 0; -- #endif /* not RE_ENABLE_I18N */ -- reg_errcode_t ret; --- re_token_t br_token; --+ re_token_t br_token = {0}; -- bin_tree_t *tree; -- -- sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -diff --git a/grub-core/lib/gnulib-patches/fix-unused-value.patch b/grub-core/lib/gnulib-patches/fix-unused-value.patch -deleted file mode 100644 -index ba51f1bf22..0000000000 ---- a/grub-core/lib/gnulib-patches/fix-unused-value.patch -+++ /dev/null -@@ -1,14 +0,0 @@ ----- a/lib/regexec.c 2020-10-21 14:25:35.310195912 +0000 --+++ b/lib/regexec.c 2020-10-21 14:32:07.961765604 +0000 --@@ -828,7 +828,11 @@ -- break; -- if (__glibc_unlikely (err != REG_NOMATCH)) -- goto free_return; --+#ifdef DEBUG --+ /* Only used for assertion below when DEBUG is set, otherwise --+ it will be over-written when we loop around. */ -- match_last = -1; --+#endif -- } -- else -- break; /* We found a match. */ diff --git a/0204-search-new-efidisk-only-option-on-EFI-systems.patch b/0204-search-new-efidisk-only-option-on-EFI-systems.patch new file mode 100644 index 0000000..3f6194a --- /dev/null +++ b/0204-search-new-efidisk-only-option-on-EFI-systems.patch @@ -0,0 +1,168 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Tue, 8 Feb 2022 08:39:11 +0100 +Subject: [PATCH] search: new --efidisk-only option on EFI systems +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When using 'search' on EFI systems, we sometimes want to exclude devices +that are not EFI disks (e.g. md, lvm). +This is typically used when wanting to chainload when having a software +raid (md) for EFI partition: +with no option, 'search --file /EFI/redhat/shimx64.efi' sets root envvar +to 'md/boot_efi' which cannot be used for chainloading since there is no +effective EFI device behind. + +This commit also refactors handling of --no-floppy option. + +Signed-off-by: Renaud Métrich +[rharwood: apply rmetrich's flags initialization fix] +Signed-off-by: Robbie Harwood +--- + grub-core/commands/search.c | 27 +++++++++++++++++++++++---- + grub-core/commands/search_wrap.c | 18 ++++++++++++------ + include/grub/search.h | 15 ++++++++++++--- + 3 files changed, 47 insertions(+), 13 deletions(-) + +diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c +index 51656e361c..57d26ced8a 100644 +--- a/grub-core/commands/search.c ++++ b/grub-core/commands/search.c +@@ -47,7 +47,7 @@ struct search_ctx + { + const char *key; + const char *var; +- int no_floppy; ++ enum search_flags flags; + char **hints; + unsigned nhints; + int count; +@@ -62,10 +62,29 @@ iterate_device (const char *name, void *data) + int found = 0; + + /* Skip floppy drives when requested. */ +- if (ctx->no_floppy && ++ if (ctx->flags & SEARCH_FLAGS_NO_FLOPPY && + name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') + return 0; + ++ /* Limit to EFI disks when requested. */ ++ if (ctx->flags & SEARCH_FLAGS_EFIDISK_ONLY) ++ { ++ grub_device_t dev; ++ dev = grub_device_open (name); ++ if (! dev) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ return 0; ++ } ++ if (! dev->disk || dev->disk->dev->id != GRUB_DISK_DEVICE_EFIDISK_ID) ++ { ++ grub_device_close (dev); ++ grub_errno = GRUB_ERR_NONE; ++ return 0; ++ } ++ grub_device_close (dev); ++ } ++ + #ifdef DO_SEARCH_FS_UUID + #define compare_fn grub_strcasecmp + #else +@@ -261,13 +280,13 @@ try (struct search_ctx *ctx) + } + + void +-FUNC_NAME (const char *key, const char *var, int no_floppy, ++FUNC_NAME (const char *key, const char *var, enum search_flags flags, + char **hints, unsigned nhints) + { + struct search_ctx ctx = { + .key = key, + .var = var, +- .no_floppy = no_floppy, ++ .flags = flags, + .hints = hints, + .nhints = nhints, + .count = 0, +diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c +index 47fc8eb996..0b62acf853 100644 +--- a/grub-core/commands/search_wrap.c ++++ b/grub-core/commands/search_wrap.c +@@ -40,6 +40,7 @@ static const struct grub_arg_option options[] = + N_("Set a variable to the first device found."), N_("VARNAME"), + ARG_TYPE_STRING}, + {"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0}, ++ {"efidisk-only", 0, 0, N_("Only probe EFI disks."), 0, 0}, + {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, +@@ -73,6 +74,7 @@ enum options + SEARCH_FS_UUID, + SEARCH_SET, + SEARCH_NO_FLOPPY, ++ SEARCH_EFIDISK_ONLY, + SEARCH_HINT, + SEARCH_HINT_IEEE1275, + SEARCH_HINT_BIOS, +@@ -89,6 +91,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) + const char *id = 0; + int i = 0, j = 0, nhints = 0; + char **hints = NULL; ++ enum search_flags flags = 0; + + if (state[SEARCH_HINT].set) + for (i = 0; state[SEARCH_HINT].args[i]; i++) +@@ -180,15 +183,18 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) + goto out; + } + ++ if (state[SEARCH_NO_FLOPPY].set) ++ flags |= SEARCH_FLAGS_NO_FLOPPY; ++ ++ if (state[SEARCH_EFIDISK_ONLY].set) ++ flags |= SEARCH_FLAGS_EFIDISK_ONLY; ++ + if (state[SEARCH_LABEL].set) +- grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, +- hints, nhints); ++ grub_search_label (id, var, flags, hints, nhints); + else if (state[SEARCH_FS_UUID].set) +- grub_search_fs_uuid (id, var, state[SEARCH_NO_FLOPPY].set, +- hints, nhints); ++ grub_search_fs_uuid (id, var, flags, hints, nhints); + else if (state[SEARCH_FILE].set) +- grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, +- hints, nhints); ++ grub_search_fs_file (id, var, flags, hints, nhints); + else + grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); + +diff --git a/include/grub/search.h b/include/grub/search.h +index d80347df34..4190aeb2cb 100644 +--- a/include/grub/search.h ++++ b/include/grub/search.h +@@ -19,11 +19,20 @@ + #ifndef GRUB_SEARCH_HEADER + #define GRUB_SEARCH_HEADER 1 + +-void grub_search_fs_file (const char *key, const char *var, int no_floppy, ++enum search_flags ++ { ++ SEARCH_FLAGS_NO_FLOPPY = 1, ++ SEARCH_FLAGS_EFIDISK_ONLY = 2 ++ }; ++ ++void grub_search_fs_file (const char *key, const char *var, ++ enum search_flags flags, + char **hints, unsigned nhints); +-void grub_search_fs_uuid (const char *key, const char *var, int no_floppy, ++void grub_search_fs_uuid (const char *key, const char *var, ++ enum search_flags flags, + char **hints, unsigned nhints); +-void grub_search_label (const char *key, const char *var, int no_floppy, ++void grub_search_label (const char *key, const char *var, ++ enum search_flags flags, + char **hints, unsigned nhints); + + #endif diff --git a/0205-commands-search-Fix-bug-stopping-iteration-when-no-f.patch b/0205-commands-search-Fix-bug-stopping-iteration-when-no-f.patch deleted file mode 100644 index 4f7feb9..0000000 --- a/0205-commands-search-Fix-bug-stopping-iteration-when-no-f.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Tue, 8 Feb 2022 08:39:10 +0100 -Subject: [PATCH] commands/search: Fix bug stopping iteration when --no-floppy - is used -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When using --no-floppy and a floppy was encountered, iterate_device() -was returning 1, causing the iteration to stop instead of continuing. - -Signed-off-by: Renaud Métrich -Reviewed-by: Daniel Kiper -(cherry picked from commit 68ba54c2298604146be83cae144dafd1cfd1fe2d) -Signed-off-by: Robbie Harwood ---- - grub-core/commands/search.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c -index ed090b3af8..51656e361c 100644 ---- a/grub-core/commands/search.c -+++ b/grub-core/commands/search.c -@@ -64,7 +64,7 @@ iterate_device (const char *name, void *data) - /* Skip floppy drives when requested. */ - if (ctx->no_floppy && - name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') -- return 1; -+ return 0; - - #ifdef DO_SEARCH_FS_UUID - #define compare_fn grub_strcasecmp diff --git a/0205-efi-new-connectefi-command.patch b/0205-efi-new-connectefi-command.patch new file mode 100644 index 0000000..f80de22 --- /dev/null +++ b/0205-efi-new-connectefi-command.patch @@ -0,0 +1,395 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Tue, 15 Feb 2022 14:05:22 +0100 +Subject: [PATCH] efi: new 'connectefi' command +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When efi.quickboot is enabled on VMWare (which is the default for +hardware release 16 and later), it may happen that not all EFI devices +are connected. Due to this, browsing the devices in make_devices() just +fails to find devices, in particular disks or partitions for a given +disk. +This typically happens when network booting, then trying to chainload to +local disk (this is used in deployment tools such as Red Hat Satellite), +which is done through using the following grub.cfg snippet: +-------- 8< ---------------- 8< ---------------- 8< -------- +unset prefix +search --file --set=prefix /EFI/redhat/grubx64.efi +if [ -n "$prefix" ]; then + chainloader ($prefix)/EFI/redhat/grubx64/efi +... +-------- 8< ---------------- 8< ---------------- 8< -------- + +With efi.quickboot, none of the devices are connected, causing "search" +to fail. Sometimes devices are connected but not the partition of the +disk matching $prefix, causing partition to not be found by +"chainloader". + +This patch introduces a new "connectefi pciroot|scsi" command which +recursively connects all EFI devices starting from a given controller +type: +- if 'pciroot' is specified, recursion is performed for all PCI root + handles +- if 'scsi' is specified, recursion is performed for all SCSI I/O + handles (recommended usage to avoid connecting unwanted handles which + may impact Grub performances) + +Typical grub.cfg snippet would then be: +-------- 8< ---------------- 8< ---------------- 8< -------- +connectefi scsi +unset prefix +search --file --set=prefix /EFI/redhat/grubx64.efi +if [ -n "$prefix" ]; then + chainloader ($prefix)/EFI/redhat/grubx64/efi +... +-------- 8< ---------------- 8< ---------------- 8< -------- + +The code is easily extensible to handle other arguments in the future if +needed. + +Signed-off-by: Renaud Métrich +Signed-off-by: Robbie Harwood +--- + grub-core/Makefile.core.def | 6 ++ + grub-core/commands/efi/connectefi.c | 205 ++++++++++++++++++++++++++++++++++++ + grub-core/commands/efi/lsefi.c | 1 + + grub-core/disk/efi/efidisk.c | 13 +++ + grub-core/kern/efi/efi.c | 13 +++ + include/grub/efi/disk.h | 2 + + include/grub/efi/efi.h | 5 + + NEWS | 2 +- + 8 files changed, 246 insertions(+), 1 deletion(-) + create mode 100644 grub-core/commands/efi/connectefi.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index ec1ec5083b..741a033978 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -836,6 +836,12 @@ module = { + enable = efi; + }; + ++module = { ++ name = connectefi; ++ common = commands/efi/connectefi.c; ++ enable = efi; ++}; ++ + module = { + name = blocklist; + common = commands/blocklist.c; +diff --git a/grub-core/commands/efi/connectefi.c b/grub-core/commands/efi/connectefi.c +new file mode 100644 +index 0000000000..8ab75bd51b +--- /dev/null ++++ b/grub-core/commands/efi/connectefi.c +@@ -0,0 +1,205 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++typedef struct handle_list ++{ ++ grub_efi_handle_t handle; ++ struct handle_list *next; ++} handle_list_t; ++ ++static handle_list_t *already_handled = NULL; ++ ++static grub_err_t ++add_handle (grub_efi_handle_t handle) ++{ ++ handle_list_t *e; ++ e = grub_malloc (sizeof (*e)); ++ if (! e) ++ return grub_errno; ++ e->handle = handle; ++ e->next = already_handled; ++ already_handled = e; ++ return GRUB_ERR_NONE; ++} ++ ++static int ++is_in_list (grub_efi_handle_t handle) ++{ ++ handle_list_t *e; ++ for (e = already_handled; e != NULL; e = e->next) ++ if (e->handle == handle) ++ return 1; ++ return 0; ++} ++ ++static void ++free_handle_list (void) ++{ ++ handle_list_t *e; ++ while ((e = already_handled) != NULL) ++ { ++ already_handled = already_handled->next; ++ grub_free (e); ++ } ++} ++ ++typedef enum searched_item_flag ++{ ++ SEARCHED_ITEM_FLAG_LOOP = 1, ++ SEARCHED_ITEM_FLAG_RECURSIVE = 2 ++} searched_item_flags; ++ ++typedef struct searched_item ++{ ++ grub_efi_guid_t guid; ++ const char *name; ++ searched_item_flags flags; ++} searched_items; ++ ++static grub_err_t ++grub_cmd_connectefi (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char **args) ++{ ++ unsigned s; ++ searched_items pciroot_items[] = ++ { ++ { GRUB_EFI_PCI_ROOT_IO_GUID, "PCI root", SEARCHED_ITEM_FLAG_RECURSIVE } ++ }; ++ searched_items scsi_items[] = ++ { ++ { GRUB_EFI_PCI_ROOT_IO_GUID, "PCI root", 0 }, ++ { GRUB_EFI_PCI_IO_GUID, "PCI", SEARCHED_ITEM_FLAG_LOOP }, ++ { GRUB_EFI_SCSI_IO_PROTOCOL_GUID, "SCSI I/O", SEARCHED_ITEM_FLAG_RECURSIVE } ++ }; ++ searched_items *items = NULL; ++ unsigned nitems = 0; ++ grub_err_t grub_err = GRUB_ERR_NONE; ++ unsigned total_connected = 0; ++ ++ if (argc != 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); ++ ++ if (grub_strcmp(args[0], N_("pciroot")) == 0) ++ { ++ items = pciroot_items; ++ nitems = ARRAY_SIZE (pciroot_items); ++ } ++ else if (grub_strcmp(args[0], N_("scsi")) == 0) ++ { ++ items = scsi_items; ++ nitems = ARRAY_SIZE (scsi_items); ++ } ++ else ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("unexpected argument `%s'"), args[0]); ++ ++ for (s = 0; s < nitems; s++) ++ { ++ grub_efi_handle_t *handles; ++ grub_efi_uintn_t num_handles; ++ unsigned i, connected = 0, loop = 0; ++ ++loop: ++ loop++; ++ grub_dprintf ("efi", "step '%s' loop %d:\n", items[s].name, loop); ++ ++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, ++ &items[s].guid, 0, &num_handles); ++ ++ if (!handles) ++ continue; ++ ++ for (i = 0; i < num_handles; i++) ++ { ++ grub_efi_handle_t handle = handles[i]; ++ grub_efi_status_t status; ++ unsigned j; ++ ++ /* Skip already handled handles */ ++ if (is_in_list (handle)) ++ { ++ grub_dprintf ("efi", " handle %p: already processed\n", ++ handle); ++ continue; ++ } ++ ++ status = grub_efi_connect_controller(handle, NULL, NULL, ++ items[s].flags & SEARCHED_ITEM_FLAG_RECURSIVE ? 1 : 0); ++ if (status == GRUB_EFI_SUCCESS) ++ { ++ connected++; ++ total_connected++; ++ grub_dprintf ("efi", " handle %p: connected\n", handle); ++ } ++ else ++ grub_dprintf ("efi", " handle %p: failed to connect (%d)\n", ++ handle, (grub_efi_int8_t) status); ++ ++ if ((grub_err = add_handle (handle)) != GRUB_ERR_NONE) ++ break; /* fatal */ ++ } ++ ++ grub_free (handles); ++ if (grub_err != GRUB_ERR_NONE) ++ break; /* fatal */ ++ ++ if (items[s].flags & SEARCHED_ITEM_FLAG_LOOP && connected) ++ { ++ connected = 0; ++ goto loop; ++ } ++ ++ free_handle_list (); ++ } ++ ++ free_handle_list (); ++ ++ if (total_connected) ++ grub_efidisk_reenumerate_disks (); ++ ++ return grub_err; ++} ++ ++static grub_command_t cmd; ++ ++GRUB_MOD_INIT(connectefi) ++{ ++ cmd = grub_register_command ("connectefi", grub_cmd_connectefi, ++ N_("pciroot|scsi"), ++ N_("Connect EFI handles." ++ " If 'pciroot' is specified, connect PCI" ++ " root EFI handles recursively." ++ " If 'scsi' is specified, connect SCSI" ++ " I/O EFI handles recursively.")); ++} ++ ++GRUB_MOD_FINI(connectefi) ++{ ++ grub_unregister_command (cmd); ++} +diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c +index d1ce99af43..f2d2430e66 100644 +--- a/grub-core/commands/efi/lsefi.c ++++ b/grub-core/commands/efi/lsefi.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c +index fe8ba6e6c9..062143dfff 100644 +--- a/grub-core/disk/efi/efidisk.c ++++ b/grub-core/disk/efi/efidisk.c +@@ -396,6 +396,19 @@ enumerate_disks (void) + free_devices (devices); + } + ++void ++grub_efidisk_reenumerate_disks (void) ++{ ++ free_devices (fd_devices); ++ free_devices (hd_devices); ++ free_devices (cd_devices); ++ fd_devices = 0; ++ hd_devices = 0; ++ cd_devices = 0; ++ ++ enumerate_disks (); ++} ++ + static int + grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 14bc10eb56..7fcca69c17 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -95,6 +95,19 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type, + return buffer; + } + ++grub_efi_status_t ++grub_efi_connect_controller (grub_efi_handle_t controller_handle, ++ grub_efi_handle_t *driver_image_handle, ++ grub_efi_device_path_protocol_t *remaining_device_path, ++ grub_efi_boolean_t recursive) ++{ ++ grub_efi_boot_services_t *b; ++ ++ b = grub_efi_system_table->boot_services; ++ return efi_call_4 (b->connect_controller, controller_handle, ++ driver_image_handle, remaining_device_path, recursive); ++} ++ + void * + grub_efi_open_protocol (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, +diff --git a/include/grub/efi/disk.h b/include/grub/efi/disk.h +index 254475c842..6845c2f1fd 100644 +--- a/include/grub/efi/disk.h ++++ b/include/grub/efi/disk.h +@@ -27,6 +27,8 @@ grub_efi_handle_t + EXPORT_FUNC(grub_efidisk_get_device_handle) (grub_disk_t disk); + char *EXPORT_FUNC(grub_efidisk_get_device_name) (grub_efi_handle_t *handle); + ++void EXPORT_FUNC(grub_efidisk_reenumerate_disks) (void); ++ + void grub_efidisk_init (void); + void grub_efidisk_fini (void); + +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 8dfc89a33b..ec52083c49 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -41,6 +41,11 @@ EXPORT_FUNC(grub_efi_locate_handle) (grub_efi_locate_search_type_t search_type, + grub_efi_guid_t *protocol, + void *search_key, + grub_efi_uintn_t *num_handles); ++grub_efi_status_t ++EXPORT_FUNC(grub_efi_connect_controller) (grub_efi_handle_t controller_handle, ++ grub_efi_handle_t *driver_image_handle, ++ grub_efi_device_path_protocol_t *remaining_device_path, ++ grub_efi_boolean_t recursive); + void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, + grub_efi_uint32_t attributes); +diff --git a/NEWS b/NEWS +index 73b8492bc4..d7c1d23aed 100644 +--- a/NEWS ++++ b/NEWS +@@ -98,7 +98,7 @@ New in 2.02: + * Prefer pmtimer for TSC calibration. + + * New/improved platform support: +- * New `efifwsetup' and `lsefi' commands on EFI platforms. ++ * New `efifwsetup', `lsefi' and `connectefi` commands on EFI platforms. + * New `cmosdump' and `cmosset' commands on platforms with CMOS support. + * New command `pcidump' for PCI platforms. + * Improve opcode parsing in ACPI halt implementation. diff --git a/0206-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch b/0206-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch new file mode 100644 index 0000000..4fe8adf --- /dev/null +++ b/0206-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Thu, 3 Mar 2022 13:10:56 +0100 +Subject: [PATCH] grub-core/loader/i386/efi/linux.c: do not validate kernels + twice + +On codebases that have shim-lock-verifier built into the grub core +(like 2.06 upstream), shim-lock-verifier is in enforcing mode when +booted with secureboot. It means that grub_cmd_linux() command +attempts to perform shim validate upon opening linux kernel image, +including kernel measurement. And the verifier correctly returns file +open error when shim validate protocol is not present or shim fails to +validate the kernel. + +This makes the call to grub_linuxefi_secure_validate() redundant, but +also harmful. As validating the kernel image twice, extends the PCRs +with the same measurement twice. Which breaks existing sealing +policies when upgrading from grub2.04+rhboot+sb+linuxefi to +grub2.06+rhboot+sb+linuxefi builds. It is also incorrect to measure +the kernel twice. + +This patch must not be ported to older editions of grub code bases +that do not have verifiers framework, or it is not builtin, or +shim-lock-verifier is an optional module. + +This patch is tested to ensure that unsigned kernels are not possible +to boot in secureboot mode when shim rejects kernel, or shim protocol +is missing, and that the measurements become stable once again. The +above also ensures that CVE-2020-15705 is not reintroduced. + +Signed-off-by: Dimitri John Ledkov +--- + grub-core/loader/i386/efi/linux.c | 13 ------------- + 1 file changed, 13 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 3cf0f9b330..941df6400b 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -30,7 +30,6 @@ + #include + #include + #include +-#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -278,7 +277,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_ssize_t start, filelen; + void *kernel = NULL; + int setup_header_end_offset; +- int rc; + + grub_dl_ref (my_mod); + +@@ -308,17 +306,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) +- { +- rc = grub_linuxefi_secure_validate (kernel, filelen); +- if (rc <= 0) +- { +- grub_error (GRUB_ERR_INVALID_COMMAND, +- N_("%s has invalid signature"), argv[0]); +- goto fail; +- } +- } +- + lh = (struct linux_i386_kernel_header *)kernel; + grub_dprintf ("linux", "original lh is at %p\n", kernel); + diff --git a/0206-search-new-efidisk-only-option-on-EFI-systems.patch b/0206-search-new-efidisk-only-option-on-EFI-systems.patch deleted file mode 100644 index 3f6194a..0000000 --- a/0206-search-new-efidisk-only-option-on-EFI-systems.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Tue, 8 Feb 2022 08:39:11 +0100 -Subject: [PATCH] search: new --efidisk-only option on EFI systems -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When using 'search' on EFI systems, we sometimes want to exclude devices -that are not EFI disks (e.g. md, lvm). -This is typically used when wanting to chainload when having a software -raid (md) for EFI partition: -with no option, 'search --file /EFI/redhat/shimx64.efi' sets root envvar -to 'md/boot_efi' which cannot be used for chainloading since there is no -effective EFI device behind. - -This commit also refactors handling of --no-floppy option. - -Signed-off-by: Renaud Métrich -[rharwood: apply rmetrich's flags initialization fix] -Signed-off-by: Robbie Harwood ---- - grub-core/commands/search.c | 27 +++++++++++++++++++++++---- - grub-core/commands/search_wrap.c | 18 ++++++++++++------ - include/grub/search.h | 15 ++++++++++++--- - 3 files changed, 47 insertions(+), 13 deletions(-) - -diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c -index 51656e361c..57d26ced8a 100644 ---- a/grub-core/commands/search.c -+++ b/grub-core/commands/search.c -@@ -47,7 +47,7 @@ struct search_ctx - { - const char *key; - const char *var; -- int no_floppy; -+ enum search_flags flags; - char **hints; - unsigned nhints; - int count; -@@ -62,10 +62,29 @@ iterate_device (const char *name, void *data) - int found = 0; - - /* Skip floppy drives when requested. */ -- if (ctx->no_floppy && -+ if (ctx->flags & SEARCH_FLAGS_NO_FLOPPY && - name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') - return 0; - -+ /* Limit to EFI disks when requested. */ -+ if (ctx->flags & SEARCH_FLAGS_EFIDISK_ONLY) -+ { -+ grub_device_t dev; -+ dev = grub_device_open (name); -+ if (! dev) -+ { -+ grub_errno = GRUB_ERR_NONE; -+ return 0; -+ } -+ if (! dev->disk || dev->disk->dev->id != GRUB_DISK_DEVICE_EFIDISK_ID) -+ { -+ grub_device_close (dev); -+ grub_errno = GRUB_ERR_NONE; -+ return 0; -+ } -+ grub_device_close (dev); -+ } -+ - #ifdef DO_SEARCH_FS_UUID - #define compare_fn grub_strcasecmp - #else -@@ -261,13 +280,13 @@ try (struct search_ctx *ctx) - } - - void --FUNC_NAME (const char *key, const char *var, int no_floppy, -+FUNC_NAME (const char *key, const char *var, enum search_flags flags, - char **hints, unsigned nhints) - { - struct search_ctx ctx = { - .key = key, - .var = var, -- .no_floppy = no_floppy, -+ .flags = flags, - .hints = hints, - .nhints = nhints, - .count = 0, -diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c -index 47fc8eb996..0b62acf853 100644 ---- a/grub-core/commands/search_wrap.c -+++ b/grub-core/commands/search_wrap.c -@@ -40,6 +40,7 @@ static const struct grub_arg_option options[] = - N_("Set a variable to the first device found."), N_("VARNAME"), - ARG_TYPE_STRING}, - {"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0}, -+ {"efidisk-only", 0, 0, N_("Only probe EFI disks."), 0, 0}, - {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, - N_("First try the device HINT. If HINT ends in comma, " - "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, -@@ -73,6 +74,7 @@ enum options - SEARCH_FS_UUID, - SEARCH_SET, - SEARCH_NO_FLOPPY, -+ SEARCH_EFIDISK_ONLY, - SEARCH_HINT, - SEARCH_HINT_IEEE1275, - SEARCH_HINT_BIOS, -@@ -89,6 +91,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) - const char *id = 0; - int i = 0, j = 0, nhints = 0; - char **hints = NULL; -+ enum search_flags flags = 0; - - if (state[SEARCH_HINT].set) - for (i = 0; state[SEARCH_HINT].args[i]; i++) -@@ -180,15 +183,18 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) - goto out; - } - -+ if (state[SEARCH_NO_FLOPPY].set) -+ flags |= SEARCH_FLAGS_NO_FLOPPY; -+ -+ if (state[SEARCH_EFIDISK_ONLY].set) -+ flags |= SEARCH_FLAGS_EFIDISK_ONLY; -+ - if (state[SEARCH_LABEL].set) -- grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, -- hints, nhints); -+ grub_search_label (id, var, flags, hints, nhints); - else if (state[SEARCH_FS_UUID].set) -- grub_search_fs_uuid (id, var, state[SEARCH_NO_FLOPPY].set, -- hints, nhints); -+ grub_search_fs_uuid (id, var, flags, hints, nhints); - else if (state[SEARCH_FILE].set) -- grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, -- hints, nhints); -+ grub_search_fs_file (id, var, flags, hints, nhints); - else - grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); - -diff --git a/include/grub/search.h b/include/grub/search.h -index d80347df34..4190aeb2cb 100644 ---- a/include/grub/search.h -+++ b/include/grub/search.h -@@ -19,11 +19,20 @@ - #ifndef GRUB_SEARCH_HEADER - #define GRUB_SEARCH_HEADER 1 - --void grub_search_fs_file (const char *key, const char *var, int no_floppy, -+enum search_flags -+ { -+ SEARCH_FLAGS_NO_FLOPPY = 1, -+ SEARCH_FLAGS_EFIDISK_ONLY = 2 -+ }; -+ -+void grub_search_fs_file (const char *key, const char *var, -+ enum search_flags flags, - char **hints, unsigned nhints); --void grub_search_fs_uuid (const char *key, const char *var, int no_floppy, -+void grub_search_fs_uuid (const char *key, const char *var, -+ enum search_flags flags, - char **hints, unsigned nhints); --void grub_search_label (const char *key, const char *var, int no_floppy, -+void grub_search_label (const char *key, const char *var, -+ enum search_flags flags, - char **hints, unsigned nhints); - - #endif diff --git a/0207-efi-new-connectefi-command.patch b/0207-efi-new-connectefi-command.patch deleted file mode 100644 index f80de22..0000000 --- a/0207-efi-new-connectefi-command.patch +++ /dev/null @@ -1,395 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Tue, 15 Feb 2022 14:05:22 +0100 -Subject: [PATCH] efi: new 'connectefi' command -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When efi.quickboot is enabled on VMWare (which is the default for -hardware release 16 and later), it may happen that not all EFI devices -are connected. Due to this, browsing the devices in make_devices() just -fails to find devices, in particular disks or partitions for a given -disk. -This typically happens when network booting, then trying to chainload to -local disk (this is used in deployment tools such as Red Hat Satellite), -which is done through using the following grub.cfg snippet: --------- 8< ---------------- 8< ---------------- 8< -------- -unset prefix -search --file --set=prefix /EFI/redhat/grubx64.efi -if [ -n "$prefix" ]; then - chainloader ($prefix)/EFI/redhat/grubx64/efi -... --------- 8< ---------------- 8< ---------------- 8< -------- - -With efi.quickboot, none of the devices are connected, causing "search" -to fail. Sometimes devices are connected but not the partition of the -disk matching $prefix, causing partition to not be found by -"chainloader". - -This patch introduces a new "connectefi pciroot|scsi" command which -recursively connects all EFI devices starting from a given controller -type: -- if 'pciroot' is specified, recursion is performed for all PCI root - handles -- if 'scsi' is specified, recursion is performed for all SCSI I/O - handles (recommended usage to avoid connecting unwanted handles which - may impact Grub performances) - -Typical grub.cfg snippet would then be: --------- 8< ---------------- 8< ---------------- 8< -------- -connectefi scsi -unset prefix -search --file --set=prefix /EFI/redhat/grubx64.efi -if [ -n "$prefix" ]; then - chainloader ($prefix)/EFI/redhat/grubx64/efi -... --------- 8< ---------------- 8< ---------------- 8< -------- - -The code is easily extensible to handle other arguments in the future if -needed. - -Signed-off-by: Renaud Métrich -Signed-off-by: Robbie Harwood ---- - grub-core/Makefile.core.def | 6 ++ - grub-core/commands/efi/connectefi.c | 205 ++++++++++++++++++++++++++++++++++++ - grub-core/commands/efi/lsefi.c | 1 + - grub-core/disk/efi/efidisk.c | 13 +++ - grub-core/kern/efi/efi.c | 13 +++ - include/grub/efi/disk.h | 2 + - include/grub/efi/efi.h | 5 + - NEWS | 2 +- - 8 files changed, 246 insertions(+), 1 deletion(-) - create mode 100644 grub-core/commands/efi/connectefi.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index ec1ec5083b..741a033978 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -836,6 +836,12 @@ module = { - enable = efi; - }; - -+module = { -+ name = connectefi; -+ common = commands/efi/connectefi.c; -+ enable = efi; -+}; -+ - module = { - name = blocklist; - common = commands/blocklist.c; -diff --git a/grub-core/commands/efi/connectefi.c b/grub-core/commands/efi/connectefi.c -new file mode 100644 -index 0000000000..8ab75bd51b ---- /dev/null -+++ b/grub-core/commands/efi/connectefi.c -@@ -0,0 +1,205 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2022 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+typedef struct handle_list -+{ -+ grub_efi_handle_t handle; -+ struct handle_list *next; -+} handle_list_t; -+ -+static handle_list_t *already_handled = NULL; -+ -+static grub_err_t -+add_handle (grub_efi_handle_t handle) -+{ -+ handle_list_t *e; -+ e = grub_malloc (sizeof (*e)); -+ if (! e) -+ return grub_errno; -+ e->handle = handle; -+ e->next = already_handled; -+ already_handled = e; -+ return GRUB_ERR_NONE; -+} -+ -+static int -+is_in_list (grub_efi_handle_t handle) -+{ -+ handle_list_t *e; -+ for (e = already_handled; e != NULL; e = e->next) -+ if (e->handle == handle) -+ return 1; -+ return 0; -+} -+ -+static void -+free_handle_list (void) -+{ -+ handle_list_t *e; -+ while ((e = already_handled) != NULL) -+ { -+ already_handled = already_handled->next; -+ grub_free (e); -+ } -+} -+ -+typedef enum searched_item_flag -+{ -+ SEARCHED_ITEM_FLAG_LOOP = 1, -+ SEARCHED_ITEM_FLAG_RECURSIVE = 2 -+} searched_item_flags; -+ -+typedef struct searched_item -+{ -+ grub_efi_guid_t guid; -+ const char *name; -+ searched_item_flags flags; -+} searched_items; -+ -+static grub_err_t -+grub_cmd_connectefi (grub_command_t cmd __attribute__ ((unused)), -+ int argc, char **args) -+{ -+ unsigned s; -+ searched_items pciroot_items[] = -+ { -+ { GRUB_EFI_PCI_ROOT_IO_GUID, "PCI root", SEARCHED_ITEM_FLAG_RECURSIVE } -+ }; -+ searched_items scsi_items[] = -+ { -+ { GRUB_EFI_PCI_ROOT_IO_GUID, "PCI root", 0 }, -+ { GRUB_EFI_PCI_IO_GUID, "PCI", SEARCHED_ITEM_FLAG_LOOP }, -+ { GRUB_EFI_SCSI_IO_PROTOCOL_GUID, "SCSI I/O", SEARCHED_ITEM_FLAG_RECURSIVE } -+ }; -+ searched_items *items = NULL; -+ unsigned nitems = 0; -+ grub_err_t grub_err = GRUB_ERR_NONE; -+ unsigned total_connected = 0; -+ -+ if (argc != 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); -+ -+ if (grub_strcmp(args[0], N_("pciroot")) == 0) -+ { -+ items = pciroot_items; -+ nitems = ARRAY_SIZE (pciroot_items); -+ } -+ else if (grub_strcmp(args[0], N_("scsi")) == 0) -+ { -+ items = scsi_items; -+ nitems = ARRAY_SIZE (scsi_items); -+ } -+ else -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("unexpected argument `%s'"), args[0]); -+ -+ for (s = 0; s < nitems; s++) -+ { -+ grub_efi_handle_t *handles; -+ grub_efi_uintn_t num_handles; -+ unsigned i, connected = 0, loop = 0; -+ -+loop: -+ loop++; -+ grub_dprintf ("efi", "step '%s' loop %d:\n", items[s].name, loop); -+ -+ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, -+ &items[s].guid, 0, &num_handles); -+ -+ if (!handles) -+ continue; -+ -+ for (i = 0; i < num_handles; i++) -+ { -+ grub_efi_handle_t handle = handles[i]; -+ grub_efi_status_t status; -+ unsigned j; -+ -+ /* Skip already handled handles */ -+ if (is_in_list (handle)) -+ { -+ grub_dprintf ("efi", " handle %p: already processed\n", -+ handle); -+ continue; -+ } -+ -+ status = grub_efi_connect_controller(handle, NULL, NULL, -+ items[s].flags & SEARCHED_ITEM_FLAG_RECURSIVE ? 1 : 0); -+ if (status == GRUB_EFI_SUCCESS) -+ { -+ connected++; -+ total_connected++; -+ grub_dprintf ("efi", " handle %p: connected\n", handle); -+ } -+ else -+ grub_dprintf ("efi", " handle %p: failed to connect (%d)\n", -+ handle, (grub_efi_int8_t) status); -+ -+ if ((grub_err = add_handle (handle)) != GRUB_ERR_NONE) -+ break; /* fatal */ -+ } -+ -+ grub_free (handles); -+ if (grub_err != GRUB_ERR_NONE) -+ break; /* fatal */ -+ -+ if (items[s].flags & SEARCHED_ITEM_FLAG_LOOP && connected) -+ { -+ connected = 0; -+ goto loop; -+ } -+ -+ free_handle_list (); -+ } -+ -+ free_handle_list (); -+ -+ if (total_connected) -+ grub_efidisk_reenumerate_disks (); -+ -+ return grub_err; -+} -+ -+static grub_command_t cmd; -+ -+GRUB_MOD_INIT(connectefi) -+{ -+ cmd = grub_register_command ("connectefi", grub_cmd_connectefi, -+ N_("pciroot|scsi"), -+ N_("Connect EFI handles." -+ " If 'pciroot' is specified, connect PCI" -+ " root EFI handles recursively." -+ " If 'scsi' is specified, connect SCSI" -+ " I/O EFI handles recursively.")); -+} -+ -+GRUB_MOD_FINI(connectefi) -+{ -+ grub_unregister_command (cmd); -+} -diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c -index d1ce99af43..f2d2430e66 100644 ---- a/grub-core/commands/efi/lsefi.c -+++ b/grub-core/commands/efi/lsefi.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c -index fe8ba6e6c9..062143dfff 100644 ---- a/grub-core/disk/efi/efidisk.c -+++ b/grub-core/disk/efi/efidisk.c -@@ -396,6 +396,19 @@ enumerate_disks (void) - free_devices (devices); - } - -+void -+grub_efidisk_reenumerate_disks (void) -+{ -+ free_devices (fd_devices); -+ free_devices (hd_devices); -+ free_devices (cd_devices); -+ fd_devices = 0; -+ hd_devices = 0; -+ cd_devices = 0; -+ -+ enumerate_disks (); -+} -+ - static int - grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, - grub_disk_pull_t pull) -diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c -index 14bc10eb56..7fcca69c17 100644 ---- a/grub-core/kern/efi/efi.c -+++ b/grub-core/kern/efi/efi.c -@@ -95,6 +95,19 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type, - return buffer; - } - -+grub_efi_status_t -+grub_efi_connect_controller (grub_efi_handle_t controller_handle, -+ grub_efi_handle_t *driver_image_handle, -+ grub_efi_device_path_protocol_t *remaining_device_path, -+ grub_efi_boolean_t recursive) -+{ -+ grub_efi_boot_services_t *b; -+ -+ b = grub_efi_system_table->boot_services; -+ return efi_call_4 (b->connect_controller, controller_handle, -+ driver_image_handle, remaining_device_path, recursive); -+} -+ - void * - grub_efi_open_protocol (grub_efi_handle_t handle, - grub_efi_guid_t *protocol, -diff --git a/include/grub/efi/disk.h b/include/grub/efi/disk.h -index 254475c842..6845c2f1fd 100644 ---- a/include/grub/efi/disk.h -+++ b/include/grub/efi/disk.h -@@ -27,6 +27,8 @@ grub_efi_handle_t - EXPORT_FUNC(grub_efidisk_get_device_handle) (grub_disk_t disk); - char *EXPORT_FUNC(grub_efidisk_get_device_name) (grub_efi_handle_t *handle); - -+void EXPORT_FUNC(grub_efidisk_reenumerate_disks) (void); -+ - void grub_efidisk_init (void); - void grub_efidisk_fini (void); - -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index 8dfc89a33b..ec52083c49 100644 ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -41,6 +41,11 @@ EXPORT_FUNC(grub_efi_locate_handle) (grub_efi_locate_search_type_t search_type, - grub_efi_guid_t *protocol, - void *search_key, - grub_efi_uintn_t *num_handles); -+grub_efi_status_t -+EXPORT_FUNC(grub_efi_connect_controller) (grub_efi_handle_t controller_handle, -+ grub_efi_handle_t *driver_image_handle, -+ grub_efi_device_path_protocol_t *remaining_device_path, -+ grub_efi_boolean_t recursive); - void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle, - grub_efi_guid_t *protocol, - grub_efi_uint32_t attributes); -diff --git a/NEWS b/NEWS -index 73b8492bc4..d7c1d23aed 100644 ---- a/NEWS -+++ b/NEWS -@@ -98,7 +98,7 @@ New in 2.02: - * Prefer pmtimer for TSC calibration. - - * New/improved platform support: -- * New `efifwsetup' and `lsefi' commands on EFI platforms. -+ * New `efifwsetup', `lsefi' and `connectefi` commands on EFI platforms. - * New `cmosdump' and `cmosset' commands on platforms with CMOS support. - * New command `pcidump' for PCI platforms. - * Improve opcode parsing in ACPI halt implementation. diff --git a/0207-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch b/0207-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch new file mode 100644 index 0000000..5b450f9 --- /dev/null +++ b/0207-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Fri, 4 Mar 2022 11:29:31 +0100 +Subject: [PATCH] grub-core/loader/arm64/linux.c: do not validate kernel twice + +Call to grub_file_open(, GRUB_FILE_TYPE_LINUX_KERNEL) already passes +the kernel file through shim-lock verifier when secureboot is on. Thus +there is no need to validate the kernel image again. And when doing so +again, duplicate PCR measurement is performed, breaking measurements +compatibility with 2.04+linuxefi. + +This patch must not be ported to older editions of grub code bases +that do not have verifiers framework, or it is not builtin, or +shim-lock-verifier is an optional module. + +Signed-off-by: Dimitri John Ledkov +--- + grub-core/loader/arm64/linux.c | 13 ------------- + 1 file changed, 13 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index f18d90bd74..d2af47c2c0 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -34,7 +34,6 @@ + #include + #include + #include +-#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -341,7 +340,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_off_t filelen; + grub_uint32_t align; + void *kernel = NULL; +- int rc; + + grub_dl_ref (my_mod); + +@@ -370,17 +368,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) +- { +- rc = grub_linuxefi_secure_validate (kernel, filelen); +- if (rc <= 0) +- { +- grub_error (GRUB_ERR_INVALID_COMMAND, +- N_("%s has invalid signature"), argv[0]); +- goto fail; +- } +- } +- + if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) + goto fail; + if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) diff --git a/0208-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch b/0208-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch new file mode 100644 index 0000000..4c56d60 --- /dev/null +++ b/0208-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Fri, 4 Mar 2022 09:31:43 +0100 +Subject: [PATCH] grub-core/loader/efi/chainloader.c: do not validate + chainloader twice + +On secureboot systems, with shimlock verifier, call to +grub_file_open(, GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE) will already +pass the chainloader target through shim-lock protocol verify +call. And create a TPM measurement. If verification fails, +grub_cmd_chainloader will fail at file open time. + +This makes previous code paths for negative, and zero return codes +from grub_linuxefi_secure_validate unreachable under secureboot. But +also breaking measurements compatibility with 2.04+linuxefi codebases, +as the chainloader file is passed through shim_lock->verify() twice +(via verifier & direct call to grub_linuxefi_secure_validate) +extending the PCRs twice. + +This reduces grub_loader options to perform +grub_secureboot_chainloader when secureboot is on, and otherwise +attempt grub_chainloader_boot. + +It means that booting with secureboot off, yet still with shim (which +always verifies things successfully), will stop choosing +grub_secureboot_chainloader, and opting for a more regular +loadimage/startimage codepath. If we want to use the +grub_secureboot_chainloader codepath in such scenarios we should adapt +the code to simply check for shim_lock protocol presence / +shim_lock->context() success?! But I am not sure if that is necessary. + +This patch must not be ported to older editions of grub code bases +that do not have verifiers framework, or it is not builtin, or +shim-lock-verifier is an optional module. + +Signed-off-by: Dimitri John Ledkov +--- + grub-core/loader/efi/chainloader.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 3af6b12292..644cd2e56f 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -906,7 +906,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_efi_device_path_t *dp = 0; + char *filename; + void *boot_image = 0; +- int rc; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -1082,9 +1081,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + orig_dev = 0; + } + +- rc = grub_linuxefi_secure_validate((void *)(unsigned long)address, fsize); +- grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc); +- if (rc > 0) ++ if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) + { + grub_file_close (file); + grub_device_close (dev); +@@ -1092,7 +1089,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_secureboot_chainloader_unload, 0); + return 0; + } +- else if (rc == 0) ++ else + { + grub_load_and_start_image(boot_image); + grub_file_close (file); +@@ -1101,7 +1098,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + + return 0; + } +- // -1 fall-through to fail + + fail: + if (orig_dev) diff --git a/0208-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch b/0208-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch deleted file mode 100644 index 4fe8adf..0000000 --- a/0208-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dimitri John Ledkov -Date: Thu, 3 Mar 2022 13:10:56 +0100 -Subject: [PATCH] grub-core/loader/i386/efi/linux.c: do not validate kernels - twice - -On codebases that have shim-lock-verifier built into the grub core -(like 2.06 upstream), shim-lock-verifier is in enforcing mode when -booted with secureboot. It means that grub_cmd_linux() command -attempts to perform shim validate upon opening linux kernel image, -including kernel measurement. And the verifier correctly returns file -open error when shim validate protocol is not present or shim fails to -validate the kernel. - -This makes the call to grub_linuxefi_secure_validate() redundant, but -also harmful. As validating the kernel image twice, extends the PCRs -with the same measurement twice. Which breaks existing sealing -policies when upgrading from grub2.04+rhboot+sb+linuxefi to -grub2.06+rhboot+sb+linuxefi builds. It is also incorrect to measure -the kernel twice. - -This patch must not be ported to older editions of grub code bases -that do not have verifiers framework, or it is not builtin, or -shim-lock-verifier is an optional module. - -This patch is tested to ensure that unsigned kernels are not possible -to boot in secureboot mode when shim rejects kernel, or shim protocol -is missing, and that the measurements become stable once again. The -above also ensures that CVE-2020-15705 is not reintroduced. - -Signed-off-by: Dimitri John Ledkov ---- - grub-core/loader/i386/efi/linux.c | 13 ------------- - 1 file changed, 13 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 3cf0f9b330..941df6400b 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -30,7 +30,6 @@ - #include - #include - #include --#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -278,7 +277,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_ssize_t start, filelen; - void *kernel = NULL; - int setup_header_end_offset; -- int rc; - - grub_dl_ref (my_mod); - -@@ -308,17 +306,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -- if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) -- { -- rc = grub_linuxefi_secure_validate (kernel, filelen); -- if (rc <= 0) -- { -- grub_error (GRUB_ERR_INVALID_COMMAND, -- N_("%s has invalid signature"), argv[0]); -- goto fail; -- } -- } -- - lh = (struct linux_i386_kernel_header *)kernel; - grub_dprintf ("linux", "original lh is at %p\n", kernel); - diff --git a/0209-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch b/0209-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch deleted file mode 100644 index 5b450f9..0000000 --- a/0209-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dimitri John Ledkov -Date: Fri, 4 Mar 2022 11:29:31 +0100 -Subject: [PATCH] grub-core/loader/arm64/linux.c: do not validate kernel twice - -Call to grub_file_open(, GRUB_FILE_TYPE_LINUX_KERNEL) already passes -the kernel file through shim-lock verifier when secureboot is on. Thus -there is no need to validate the kernel image again. And when doing so -again, duplicate PCR measurement is performed, breaking measurements -compatibility with 2.04+linuxefi. - -This patch must not be ported to older editions of grub code bases -that do not have verifiers framework, or it is not builtin, or -shim-lock-verifier is an optional module. - -Signed-off-by: Dimitri John Ledkov ---- - grub-core/loader/arm64/linux.c | 13 ------------- - 1 file changed, 13 deletions(-) - -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index f18d90bd74..d2af47c2c0 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -34,7 +34,6 @@ - #include - #include - #include --#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -341,7 +340,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_off_t filelen; - grub_uint32_t align; - void *kernel = NULL; -- int rc; - - grub_dl_ref (my_mod); - -@@ -370,17 +368,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -- if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) -- { -- rc = grub_linuxefi_secure_validate (kernel, filelen); -- if (rc <= 0) -- { -- grub_error (GRUB_ERR_INVALID_COMMAND, -- N_("%s has invalid signature"), argv[0]); -- goto fail; -- } -- } -- - if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) - goto fail; - if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) diff --git a/0209-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch b/0209-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch new file mode 100644 index 0000000..c683fcb --- /dev/null +++ b/0209-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Fri, 4 Mar 2022 11:36:09 +0100 +Subject: [PATCH] grub-core/loader/efi/linux.c: drop now unused + grub_linuxefi_secure_validate + +Drop the now unused grub_linuxefi_secure_validate() as all prior users +of this API now rely on the shim-lock-verifier codepath instead. + +This patch must not be ported to older editions of grub code bases +that do not have verifiers framework, or it is not builtin, or +shim-lock-verifier is an optional module. + +Signed-off-by: Dimitri John Ledkov +--- + grub-core/loader/efi/linux.c | 40 ---------------------------------------- + include/grub/efi/linux.h | 2 -- + 2 files changed, 42 deletions(-) + +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index 9260731c10..9265cf4200 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -24,46 +24,6 @@ + #include + #include + +-#define SHIM_LOCK_GUID \ +- { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } +- +-struct grub_efi_shim_lock +-{ +- grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size); +-}; +-typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; +- +-// Returns 1 on success, -1 on error, 0 when not available +-int +-grub_linuxefi_secure_validate (void *data, grub_uint32_t size) +-{ +- grub_efi_guid_t guid = SHIM_LOCK_GUID; +- grub_efi_shim_lock_t *shim_lock; +- grub_efi_status_t status; +- +- shim_lock = grub_efi_locate_protocol(&guid, NULL); +- grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock); +- if (!shim_lock) +- { +- grub_dprintf ("secureboot", "shim not available\n"); +- return 0; +- } +- +- grub_dprintf ("secureboot", "Asking shim to verify kernel signature\n"); +- status = shim_lock->verify (data, size); +- grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", (long int)status); +- if (status == GRUB_EFI_SUCCESS) +- { +- grub_dprintf ("secureboot", "Kernel signature verification passed\n"); +- return 1; +- } +- +- grub_dprintf ("secureboot", "Kernel signature verification failed (0x%lx)\n", +- (unsigned long) status); +- +- return -1; +-} +- + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + +diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h +index 0033d9305a..887b02fd9f 100644 +--- a/include/grub/efi/linux.h ++++ b/include/grub/efi/linux.h +@@ -22,8 +22,6 @@ + #include + #include + +-int +-EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size); + grub_err_t + EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, + void *kernel_param); diff --git a/0210-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch b/0210-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch deleted file mode 100644 index 4c56d60..0000000 --- a/0210-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dimitri John Ledkov -Date: Fri, 4 Mar 2022 09:31:43 +0100 -Subject: [PATCH] grub-core/loader/efi/chainloader.c: do not validate - chainloader twice - -On secureboot systems, with shimlock verifier, call to -grub_file_open(, GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE) will already -pass the chainloader target through shim-lock protocol verify -call. And create a TPM measurement. If verification fails, -grub_cmd_chainloader will fail at file open time. - -This makes previous code paths for negative, and zero return codes -from grub_linuxefi_secure_validate unreachable under secureboot. But -also breaking measurements compatibility with 2.04+linuxefi codebases, -as the chainloader file is passed through shim_lock->verify() twice -(via verifier & direct call to grub_linuxefi_secure_validate) -extending the PCRs twice. - -This reduces grub_loader options to perform -grub_secureboot_chainloader when secureboot is on, and otherwise -attempt grub_chainloader_boot. - -It means that booting with secureboot off, yet still with shim (which -always verifies things successfully), will stop choosing -grub_secureboot_chainloader, and opting for a more regular -loadimage/startimage codepath. If we want to use the -grub_secureboot_chainloader codepath in such scenarios we should adapt -the code to simply check for shim_lock protocol presence / -shim_lock->context() success?! But I am not sure if that is necessary. - -This patch must not be ported to older editions of grub code bases -that do not have verifiers framework, or it is not builtin, or -shim-lock-verifier is an optional module. - -Signed-off-by: Dimitri John Ledkov ---- - grub-core/loader/efi/chainloader.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 3af6b12292..644cd2e56f 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -906,7 +906,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_efi_device_path_t *dp = 0; - char *filename; - void *boot_image = 0; -- int rc; - - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -@@ -1082,9 +1081,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - orig_dev = 0; - } - -- rc = grub_linuxefi_secure_validate((void *)(unsigned long)address, fsize); -- grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc); -- if (rc > 0) -+ if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) - { - grub_file_close (file); - grub_device_close (dev); -@@ -1092,7 +1089,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_secureboot_chainloader_unload, 0); - return 0; - } -- else if (rc == 0) -+ else - { - grub_load_and_start_image(boot_image); - grub_file_close (file); -@@ -1101,7 +1098,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - - return 0; - } -- // -1 fall-through to fail - - fail: - if (orig_dev) diff --git a/0210-powerpc-prefix-detection-support-device-names-with-c.patch b/0210-powerpc-prefix-detection-support-device-names-with-c.patch new file mode 100644 index 0000000..1c16fd3 --- /dev/null +++ b/0210-powerpc-prefix-detection-support-device-names-with-c.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 24 Mar 2022 14:34:32 +1100 +Subject: [PATCH] powerpc: prefix detection: support device names with commas + +Frustratingly, the device name itself can contain an embedded comma: +e.g /pci@800000020000015/pci1014,034A@0/sas/disk@5000c50098a0ee8b + +So my previous approach was wrong: we cannot rely upon the presence +of a comma to say that a partition has been specified! + +It turns out for prefixes like (,gpt2)/grub2 we really want to make +up a full (device,partition)/patch prefix, because root discovery code +in 10_linux will reset the root variable and use search to fill it again. +If you have run grub-install, you probably don't have search built in, +and if you don't have prefix containing (device,partition), grub will +construct ($root)$prefix/powerpc-ieee1275/search.mod - but because $root +has just been changed, this will no longer work, and the boot will fail! + +Retain the gist of the logic, but instead of looking for a comma, look for +a leading '('. This matches the earlier code better anyway. + +There's certainly a better fix to be had. But any time you chose to build +with a bare prefix like '/grub2', you're almost certainly going to build in +search anyway, so this will do. + +Signed-off-by: Daniel Axtens +--- + grub-core/kern/main.c | 27 +++++++++++++++++++++------ + 1 file changed, 21 insertions(+), 6 deletions(-) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index 993b8a8598..e94a2f78fb 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -242,14 +242,29 @@ grub_set_prefix_and_root (void) + what sorts of paths represent disks with partition tables and those + without partition tables. + +- So we act unless there is a comma in the device, which would indicate +- a partition has already been specified. ++ - Frustratingly, the device name itself can contain an embedded comma: ++ /pci@800000020000015/pci1014,034A@0/sas/disk@5000c50098a0ee8b ++ So we cannot even rely upon the presence of a comma to say that a ++ partition has been specified! + +- (If we only have a path, the code in normal to discover config files +- will try both without partitions and then with any partitions so we +- will cover both CDs and HDs.) ++ If we only have a path in $prefix, the code in normal to discover ++ config files will try all disks, both without partitions and then with ++ any partitions so we will cover both CDs and HDs. ++ ++ However, it doesn't then set the prefix to be something like ++ (discovered partition)/path, and so it is fragile against runtime ++ changes to $root. For example some of the stuff done in 10_linux to ++ reload $root sets root differently and then uses search to find it ++ again. If the search module is not built in, when we change root, grub ++ will look in (new root)/path/powerpc-ieee1275, that won't work, and we ++ will not be able to load the search module and the boot will fail. ++ ++ This is particularly likely to hit us in the grub-install ++ (,msdos2)/grub2 case, so we act unless the supplied prefix starts with ++ '(', which would likely indicate a partition has already been ++ specified. + */ +- if (grub_strchr (device, ',') == NULL) ++ if (prefix && prefix[0] != '(') + grub_env_set ("prefix", path); + else + #endif diff --git a/0211-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch b/0211-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch deleted file mode 100644 index c683fcb..0000000 --- a/0211-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dimitri John Ledkov -Date: Fri, 4 Mar 2022 11:36:09 +0100 -Subject: [PATCH] grub-core/loader/efi/linux.c: drop now unused - grub_linuxefi_secure_validate - -Drop the now unused grub_linuxefi_secure_validate() as all prior users -of this API now rely on the shim-lock-verifier codepath instead. - -This patch must not be ported to older editions of grub code bases -that do not have verifiers framework, or it is not builtin, or -shim-lock-verifier is an optional module. - -Signed-off-by: Dimitri John Ledkov ---- - grub-core/loader/efi/linux.c | 40 ---------------------------------------- - include/grub/efi/linux.h | 2 -- - 2 files changed, 42 deletions(-) - -diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c -index 9260731c10..9265cf4200 100644 ---- a/grub-core/loader/efi/linux.c -+++ b/grub-core/loader/efi/linux.c -@@ -24,46 +24,6 @@ - #include - #include - --#define SHIM_LOCK_GUID \ -- { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } -- --struct grub_efi_shim_lock --{ -- grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size); --}; --typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; -- --// Returns 1 on success, -1 on error, 0 when not available --int --grub_linuxefi_secure_validate (void *data, grub_uint32_t size) --{ -- grub_efi_guid_t guid = SHIM_LOCK_GUID; -- grub_efi_shim_lock_t *shim_lock; -- grub_efi_status_t status; -- -- shim_lock = grub_efi_locate_protocol(&guid, NULL); -- grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock); -- if (!shim_lock) -- { -- grub_dprintf ("secureboot", "shim not available\n"); -- return 0; -- } -- -- grub_dprintf ("secureboot", "Asking shim to verify kernel signature\n"); -- status = shim_lock->verify (data, size); -- grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", (long int)status); -- if (status == GRUB_EFI_SUCCESS) -- { -- grub_dprintf ("secureboot", "Kernel signature verification passed\n"); -- return 1; -- } -- -- grub_dprintf ("secureboot", "Kernel signature verification failed (0x%lx)\n", -- (unsigned long) status); -- -- return -1; --} -- - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" - -diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h -index 0033d9305a..887b02fd9f 100644 ---- a/include/grub/efi/linux.h -+++ b/include/grub/efi/linux.h -@@ -22,8 +22,6 @@ - #include - #include - --int --EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size); - grub_err_t - EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, - void *kernel_param); diff --git a/0211-make-ofdisk_retries-optional.patch b/0211-make-ofdisk_retries-optional.patch new file mode 100644 index 0000000..fce9702 --- /dev/null +++ b/0211-make-ofdisk_retries-optional.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Diego Domingos +Date: Thu, 24 Mar 2022 13:14:42 -0400 +Subject: [PATCH] make ofdisk_retries optional + +The feature Retry on Fail added to GRUB can cause a LPM to take +longer if the SAN is slow. + +When a LPM to external site occur, the path of the disk can change +and thus the disk search function on grub can take some time since +it is used as a hint. This can cause the Retry on Fail feature to +try to access the disk 20x times (since this is hardcoded number) +and, if the SAN is slow, the boot time can increase a lot. +In some situations not acceptable. + +The following patch enables a configuration at user space of the +maximum number of retries we want for this feature. + +The variable ofdisk_retries should be set using grub2-editenv +and will be checked by retry function. If the variable is not set, +so the default number of retries will be used instead. +--- + include/grub/ieee1275/ofdisk.h | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h +index 7d2d540930..0074d55eee 100644 +--- a/include/grub/ieee1275/ofdisk.h ++++ b/include/grub/ieee1275/ofdisk.h +@@ -25,7 +25,12 @@ extern void grub_ofdisk_fini (void); + #define MAX_RETRIES 20 + + +-#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) unsigned retry_i=0;for(retry_i=0; retry_i < MAX_RETRIES; retry_i++){ \ ++#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) \ ++ unsigned max_retries = MAX_RETRIES; \ ++ if(grub_env_get("ofdisk_retries") != NULL) \ ++ max_retries = grub_strtoul(grub_env_get("ofdisk_retries"), 0, 10)+1; \ ++ grub_dprintf("ofdisk","MAX_RETRIES set to %u\n",max_retries); \ ++ unsigned retry_i=0;for(retry_i=0; retry_i < max_retries; retry_i++){ \ + if(!grub_ieee1275_open(device, last_ihandle)) \ + break; \ + grub_dprintf("ofdisk","Opening disk %s failed. Retrying...\n",device); } diff --git a/0212-loader-efi-chainloader-grub_load_and_start_image-doe.patch b/0212-loader-efi-chainloader-grub_load_and_start_image-doe.patch new file mode 100644 index 0000000..f61ed28 --- /dev/null +++ b/0212-loader-efi-chainloader-grub_load_and_start_image-doe.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Thu, 28 Apr 2022 21:53:36 +0100 +Subject: [PATCH] loader/efi/chainloader: grub_load_and_start_image doesn't + load and start + +grub_load_and_start_image only loads an image - it still requires the +caller to start it. This renames it to grub_load_image. + +It's called from 2 places: +- grub_cmd_chainloader when not using the shim protocol. +- grub_secureboot_chainloader_boot if handle_image returns an error. +In this case, the image is loaded and then nothing else happens which +seems strange. I assume the intention is that it falls back to LoadImage +and StartImage if handle_image fails, so I've made it do that. + +Signed-off-by: Chris Coulson +(cherry picked from commit b4d70820a65c00561045856b7b8355461a9545f6) +--- + grub-core/loader/efi/chainloader.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 644cd2e56f..d3bf02ed8a 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -841,7 +841,7 @@ grub_secureboot_chainloader_unload (void) + } + + static grub_err_t +-grub_load_and_start_image(void *boot_image) ++grub_load_image(void *boot_image) + { + grub_efi_boot_services_t *b; + grub_efi_status_t status; +@@ -883,13 +883,23 @@ grub_load_and_start_image(void *boot_image) + static grub_err_t + grub_secureboot_chainloader_boot (void) + { ++ grub_efi_boot_services_t *b; + int rc; ++ + rc = handle_image ((void *)(unsigned long)address, fsize); + if (rc == 0) + { +- grub_load_and_start_image((void *)(unsigned long)address); ++ /* We weren't able to attempt to execute the image, so fall back ++ * to LoadImage / StartImage. ++ */ ++ rc = grub_load_image((void *)(unsigned long)address); ++ if (rc == 0) ++ grub_chainloader_boot (); + } + ++ b = grub_efi_system_table->boot_services; ++ efi_call_1 (b->unload_image, image_handle); ++ + grub_loader_unset (); + return grub_errno; + } +@@ -1091,7 +1101,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + } + else + { +- grub_load_and_start_image(boot_image); ++ grub_load_image(boot_image); + grub_file_close (file); + grub_device_close (dev); + grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); diff --git a/0212-powerpc-do-CAS-in-a-more-compatible-way.patch b/0212-powerpc-do-CAS-in-a-more-compatible-way.patch deleted file mode 100644 index 20b95f7..0000000 --- a/0212-powerpc-do-CAS-in-a-more-compatible-way.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 8 Apr 2022 12:35:28 +1000 -Subject: [PATCH] powerpc: do CAS in a more compatible way - -I wrongly assumed that the most compatible way to perform CAS -negotiation was to only set the minimum number of vectors required -to ask for more memory. It turns out that this messes up booting -if the minimum VP capacity would be less than the default 10% in -vector 4. - -Linux configures the minimum capacity to be 1%, so copy it for that -and for vector 3 which we now need to specify as well. - -Signed-off-by: Daniel Axtens ---- - grub-core/kern/ieee1275/init.c | 54 ++++++++++++++++++++++++------------------ - 1 file changed, 31 insertions(+), 23 deletions(-) - -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index 9704715c83..ef55107467 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -298,33 +298,37 @@ grub_ieee1275_total_mem (grub_uint64_t *total) - - /* Based on linux - arch/powerpc/kernel/prom_init.c */ - struct option_vector2 { -- grub_uint8_t byte1; -- grub_uint16_t reserved; -- grub_uint32_t real_base; -- grub_uint32_t real_size; -- grub_uint32_t virt_base; -- grub_uint32_t virt_size; -- grub_uint32_t load_base; -- grub_uint32_t min_rma; -- grub_uint32_t min_load; -- grub_uint8_t min_rma_percent; -- grub_uint8_t max_pft_size; -+ grub_uint8_t byte1; -+ grub_uint16_t reserved; -+ grub_uint32_t real_base; -+ grub_uint32_t real_size; -+ grub_uint32_t virt_base; -+ grub_uint32_t virt_size; -+ grub_uint32_t load_base; -+ grub_uint32_t min_rma; -+ grub_uint32_t min_load; -+ grub_uint8_t min_rma_percent; -+ grub_uint8_t max_pft_size; - } __attribute__((packed)); - - struct pvr_entry { -- grub_uint32_t mask; -- grub_uint32_t entry; -+ grub_uint32_t mask; -+ grub_uint32_t entry; - }; - - struct cas_vector { -- struct { -- struct pvr_entry terminal; -- } pvr_list; -- grub_uint8_t num_vecs; -- grub_uint8_t vec1_size; -- grub_uint8_t vec1; -- grub_uint8_t vec2_size; -- struct option_vector2 vec2; -+ struct { -+ struct pvr_entry terminal; -+ } pvr_list; -+ grub_uint8_t num_vecs; -+ grub_uint8_t vec1_size; -+ grub_uint8_t vec1; -+ grub_uint8_t vec2_size; -+ struct option_vector2 vec2; -+ grub_uint8_t vec3_size; -+ grub_uint16_t vec3; -+ grub_uint8_t vec4_size; -+ grub_uint16_t vec4; - } __attribute__((packed)); - - /* Call ibm,client-architecture-support to try to get more RMA. -@@ -345,13 +349,17 @@ grub_ieee1275_ibm_cas (void) - } args; - struct cas_vector vector = { - .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ -- .num_vecs = 2 - 1, -+ .num_vecs = 4 - 1, - .vec1_size = 0, - .vec1 = 0x80, /* ignore */ - .vec2_size = 1 + sizeof(struct option_vector2) - 2, - .vec2 = { - 0, 0, -1, -1, -1, -1, -1, 512, -1, 0, 48 - }, -+ .vec3_size = 2 - 1, -+ .vec3 = 0x00e0, // ask for FP + VMX + DFP but don't halt if unsatisfied -+ .vec4_size = 2 - 1, -+ .vec4 = 0x0001, // set required minimum capacity % to the lowest value - }; - - INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); -@@ -364,7 +372,7 @@ grub_ieee1275_ibm_cas (void) - args.ihandle = root; - args.cas_addr = (grub_ieee1275_cell_t)&vector; - -- grub_printf("Calling ibm,client-architecture-support..."); -+ grub_printf("Calling ibm,client-architecture-support from grub..."); - IEEE1275_CALL_ENTRY_FN (&args); - grub_printf("done\n"); - diff --git a/0213-loader-efi-chainloader-simplify-the-loader-state.patch b/0213-loader-efi-chainloader-simplify-the-loader-state.patch new file mode 100644 index 0000000..205124e --- /dev/null +++ b/0213-loader-efi-chainloader-simplify-the-loader-state.patch @@ -0,0 +1,330 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Fri, 29 Apr 2022 21:13:08 +0100 +Subject: [PATCH] loader/efi/chainloader: simplify the loader state + +When not using the shim lock protocol, the chainloader command retains +the source buffer and device path passed to LoadImage, requiring the +unload hook passed to grub_loader_set to free them. It isn't required +to retain this state though - they aren't required by StartImage or +anything else in the boot hook, so clean them up before +grub_cmd_chainloader finishes. + +This also wraps the loader state when using the shim lock protocol +inside a struct. + +Signed-off-by: Chris Coulson +(cherry picked from commit fa39862933b3be1553a580a3a5c28073257d8046) +[rharwood: fix unitialized handle and double-frees of file/dev] +Signed-off-by: Robbie Harwood +--- + grub-core/loader/efi/chainloader.c | 160 +++++++++++++++++++++++-------------- + 1 file changed, 102 insertions(+), 58 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index d3bf02ed8a..3342492ff1 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -48,38 +48,21 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_dl_t my_mod; + +-static grub_efi_physical_address_t address; +-static grub_efi_uintn_t pages; +-static grub_ssize_t fsize; +-static grub_efi_device_path_t *file_path; + static grub_efi_handle_t image_handle; +-static grub_efi_char16_t *cmdline; +-static grub_ssize_t cmdline_len; +-static grub_efi_handle_t dev_handle; + +-static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); ++struct grub_secureboot_chainloader_context { ++ grub_efi_physical_address_t address; ++ grub_efi_uintn_t pages; ++ grub_ssize_t fsize; ++ grub_efi_device_path_t *file_path; ++ grub_efi_char16_t *cmdline; ++ grub_ssize_t cmdline_len; ++ grub_efi_handle_t dev_handle; ++}; ++static struct grub_secureboot_chainloader_context *sb_context; + + static grub_err_t +-grub_chainloader_unload (void) +-{ +- grub_efi_boot_services_t *b; +- +- b = grub_efi_system_table->boot_services; +- efi_call_1 (b->unload_image, image_handle); +- grub_efi_free_pages (address, pages); +- +- grub_free (file_path); +- grub_free (cmdline); +- cmdline = 0; +- file_path = 0; +- dev_handle = 0; +- +- grub_dl_unref (my_mod); +- return GRUB_ERR_NONE; +-} +- +-static grub_err_t +-grub_chainloader_boot (void) ++grub_start_image (grub_efi_handle_t handle) + { + grub_efi_boot_services_t *b; + grub_efi_status_t status; +@@ -87,7 +70,7 @@ grub_chainloader_boot (void) + grub_efi_char16_t *exit_data = NULL; + + b = grub_efi_system_table->boot_services; +- status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data); ++ status = efi_call_3 (b->start_image, handle, &exit_data_size, &exit_data); + if (status != GRUB_EFI_SUCCESS) + { + if (exit_data) +@@ -111,11 +94,37 @@ grub_chainloader_boot (void) + if (exit_data) + grub_efi_free_pool (exit_data); + +- grub_loader_unset (); +- + return grub_errno; + } + ++static grub_err_t ++grub_chainloader_unload (void) ++{ ++ grub_efi_loaded_image_t *loaded_image; ++ grub_efi_boot_services_t *b; ++ ++ loaded_image = grub_efi_get_loaded_image (image_handle); ++ if (loaded_image != NULL) ++ grub_free (loaded_image->load_options); ++ ++ b = grub_efi_system_table->boot_services; ++ efi_call_1 (b->unload_image, image_handle); ++ ++ grub_dl_unref (my_mod); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_chainloader_boot (void) ++{ ++ grub_err_t err; ++ ++ err = grub_start_image (image_handle); ++ ++ grub_loader_unset (); ++ return err; ++} ++ + static grub_err_t + copy_file_path (grub_efi_file_path_device_path_t *fp, + const char *str, grub_efi_uint16_t len) +@@ -150,7 +159,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) + char *dir_start; + char *dir_end; + grub_size_t size; +- grub_efi_device_path_t *d; ++ grub_efi_device_path_t *d, *file_path; + + dir_start = grub_strchr (filename, ')'); + if (! dir_start) +@@ -526,10 +535,12 @@ grub_efi_get_media_file_path (grub_efi_device_path_t *dp) + } + + static grub_efi_boolean_t +-handle_image (void *data, grub_efi_uint32_t datasize) ++handle_image (struct grub_secureboot_chainloader_context *load_context) + { + grub_efi_loaded_image_t *li, li_bak; + grub_efi_status_t efi_status; ++ void *data = (void *)(unsigned long)load_context->address; ++ grub_efi_uint32_t datasize = load_context->fsize; + void *buffer = NULL; + char *buffer_aligned = NULL; + grub_efi_uint32_t i; +@@ -540,6 +551,7 @@ handle_image (void *data, grub_efi_uint32_t datasize) + grub_uint32_t buffer_size; + int found_entry_point = 0; + int rc; ++ grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); + + rc = read_header (data, datasize, &context); + if (rc < 0) +@@ -797,10 +809,10 @@ handle_image (void *data, grub_efi_uint32_t datasize) + grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t)); + li->image_base = buffer_aligned; + li->image_size = context.image_size; +- li->load_options = cmdline; +- li->load_options_size = cmdline_len; +- li->file_path = grub_efi_get_media_file_path (file_path); +- li->device_handle = dev_handle; ++ li->load_options = load_context->cmdline; ++ li->load_options_size = load_context->cmdline_len; ++ li->file_path = grub_efi_get_media_file_path (load_context->file_path); ++ li->device_handle = load_context->dev_handle; + if (!li->file_path) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found"); +@@ -829,19 +841,22 @@ error_exit: + static grub_err_t + grub_secureboot_chainloader_unload (void) + { +- grub_efi_free_pages (address, pages); +- grub_free (file_path); +- grub_free (cmdline); +- cmdline = 0; +- file_path = 0; +- dev_handle = 0; ++ grub_efi_free_pages (sb_context->address, sb_context->pages); ++ grub_free (sb_context->file_path); ++ grub_free (sb_context->cmdline); ++ grub_free (sb_context); ++ ++ sb_context = 0; + + grub_dl_unref (my_mod); + return GRUB_ERR_NONE; + } + + static grub_err_t +-grub_load_image(void *boot_image) ++grub_load_image(grub_efi_device_path_t *file_path, void *boot_image, ++ grub_efi_uintn_t image_size, grub_efi_handle_t dev_handle, ++ grub_efi_char16_t *cmdline, grub_ssize_t cmdline_len, ++ grub_efi_handle_t *image_handle_out) + { + grub_efi_boot_services_t *b; + grub_efi_status_t status; +@@ -850,7 +865,7 @@ grub_load_image(void *boot_image) + b = grub_efi_system_table->boot_services; + + status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, +- boot_image, fsize, &image_handle); ++ boot_image, image_size, image_handle_out); + if (status != GRUB_EFI_SUCCESS) + { + if (status == GRUB_EFI_OUT_OF_RESOURCES) +@@ -863,7 +878,7 @@ grub_load_image(void *boot_image) + /* LoadImage does not set a device handler when the image is + loaded from memory, so it is necessary to set it explicitly here. + This is a mess. */ +- loaded_image = grub_efi_get_loaded_image (image_handle); ++ loaded_image = grub_efi_get_loaded_image (*image_handle_out); + if (! loaded_image) + { + grub_error (GRUB_ERR_BAD_OS, "no loaded image available"); +@@ -885,20 +900,25 @@ grub_secureboot_chainloader_boot (void) + { + grub_efi_boot_services_t *b; + int rc; ++ grub_efi_handle_t handle = 0; + +- rc = handle_image ((void *)(unsigned long)address, fsize); ++ rc = handle_image (sb_context); + if (rc == 0) + { + /* We weren't able to attempt to execute the image, so fall back + * to LoadImage / StartImage. + */ +- rc = grub_load_image((void *)(unsigned long)address); ++ rc = grub_load_image(sb_context->file_path, ++ (void *)(unsigned long)sb_context->address, ++ sb_context->fsize, sb_context->dev_handle, ++ sb_context->cmdline, sb_context->cmdline_len, ++ &handle); + if (rc == 0) +- grub_chainloader_boot (); ++ grub_start_image (handle); + } + + b = grub_efi_system_table->boot_services; +- efi_call_1 (b->unload_image, image_handle); ++ efi_call_1 (b->unload_image, handle); + + grub_loader_unset (); + return grub_errno; +@@ -913,9 +933,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_efi_boot_services_t *b; + grub_device_t dev = 0; + grub_device_t orig_dev = 0; +- grub_efi_device_path_t *dp = 0; ++ grub_efi_device_path_t *dp = 0, *file_path = 0; + char *filename; + void *boot_image = 0; ++ grub_efi_physical_address_t address = 0; ++ grub_ssize_t fsize; ++ grub_efi_uintn_t pages = 0; ++ grub_efi_char16_t *cmdline = 0; ++ grub_ssize_t cmdline_len = 0; ++ grub_efi_handle_t dev_handle = 0; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -923,12 +949,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + + grub_dl_ref (my_mod); + +- /* Initialize some global variables. */ +- address = 0; +- image_handle = 0; +- file_path = 0; +- dev_handle = 0; +- + b = grub_efi_system_table->boot_services; + + if (argc > 1) +@@ -1093,17 +1113,35 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + + if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) + { ++ sb_context = grub_malloc (sizeof (*sb_context)); ++ if (sb_context == NULL) ++ goto fail; ++ sb_context->address = address; ++ sb_context->fsize = fsize; ++ sb_context->pages = pages; ++ sb_context->file_path = file_path; ++ sb_context->cmdline = cmdline; ++ sb_context->cmdline_len = cmdline_len; ++ sb_context->dev_handle = dev_handle; ++ + grub_file_close (file); + grub_device_close (dev); ++ + grub_loader_set (grub_secureboot_chainloader_boot, + grub_secureboot_chainloader_unload, 0); + return 0; + } + else + { +- grub_load_image(boot_image); ++ grub_load_image(file_path, boot_image, fsize, dev_handle, cmdline, ++ cmdline_len, &image_handle); + grub_file_close (file); + grub_device_close (dev); ++ ++ /* We're finished with the source image buffer and file path now */ ++ efi_call_2 (b->free_pages, address, pages); ++ grub_free (file_path); ++ + grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); + + return 0; +@@ -1130,6 +1168,12 @@ fail: + if (cmdline) + grub_free (cmdline); + ++ if (image_handle != 0) ++ { ++ efi_call_1 (b->unload_image, image_handle); ++ image_handle = 0; ++ } ++ + grub_dl_unref (my_mod); + + return grub_errno; diff --git a/0213-powerpc-prefix-detection-support-device-names-with-c.patch b/0213-powerpc-prefix-detection-support-device-names-with-c.patch deleted file mode 100644 index 1c16fd3..0000000 --- a/0213-powerpc-prefix-detection-support-device-names-with-c.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 24 Mar 2022 14:34:32 +1100 -Subject: [PATCH] powerpc: prefix detection: support device names with commas - -Frustratingly, the device name itself can contain an embedded comma: -e.g /pci@800000020000015/pci1014,034A@0/sas/disk@5000c50098a0ee8b - -So my previous approach was wrong: we cannot rely upon the presence -of a comma to say that a partition has been specified! - -It turns out for prefixes like (,gpt2)/grub2 we really want to make -up a full (device,partition)/patch prefix, because root discovery code -in 10_linux will reset the root variable and use search to fill it again. -If you have run grub-install, you probably don't have search built in, -and if you don't have prefix containing (device,partition), grub will -construct ($root)$prefix/powerpc-ieee1275/search.mod - but because $root -has just been changed, this will no longer work, and the boot will fail! - -Retain the gist of the logic, but instead of looking for a comma, look for -a leading '('. This matches the earlier code better anyway. - -There's certainly a better fix to be had. But any time you chose to build -with a bare prefix like '/grub2', you're almost certainly going to build in -search anyway, so this will do. - -Signed-off-by: Daniel Axtens ---- - grub-core/kern/main.c | 27 +++++++++++++++++++++------ - 1 file changed, 21 insertions(+), 6 deletions(-) - -diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index 993b8a8598..e94a2f78fb 100644 ---- a/grub-core/kern/main.c -+++ b/grub-core/kern/main.c -@@ -242,14 +242,29 @@ grub_set_prefix_and_root (void) - what sorts of paths represent disks with partition tables and those - without partition tables. - -- So we act unless there is a comma in the device, which would indicate -- a partition has already been specified. -+ - Frustratingly, the device name itself can contain an embedded comma: -+ /pci@800000020000015/pci1014,034A@0/sas/disk@5000c50098a0ee8b -+ So we cannot even rely upon the presence of a comma to say that a -+ partition has been specified! - -- (If we only have a path, the code in normal to discover config files -- will try both without partitions and then with any partitions so we -- will cover both CDs and HDs.) -+ If we only have a path in $prefix, the code in normal to discover -+ config files will try all disks, both without partitions and then with -+ any partitions so we will cover both CDs and HDs. -+ -+ However, it doesn't then set the prefix to be something like -+ (discovered partition)/path, and so it is fragile against runtime -+ changes to $root. For example some of the stuff done in 10_linux to -+ reload $root sets root differently and then uses search to find it -+ again. If the search module is not built in, when we change root, grub -+ will look in (new root)/path/powerpc-ieee1275, that won't work, and we -+ will not be able to load the search module and the boot will fail. -+ -+ This is particularly likely to hit us in the grub-install -+ (,msdos2)/grub2 case, so we act unless the supplied prefix starts with -+ '(', which would likely indicate a partition has already been -+ specified. - */ -- if (grub_strchr (device, ',') == NULL) -+ if (prefix && prefix[0] != '(') - grub_env_set ("prefix", path); - else - #endif diff --git a/0214-commands-boot-Add-API-to-pass-context-to-loader.patch b/0214-commands-boot-Add-API-to-pass-context-to-loader.patch new file mode 100644 index 0000000..63a2d76 --- /dev/null +++ b/0214-commands-boot-Add-API-to-pass-context-to-loader.patch @@ -0,0 +1,158 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Fri, 29 Apr 2022 21:16:02 +0100 +Subject: [PATCH] commands/boot: Add API to pass context to loader + +Loaders rely on global variables for saving context which is consumed +in the boot hook and freed in the unload hook. In the case where a loader +command is executed twice, calling grub_loader_set a second time executes +the unload hook, but in some cases this runs when the loader's global +context has already been updated, resulting in the updated context being +freed and potential use-after-free bugs when the boot hook is subsequently +called. + +This adds a new API (grub_loader_set_ex) which allows a loader to specify +context that is passed to its boot and unload hooks. This is an alternative +to requiring that loaders call grub_loader_unset before mutating their +global context. + +Signed-off-by: Chris Coulson +(cherry picked from commit 4322a64dde7e8fedb58e50b79408667129d45dd3) +--- + grub-core/commands/boot.c | 66 +++++++++++++++++++++++++++++++++++++++++------ + include/grub/loader.h | 5 ++++ + 2 files changed, 63 insertions(+), 8 deletions(-) + +diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c +index bbca81e947..53691a62d9 100644 +--- a/grub-core/commands/boot.c ++++ b/grub-core/commands/boot.c +@@ -27,10 +27,20 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + +-static grub_err_t (*grub_loader_boot_func) (void); +-static grub_err_t (*grub_loader_unload_func) (void); ++static grub_err_t (*grub_loader_boot_func) (void *); ++static grub_err_t (*grub_loader_unload_func) (void *); ++static void *grub_loader_context; + static int grub_loader_flags; + ++struct grub_simple_loader_hooks ++{ ++ grub_err_t (*boot) (void); ++ grub_err_t (*unload) (void); ++}; ++ ++/* Don't heap allocate this to avoid making grub_loader_set fallible. */ ++static struct grub_simple_loader_hooks simple_loader_hooks; ++ + struct grub_preboot + { + grub_err_t (*preboot_func) (int); +@@ -44,6 +54,29 @@ static int grub_loader_loaded; + static struct grub_preboot *preboots_head = 0, + *preboots_tail = 0; + ++static grub_err_t ++grub_simple_boot_hook (void *context) ++{ ++ struct grub_simple_loader_hooks *hooks; ++ ++ hooks = (struct grub_simple_loader_hooks *) context; ++ return hooks->boot (); ++} ++ ++static grub_err_t ++grub_simple_unload_hook (void *context) ++{ ++ struct grub_simple_loader_hooks *hooks; ++ grub_err_t ret; ++ ++ hooks = (struct grub_simple_loader_hooks *) context; ++ ++ ret = hooks->unload (); ++ grub_memset (hooks, 0, sizeof (*hooks)); ++ ++ return ret; ++} ++ + int + grub_loader_is_loaded (void) + { +@@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd) + } + + void +-grub_loader_set (grub_err_t (*boot) (void), +- grub_err_t (*unload) (void), +- int flags) ++grub_loader_set_ex (grub_err_t (*boot) (void *), ++ grub_err_t (*unload) (void *), ++ void *context, ++ int flags) + { + if (grub_loader_loaded && grub_loader_unload_func) +- grub_loader_unload_func (); ++ grub_loader_unload_func (grub_loader_context); + + grub_loader_boot_func = boot; + grub_loader_unload_func = unload; ++ grub_loader_context = context; + grub_loader_flags = flags; + + grub_loader_loaded = 1; + } + ++void ++grub_loader_set (grub_err_t (*boot) (void), ++ grub_err_t (*unload) (void), ++ int flags) ++{ ++ grub_loader_set_ex (grub_simple_boot_hook, ++ grub_simple_unload_hook, ++ &simple_loader_hooks, ++ flags); ++ ++ simple_loader_hooks.boot = boot; ++ simple_loader_hooks.unload = unload; ++} ++ + void + grub_loader_unset(void) + { + if (grub_loader_loaded && grub_loader_unload_func) +- grub_loader_unload_func (); ++ grub_loader_unload_func (grub_loader_context); + + grub_loader_boot_func = 0; + grub_loader_unload_func = 0; ++ grub_loader_context = 0; + + grub_loader_loaded = 0; + } +@@ -158,7 +208,7 @@ grub_loader_boot (void) + return err; + } + } +- err = (grub_loader_boot_func) (); ++ err = (grub_loader_boot_func) (grub_loader_context); + + for (cur = preboots_tail; cur; cur = cur->prev) + if (! err) +diff --git a/include/grub/loader.h b/include/grub/loader.h +index b208642821..1846fa6c5f 100644 +--- a/include/grub/loader.h ++++ b/include/grub/loader.h +@@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void), + grub_err_t (*unload) (void), + int flags); + ++void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *), ++ grub_err_t (*unload) (void *), ++ void *context, ++ int flags); ++ + /* Unset current loader, if any. */ + void EXPORT_FUNC (grub_loader_unset) (void); + diff --git a/0214-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch b/0214-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch deleted file mode 100644 index 5e3a794..0000000 --- a/0214-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch +++ /dev/null @@ -1,236 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Stefan Berger -Date: Sun, 15 Mar 2020 12:37:10 -0400 -Subject: [PATCH] ibmvtpm: Add support for trusted boot using a vTPM 2.0 - -Add support for trusted boot using a vTPM 2.0 on the IBM IEEE1275 -PowerPC platform. With this patch grub now measures text and binary data -into the TPM's PCRs 8 and 9 in the same way as the x86_64 platform -does. - -This patch requires Daniel Axtens's patches for claiming more memory. - -For vTPM support to work on PowerVM, system driver levels 1010.30 -or 1020.00 are required. - -Note: Previous versions of firmware levels with the 2hash-ext-log -API call have a bug that, once this API call is invoked, has the -effect of disabling the vTPM driver under Linux causing an error -message to be displayed in the Linux kernel log. Those users will -have to update their machines to the firmware levels mentioned -above. - -Cc: Eric Snowberg -Signed-off-by: Stefan Berger ---- - grub-core/Makefile.core.def | 7 ++ - grub-core/commands/ieee1275/ibmvtpm.c | 152 ++++++++++++++++++++++++++++++++++ - include/grub/ieee1275/ieee1275.h | 3 + - docs/grub.texi | 3 +- - 4 files changed, 164 insertions(+), 1 deletion(-) - create mode 100644 grub-core/commands/ieee1275/ibmvtpm.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 741a033978..e038c5e6fd 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -1175,6 +1175,13 @@ module = { - enable = powerpc_ieee1275; - }; - -+module = { -+ name = tpm; -+ common = commands/tpm.c; -+ ieee1275 = commands/ieee1275/ibmvtpm.c; -+ enable = powerpc_ieee1275; -+}; -+ - module = { - name = terminal; - common = commands/terminal.c; -diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c -new file mode 100644 -index 0000000000..e68b8448bc ---- /dev/null -+++ b/grub-core/commands/ieee1275/ibmvtpm.c -@@ -0,0 +1,152 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2021 Free Software Foundation, Inc. -+ * Copyright (C) 2021 IBM Corporation -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ * -+ * IBM vTPM support code. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static grub_ieee1275_ihandle_t tpm_ihandle; -+static grub_uint8_t tpm_version; -+ -+#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t)0) -+ -+static void -+tpm_get_tpm_version (void) -+{ -+ grub_ieee1275_phandle_t vtpm; -+ char buffer[20]; -+ -+ if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) && -+ !grub_ieee1275_get_property (vtpm, "compatible", buffer, -+ sizeof (buffer), NULL) && -+ !grub_strcmp (buffer, "IBM,vtpm20")) -+ tpm_version = 2; -+} -+ -+static grub_err_t -+tpm_init (void) -+{ -+ static int init_success = 0; -+ -+ if (!init_success) -+ { -+ if (grub_ieee1275_open ("/vdevice/vtpm", &tpm_ihandle) < 0) { -+ tpm_ihandle = IEEE1275_IHANDLE_INVALID; -+ return GRUB_ERR_UNKNOWN_DEVICE; -+ } -+ -+ init_success = 1; -+ -+ tpm_get_tpm_version (); -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+static int -+ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex, -+ grub_uint32_t eventtype, -+ const char *description, -+ grub_size_t description_size, -+ void *buf, grub_size_t size) -+{ -+ struct tpm_2hash_ext_log -+ { -+ struct grub_ieee1275_common_hdr common; -+ grub_ieee1275_cell_t method; -+ grub_ieee1275_cell_t ihandle; -+ grub_ieee1275_cell_t size; -+ grub_ieee1275_cell_t buf; -+ grub_ieee1275_cell_t description_size; -+ grub_ieee1275_cell_t description; -+ grub_ieee1275_cell_t eventtype; -+ grub_ieee1275_cell_t pcrindex; -+ grub_ieee1275_cell_t catch_result; -+ grub_ieee1275_cell_t rc; -+ } -+ args; -+ -+ INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2); -+ args.method = (grub_ieee1275_cell_t) "2hash-ext-log"; -+ args.ihandle = tpm_ihandle; -+ args.pcrindex = pcrindex; -+ args.eventtype = eventtype; -+ args.description = (grub_ieee1275_cell_t) description; -+ args.description_size = description_size; -+ args.buf = (grub_ieee1275_cell_t) buf; -+ args.size = (grub_ieee1275_cell_t) size; -+ -+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1) -+ return -1; -+ -+ /* -+ * catch_result is set if firmware does not support 2hash-ext-log -+ * rc is GRUB_IEEE1275_CELL_FALSE (0) on failure -+ */ -+ if ((args.catch_result) || args.rc == GRUB_IEEE1275_CELL_FALSE) -+ return -1; -+ -+ return 0; -+} -+ -+static grub_err_t -+tpm2_log_event (unsigned char *buf, -+ grub_size_t size, grub_uint8_t pcr, -+ const char *description) -+{ -+ static int error_displayed = 0; -+ int err; -+ -+ err = ibmvtpm_2hash_ext_log (pcr, EV_IPL, -+ description, -+ grub_strlen(description) + 1, -+ buf, size); -+ if (err && !error_displayed) -+ { -+ error_displayed++; -+ return grub_error (GRUB_ERR_BAD_DEVICE, -+ "2HASH-EXT-LOG failed: Firmware is likely too old.\n"); -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+grub_err_t -+grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, -+ const char *description) -+{ -+ grub_err_t err = tpm_init(); -+ -+ /* Absence of a TPM isn't a failure. */ -+ if (err != GRUB_ERR_NONE) -+ return GRUB_ERR_NONE; -+ -+ grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n", -+ pcr, size, description); -+ -+ if (tpm_version == 2) -+ return tpm2_log_event (buf, size, pcr, description); -+ -+ return GRUB_ERR_NONE; -+} -diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h -index e0a6c2ce1e..f4c85265fe 100644 ---- a/include/grub/ieee1275/ieee1275.h -+++ b/include/grub/ieee1275/ieee1275.h -@@ -24,6 +24,9 @@ - #include - #include - -+#define GRUB_IEEE1275_CELL_FALSE ((grub_ieee1275_cell_t) 0) -+#define GRUB_IEEE1275_CELL_TRUE ((grub_ieee1275_cell_t) -1) -+ - struct grub_ieee1275_mem_region - { - unsigned int start; -diff --git a/docs/grub.texi b/docs/grub.texi -index a4da9c2a1b..c433240f34 100644 ---- a/docs/grub.texi -+++ b/docs/grub.texi -@@ -6221,7 +6221,8 @@ tpm module is loaded. As such it is recommended that the tpm module be built - into @file{core.img} in order to avoid a potential gap in measurement between - @file{core.img} being loaded and the tpm module being loaded. - --Measured boot is currently only supported on EFI platforms. -+Measured boot is currently only supported on EFI and IBM IEEE1275 PowerPC -+platforms. - - @node Lockdown - @section Lockdown when booting on a secure setup diff --git a/0215-loader-efi-chainloader-Use-grub_loader_set_ex.patch b/0215-loader-efi-chainloader-Use-grub_loader_set_ex.patch new file mode 100644 index 0000000..fc15b84 --- /dev/null +++ b/0215-loader-efi-chainloader-Use-grub_loader_set_ex.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Fri, 29 Apr 2022 21:30:56 +0100 +Subject: [PATCH] loader/efi/chainloader: Use grub_loader_set_ex + +This ports the EFI chainloader to use grub_loader_set_ex in order to fix +a use-after-free bug that occurs when grub_cmd_chainloader is executed +more than once before a boot attempt is performed. + +Signed-off-by: Chris Coulson +(cherry picked from commit 4b7f0402b7cb0f67a93be736f2b75b818d7f44c9) +[rharwood: context sludge from other change] +Signed-off-by: Robbie Harwood +--- + grub-core/loader/efi/chainloader.c | 38 ++++++++++++++++++++++---------------- + 1 file changed, 22 insertions(+), 16 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 3342492ff1..fb874f1855 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -48,8 +48,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_dl_t my_mod; + +-static grub_efi_handle_t image_handle; +- + struct grub_secureboot_chainloader_context { + grub_efi_physical_address_t address; + grub_efi_uintn_t pages; +@@ -59,7 +57,6 @@ struct grub_secureboot_chainloader_context { + grub_ssize_t cmdline_len; + grub_efi_handle_t dev_handle; + }; +-static struct grub_secureboot_chainloader_context *sb_context; + + static grub_err_t + grub_start_image (grub_efi_handle_t handle) +@@ -98,11 +95,14 @@ grub_start_image (grub_efi_handle_t handle) + } + + static grub_err_t +-grub_chainloader_unload (void) ++grub_chainloader_unload (void *context) + { ++ grub_efi_handle_t image_handle; + grub_efi_loaded_image_t *loaded_image; + grub_efi_boot_services_t *b; + ++ image_handle = (grub_efi_handle_t) context; ++ + loaded_image = grub_efi_get_loaded_image (image_handle); + if (loaded_image != NULL) + grub_free (loaded_image->load_options); +@@ -115,10 +115,12 @@ grub_chainloader_unload (void) + } + + static grub_err_t +-grub_chainloader_boot (void) ++grub_chainloader_boot (void *context) + { ++ grub_efi_handle_t image_handle; + grub_err_t err; + ++ image_handle = (grub_efi_handle_t) context; + err = grub_start_image (image_handle); + + grub_loader_unset (); +@@ -839,15 +841,17 @@ error_exit: + } + + static grub_err_t +-grub_secureboot_chainloader_unload (void) ++grub_secureboot_chainloader_unload (void *context) + { ++ struct grub_secureboot_chainloader_context *sb_context; ++ ++ sb_context = (struct grub_secureboot_chainloader_context *) context; ++ + grub_efi_free_pages (sb_context->address, sb_context->pages); + grub_free (sb_context->file_path); + grub_free (sb_context->cmdline); + grub_free (sb_context); + +- sb_context = 0; +- + grub_dl_unref (my_mod); + return GRUB_ERR_NONE; + } +@@ -896,12 +900,15 @@ grub_load_image(grub_efi_device_path_t *file_path, void *boot_image, + } + + static grub_err_t +-grub_secureboot_chainloader_boot (void) ++grub_secureboot_chainloader_boot (void *context) + { ++ struct grub_secureboot_chainloader_context *sb_context; + grub_efi_boot_services_t *b; + int rc; + grub_efi_handle_t handle = 0; + ++ sb_context = (struct grub_secureboot_chainloader_context *) context; ++ + rc = handle_image (sb_context); + if (rc == 0) + { +@@ -942,6 +949,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_efi_char16_t *cmdline = 0; + grub_ssize_t cmdline_len = 0; + grub_efi_handle_t dev_handle = 0; ++ grub_efi_handle_t image_handle = 0; ++ struct grub_secureboot_chainloader_context *sb_context = 0; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -1127,8 +1136,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_file_close (file); + grub_device_close (dev); + +- grub_loader_set (grub_secureboot_chainloader_boot, +- grub_secureboot_chainloader_unload, 0); ++ grub_loader_set_ex (grub_secureboot_chainloader_boot, ++ grub_secureboot_chainloader_unload, sb_context, 0); + return 0; + } + else +@@ -1142,7 +1151,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + efi_call_2 (b->free_pages, address, pages); + grub_free (file_path); + +- grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); ++ grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0); + + return 0; + } +@@ -1169,10 +1178,7 @@ fail: + grub_free (cmdline); + + if (image_handle != 0) +- { +- efi_call_1 (b->unload_image, image_handle); +- image_handle = 0; +- } ++ efi_call_1 (b->unload_image, image_handle); + + grub_dl_unref (my_mod); + diff --git a/0215-make-ofdisk_retries-optional.patch b/0215-make-ofdisk_retries-optional.patch deleted file mode 100644 index fce9702..0000000 --- a/0215-make-ofdisk_retries-optional.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Diego Domingos -Date: Thu, 24 Mar 2022 13:14:42 -0400 -Subject: [PATCH] make ofdisk_retries optional - -The feature Retry on Fail added to GRUB can cause a LPM to take -longer if the SAN is slow. - -When a LPM to external site occur, the path of the disk can change -and thus the disk search function on grub can take some time since -it is used as a hint. This can cause the Retry on Fail feature to -try to access the disk 20x times (since this is hardcoded number) -and, if the SAN is slow, the boot time can increase a lot. -In some situations not acceptable. - -The following patch enables a configuration at user space of the -maximum number of retries we want for this feature. - -The variable ofdisk_retries should be set using grub2-editenv -and will be checked by retry function. If the variable is not set, -so the default number of retries will be used instead. ---- - include/grub/ieee1275/ofdisk.h | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h -index 7d2d540930..0074d55eee 100644 ---- a/include/grub/ieee1275/ofdisk.h -+++ b/include/grub/ieee1275/ofdisk.h -@@ -25,7 +25,12 @@ extern void grub_ofdisk_fini (void); - #define MAX_RETRIES 20 - - --#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) unsigned retry_i=0;for(retry_i=0; retry_i < MAX_RETRIES; retry_i++){ \ -+#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) \ -+ unsigned max_retries = MAX_RETRIES; \ -+ if(grub_env_get("ofdisk_retries") != NULL) \ -+ max_retries = grub_strtoul(grub_env_get("ofdisk_retries"), 0, 10)+1; \ -+ grub_dprintf("ofdisk","MAX_RETRIES set to %u\n",max_retries); \ -+ unsigned retry_i=0;for(retry_i=0; retry_i < max_retries; retry_i++){ \ - if(!grub_ieee1275_open(device, last_ihandle)) \ - break; \ - grub_dprintf("ofdisk","Opening disk %s failed. Retrying...\n",device); } diff --git a/0216-loader-efi-chainloader-grub_load_and_start_image-doe.patch b/0216-loader-efi-chainloader-grub_load_and_start_image-doe.patch deleted file mode 100644 index f61ed28..0000000 --- a/0216-loader-efi-chainloader-grub_load_and_start_image-doe.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Thu, 28 Apr 2022 21:53:36 +0100 -Subject: [PATCH] loader/efi/chainloader: grub_load_and_start_image doesn't - load and start - -grub_load_and_start_image only loads an image - it still requires the -caller to start it. This renames it to grub_load_image. - -It's called from 2 places: -- grub_cmd_chainloader when not using the shim protocol. -- grub_secureboot_chainloader_boot if handle_image returns an error. -In this case, the image is loaded and then nothing else happens which -seems strange. I assume the intention is that it falls back to LoadImage -and StartImage if handle_image fails, so I've made it do that. - -Signed-off-by: Chris Coulson -(cherry picked from commit b4d70820a65c00561045856b7b8355461a9545f6) ---- - grub-core/loader/efi/chainloader.c | 16 +++++++++++++--- - 1 file changed, 13 insertions(+), 3 deletions(-) - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 644cd2e56f..d3bf02ed8a 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -841,7 +841,7 @@ grub_secureboot_chainloader_unload (void) - } - - static grub_err_t --grub_load_and_start_image(void *boot_image) -+grub_load_image(void *boot_image) - { - grub_efi_boot_services_t *b; - grub_efi_status_t status; -@@ -883,13 +883,23 @@ grub_load_and_start_image(void *boot_image) - static grub_err_t - grub_secureboot_chainloader_boot (void) - { -+ grub_efi_boot_services_t *b; - int rc; -+ - rc = handle_image ((void *)(unsigned long)address, fsize); - if (rc == 0) - { -- grub_load_and_start_image((void *)(unsigned long)address); -+ /* We weren't able to attempt to execute the image, so fall back -+ * to LoadImage / StartImage. -+ */ -+ rc = grub_load_image((void *)(unsigned long)address); -+ if (rc == 0) -+ grub_chainloader_boot (); - } - -+ b = grub_efi_system_table->boot_services; -+ efi_call_1 (b->unload_image, image_handle); -+ - grub_loader_unset (); - return grub_errno; - } -@@ -1091,7 +1101,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - } - else - { -- grub_load_and_start_image(boot_image); -+ grub_load_image(boot_image); - grub_file_close (file); - grub_device_close (dev); - grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); diff --git a/0216-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch b/0216-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch new file mode 100644 index 0000000..b79c78c --- /dev/null +++ b/0216-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Mon, 2 May 2022 14:39:31 +0200 +Subject: [PATCH] loader/i386/efi/linux: Avoid a use-after-free in the linuxefi + loader + +In some error paths in grub_cmd_linux, the pointer to lh may be +dereferenced after the buffer it points to has been freed. There aren't +any security implications from this because nothing else uses the +allocator after the buffer is freed and before the pointer is +dereferenced, but fix it anyway. + +Signed-off-by: Chris Coulson +(cherry picked from commit 8224f5a71af94bec8697de17e7e579792db9f9e2) +--- + grub-core/loader/i386/efi/linux.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 941df6400b..27bc2aa161 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -465,9 +465,6 @@ fail: + if (file) + grub_file_close (file); + +- if (kernel) +- grub_free (kernel); +- + if (grub_errno != GRUB_ERR_NONE) + { + grub_dl_unref (my_mod); +@@ -483,6 +480,8 @@ fail: + kernel_free (params, sizeof(*params)); + } + ++ grub_free (kernel); ++ + return grub_errno; + } + diff --git a/0217-loader-efi-chainloader-simplify-the-loader-state.patch b/0217-loader-efi-chainloader-simplify-the-loader-state.patch deleted file mode 100644 index 205124e..0000000 --- a/0217-loader-efi-chainloader-simplify-the-loader-state.patch +++ /dev/null @@ -1,330 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Fri, 29 Apr 2022 21:13:08 +0100 -Subject: [PATCH] loader/efi/chainloader: simplify the loader state - -When not using the shim lock protocol, the chainloader command retains -the source buffer and device path passed to LoadImage, requiring the -unload hook passed to grub_loader_set to free them. It isn't required -to retain this state though - they aren't required by StartImage or -anything else in the boot hook, so clean them up before -grub_cmd_chainloader finishes. - -This also wraps the loader state when using the shim lock protocol -inside a struct. - -Signed-off-by: Chris Coulson -(cherry picked from commit fa39862933b3be1553a580a3a5c28073257d8046) -[rharwood: fix unitialized handle and double-frees of file/dev] -Signed-off-by: Robbie Harwood ---- - grub-core/loader/efi/chainloader.c | 160 +++++++++++++++++++++++-------------- - 1 file changed, 102 insertions(+), 58 deletions(-) - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index d3bf02ed8a..3342492ff1 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -48,38 +48,21 @@ GRUB_MOD_LICENSE ("GPLv3+"); - - static grub_dl_t my_mod; - --static grub_efi_physical_address_t address; --static grub_efi_uintn_t pages; --static grub_ssize_t fsize; --static grub_efi_device_path_t *file_path; - static grub_efi_handle_t image_handle; --static grub_efi_char16_t *cmdline; --static grub_ssize_t cmdline_len; --static grub_efi_handle_t dev_handle; - --static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); -+struct grub_secureboot_chainloader_context { -+ grub_efi_physical_address_t address; -+ grub_efi_uintn_t pages; -+ grub_ssize_t fsize; -+ grub_efi_device_path_t *file_path; -+ grub_efi_char16_t *cmdline; -+ grub_ssize_t cmdline_len; -+ grub_efi_handle_t dev_handle; -+}; -+static struct grub_secureboot_chainloader_context *sb_context; - - static grub_err_t --grub_chainloader_unload (void) --{ -- grub_efi_boot_services_t *b; -- -- b = grub_efi_system_table->boot_services; -- efi_call_1 (b->unload_image, image_handle); -- grub_efi_free_pages (address, pages); -- -- grub_free (file_path); -- grub_free (cmdline); -- cmdline = 0; -- file_path = 0; -- dev_handle = 0; -- -- grub_dl_unref (my_mod); -- return GRUB_ERR_NONE; --} -- --static grub_err_t --grub_chainloader_boot (void) -+grub_start_image (grub_efi_handle_t handle) - { - grub_efi_boot_services_t *b; - grub_efi_status_t status; -@@ -87,7 +70,7 @@ grub_chainloader_boot (void) - grub_efi_char16_t *exit_data = NULL; - - b = grub_efi_system_table->boot_services; -- status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data); -+ status = efi_call_3 (b->start_image, handle, &exit_data_size, &exit_data); - if (status != GRUB_EFI_SUCCESS) - { - if (exit_data) -@@ -111,11 +94,37 @@ grub_chainloader_boot (void) - if (exit_data) - grub_efi_free_pool (exit_data); - -- grub_loader_unset (); -- - return grub_errno; - } - -+static grub_err_t -+grub_chainloader_unload (void) -+{ -+ grub_efi_loaded_image_t *loaded_image; -+ grub_efi_boot_services_t *b; -+ -+ loaded_image = grub_efi_get_loaded_image (image_handle); -+ if (loaded_image != NULL) -+ grub_free (loaded_image->load_options); -+ -+ b = grub_efi_system_table->boot_services; -+ efi_call_1 (b->unload_image, image_handle); -+ -+ grub_dl_unref (my_mod); -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_chainloader_boot (void) -+{ -+ grub_err_t err; -+ -+ err = grub_start_image (image_handle); -+ -+ grub_loader_unset (); -+ return err; -+} -+ - static grub_err_t - copy_file_path (grub_efi_file_path_device_path_t *fp, - const char *str, grub_efi_uint16_t len) -@@ -150,7 +159,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) - char *dir_start; - char *dir_end; - grub_size_t size; -- grub_efi_device_path_t *d; -+ grub_efi_device_path_t *d, *file_path; - - dir_start = grub_strchr (filename, ')'); - if (! dir_start) -@@ -526,10 +535,12 @@ grub_efi_get_media_file_path (grub_efi_device_path_t *dp) - } - - static grub_efi_boolean_t --handle_image (void *data, grub_efi_uint32_t datasize) -+handle_image (struct grub_secureboot_chainloader_context *load_context) - { - grub_efi_loaded_image_t *li, li_bak; - grub_efi_status_t efi_status; -+ void *data = (void *)(unsigned long)load_context->address; -+ grub_efi_uint32_t datasize = load_context->fsize; - void *buffer = NULL; - char *buffer_aligned = NULL; - grub_efi_uint32_t i; -@@ -540,6 +551,7 @@ handle_image (void *data, grub_efi_uint32_t datasize) - grub_uint32_t buffer_size; - int found_entry_point = 0; - int rc; -+ grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); - - rc = read_header (data, datasize, &context); - if (rc < 0) -@@ -797,10 +809,10 @@ handle_image (void *data, grub_efi_uint32_t datasize) - grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t)); - li->image_base = buffer_aligned; - li->image_size = context.image_size; -- li->load_options = cmdline; -- li->load_options_size = cmdline_len; -- li->file_path = grub_efi_get_media_file_path (file_path); -- li->device_handle = dev_handle; -+ li->load_options = load_context->cmdline; -+ li->load_options_size = load_context->cmdline_len; -+ li->file_path = grub_efi_get_media_file_path (load_context->file_path); -+ li->device_handle = load_context->dev_handle; - if (!li->file_path) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found"); -@@ -829,19 +841,22 @@ error_exit: - static grub_err_t - grub_secureboot_chainloader_unload (void) - { -- grub_efi_free_pages (address, pages); -- grub_free (file_path); -- grub_free (cmdline); -- cmdline = 0; -- file_path = 0; -- dev_handle = 0; -+ grub_efi_free_pages (sb_context->address, sb_context->pages); -+ grub_free (sb_context->file_path); -+ grub_free (sb_context->cmdline); -+ grub_free (sb_context); -+ -+ sb_context = 0; - - grub_dl_unref (my_mod); - return GRUB_ERR_NONE; - } - - static grub_err_t --grub_load_image(void *boot_image) -+grub_load_image(grub_efi_device_path_t *file_path, void *boot_image, -+ grub_efi_uintn_t image_size, grub_efi_handle_t dev_handle, -+ grub_efi_char16_t *cmdline, grub_ssize_t cmdline_len, -+ grub_efi_handle_t *image_handle_out) - { - grub_efi_boot_services_t *b; - grub_efi_status_t status; -@@ -850,7 +865,7 @@ grub_load_image(void *boot_image) - b = grub_efi_system_table->boot_services; - - status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, -- boot_image, fsize, &image_handle); -+ boot_image, image_size, image_handle_out); - if (status != GRUB_EFI_SUCCESS) - { - if (status == GRUB_EFI_OUT_OF_RESOURCES) -@@ -863,7 +878,7 @@ grub_load_image(void *boot_image) - /* LoadImage does not set a device handler when the image is - loaded from memory, so it is necessary to set it explicitly here. - This is a mess. */ -- loaded_image = grub_efi_get_loaded_image (image_handle); -+ loaded_image = grub_efi_get_loaded_image (*image_handle_out); - if (! loaded_image) - { - grub_error (GRUB_ERR_BAD_OS, "no loaded image available"); -@@ -885,20 +900,25 @@ grub_secureboot_chainloader_boot (void) - { - grub_efi_boot_services_t *b; - int rc; -+ grub_efi_handle_t handle = 0; - -- rc = handle_image ((void *)(unsigned long)address, fsize); -+ rc = handle_image (sb_context); - if (rc == 0) - { - /* We weren't able to attempt to execute the image, so fall back - * to LoadImage / StartImage. - */ -- rc = grub_load_image((void *)(unsigned long)address); -+ rc = grub_load_image(sb_context->file_path, -+ (void *)(unsigned long)sb_context->address, -+ sb_context->fsize, sb_context->dev_handle, -+ sb_context->cmdline, sb_context->cmdline_len, -+ &handle); - if (rc == 0) -- grub_chainloader_boot (); -+ grub_start_image (handle); - } - - b = grub_efi_system_table->boot_services; -- efi_call_1 (b->unload_image, image_handle); -+ efi_call_1 (b->unload_image, handle); - - grub_loader_unset (); - return grub_errno; -@@ -913,9 +933,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_efi_boot_services_t *b; - grub_device_t dev = 0; - grub_device_t orig_dev = 0; -- grub_efi_device_path_t *dp = 0; -+ grub_efi_device_path_t *dp = 0, *file_path = 0; - char *filename; - void *boot_image = 0; -+ grub_efi_physical_address_t address = 0; -+ grub_ssize_t fsize; -+ grub_efi_uintn_t pages = 0; -+ grub_efi_char16_t *cmdline = 0; -+ grub_ssize_t cmdline_len = 0; -+ grub_efi_handle_t dev_handle = 0; - - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -@@ -923,12 +949,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - - grub_dl_ref (my_mod); - -- /* Initialize some global variables. */ -- address = 0; -- image_handle = 0; -- file_path = 0; -- dev_handle = 0; -- - b = grub_efi_system_table->boot_services; - - if (argc > 1) -@@ -1093,17 +1113,35 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - - if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) - { -+ sb_context = grub_malloc (sizeof (*sb_context)); -+ if (sb_context == NULL) -+ goto fail; -+ sb_context->address = address; -+ sb_context->fsize = fsize; -+ sb_context->pages = pages; -+ sb_context->file_path = file_path; -+ sb_context->cmdline = cmdline; -+ sb_context->cmdline_len = cmdline_len; -+ sb_context->dev_handle = dev_handle; -+ - grub_file_close (file); - grub_device_close (dev); -+ - grub_loader_set (grub_secureboot_chainloader_boot, - grub_secureboot_chainloader_unload, 0); - return 0; - } - else - { -- grub_load_image(boot_image); -+ grub_load_image(file_path, boot_image, fsize, dev_handle, cmdline, -+ cmdline_len, &image_handle); - grub_file_close (file); - grub_device_close (dev); -+ -+ /* We're finished with the source image buffer and file path now */ -+ efi_call_2 (b->free_pages, address, pages); -+ grub_free (file_path); -+ - grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); - - return 0; -@@ -1130,6 +1168,12 @@ fail: - if (cmdline) - grub_free (cmdline); - -+ if (image_handle != 0) -+ { -+ efi_call_1 (b->unload_image, image_handle); -+ image_handle = 0; -+ } -+ - grub_dl_unref (my_mod); - - return grub_errno; diff --git a/0217-loader-i386-efi-linux-Use-grub_loader_set_ex.patch b/0217-loader-i386-efi-linux-Use-grub_loader_set_ex.patch new file mode 100644 index 0000000..1a129db --- /dev/null +++ b/0217-loader-i386-efi-linux-Use-grub_loader_set_ex.patch @@ -0,0 +1,296 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Mon, 2 May 2022 17:04:23 +0200 +Subject: [PATCH] loader/i386/efi/linux: Use grub_loader_set_ex + +This ports the linuxefi loader to use grub_loader_set_ex in order to fix +a use-after-fre bug that occurs when grub_cmd_linux is executed more than +once before a boot attempt is performed. + +This is more complicated than for the chainloader command, as the initrd +command needs access to the loader state. To solve this, the linuxefi +module registers a dummy initrd command at startup that returns an error. +The linuxefi command then registers a proper initrd command with a higher +priority that is passed the loader state. + +Signed-off-by: Chris Coulson +(cherry picked from commit 7cf736436b4c934df5ddfa6f44b46a7e07d99fdc) +[rharwood/pjones: set kernel_size in context] +Signed-off-by: Robbie Harwood +--- + grub-core/loader/i386/efi/linux.c | 146 +++++++++++++++++++++++--------------- + 1 file changed, 87 insertions(+), 59 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 27bc2aa161..e3c2d6fe0b 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -34,13 +34,19 @@ + GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_dl_t my_mod; +-static int loaded; +-static void *kernel_mem; +-static grub_uint64_t kernel_size; +-static void *initrd_mem; +-static grub_uint32_t handover_offset; +-struct linux_kernel_params *params; +-static char *linux_cmdline; ++ ++static grub_command_t cmd_linux, cmd_initrd; ++static grub_command_t cmd_linuxefi, cmd_initrdefi; ++ ++struct grub_linuxefi_context { ++ void *kernel_mem; ++ grub_uint64_t kernel_size; ++ grub_uint32_t handover_offset; ++ struct linux_kernel_params *params; ++ char *cmdline; ++ ++ void *initrd_mem; ++}; + + #define MIN(a, b) \ + ({ typeof (a) _a = (a); \ +@@ -123,25 +129,32 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) + } + + static grub_err_t +-grub_linuxefi_boot (void) ++grub_linuxefi_boot (void *data) + { ++ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data; ++ + asm volatile ("cli"); + +- return grub_efi_linux_boot ((char *)kernel_mem, +- handover_offset, +- params); ++ return grub_efi_linux_boot ((char *)context->kernel_mem, ++ context->handover_offset, ++ context->params); + } + + static grub_err_t +-grub_linuxefi_unload (void) ++grub_linuxefi_unload (void *data) + { ++ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data; ++ struct linux_kernel_params *params = context->params; ++ + grub_dl_unref (my_mod); +- loaded = 0; + +- kernel_free(initrd_mem, params->ramdisk_size); +- kernel_free(linux_cmdline, params->cmdline_size + 1); +- kernel_free(kernel_mem, kernel_size); +- kernel_free(params, sizeof(*params)); ++ kernel_free (context->initrd_mem, params->ramdisk_size); ++ kernel_free (context->cmdline, params->cmdline_size + 1); ++ kernel_free (context->kernel_mem, context->kernel_size); ++ kernel_free (params, sizeof(*params)); ++ cmd_initrd->data = 0; ++ cmd_initrdefi->data = 0; ++ grub_free (context); + + return GRUB_ERR_NONE; + } +@@ -188,13 +201,14 @@ read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) + #define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull)) + + static grub_err_t +-grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), +- int argc, char *argv[]) ++grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + { + grub_file_t *files = 0; + int i, nfiles = 0; + grub_size_t size = 0; + grub_uint8_t *ptr; ++ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data; ++ struct linux_kernel_params *params; + + if (argc == 0) + { +@@ -202,12 +216,14 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- if (!loaded) ++ if (!context) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); + goto fail; + } + ++ params = context->params; ++ + files = grub_calloc (argc, sizeof (files[0])); + if (!files) + goto fail; +@@ -225,19 +241,19 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + } + } + +- initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); +- if (initrd_mem == NULL) ++ context->initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); ++ if (context->initrd_mem == NULL) + goto fail; +- grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); ++ grub_dprintf ("linux", "initrd_mem = %p\n", context->initrd_mem); + + params->ramdisk_size = LOW_U32(size); +- params->ramdisk_image = LOW_U32(initrd_mem); ++ params->ramdisk_image = LOW_U32(context->initrd_mem); + #if defined(__x86_64__) + params->ext_ramdisk_size = HIGH_U32(size); +- params->ext_ramdisk_image = HIGH_U32(initrd_mem); ++ params->ext_ramdisk_image = HIGH_U32(context->initrd_mem); + #endif + +- ptr = initrd_mem; ++ ptr = context->initrd_mem; + + for (i = 0; i < nfiles; i++) + { +@@ -261,8 +277,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + grub_file_close (files[i]); + grub_free (files); + +- if (initrd_mem && grub_errno) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, ++ if (context->initrd_mem && grub_errno) ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem, + BYTES_TO_PAGES(size)); + + return grub_errno; +@@ -277,6 +293,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_ssize_t start, filelen; + void *kernel = NULL; + int setup_header_end_offset; ++ void *kernel_mem = 0; ++ grub_uint64_t kernel_size = 0; ++ grub_uint32_t handover_offset; ++ struct linux_kernel_params *params = 0; ++ char *cmdline = 0; ++ struct grub_linuxefi_context *context = 0; + + grub_dl_ref (my_mod); + +@@ -390,27 +412,27 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "new lh is at %p\n", lh); + + grub_dprintf ("linux", "setting up cmdline\n"); +- linux_cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); +- if (!linux_cmdline) ++ cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); ++ if (!cmdline) + goto fail; +- grub_dprintf ("linux", "linux_cmdline = %p\n", linux_cmdline); ++ grub_dprintf ("linux", "cmdline = %p\n", cmdline); + +- grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); ++ grub_memcpy (cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); + grub_create_loader_cmdline (argc, argv, +- linux_cmdline + sizeof (LINUX_IMAGE) - 1, ++ cmdline + sizeof (LINUX_IMAGE) - 1, + lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1), + GRUB_VERIFY_KERNEL_CMDLINE); + +- grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline); ++ grub_dprintf ("linux", "cmdline:%s\n", cmdline); + grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n", +- LOW_U32(linux_cmdline)); +- lh->cmd_line_ptr = LOW_U32(linux_cmdline); ++ LOW_U32(cmdline)); ++ lh->cmd_line_ptr = LOW_U32(cmdline); + #if defined(__x86_64__) +- if ((grub_efi_uintn_t)linux_cmdline > 0xffffffffull) ++ if ((grub_efi_uintn_t)cmdline > 0xffffffffull) + { + grub_dprintf ("linux", "setting params->ext_cmd_line_ptr to 0x%08x\n", +- HIGH_U32(linux_cmdline)); +- params->ext_cmd_line_ptr = HIGH_U32(linux_cmdline); ++ HIGH_U32(cmdline)); ++ params->ext_cmd_line_ptr = HIGH_U32(cmdline); + } + #endif + +@@ -435,16 +457,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; +- kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel")); ++ kernel_size = lh->init_size; ++ kernel_mem = kernel_alloc (kernel_size, N_("can't allocate kernel")); + restore_addresses(); + if (!kernel_mem) + goto fail; + grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem); + +- grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); +- +- loaded = 1; +- + grub_dprintf ("linux", "setting lh->code32_start to 0x%08x\n", + LOW_U32(kernel_mem)); + lh->code32_start = LOW_U32(kernel_mem); +@@ -461,33 +480,42 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + "setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n", + params->ext_loader_type, params->ext_loader_ver); + ++ context = grub_zalloc (sizeof (*context)); ++ if (!context) ++ goto fail; ++ context->kernel_mem = kernel_mem; ++ context->kernel_size = kernel_size; ++ context->handover_offset = handover_offset; ++ context->params = params; ++ context->cmdline = cmdline; ++ ++ grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0); ++ ++ cmd_initrd->data = context; ++ cmd_initrdefi->data = context; ++ ++ grub_file_close (file); ++ grub_free (kernel); ++ return 0; ++ + fail: + if (file) + grub_file_close (file); + +- if (grub_errno != GRUB_ERR_NONE) +- { +- grub_dl_unref (my_mod); +- loaded = 0; +- } ++ grub_dl_unref (my_mod); + +- if (!loaded) +- { +- if (lh) +- kernel_free (linux_cmdline, lh->cmdline_size + 1); ++ if (lh) ++ kernel_free (cmdline, lh->cmdline_size + 1); + +- kernel_free (kernel_mem, kernel_size); +- kernel_free (params, sizeof(*params)); +- } ++ kernel_free (kernel_mem, kernel_size); ++ kernel_free (params, sizeof(*params)); + ++ grub_free (context); + grub_free (kernel); + + return grub_errno; + } + +-static grub_command_t cmd_linux, cmd_initrd; +-static grub_command_t cmd_linuxefi, cmd_initrdefi; +- + GRUB_MOD_INIT(linux) + { + cmd_linux = diff --git a/0218-commands-boot-Add-API-to-pass-context-to-loader.patch b/0218-commands-boot-Add-API-to-pass-context-to-loader.patch deleted file mode 100644 index 63a2d76..0000000 --- a/0218-commands-boot-Add-API-to-pass-context-to-loader.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Fri, 29 Apr 2022 21:16:02 +0100 -Subject: [PATCH] commands/boot: Add API to pass context to loader - -Loaders rely on global variables for saving context which is consumed -in the boot hook and freed in the unload hook. In the case where a loader -command is executed twice, calling grub_loader_set a second time executes -the unload hook, but in some cases this runs when the loader's global -context has already been updated, resulting in the updated context being -freed and potential use-after-free bugs when the boot hook is subsequently -called. - -This adds a new API (grub_loader_set_ex) which allows a loader to specify -context that is passed to its boot and unload hooks. This is an alternative -to requiring that loaders call grub_loader_unset before mutating their -global context. - -Signed-off-by: Chris Coulson -(cherry picked from commit 4322a64dde7e8fedb58e50b79408667129d45dd3) ---- - grub-core/commands/boot.c | 66 +++++++++++++++++++++++++++++++++++++++++------ - include/grub/loader.h | 5 ++++ - 2 files changed, 63 insertions(+), 8 deletions(-) - -diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c -index bbca81e947..53691a62d9 100644 ---- a/grub-core/commands/boot.c -+++ b/grub-core/commands/boot.c -@@ -27,10 +27,20 @@ - - GRUB_MOD_LICENSE ("GPLv3+"); - --static grub_err_t (*grub_loader_boot_func) (void); --static grub_err_t (*grub_loader_unload_func) (void); -+static grub_err_t (*grub_loader_boot_func) (void *); -+static grub_err_t (*grub_loader_unload_func) (void *); -+static void *grub_loader_context; - static int grub_loader_flags; - -+struct grub_simple_loader_hooks -+{ -+ grub_err_t (*boot) (void); -+ grub_err_t (*unload) (void); -+}; -+ -+/* Don't heap allocate this to avoid making grub_loader_set fallible. */ -+static struct grub_simple_loader_hooks simple_loader_hooks; -+ - struct grub_preboot - { - grub_err_t (*preboot_func) (int); -@@ -44,6 +54,29 @@ static int grub_loader_loaded; - static struct grub_preboot *preboots_head = 0, - *preboots_tail = 0; - -+static grub_err_t -+grub_simple_boot_hook (void *context) -+{ -+ struct grub_simple_loader_hooks *hooks; -+ -+ hooks = (struct grub_simple_loader_hooks *) context; -+ return hooks->boot (); -+} -+ -+static grub_err_t -+grub_simple_unload_hook (void *context) -+{ -+ struct grub_simple_loader_hooks *hooks; -+ grub_err_t ret; -+ -+ hooks = (struct grub_simple_loader_hooks *) context; -+ -+ ret = hooks->unload (); -+ grub_memset (hooks, 0, sizeof (*hooks)); -+ -+ return ret; -+} -+ - int - grub_loader_is_loaded (void) - { -@@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd) - } - - void --grub_loader_set (grub_err_t (*boot) (void), -- grub_err_t (*unload) (void), -- int flags) -+grub_loader_set_ex (grub_err_t (*boot) (void *), -+ grub_err_t (*unload) (void *), -+ void *context, -+ int flags) - { - if (grub_loader_loaded && grub_loader_unload_func) -- grub_loader_unload_func (); -+ grub_loader_unload_func (grub_loader_context); - - grub_loader_boot_func = boot; - grub_loader_unload_func = unload; -+ grub_loader_context = context; - grub_loader_flags = flags; - - grub_loader_loaded = 1; - } - -+void -+grub_loader_set (grub_err_t (*boot) (void), -+ grub_err_t (*unload) (void), -+ int flags) -+{ -+ grub_loader_set_ex (grub_simple_boot_hook, -+ grub_simple_unload_hook, -+ &simple_loader_hooks, -+ flags); -+ -+ simple_loader_hooks.boot = boot; -+ simple_loader_hooks.unload = unload; -+} -+ - void - grub_loader_unset(void) - { - if (grub_loader_loaded && grub_loader_unload_func) -- grub_loader_unload_func (); -+ grub_loader_unload_func (grub_loader_context); - - grub_loader_boot_func = 0; - grub_loader_unload_func = 0; -+ grub_loader_context = 0; - - grub_loader_loaded = 0; - } -@@ -158,7 +208,7 @@ grub_loader_boot (void) - return err; - } - } -- err = (grub_loader_boot_func) (); -+ err = (grub_loader_boot_func) (grub_loader_context); - - for (cur = preboots_tail; cur; cur = cur->prev) - if (! err) -diff --git a/include/grub/loader.h b/include/grub/loader.h -index b208642821..1846fa6c5f 100644 ---- a/include/grub/loader.h -+++ b/include/grub/loader.h -@@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void), - grub_err_t (*unload) (void), - int flags); - -+void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *), -+ grub_err_t (*unload) (void *), -+ void *context, -+ int flags); -+ - /* Unset current loader, if any. */ - void EXPORT_FUNC (grub_loader_unset) (void); - diff --git a/0218-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch b/0218-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch new file mode 100644 index 0000000..51953fd --- /dev/null +++ b/0218-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Tue, 3 May 2022 09:47:35 +0200 +Subject: [PATCH] loader/i386/efi/linux: Fix a memory leak in the initrd + command + +Subsequent invocations of the initrd command result in the previous +initrd being leaked, so fix that. + +Signed-off-by: Chris Coulson +(cherry picked from commit d98af31ce1e31bb22163960d53f5eb28c66582a0) +--- + grub-core/loader/i386/efi/linux.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index e3c2d6fe0b..9e5c11ac69 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -209,6 +209,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + grub_uint8_t *ptr; + struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data; + struct linux_kernel_params *params; ++ void *initrd_mem = 0; + + if (argc == 0) + { +@@ -241,19 +242,19 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + } + } + +- context->initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); +- if (context->initrd_mem == NULL) ++ initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); ++ if (initrd_mem == NULL) + goto fail; +- grub_dprintf ("linux", "initrd_mem = %p\n", context->initrd_mem); ++ grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); + + params->ramdisk_size = LOW_U32(size); +- params->ramdisk_image = LOW_U32(context->initrd_mem); ++ params->ramdisk_image = LOW_U32(initrd_mem); + #if defined(__x86_64__) + params->ext_ramdisk_size = HIGH_U32(size); +- params->ext_ramdisk_image = HIGH_U32(context->initrd_mem); ++ params->ext_ramdisk_image = HIGH_U32(initrd_mem); + #endif + +- ptr = context->initrd_mem; ++ ptr = initrd_mem; + + for (i = 0; i < nfiles; i++) + { +@@ -270,6 +271,9 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + ptr += ALIGN_UP_OVERHEAD (cursize, 4); + } + ++ kernel_free(context->initrd_mem, params->ramdisk_size); ++ ++ context->initrd_mem = initrd_mem; + params->ramdisk_size = size; + + fail: +@@ -277,9 +281,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + grub_file_close (files[i]); + grub_free (files); + +- if (context->initrd_mem && grub_errno) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem, +- BYTES_TO_PAGES(size)); ++ if (initrd_mem && grub_errno) ++ kernel_free (initrd_mem, size); + + return grub_errno; + } diff --git a/0219-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch b/0219-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch new file mode 100644 index 0000000..715e6e1 --- /dev/null +++ b/0219-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Julian Andres Klode +Date: Thu, 2 Dec 2021 15:03:53 +0100 +Subject: [PATCH] kern/efi/sb: Reject non-kernel files in the shim_lock + verifier + +We must not allow other verifiers to pass things like the GRUB modules. +Instead of maintaining a blocklist, maintain an allowlist of things +that we do not care about. + +This allowlist really should be made reusable, and shared by the +lockdown verifier, but this is the minimal patch addressing +security concerns where the TPM verifier was able to mark modules +as verified (or the OpenPGP verifier for that matter), when it +should not do so on shim-powered secure boot systems. + +Fixes: CVE-2022-28735 + +Signed-off-by: Julian Andres Klode +Reviewed-by: Daniel Kiper +(cherry picked from commit fa61ad69861c1cb3f68bf853d78fae7fd93986a0) +--- + grub-core/kern/efi/sb.c | 39 ++++++++++++++++++++++++++++++++++++--- + include/grub/verify.h | 1 + + 2 files changed, 37 insertions(+), 3 deletions(-) + +diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c +index c52ec6226a..89c4bb3fd1 100644 +--- a/grub-core/kern/efi/sb.c ++++ b/grub-core/kern/efi/sb.c +@@ -119,10 +119,11 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), + void **context __attribute__ ((unused)), + enum grub_verify_flags *flags) + { +- *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; ++ *flags = GRUB_VERIFY_FLAGS_NONE; + + switch (type & GRUB_FILE_TYPE_MASK) + { ++ /* Files we check. */ + case GRUB_FILE_TYPE_LINUX_KERNEL: + case GRUB_FILE_TYPE_MULTIBOOT_KERNEL: + case GRUB_FILE_TYPE_BSD_KERNEL: +@@ -130,11 +131,43 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), + case GRUB_FILE_TYPE_PLAN9_KERNEL: + case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: + *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; ++ return GRUB_ERR_NONE; + +- /* Fall through. */ ++ /* Files that do not affect secureboot state. */ ++ case GRUB_FILE_TYPE_NONE: ++ case GRUB_FILE_TYPE_LOOPBACK: ++ case GRUB_FILE_TYPE_LINUX_INITRD: ++ case GRUB_FILE_TYPE_OPENBSD_RAMDISK: ++ case GRUB_FILE_TYPE_XNU_RAMDISK: ++ case GRUB_FILE_TYPE_SIGNATURE: ++ case GRUB_FILE_TYPE_PUBLIC_KEY: ++ case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST: ++ case GRUB_FILE_TYPE_PRINT_BLOCKLIST: ++ case GRUB_FILE_TYPE_TESTLOAD: ++ case GRUB_FILE_TYPE_GET_SIZE: ++ case GRUB_FILE_TYPE_FONT: ++ case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY: ++ case GRUB_FILE_TYPE_CAT: ++ case GRUB_FILE_TYPE_HEXCAT: ++ case GRUB_FILE_TYPE_CMP: ++ case GRUB_FILE_TYPE_HASHLIST: ++ case GRUB_FILE_TYPE_TO_HASH: ++ case GRUB_FILE_TYPE_KEYBOARD_LAYOUT: ++ case GRUB_FILE_TYPE_PIXMAP: ++ case GRUB_FILE_TYPE_GRUB_MODULE_LIST: ++ case GRUB_FILE_TYPE_CONFIG: ++ case GRUB_FILE_TYPE_THEME: ++ case GRUB_FILE_TYPE_GETTEXT_CATALOG: ++ case GRUB_FILE_TYPE_FS_SEARCH: ++ case GRUB_FILE_TYPE_LOADENV: ++ case GRUB_FILE_TYPE_SAVEENV: ++ case GRUB_FILE_TYPE_VERIFY_SIGNATURE: ++ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; ++ return GRUB_ERR_NONE; + ++ /* Other files. */ + default: +- return GRUB_ERR_NONE; ++ return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot policy")); + } + } + +diff --git a/include/grub/verify.h b/include/grub/verify.h +index cd129c398f..672ae16924 100644 +--- a/include/grub/verify.h ++++ b/include/grub/verify.h +@@ -24,6 +24,7 @@ + + enum grub_verify_flags + { ++ GRUB_VERIFY_FLAGS_NONE = 0, + GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1, + GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2, + /* Defer verification to another authority. */ diff --git a/0219-loader-efi-chainloader-Use-grub_loader_set_ex.patch b/0219-loader-efi-chainloader-Use-grub_loader_set_ex.patch deleted file mode 100644 index fc15b84..0000000 --- a/0219-loader-efi-chainloader-Use-grub_loader_set_ex.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Fri, 29 Apr 2022 21:30:56 +0100 -Subject: [PATCH] loader/efi/chainloader: Use grub_loader_set_ex - -This ports the EFI chainloader to use grub_loader_set_ex in order to fix -a use-after-free bug that occurs when grub_cmd_chainloader is executed -more than once before a boot attempt is performed. - -Signed-off-by: Chris Coulson -(cherry picked from commit 4b7f0402b7cb0f67a93be736f2b75b818d7f44c9) -[rharwood: context sludge from other change] -Signed-off-by: Robbie Harwood ---- - grub-core/loader/efi/chainloader.c | 38 ++++++++++++++++++++++---------------- - 1 file changed, 22 insertions(+), 16 deletions(-) - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 3342492ff1..fb874f1855 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -48,8 +48,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); - - static grub_dl_t my_mod; - --static grub_efi_handle_t image_handle; -- - struct grub_secureboot_chainloader_context { - grub_efi_physical_address_t address; - grub_efi_uintn_t pages; -@@ -59,7 +57,6 @@ struct grub_secureboot_chainloader_context { - grub_ssize_t cmdline_len; - grub_efi_handle_t dev_handle; - }; --static struct grub_secureboot_chainloader_context *sb_context; - - static grub_err_t - grub_start_image (grub_efi_handle_t handle) -@@ -98,11 +95,14 @@ grub_start_image (grub_efi_handle_t handle) - } - - static grub_err_t --grub_chainloader_unload (void) -+grub_chainloader_unload (void *context) - { -+ grub_efi_handle_t image_handle; - grub_efi_loaded_image_t *loaded_image; - grub_efi_boot_services_t *b; - -+ image_handle = (grub_efi_handle_t) context; -+ - loaded_image = grub_efi_get_loaded_image (image_handle); - if (loaded_image != NULL) - grub_free (loaded_image->load_options); -@@ -115,10 +115,12 @@ grub_chainloader_unload (void) - } - - static grub_err_t --grub_chainloader_boot (void) -+grub_chainloader_boot (void *context) - { -+ grub_efi_handle_t image_handle; - grub_err_t err; - -+ image_handle = (grub_efi_handle_t) context; - err = grub_start_image (image_handle); - - grub_loader_unset (); -@@ -839,15 +841,17 @@ error_exit: - } - - static grub_err_t --grub_secureboot_chainloader_unload (void) -+grub_secureboot_chainloader_unload (void *context) - { -+ struct grub_secureboot_chainloader_context *sb_context; -+ -+ sb_context = (struct grub_secureboot_chainloader_context *) context; -+ - grub_efi_free_pages (sb_context->address, sb_context->pages); - grub_free (sb_context->file_path); - grub_free (sb_context->cmdline); - grub_free (sb_context); - -- sb_context = 0; -- - grub_dl_unref (my_mod); - return GRUB_ERR_NONE; - } -@@ -896,12 +900,15 @@ grub_load_image(grub_efi_device_path_t *file_path, void *boot_image, - } - - static grub_err_t --grub_secureboot_chainloader_boot (void) -+grub_secureboot_chainloader_boot (void *context) - { -+ struct grub_secureboot_chainloader_context *sb_context; - grub_efi_boot_services_t *b; - int rc; - grub_efi_handle_t handle = 0; - -+ sb_context = (struct grub_secureboot_chainloader_context *) context; -+ - rc = handle_image (sb_context); - if (rc == 0) - { -@@ -942,6 +949,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_efi_char16_t *cmdline = 0; - grub_ssize_t cmdline_len = 0; - grub_efi_handle_t dev_handle = 0; -+ grub_efi_handle_t image_handle = 0; -+ struct grub_secureboot_chainloader_context *sb_context = 0; - - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -@@ -1127,8 +1136,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_file_close (file); - grub_device_close (dev); - -- grub_loader_set (grub_secureboot_chainloader_boot, -- grub_secureboot_chainloader_unload, 0); -+ grub_loader_set_ex (grub_secureboot_chainloader_boot, -+ grub_secureboot_chainloader_unload, sb_context, 0); - return 0; - } - else -@@ -1142,7 +1151,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - efi_call_2 (b->free_pages, address, pages); - grub_free (file_path); - -- grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); -+ grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0); - - return 0; - } -@@ -1169,10 +1178,7 @@ fail: - grub_free (cmdline); - - if (image_handle != 0) -- { -- efi_call_1 (b->unload_image, image_handle); -- image_handle = 0; -- } -+ efi_call_1 (b->unload_image, image_handle); - - grub_dl_unref (my_mod); - diff --git a/0220-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch b/0220-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch new file mode 100644 index 0000000..59f9471 --- /dev/null +++ b/0220-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Fri, 25 Jun 2021 02:19:05 +1000 +Subject: [PATCH] kern/file: Do not leak device_name on error in + grub_file_open() + +If we have an error in grub_file_open() before we free device_name, we +will leak it. + +Free device_name in the error path and null out the pointer in the good +path once we free it there. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 1499a5068839fa37cb77ecef4b5bdacbd1ed12ea) +--- + grub-core/kern/file.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c +index ec10e54fc0..db938e099d 100644 +--- a/grub-core/kern/file.c ++++ b/grub-core/kern/file.c +@@ -84,6 +84,7 @@ grub_file_open (const char *name, enum grub_file_type type) + + device = grub_device_open (device_name); + grub_free (device_name); ++ device_name = NULL; + if (! device) + goto fail; + +@@ -138,6 +139,7 @@ grub_file_open (const char *name, enum grub_file_type type) + return file; + + fail: ++ grub_free (device_name); + if (device) + grub_device_close (device); + diff --git a/0220-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch b/0220-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch deleted file mode 100644 index b79c78c..0000000 --- a/0220-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Mon, 2 May 2022 14:39:31 +0200 -Subject: [PATCH] loader/i386/efi/linux: Avoid a use-after-free in the linuxefi - loader - -In some error paths in grub_cmd_linux, the pointer to lh may be -dereferenced after the buffer it points to has been freed. There aren't -any security implications from this because nothing else uses the -allocator after the buffer is freed and before the pointer is -dereferenced, but fix it anyway. - -Signed-off-by: Chris Coulson -(cherry picked from commit 8224f5a71af94bec8697de17e7e579792db9f9e2) ---- - grub-core/loader/i386/efi/linux.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 941df6400b..27bc2aa161 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -465,9 +465,6 @@ fail: - if (file) - grub_file_close (file); - -- if (kernel) -- grub_free (kernel); -- - if (grub_errno != GRUB_ERR_NONE) - { - grub_dl_unref (my_mod); -@@ -483,6 +480,8 @@ fail: - kernel_free (params, sizeof(*params)); - } - -+ grub_free (kernel); -+ - return grub_errno; - } - diff --git a/0221-loader-i386-efi-linux-Use-grub_loader_set_ex.patch b/0221-loader-i386-efi-linux-Use-grub_loader_set_ex.patch deleted file mode 100644 index 1a129db..0000000 --- a/0221-loader-i386-efi-linux-Use-grub_loader_set_ex.patch +++ /dev/null @@ -1,296 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Mon, 2 May 2022 17:04:23 +0200 -Subject: [PATCH] loader/i386/efi/linux: Use grub_loader_set_ex - -This ports the linuxefi loader to use grub_loader_set_ex in order to fix -a use-after-fre bug that occurs when grub_cmd_linux is executed more than -once before a boot attempt is performed. - -This is more complicated than for the chainloader command, as the initrd -command needs access to the loader state. To solve this, the linuxefi -module registers a dummy initrd command at startup that returns an error. -The linuxefi command then registers a proper initrd command with a higher -priority that is passed the loader state. - -Signed-off-by: Chris Coulson -(cherry picked from commit 7cf736436b4c934df5ddfa6f44b46a7e07d99fdc) -[rharwood/pjones: set kernel_size in context] -Signed-off-by: Robbie Harwood ---- - grub-core/loader/i386/efi/linux.c | 146 +++++++++++++++++++++++--------------- - 1 file changed, 87 insertions(+), 59 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 27bc2aa161..e3c2d6fe0b 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -34,13 +34,19 @@ - GRUB_MOD_LICENSE ("GPLv3+"); - - static grub_dl_t my_mod; --static int loaded; --static void *kernel_mem; --static grub_uint64_t kernel_size; --static void *initrd_mem; --static grub_uint32_t handover_offset; --struct linux_kernel_params *params; --static char *linux_cmdline; -+ -+static grub_command_t cmd_linux, cmd_initrd; -+static grub_command_t cmd_linuxefi, cmd_initrdefi; -+ -+struct grub_linuxefi_context { -+ void *kernel_mem; -+ grub_uint64_t kernel_size; -+ grub_uint32_t handover_offset; -+ struct linux_kernel_params *params; -+ char *cmdline; -+ -+ void *initrd_mem; -+}; - - #define MIN(a, b) \ - ({ typeof (a) _a = (a); \ -@@ -123,25 +129,32 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) - } - - static grub_err_t --grub_linuxefi_boot (void) -+grub_linuxefi_boot (void *data) - { -+ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data; -+ - asm volatile ("cli"); - -- return grub_efi_linux_boot ((char *)kernel_mem, -- handover_offset, -- params); -+ return grub_efi_linux_boot ((char *)context->kernel_mem, -+ context->handover_offset, -+ context->params); - } - - static grub_err_t --grub_linuxefi_unload (void) -+grub_linuxefi_unload (void *data) - { -+ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data; -+ struct linux_kernel_params *params = context->params; -+ - grub_dl_unref (my_mod); -- loaded = 0; - -- kernel_free(initrd_mem, params->ramdisk_size); -- kernel_free(linux_cmdline, params->cmdline_size + 1); -- kernel_free(kernel_mem, kernel_size); -- kernel_free(params, sizeof(*params)); -+ kernel_free (context->initrd_mem, params->ramdisk_size); -+ kernel_free (context->cmdline, params->cmdline_size + 1); -+ kernel_free (context->kernel_mem, context->kernel_size); -+ kernel_free (params, sizeof(*params)); -+ cmd_initrd->data = 0; -+ cmd_initrdefi->data = 0; -+ grub_free (context); - - return GRUB_ERR_NONE; - } -@@ -188,13 +201,14 @@ read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) - #define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull)) - - static grub_err_t --grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), -- int argc, char *argv[]) -+grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - { - grub_file_t *files = 0; - int i, nfiles = 0; - grub_size_t size = 0; - grub_uint8_t *ptr; -+ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data; -+ struct linux_kernel_params *params; - - if (argc == 0) - { -@@ -202,12 +216,14 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -- if (!loaded) -+ if (!context) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); - goto fail; - } - -+ params = context->params; -+ - files = grub_calloc (argc, sizeof (files[0])); - if (!files) - goto fail; -@@ -225,19 +241,19 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - } - } - -- initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -- if (initrd_mem == NULL) -+ context->initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -+ if (context->initrd_mem == NULL) - goto fail; -- grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); -+ grub_dprintf ("linux", "initrd_mem = %p\n", context->initrd_mem); - - params->ramdisk_size = LOW_U32(size); -- params->ramdisk_image = LOW_U32(initrd_mem); -+ params->ramdisk_image = LOW_U32(context->initrd_mem); - #if defined(__x86_64__) - params->ext_ramdisk_size = HIGH_U32(size); -- params->ext_ramdisk_image = HIGH_U32(initrd_mem); -+ params->ext_ramdisk_image = HIGH_U32(context->initrd_mem); - #endif - -- ptr = initrd_mem; -+ ptr = context->initrd_mem; - - for (i = 0; i < nfiles; i++) - { -@@ -261,8 +277,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - grub_file_close (files[i]); - grub_free (files); - -- if (initrd_mem && grub_errno) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, -+ if (context->initrd_mem && grub_errno) -+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem, - BYTES_TO_PAGES(size)); - - return grub_errno; -@@ -277,6 +293,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_ssize_t start, filelen; - void *kernel = NULL; - int setup_header_end_offset; -+ void *kernel_mem = 0; -+ grub_uint64_t kernel_size = 0; -+ grub_uint32_t handover_offset; -+ struct linux_kernel_params *params = 0; -+ char *cmdline = 0; -+ struct grub_linuxefi_context *context = 0; - - grub_dl_ref (my_mod); - -@@ -390,27 +412,27 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "new lh is at %p\n", lh); - - grub_dprintf ("linux", "setting up cmdline\n"); -- linux_cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); -- if (!linux_cmdline) -+ cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); -+ if (!cmdline) - goto fail; -- grub_dprintf ("linux", "linux_cmdline = %p\n", linux_cmdline); -+ grub_dprintf ("linux", "cmdline = %p\n", cmdline); - -- grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); -+ grub_memcpy (cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); - grub_create_loader_cmdline (argc, argv, -- linux_cmdline + sizeof (LINUX_IMAGE) - 1, -+ cmdline + sizeof (LINUX_IMAGE) - 1, - lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1), - GRUB_VERIFY_KERNEL_CMDLINE); - -- grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline); -+ grub_dprintf ("linux", "cmdline:%s\n", cmdline); - grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n", -- LOW_U32(linux_cmdline)); -- lh->cmd_line_ptr = LOW_U32(linux_cmdline); -+ LOW_U32(cmdline)); -+ lh->cmd_line_ptr = LOW_U32(cmdline); - #if defined(__x86_64__) -- if ((grub_efi_uintn_t)linux_cmdline > 0xffffffffull) -+ if ((grub_efi_uintn_t)cmdline > 0xffffffffull) - { - grub_dprintf ("linux", "setting params->ext_cmd_line_ptr to 0x%08x\n", -- HIGH_U32(linux_cmdline)); -- params->ext_cmd_line_ptr = HIGH_U32(linux_cmdline); -+ HIGH_U32(cmdline)); -+ params->ext_cmd_line_ptr = HIGH_U32(cmdline); - } - #endif - -@@ -435,16 +457,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -- kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel")); -+ kernel_size = lh->init_size; -+ kernel_mem = kernel_alloc (kernel_size, N_("can't allocate kernel")); - restore_addresses(); - if (!kernel_mem) - goto fail; - grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem); - -- grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); -- -- loaded = 1; -- - grub_dprintf ("linux", "setting lh->code32_start to 0x%08x\n", - LOW_U32(kernel_mem)); - lh->code32_start = LOW_U32(kernel_mem); -@@ -461,33 +480,42 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - "setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n", - params->ext_loader_type, params->ext_loader_ver); - -+ context = grub_zalloc (sizeof (*context)); -+ if (!context) -+ goto fail; -+ context->kernel_mem = kernel_mem; -+ context->kernel_size = kernel_size; -+ context->handover_offset = handover_offset; -+ context->params = params; -+ context->cmdline = cmdline; -+ -+ grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0); -+ -+ cmd_initrd->data = context; -+ cmd_initrdefi->data = context; -+ -+ grub_file_close (file); -+ grub_free (kernel); -+ return 0; -+ - fail: - if (file) - grub_file_close (file); - -- if (grub_errno != GRUB_ERR_NONE) -- { -- grub_dl_unref (my_mod); -- loaded = 0; -- } -+ grub_dl_unref (my_mod); - -- if (!loaded) -- { -- if (lh) -- kernel_free (linux_cmdline, lh->cmdline_size + 1); -+ if (lh) -+ kernel_free (cmdline, lh->cmdline_size + 1); - -- kernel_free (kernel_mem, kernel_size); -- kernel_free (params, sizeof(*params)); -- } -+ kernel_free (kernel_mem, kernel_size); -+ kernel_free (params, sizeof(*params)); - -+ grub_free (context); - grub_free (kernel); - - return grub_errno; - } - --static grub_command_t cmd_linux, cmd_initrd; --static grub_command_t cmd_linuxefi, cmd_initrdefi; -- - GRUB_MOD_INIT(linux) - { - cmd_linux = diff --git a/0221-video-readers-png-Abort-sooner-if-a-read-operation-f.patch b/0221-video-readers-png-Abort-sooner-if-a-read-operation-f.patch new file mode 100644 index 0000000..385d3ed --- /dev/null +++ b/0221-video-readers-png-Abort-sooner-if-a-read-operation-f.patch @@ -0,0 +1,198 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 6 Jul 2021 14:02:55 +1000 +Subject: [PATCH] video/readers/png: Abort sooner if a read operation fails + +Fuzzing revealed some inputs that were taking a long time, potentially +forever, because they did not bail quickly upon encountering an I/O error. + +Try to catch I/O errors sooner and bail out. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 882be97d1df6449b9fd4d593f0cb70005fde3494) +--- + grub-core/video/readers/png.c | 55 ++++++++++++++++++++++++++++++++++++------- + 1 file changed, 47 insertions(+), 8 deletions(-) + +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index 0157ff7420..e2a6b1cf3c 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -142,6 +142,7 @@ static grub_uint8_t + grub_png_get_byte (struct grub_png_data *data) + { + grub_uint8_t r; ++ grub_ssize_t bytes_read = 0; + + if ((data->inside_idat) && (data->idat_remain == 0)) + { +@@ -175,7 +176,14 @@ grub_png_get_byte (struct grub_png_data *data) + } + + r = 0; +- grub_file_read (data->file, &r, 1); ++ bytes_read = grub_file_read (data->file, &r, 1); ++ ++ if (bytes_read != 1) ++ { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "png: unexpected end of data"); ++ return 0; ++ } + + if (data->inside_idat) + data->idat_remain--; +@@ -231,15 +239,16 @@ grub_png_decode_image_palette (struct grub_png_data *data, + if (len == 0) + return GRUB_ERR_NONE; + +- for (i = 0; 3 * i < len && i < 256; i++) ++ grub_errno = GRUB_ERR_NONE; ++ for (i = 0; 3 * i < len && i < 256 && grub_errno == GRUB_ERR_NONE; i++) + for (j = 0; j < 3; j++) + data->palette[i][j] = grub_png_get_byte (data); +- for (i *= 3; i < len; i++) ++ for (i *= 3; i < len && grub_errno == GRUB_ERR_NONE; i++) + grub_png_get_byte (data); + + grub_png_get_dword (data); + +- return GRUB_ERR_NONE; ++ return grub_errno; + } + + static grub_err_t +@@ -256,9 +265,13 @@ grub_png_decode_image_header (struct grub_png_data *data) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size"); + + color_bits = grub_png_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + data->is_16bit = (color_bits == 16); + + color_type = grub_png_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + /* According to PNG spec, no other types are valid. */ + if ((color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR)) +@@ -340,14 +353,20 @@ grub_png_decode_image_header (struct grub_png_data *data) + if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "png: compression method not supported"); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "png: filter method not supported"); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + if (grub_png_get_byte (data) != PNG_INTERLACE_NONE) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "png: interlace method not supported"); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + /* Skip crc checksum. */ + grub_png_get_dword (data); +@@ -449,7 +468,7 @@ grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht) + int code, i; + + code = 0; +- for (i = 0; i < ht->max_length; i++) ++ for (i = 0; i < ht->max_length && grub_errno == GRUB_ERR_NONE; i++) + { + code = (code << 1) + grub_png_get_bits (data, 1); + if (code < ht->maxval[i]) +@@ -504,8 +523,14 @@ grub_png_init_dynamic_block (struct grub_png_data *data) + grub_uint8_t lens[DEFLATE_HCLEN_MAX]; + + nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) || + (nb > DEFLATE_HCLEN_MAX)) +@@ -533,7 +558,7 @@ grub_png_init_dynamic_block (struct grub_png_data *data) + data->dist_offset); + + prev = 0; +- for (i = 0; i < nl + nd; i++) ++ for (i = 0; i < nl + nd && grub_errno == GRUB_ERR_NONE; i++) + { + int n, code; + struct huff_table *ht; +@@ -721,17 +746,21 @@ grub_png_read_dynamic_block (struct grub_png_data *data) + len = cplens[n]; + if (cplext[n]) + len += grub_png_get_bits (data, cplext[n]); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + n = grub_png_get_huff_code (data, &data->dist_table); + dist = cpdist[n]; + if (cpdext[n]) + dist += grub_png_get_bits (data, cpdext[n]); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + pos = data->wp - dist; + if (pos < 0) + pos += WSIZE; + +- while (len > 0) ++ while (len > 0 && grub_errno == GRUB_ERR_NONE) + { + data->slide[data->wp] = data->slide[pos]; + grub_png_output_byte (data, data->slide[data->wp]); +@@ -759,7 +788,11 @@ grub_png_decode_image_data (struct grub_png_data *data) + int final; + + cmf = grub_png_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + flg = grub_png_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + if ((cmf & 0xF) != Z_DEFLATED) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, +@@ -774,7 +807,11 @@ grub_png_decode_image_data (struct grub_png_data *data) + int block_type; + + final = grub_png_get_bits (data, 1); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + block_type = grub_png_get_bits (data, 2); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + switch (block_type) + { +@@ -790,7 +827,7 @@ grub_png_decode_image_data (struct grub_png_data *data) + grub_png_get_byte (data); + grub_png_get_byte (data); + +- for (i = 0; i < len; i++) ++ for (i = 0; i < len && grub_errno == GRUB_ERR_NONE; i++) + grub_png_output_byte (data, grub_png_get_byte (data)); + + break; +@@ -1045,6 +1082,8 @@ grub_png_decode_png (struct grub_png_data *data) + + len = grub_png_get_dword (data); + type = grub_png_get_dword (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ break; + data->next_offset = data->file->offset + len + 4; + + switch (type) diff --git a/0222-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch b/0222-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch deleted file mode 100644 index 51953fd..0000000 --- a/0222-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Tue, 3 May 2022 09:47:35 +0200 -Subject: [PATCH] loader/i386/efi/linux: Fix a memory leak in the initrd - command - -Subsequent invocations of the initrd command result in the previous -initrd being leaked, so fix that. - -Signed-off-by: Chris Coulson -(cherry picked from commit d98af31ce1e31bb22163960d53f5eb28c66582a0) ---- - grub-core/loader/i386/efi/linux.c | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index e3c2d6fe0b..9e5c11ac69 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -209,6 +209,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - grub_uint8_t *ptr; - struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data; - struct linux_kernel_params *params; -+ void *initrd_mem = 0; - - if (argc == 0) - { -@@ -241,19 +242,19 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - } - } - -- context->initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -- if (context->initrd_mem == NULL) -+ initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -+ if (initrd_mem == NULL) - goto fail; -- grub_dprintf ("linux", "initrd_mem = %p\n", context->initrd_mem); -+ grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); - - params->ramdisk_size = LOW_U32(size); -- params->ramdisk_image = LOW_U32(context->initrd_mem); -+ params->ramdisk_image = LOW_U32(initrd_mem); - #if defined(__x86_64__) - params->ext_ramdisk_size = HIGH_U32(size); -- params->ext_ramdisk_image = HIGH_U32(context->initrd_mem); -+ params->ext_ramdisk_image = HIGH_U32(initrd_mem); - #endif - -- ptr = context->initrd_mem; -+ ptr = initrd_mem; - - for (i = 0; i < nfiles; i++) - { -@@ -270,6 +271,9 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - ptr += ALIGN_UP_OVERHEAD (cursize, 4); - } - -+ kernel_free(context->initrd_mem, params->ramdisk_size); -+ -+ context->initrd_mem = initrd_mem; - params->ramdisk_size = size; - - fail: -@@ -277,9 +281,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - grub_file_close (files[i]); - grub_free (files); - -- if (context->initrd_mem && grub_errno) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem, -- BYTES_TO_PAGES(size)); -+ if (initrd_mem && grub_errno) -+ kernel_free (initrd_mem, size); - - return grub_errno; - } diff --git a/0222-video-readers-png-Refuse-to-handle-multiple-image-he.patch b/0222-video-readers-png-Refuse-to-handle-multiple-image-he.patch new file mode 100644 index 0000000..9168fe5 --- /dev/null +++ b/0222-video-readers-png-Refuse-to-handle-multiple-image-he.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 6 Jul 2021 14:13:40 +1000 +Subject: [PATCH] video/readers/png: Refuse to handle multiple image headers + +This causes the bitmap to be leaked. Do not permit multiple image headers. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 8ce433557adeadbc46429aabb9f850b02ad2bdfb) +--- + grub-core/video/readers/png.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index e2a6b1cf3c..8955b8ecfd 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -258,6 +258,9 @@ grub_png_decode_image_header (struct grub_png_data *data) + int color_bits; + enum grub_video_blit_format blt; + ++ if (data->image_width || data->image_height) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: two image headers found"); ++ + data->image_width = grub_png_get_dword (data); + data->image_height = grub_png_get_dword (data); + diff --git a/0223-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch b/0223-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch deleted file mode 100644 index 715e6e1..0000000 --- a/0223-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Julian Andres Klode -Date: Thu, 2 Dec 2021 15:03:53 +0100 -Subject: [PATCH] kern/efi/sb: Reject non-kernel files in the shim_lock - verifier - -We must not allow other verifiers to pass things like the GRUB modules. -Instead of maintaining a blocklist, maintain an allowlist of things -that we do not care about. - -This allowlist really should be made reusable, and shared by the -lockdown verifier, but this is the minimal patch addressing -security concerns where the TPM verifier was able to mark modules -as verified (or the OpenPGP verifier for that matter), when it -should not do so on shim-powered secure boot systems. - -Fixes: CVE-2022-28735 - -Signed-off-by: Julian Andres Klode -Reviewed-by: Daniel Kiper -(cherry picked from commit fa61ad69861c1cb3f68bf853d78fae7fd93986a0) ---- - grub-core/kern/efi/sb.c | 39 ++++++++++++++++++++++++++++++++++++--- - include/grub/verify.h | 1 + - 2 files changed, 37 insertions(+), 3 deletions(-) - -diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c -index c52ec6226a..89c4bb3fd1 100644 ---- a/grub-core/kern/efi/sb.c -+++ b/grub-core/kern/efi/sb.c -@@ -119,10 +119,11 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), - void **context __attribute__ ((unused)), - enum grub_verify_flags *flags) - { -- *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; -+ *flags = GRUB_VERIFY_FLAGS_NONE; - - switch (type & GRUB_FILE_TYPE_MASK) - { -+ /* Files we check. */ - case GRUB_FILE_TYPE_LINUX_KERNEL: - case GRUB_FILE_TYPE_MULTIBOOT_KERNEL: - case GRUB_FILE_TYPE_BSD_KERNEL: -@@ -130,11 +131,43 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), - case GRUB_FILE_TYPE_PLAN9_KERNEL: - case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: - *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; -+ return GRUB_ERR_NONE; - -- /* Fall through. */ -+ /* Files that do not affect secureboot state. */ -+ case GRUB_FILE_TYPE_NONE: -+ case GRUB_FILE_TYPE_LOOPBACK: -+ case GRUB_FILE_TYPE_LINUX_INITRD: -+ case GRUB_FILE_TYPE_OPENBSD_RAMDISK: -+ case GRUB_FILE_TYPE_XNU_RAMDISK: -+ case GRUB_FILE_TYPE_SIGNATURE: -+ case GRUB_FILE_TYPE_PUBLIC_KEY: -+ case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST: -+ case GRUB_FILE_TYPE_PRINT_BLOCKLIST: -+ case GRUB_FILE_TYPE_TESTLOAD: -+ case GRUB_FILE_TYPE_GET_SIZE: -+ case GRUB_FILE_TYPE_FONT: -+ case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY: -+ case GRUB_FILE_TYPE_CAT: -+ case GRUB_FILE_TYPE_HEXCAT: -+ case GRUB_FILE_TYPE_CMP: -+ case GRUB_FILE_TYPE_HASHLIST: -+ case GRUB_FILE_TYPE_TO_HASH: -+ case GRUB_FILE_TYPE_KEYBOARD_LAYOUT: -+ case GRUB_FILE_TYPE_PIXMAP: -+ case GRUB_FILE_TYPE_GRUB_MODULE_LIST: -+ case GRUB_FILE_TYPE_CONFIG: -+ case GRUB_FILE_TYPE_THEME: -+ case GRUB_FILE_TYPE_GETTEXT_CATALOG: -+ case GRUB_FILE_TYPE_FS_SEARCH: -+ case GRUB_FILE_TYPE_LOADENV: -+ case GRUB_FILE_TYPE_SAVEENV: -+ case GRUB_FILE_TYPE_VERIFY_SIGNATURE: -+ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; -+ return GRUB_ERR_NONE; - -+ /* Other files. */ - default: -- return GRUB_ERR_NONE; -+ return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot policy")); - } - } - -diff --git a/include/grub/verify.h b/include/grub/verify.h -index cd129c398f..672ae16924 100644 ---- a/include/grub/verify.h -+++ b/include/grub/verify.h -@@ -24,6 +24,7 @@ - - enum grub_verify_flags - { -+ GRUB_VERIFY_FLAGS_NONE = 0, - GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1, - GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2, - /* Defer verification to another authority. */ diff --git a/0223-video-readers-png-Drop-greyscale-support-to-fix-heap.patch b/0223-video-readers-png-Drop-greyscale-support-to-fix-heap.patch new file mode 100644 index 0000000..4529cb8 --- /dev/null +++ b/0223-video-readers-png-Drop-greyscale-support-to-fix-heap.patch @@ -0,0 +1,170 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 6 Jul 2021 18:51:35 +1000 +Subject: [PATCH] video/readers/png: Drop greyscale support to fix heap + out-of-bounds write + +A 16-bit greyscale PNG without alpha is processed in the following loop: + + for (i = 0; i < (data->image_width * data->image_height); + i++, d1 += 4, d2 += 2) + { + d1[R3] = d2[1]; + d1[G3] = d2[1]; + d1[B3] = d2[1]; + } + +The increment of d1 is wrong. d1 is incremented by 4 bytes per iteration, +but there are only 3 bytes allocated for storage. This means that image +data will overwrite somewhat-attacker-controlled parts of memory - 3 bytes +out of every 4 following the end of the image. + +This has existed since greyscale support was added in 2013 in commit +3ccf16dff98f (grub-core/video/readers/png.c: Support grayscale). + +Saving starfield.png as a 16-bit greyscale image without alpha in the gimp +and attempting to load it causes grub-emu to crash - I don't think this code +has ever worked. + +Delete all PNG greyscale support. + +Fixes: CVE-2021-3695 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 0e1d163382669bd734439d8864ee969616d971d9) +[rharwood: context conflict] +Signed-off-by: Robbie Harwood +--- + grub-core/video/readers/png.c | 85 +++---------------------------------------- + 1 file changed, 6 insertions(+), 79 deletions(-) + +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index 8955b8ecfd..a3161e25b6 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -100,7 +100,7 @@ struct grub_png_data + + unsigned image_width, image_height; + int bpp, is_16bit; +- int raw_bytes, is_gray, is_alpha, is_palette; ++ int raw_bytes, is_alpha, is_palette; + int row_bytes, color_bits; + grub_uint8_t *image_data; + +@@ -296,13 +296,13 @@ grub_png_decode_image_header (struct grub_png_data *data) + data->bpp = 3; + else + { +- data->is_gray = 1; +- data->bpp = 1; ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "png: color type not supported"); + } + + if ((color_bits != 8) && (color_bits != 16) + && (color_bits != 4 +- || !(data->is_gray || data->is_palette))) ++ || !data->is_palette)) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "png: bit depth must be 8 or 16"); + +@@ -331,7 +331,7 @@ grub_png_decode_image_header (struct grub_png_data *data) + } + + #ifndef GRUB_CPU_WORDS_BIGENDIAN +- if (data->is_16bit || data->is_gray || data->is_palette) ++ if (data->is_16bit || data->is_palette) + #endif + { + data->image_data = grub_calloc (data->image_height, data->row_bytes); +@@ -899,27 +899,8 @@ grub_png_convert_image (struct grub_png_data *data) + int shift; + int mask = (1 << data->color_bits) - 1; + unsigned j; +- if (data->is_gray) +- { +- /* Generic formula is +- (0xff * i) / ((1U << data->color_bits) - 1) +- but for allowed bit depth of 1, 2 and for it's +- equivalent to +- (0xff / ((1U << data->color_bits) - 1)) * i +- Precompute the multipliers to avoid division. +- */ + +- const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 }; +- for (i = 0; i < (1U << data->color_bits); i++) +- { +- grub_uint8_t col = multipliers[data->color_bits] * i; +- palette[i][0] = col; +- palette[i][1] = col; +- palette[i][2] = col; +- } +- } +- else +- grub_memcpy (palette, data->palette, 3 << data->color_bits); ++ grub_memcpy (palette, data->palette, 3 << data->color_bits); + d1c = d1; + d2c = d2; + for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3, +@@ -956,60 +937,6 @@ grub_png_convert_image (struct grub_png_data *data) + } + return; + } +- +- if (data->is_gray) +- { +- switch (data->bpp) +- { +- case 4: +- /* 16-bit gray with alpha. */ +- for (i = 0; i < (data->image_width * data->image_height); +- i++, d1 += 4, d2 += 4) +- { +- d1[R4] = d2[3]; +- d1[G4] = d2[3]; +- d1[B4] = d2[3]; +- d1[A4] = d2[1]; +- } +- break; +- case 2: +- if (data->is_16bit) +- /* 16-bit gray without alpha. */ +- { +- for (i = 0; i < (data->image_width * data->image_height); +- i++, d1 += 4, d2 += 2) +- { +- d1[R3] = d2[1]; +- d1[G3] = d2[1]; +- d1[B3] = d2[1]; +- } +- } +- else +- /* 8-bit gray with alpha. */ +- { +- for (i = 0; i < (data->image_width * data->image_height); +- i++, d1 += 4, d2 += 2) +- { +- d1[R4] = d2[1]; +- d1[G4] = d2[1]; +- d1[B4] = d2[1]; +- d1[A4] = d2[0]; +- } +- } +- break; +- /* 8-bit gray without alpha. */ +- case 1: +- for (i = 0; i < (data->image_width * data->image_height); +- i++, d1 += 3, d2++) +- { +- d1[R3] = d2[0]; +- d1[G3] = d2[0]; +- d1[B3] = d2[0]; +- } +- break; +- } +- return; +- } + + { + /* Only copy the upper 8 bit. */ diff --git a/0224-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch b/0224-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch deleted file mode 100644 index 59f9471..0000000 --- a/0224-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 25 Jun 2021 02:19:05 +1000 -Subject: [PATCH] kern/file: Do not leak device_name on error in - grub_file_open() - -If we have an error in grub_file_open() before we free device_name, we -will leak it. - -Free device_name in the error path and null out the pointer in the good -path once we free it there. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 1499a5068839fa37cb77ecef4b5bdacbd1ed12ea) ---- - grub-core/kern/file.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c -index ec10e54fc0..db938e099d 100644 ---- a/grub-core/kern/file.c -+++ b/grub-core/kern/file.c -@@ -84,6 +84,7 @@ grub_file_open (const char *name, enum grub_file_type type) - - device = grub_device_open (device_name); - grub_free (device_name); -+ device_name = NULL; - if (! device) - goto fail; - -@@ -138,6 +139,7 @@ grub_file_open (const char *name, enum grub_file_type type) - return file; - - fail: -+ grub_free (device_name); - if (device) - grub_device_close (device); - diff --git a/0224-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch b/0224-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch new file mode 100644 index 0000000..51dddfe --- /dev/null +++ b/0224-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 6 Jul 2021 23:25:07 +1000 +Subject: [PATCH] video/readers/png: Avoid heap OOB R/W inserting huff table + items + +In fuzzing we observed crashes where a code would attempt to be inserted +into a huffman table before the start, leading to a set of heap OOB reads +and writes as table entries with negative indices were shifted around and +the new code written in. + +Catch the case where we would underflow the array and bail. + +Fixes: CVE-2021-3696 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 1ae9a91d42cb40da8a6f11fac65541858e340afa) +--- + grub-core/video/readers/png.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index a3161e25b6..d7ed5aa6cf 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -438,6 +438,13 @@ grub_png_insert_huff_item (struct huff_table *ht, int code, int len) + for (i = len; i < ht->max_length; i++) + n += ht->maxval[i]; + ++ if (n > ht->num_values) ++ { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "png: out of range inserting huffman table item"); ++ return; ++ } ++ + for (i = 0; i < n; i++) + ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1]; + diff --git a/0225-video-readers-png-Abort-sooner-if-a-read-operation-f.patch b/0225-video-readers-png-Abort-sooner-if-a-read-operation-f.patch deleted file mode 100644 index 385d3ed..0000000 --- a/0225-video-readers-png-Abort-sooner-if-a-read-operation-f.patch +++ /dev/null @@ -1,198 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 6 Jul 2021 14:02:55 +1000 -Subject: [PATCH] video/readers/png: Abort sooner if a read operation fails - -Fuzzing revealed some inputs that were taking a long time, potentially -forever, because they did not bail quickly upon encountering an I/O error. - -Try to catch I/O errors sooner and bail out. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 882be97d1df6449b9fd4d593f0cb70005fde3494) ---- - grub-core/video/readers/png.c | 55 ++++++++++++++++++++++++++++++++++++------- - 1 file changed, 47 insertions(+), 8 deletions(-) - -diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c -index 0157ff7420..e2a6b1cf3c 100644 ---- a/grub-core/video/readers/png.c -+++ b/grub-core/video/readers/png.c -@@ -142,6 +142,7 @@ static grub_uint8_t - grub_png_get_byte (struct grub_png_data *data) - { - grub_uint8_t r; -+ grub_ssize_t bytes_read = 0; - - if ((data->inside_idat) && (data->idat_remain == 0)) - { -@@ -175,7 +176,14 @@ grub_png_get_byte (struct grub_png_data *data) - } - - r = 0; -- grub_file_read (data->file, &r, 1); -+ bytes_read = grub_file_read (data->file, &r, 1); -+ -+ if (bytes_read != 1) -+ { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "png: unexpected end of data"); -+ return 0; -+ } - - if (data->inside_idat) - data->idat_remain--; -@@ -231,15 +239,16 @@ grub_png_decode_image_palette (struct grub_png_data *data, - if (len == 0) - return GRUB_ERR_NONE; - -- for (i = 0; 3 * i < len && i < 256; i++) -+ grub_errno = GRUB_ERR_NONE; -+ for (i = 0; 3 * i < len && i < 256 && grub_errno == GRUB_ERR_NONE; i++) - for (j = 0; j < 3; j++) - data->palette[i][j] = grub_png_get_byte (data); -- for (i *= 3; i < len; i++) -+ for (i *= 3; i < len && grub_errno == GRUB_ERR_NONE; i++) - grub_png_get_byte (data); - - grub_png_get_dword (data); - -- return GRUB_ERR_NONE; -+ return grub_errno; - } - - static grub_err_t -@@ -256,9 +265,13 @@ grub_png_decode_image_header (struct grub_png_data *data) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size"); - - color_bits = grub_png_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - data->is_16bit = (color_bits == 16); - - color_type = grub_png_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - /* According to PNG spec, no other types are valid. */ - if ((color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR)) -@@ -340,14 +353,20 @@ grub_png_decode_image_header (struct grub_png_data *data) - if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "png: compression method not supported"); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "png: filter method not supported"); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - if (grub_png_get_byte (data) != PNG_INTERLACE_NONE) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "png: interlace method not supported"); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - /* Skip crc checksum. */ - grub_png_get_dword (data); -@@ -449,7 +468,7 @@ grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht) - int code, i; - - code = 0; -- for (i = 0; i < ht->max_length; i++) -+ for (i = 0; i < ht->max_length && grub_errno == GRUB_ERR_NONE; i++) - { - code = (code << 1) + grub_png_get_bits (data, 1); - if (code < ht->maxval[i]) -@@ -504,8 +523,14 @@ grub_png_init_dynamic_block (struct grub_png_data *data) - grub_uint8_t lens[DEFLATE_HCLEN_MAX]; - - nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) || - (nb > DEFLATE_HCLEN_MAX)) -@@ -533,7 +558,7 @@ grub_png_init_dynamic_block (struct grub_png_data *data) - data->dist_offset); - - prev = 0; -- for (i = 0; i < nl + nd; i++) -+ for (i = 0; i < nl + nd && grub_errno == GRUB_ERR_NONE; i++) - { - int n, code; - struct huff_table *ht; -@@ -721,17 +746,21 @@ grub_png_read_dynamic_block (struct grub_png_data *data) - len = cplens[n]; - if (cplext[n]) - len += grub_png_get_bits (data, cplext[n]); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - n = grub_png_get_huff_code (data, &data->dist_table); - dist = cpdist[n]; - if (cpdext[n]) - dist += grub_png_get_bits (data, cpdext[n]); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - pos = data->wp - dist; - if (pos < 0) - pos += WSIZE; - -- while (len > 0) -+ while (len > 0 && grub_errno == GRUB_ERR_NONE) - { - data->slide[data->wp] = data->slide[pos]; - grub_png_output_byte (data, data->slide[data->wp]); -@@ -759,7 +788,11 @@ grub_png_decode_image_data (struct grub_png_data *data) - int final; - - cmf = grub_png_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - flg = grub_png_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - if ((cmf & 0xF) != Z_DEFLATED) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, -@@ -774,7 +807,11 @@ grub_png_decode_image_data (struct grub_png_data *data) - int block_type; - - final = grub_png_get_bits (data, 1); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - block_type = grub_png_get_bits (data, 2); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - switch (block_type) - { -@@ -790,7 +827,7 @@ grub_png_decode_image_data (struct grub_png_data *data) - grub_png_get_byte (data); - grub_png_get_byte (data); - -- for (i = 0; i < len; i++) -+ for (i = 0; i < len && grub_errno == GRUB_ERR_NONE; i++) - grub_png_output_byte (data, grub_png_get_byte (data)); - - break; -@@ -1045,6 +1082,8 @@ grub_png_decode_png (struct grub_png_data *data) - - len = grub_png_get_dword (data); - type = grub_png_get_dword (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ break; - data->next_offset = data->file->offset + len + 4; - - switch (type) diff --git a/0225-video-readers-png-Sanity-check-some-huffman-codes.patch b/0225-video-readers-png-Sanity-check-some-huffman-codes.patch new file mode 100644 index 0000000..c9cef25 --- /dev/null +++ b/0225-video-readers-png-Sanity-check-some-huffman-codes.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 6 Jul 2021 19:19:11 +1000 +Subject: [PATCH] video/readers/png: Sanity check some huffman codes + +ASAN picked up two OOB global reads: we weren't checking if some code +values fit within the cplens or cpdext arrays. Check and throw an error +if not. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit c3a8ab0cbd24153ec7b1f84a96ddfdd72ef8d117) +--- + grub-core/video/readers/png.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index d7ed5aa6cf..7f2ba7849b 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -753,6 +753,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data) + int len, dist, pos; + + n -= 257; ++ if (((unsigned int) n) >= ARRAY_SIZE (cplens)) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "png: invalid huff code"); + len = cplens[n]; + if (cplext[n]) + len += grub_png_get_bits (data, cplext[n]); +@@ -760,6 +763,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data) + return grub_errno; + + n = grub_png_get_huff_code (data, &data->dist_table); ++ if (((unsigned int) n) >= ARRAY_SIZE (cpdist)) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "png: invalid huff code"); + dist = cpdist[n]; + if (cpdext[n]) + dist += grub_png_get_bits (data, cpdext[n]); diff --git a/0226-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch b/0226-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch new file mode 100644 index 0000000..5491816 --- /dev/null +++ b/0226-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch @@ -0,0 +1,255 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 28 Jun 2021 14:16:14 +1000 +Subject: [PATCH] video/readers/jpeg: Abort sooner if a read operation fails + +Fuzzing revealed some inputs that were taking a long time, potentially +forever, because they did not bail quickly upon encountering an I/O error. + +Try to catch I/O errors sooner and bail out. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit ab2e5d2e4bff488bbb557ed435a61ae102ef9f0c) +--- + grub-core/video/readers/jpeg.c | 86 ++++++++++++++++++++++++++++++++++-------- + 1 file changed, 70 insertions(+), 16 deletions(-) + +diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c +index e31602f766..10225abd53 100644 +--- a/grub-core/video/readers/jpeg.c ++++ b/grub-core/video/readers/jpeg.c +@@ -109,9 +109,17 @@ static grub_uint8_t + grub_jpeg_get_byte (struct grub_jpeg_data *data) + { + grub_uint8_t r; ++ grub_ssize_t bytes_read; + + r = 0; +- grub_file_read (data->file, &r, 1); ++ bytes_read = grub_file_read (data->file, &r, 1); ++ ++ if (bytes_read != 1) ++ { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: unexpected end of data"); ++ return 0; ++ } + + return r; + } +@@ -120,9 +128,17 @@ static grub_uint16_t + grub_jpeg_get_word (struct grub_jpeg_data *data) + { + grub_uint16_t r; ++ grub_ssize_t bytes_read; + + r = 0; +- grub_file_read (data->file, &r, sizeof (grub_uint16_t)); ++ bytes_read = grub_file_read (data->file, &r, sizeof (grub_uint16_t)); ++ ++ if (bytes_read != sizeof (grub_uint16_t)) ++ { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: unexpected end of data"); ++ return 0; ++ } + + return grub_be_to_cpu16 (r); + } +@@ -135,6 +151,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data) + if (data->bit_mask == 0) + { + data->bit_save = grub_jpeg_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: file read error"); ++ return 0; ++ } + if (data->bit_save == JPEG_ESC_CHAR) + { + if (grub_jpeg_get_byte (data) != 0) +@@ -143,6 +164,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data) + "jpeg: invalid 0xFF in data stream"); + return 0; + } ++ if (grub_errno != GRUB_ERR_NONE) ++ { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: file read error"); ++ return 0; ++ } + } + data->bit_mask = 0x80; + } +@@ -161,7 +187,7 @@ grub_jpeg_get_number (struct grub_jpeg_data *data, int num) + return 0; + + msb = value = grub_jpeg_get_bit (data); +- for (i = 1; i < num; i++) ++ for (i = 1; i < num && grub_errno == GRUB_ERR_NONE; i++) + value = (value << 1) + (grub_jpeg_get_bit (data) != 0); + if (!msb) + value += 1 - (1 << num); +@@ -202,6 +228,8 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data) + while (data->file->offset + sizeof (count) + 1 <= next_marker) + { + id = grub_jpeg_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + ac = (id >> 4) & 1; + id &= 0xF; + if (id > 1) +@@ -252,6 +280,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data) + + next_marker = data->file->offset; + next_marker += grub_jpeg_get_word (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + if (next_marker > data->file->size) + { +@@ -263,6 +293,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data) + <= next_marker) + { + id = grub_jpeg_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + if (id >= 0x10) /* Upper 4-bit is precision. */ + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "jpeg: only 8-bit precision is supported"); +@@ -294,6 +326,9 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data) + next_marker = data->file->offset; + next_marker += grub_jpeg_get_word (data); + ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; ++ + if (grub_jpeg_get_byte (data) != 8) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "jpeg: only 8-bit precision is supported"); +@@ -319,6 +354,8 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index"); + + ss = grub_jpeg_get_byte (data); /* Sampling factor. */ ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + if (!id) + { + grub_uint8_t vs, hs; +@@ -498,7 +535,7 @@ grub_jpeg_idct_transform (jpeg_data_unit_t du) + } + } + +-static void ++static grub_err_t + grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) + { + int h1, h2, qt; +@@ -513,6 +550,9 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) + data->dc_value[id] += + grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1)); + ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; ++ + du[0] = data->dc_value[id] * (int) data->quan_table[qt][0]; + pos = 1; + while (pos < ARRAY_SIZE (data->quan_table[qt])) +@@ -527,11 +567,13 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) + num >>= 4; + pos += num; + ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; ++ + if (pos >= ARRAY_SIZE (jpeg_zigzag_order)) + { +- grub_error (GRUB_ERR_BAD_FILE_TYPE, +- "jpeg: invalid position in zigzag order!?"); +- return; ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: invalid position in zigzag order!?"); + } + + du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos]; +@@ -539,6 +581,7 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) + } + + grub_jpeg_idct_transform (du); ++ return GRUB_ERR_NONE; + } + + static void +@@ -597,7 +640,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) + data_offset += grub_jpeg_get_word (data); + + cc = grub_jpeg_get_byte (data); +- ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + if (cc != 3 && cc != 1) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "jpeg: component count must be 1 or 3"); +@@ -610,7 +654,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) + id = grub_jpeg_get_byte (data) - 1; + if ((id < 0) || (id >= 3)) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index"); +- ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + ht = grub_jpeg_get_byte (data); + data->comp_index[id][1] = (ht >> 4); + data->comp_index[id][2] = (ht & 0xF) + 2; +@@ -618,11 +663,14 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) + if ((data->comp_index[id][1] < 0) || (data->comp_index[id][1] > 3) || + (data->comp_index[id][2] < 0) || (data->comp_index[id][2] > 3)) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid hufftable index"); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + } + + grub_jpeg_get_byte (data); /* Skip 3 unused bytes. */ + grub_jpeg_get_word (data); +- ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + if (data->file->offset != data_offset) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos"); + +@@ -640,6 +688,7 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) + { + unsigned c1, vb, hb, nr1, nc1; + int rst = data->dri; ++ grub_err_t err = GRUB_ERR_NONE; + + vb = 8 << data->log_vs; + hb = 8 << data->log_hs; +@@ -660,17 +709,22 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) + + for (r2 = 0; r2 < (1U << data->log_vs); r2++) + for (c2 = 0; c2 < (1U << data->log_hs); c2++) +- grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]); ++ { ++ err = grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } + + if (data->color_components >= 3) + { +- grub_jpeg_decode_du (data, 1, data->cbdu); +- grub_jpeg_decode_du (data, 2, data->crdu); ++ err = grub_jpeg_decode_du (data, 1, data->cbdu); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ err = grub_jpeg_decode_du (data, 2, data->crdu); ++ if (err != GRUB_ERR_NONE) ++ return err; + } + +- if (grub_errno) +- return grub_errno; +- + nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb; + nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb; + diff --git a/0226-video-readers-png-Refuse-to-handle-multiple-image-he.patch b/0226-video-readers-png-Refuse-to-handle-multiple-image-he.patch deleted file mode 100644 index 9168fe5..0000000 --- a/0226-video-readers-png-Refuse-to-handle-multiple-image-he.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 6 Jul 2021 14:13:40 +1000 -Subject: [PATCH] video/readers/png: Refuse to handle multiple image headers - -This causes the bitmap to be leaked. Do not permit multiple image headers. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 8ce433557adeadbc46429aabb9f850b02ad2bdfb) ---- - grub-core/video/readers/png.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c -index e2a6b1cf3c..8955b8ecfd 100644 ---- a/grub-core/video/readers/png.c -+++ b/grub-core/video/readers/png.c -@@ -258,6 +258,9 @@ grub_png_decode_image_header (struct grub_png_data *data) - int color_bits; - enum grub_video_blit_format blt; - -+ if (data->image_width || data->image_height) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: two image headers found"); -+ - data->image_width = grub_png_get_dword (data); - data->image_height = grub_png_get_dword (data); - diff --git a/0227-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch b/0227-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch new file mode 100644 index 0000000..199ec32 --- /dev/null +++ b/0227-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 28 Jun 2021 14:16:58 +1000 +Subject: [PATCH] video/readers/jpeg: Do not reallocate a given huff table + +Fix a memory leak where an invalid file could cause us to reallocate +memory for a huffman table we had already allocated memory for. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit bc06e12b4de55cc6f926af9f064170c82b1403e9) +--- + grub-core/video/readers/jpeg.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c +index 10225abd53..caa211f06d 100644 +--- a/grub-core/video/readers/jpeg.c ++++ b/grub-core/video/readers/jpeg.c +@@ -245,6 +245,9 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data) + n += count[i]; + + id += ac * 2; ++ if (data->huff_value[id] != NULL) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: attempt to reallocate huffman table"); + data->huff_value[id] = grub_malloc (n); + if (grub_errno) + return grub_errno; diff --git a/0227-video-readers-png-Drop-greyscale-support-to-fix-heap.patch b/0227-video-readers-png-Drop-greyscale-support-to-fix-heap.patch deleted file mode 100644 index 4529cb8..0000000 --- a/0227-video-readers-png-Drop-greyscale-support-to-fix-heap.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 6 Jul 2021 18:51:35 +1000 -Subject: [PATCH] video/readers/png: Drop greyscale support to fix heap - out-of-bounds write - -A 16-bit greyscale PNG without alpha is processed in the following loop: - - for (i = 0; i < (data->image_width * data->image_height); - i++, d1 += 4, d2 += 2) - { - d1[R3] = d2[1]; - d1[G3] = d2[1]; - d1[B3] = d2[1]; - } - -The increment of d1 is wrong. d1 is incremented by 4 bytes per iteration, -but there are only 3 bytes allocated for storage. This means that image -data will overwrite somewhat-attacker-controlled parts of memory - 3 bytes -out of every 4 following the end of the image. - -This has existed since greyscale support was added in 2013 in commit -3ccf16dff98f (grub-core/video/readers/png.c: Support grayscale). - -Saving starfield.png as a 16-bit greyscale image without alpha in the gimp -and attempting to load it causes grub-emu to crash - I don't think this code -has ever worked. - -Delete all PNG greyscale support. - -Fixes: CVE-2021-3695 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 0e1d163382669bd734439d8864ee969616d971d9) -[rharwood: context conflict] -Signed-off-by: Robbie Harwood ---- - grub-core/video/readers/png.c | 85 +++---------------------------------------- - 1 file changed, 6 insertions(+), 79 deletions(-) - -diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c -index 8955b8ecfd..a3161e25b6 100644 ---- a/grub-core/video/readers/png.c -+++ b/grub-core/video/readers/png.c -@@ -100,7 +100,7 @@ struct grub_png_data - - unsigned image_width, image_height; - int bpp, is_16bit; -- int raw_bytes, is_gray, is_alpha, is_palette; -+ int raw_bytes, is_alpha, is_palette; - int row_bytes, color_bits; - grub_uint8_t *image_data; - -@@ -296,13 +296,13 @@ grub_png_decode_image_header (struct grub_png_data *data) - data->bpp = 3; - else - { -- data->is_gray = 1; -- data->bpp = 1; -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "png: color type not supported"); - } - - if ((color_bits != 8) && (color_bits != 16) - && (color_bits != 4 -- || !(data->is_gray || data->is_palette))) -+ || !data->is_palette)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "png: bit depth must be 8 or 16"); - -@@ -331,7 +331,7 @@ grub_png_decode_image_header (struct grub_png_data *data) - } - - #ifndef GRUB_CPU_WORDS_BIGENDIAN -- if (data->is_16bit || data->is_gray || data->is_palette) -+ if (data->is_16bit || data->is_palette) - #endif - { - data->image_data = grub_calloc (data->image_height, data->row_bytes); -@@ -899,27 +899,8 @@ grub_png_convert_image (struct grub_png_data *data) - int shift; - int mask = (1 << data->color_bits) - 1; - unsigned j; -- if (data->is_gray) -- { -- /* Generic formula is -- (0xff * i) / ((1U << data->color_bits) - 1) -- but for allowed bit depth of 1, 2 and for it's -- equivalent to -- (0xff / ((1U << data->color_bits) - 1)) * i -- Precompute the multipliers to avoid division. -- */ - -- const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 }; -- for (i = 0; i < (1U << data->color_bits); i++) -- { -- grub_uint8_t col = multipliers[data->color_bits] * i; -- palette[i][0] = col; -- palette[i][1] = col; -- palette[i][2] = col; -- } -- } -- else -- grub_memcpy (palette, data->palette, 3 << data->color_bits); -+ grub_memcpy (palette, data->palette, 3 << data->color_bits); - d1c = d1; - d2c = d2; - for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3, -@@ -956,60 +937,6 @@ grub_png_convert_image (struct grub_png_data *data) - } - return; - } -- -- if (data->is_gray) -- { -- switch (data->bpp) -- { -- case 4: -- /* 16-bit gray with alpha. */ -- for (i = 0; i < (data->image_width * data->image_height); -- i++, d1 += 4, d2 += 4) -- { -- d1[R4] = d2[3]; -- d1[G4] = d2[3]; -- d1[B4] = d2[3]; -- d1[A4] = d2[1]; -- } -- break; -- case 2: -- if (data->is_16bit) -- /* 16-bit gray without alpha. */ -- { -- for (i = 0; i < (data->image_width * data->image_height); -- i++, d1 += 4, d2 += 2) -- { -- d1[R3] = d2[1]; -- d1[G3] = d2[1]; -- d1[B3] = d2[1]; -- } -- } -- else -- /* 8-bit gray with alpha. */ -- { -- for (i = 0; i < (data->image_width * data->image_height); -- i++, d1 += 4, d2 += 2) -- { -- d1[R4] = d2[1]; -- d1[G4] = d2[1]; -- d1[B4] = d2[1]; -- d1[A4] = d2[0]; -- } -- } -- break; -- /* 8-bit gray without alpha. */ -- case 1: -- for (i = 0; i < (data->image_width * data->image_height); -- i++, d1 += 3, d2++) -- { -- d1[R3] = d2[0]; -- d1[G3] = d2[0]; -- d1[B3] = d2[0]; -- } -- break; -- } -- return; -- } - - { - /* Only copy the upper 8 bit. */ diff --git a/0228-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch b/0228-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch new file mode 100644 index 0000000..179238b --- /dev/null +++ b/0228-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 28 Jun 2021 14:25:17 +1000 +Subject: [PATCH] video/readers/jpeg: Refuse to handle multiple start of + streams + +An invalid file could contain multiple start of stream blocks, which +would cause us to reallocate and leak our bitmap. Refuse to handle +multiple start of streams. + +Additionally, fix a grub_error() call formatting. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit f3a854def3e281b7ad4bbea730cd3046de1da52f) +--- + grub-core/video/readers/jpeg.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c +index caa211f06d..1df1171d78 100644 +--- a/grub-core/video/readers/jpeg.c ++++ b/grub-core/video/readers/jpeg.c +@@ -677,6 +677,9 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) + if (data->file->offset != data_offset) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos"); + ++ if (*data->bitmap) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: too many start of scan blocks"); ++ + if (grub_video_bitmap_create (data->bitmap, data->image_width, + data->image_height, + GRUB_VIDEO_BLIT_FORMAT_RGB_888)) +@@ -699,8 +702,8 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) + nc1 = (data->image_width + hb - 1) >> (3 + data->log_hs); + + if (data->bitmap_ptr == NULL) +- return grub_error(GRUB_ERR_BAD_FILE_TYPE, +- "jpeg: attempted to decode data before start of stream"); ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: attempted to decode data before start of stream"); + + for (; data->r1 < nr1 && (!data->dri || rst); + data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) diff --git a/0228-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch b/0228-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch deleted file mode 100644 index 51dddfe..0000000 --- a/0228-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 6 Jul 2021 23:25:07 +1000 -Subject: [PATCH] video/readers/png: Avoid heap OOB R/W inserting huff table - items - -In fuzzing we observed crashes where a code would attempt to be inserted -into a huffman table before the start, leading to a set of heap OOB reads -and writes as table entries with negative indices were shifted around and -the new code written in. - -Catch the case where we would underflow the array and bail. - -Fixes: CVE-2021-3696 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 1ae9a91d42cb40da8a6f11fac65541858e340afa) ---- - grub-core/video/readers/png.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c -index a3161e25b6..d7ed5aa6cf 100644 ---- a/grub-core/video/readers/png.c -+++ b/grub-core/video/readers/png.c -@@ -438,6 +438,13 @@ grub_png_insert_huff_item (struct huff_table *ht, int code, int len) - for (i = len; i < ht->max_length; i++) - n += ht->maxval[i]; - -+ if (n > ht->num_values) -+ { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "png: out of range inserting huffman table item"); -+ return; -+ } -+ - for (i = 0; i < n; i++) - ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1]; - diff --git a/0229-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch b/0229-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch new file mode 100644 index 0000000..99eeb62 --- /dev/null +++ b/0229-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Wed, 7 Jul 2021 15:38:19 +1000 +Subject: [PATCH] video/readers/jpeg: Block int underflow -> wild pointer write + +Certain 1 px wide images caused a wild pointer write in +grub_jpeg_ycrcb_to_rgb(). This was caused because in grub_jpeg_decode_data(), +we have the following loop: + +for (; data->r1 < nr1 && (!data->dri || rst); + data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) + +We did not check if vb * width >= hb * nc1. + +On a 64-bit platform, if that turns out to be negative, it will underflow, +be interpreted as unsigned 64-bit, then be added to the 64-bit pointer, so +we see data->bitmap_ptr jump, e.g.: + +0x6180_0000_0480 to +0x6181_0000_0498 + ^ + ~--- carry has occurred and this pointer is now far away from + any object. + +On a 32-bit platform, it will decrement the pointer, creating a pointer +that won't crash but will overwrite random data. + +Catch the underflow and error out. + +Fixes: CVE-2021-3697 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 41aeb2004db9924fecd9f2dd64bc2a5a5594a4b5) +--- + grub-core/video/readers/jpeg.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c +index 1df1171d78..2da04094b3 100644 +--- a/grub-core/video/readers/jpeg.c ++++ b/grub-core/video/readers/jpeg.c +@@ -705,6 +705,10 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "jpeg: attempted to decode data before start of stream"); + ++ if (vb * data->image_width <= hb * nc1) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: cannot decode image with these dimensions"); ++ + for (; data->r1 < nr1 && (!data->dri || rst); + data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) + for (c1 = 0; c1 < nc1 && (!data->dri || rst); diff --git a/0229-video-readers-png-Sanity-check-some-huffman-codes.patch b/0229-video-readers-png-Sanity-check-some-huffman-codes.patch deleted file mode 100644 index c9cef25..0000000 --- a/0229-video-readers-png-Sanity-check-some-huffman-codes.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 6 Jul 2021 19:19:11 +1000 -Subject: [PATCH] video/readers/png: Sanity check some huffman codes - -ASAN picked up two OOB global reads: we weren't checking if some code -values fit within the cplens or cpdext arrays. Check and throw an error -if not. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit c3a8ab0cbd24153ec7b1f84a96ddfdd72ef8d117) ---- - grub-core/video/readers/png.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c -index d7ed5aa6cf..7f2ba7849b 100644 ---- a/grub-core/video/readers/png.c -+++ b/grub-core/video/readers/png.c -@@ -753,6 +753,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data) - int len, dist, pos; - - n -= 257; -+ if (((unsigned int) n) >= ARRAY_SIZE (cplens)) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "png: invalid huff code"); - len = cplens[n]; - if (cplext[n]) - len += grub_png_get_bits (data, cplext[n]); -@@ -760,6 +763,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data) - return grub_errno; - - n = grub_png_get_huff_code (data, &data->dist_table); -+ if (((unsigned int) n) >= ARRAY_SIZE (cpdist)) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "png: invalid huff code"); - dist = cpdist[n]; - if (cpdext[n]) - dist += grub_png_get_bits (data, cpdext[n]); diff --git a/0230-normal-charset-Fix-array-out-of-bounds-formatting-un.patch b/0230-normal-charset-Fix-array-out-of-bounds-formatting-un.patch new file mode 100644 index 0000000..6e64ed8 --- /dev/null +++ b/0230-normal-charset-Fix-array-out-of-bounds-formatting-un.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 13 Jul 2021 13:24:38 +1000 +Subject: [PATCH] normal/charset: Fix array out-of-bounds formatting unicode + for display + +In some cases attempting to display arbitrary binary strings leads +to ASAN splats reading the widthspec array out of bounds. + +Check the index. If it would be out of bounds, return a width of 1. +I don't know if that's strictly correct, but we're not really expecting +great display of arbitrary binary data, and it's certainly not worse than +an OOB read. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit fdf32abc7a3928852422c0f291d8cd1dd6b34a8d) +--- + grub-core/normal/charset.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c +index 4dfcc31078..7a5a7c153c 100644 +--- a/grub-core/normal/charset.c ++++ b/grub-core/normal/charset.c +@@ -395,6 +395,8 @@ grub_unicode_estimate_width (const struct grub_unicode_glyph *c) + { + if (grub_unicode_get_comb_type (c->base)) + return 0; ++ if (((unsigned long) (c->base >> 3)) >= ARRAY_SIZE (widthspec)) ++ return 1; + if (widthspec[c->base >> 3] & (1 << (c->base & 7))) + return 2; + else diff --git a/0230-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch b/0230-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch deleted file mode 100644 index 5491816..0000000 --- a/0230-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch +++ /dev/null @@ -1,255 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 28 Jun 2021 14:16:14 +1000 -Subject: [PATCH] video/readers/jpeg: Abort sooner if a read operation fails - -Fuzzing revealed some inputs that were taking a long time, potentially -forever, because they did not bail quickly upon encountering an I/O error. - -Try to catch I/O errors sooner and bail out. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit ab2e5d2e4bff488bbb557ed435a61ae102ef9f0c) ---- - grub-core/video/readers/jpeg.c | 86 ++++++++++++++++++++++++++++++++++-------- - 1 file changed, 70 insertions(+), 16 deletions(-) - -diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c -index e31602f766..10225abd53 100644 ---- a/grub-core/video/readers/jpeg.c -+++ b/grub-core/video/readers/jpeg.c -@@ -109,9 +109,17 @@ static grub_uint8_t - grub_jpeg_get_byte (struct grub_jpeg_data *data) - { - grub_uint8_t r; -+ grub_ssize_t bytes_read; - - r = 0; -- grub_file_read (data->file, &r, 1); -+ bytes_read = grub_file_read (data->file, &r, 1); -+ -+ if (bytes_read != 1) -+ { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: unexpected end of data"); -+ return 0; -+ } - - return r; - } -@@ -120,9 +128,17 @@ static grub_uint16_t - grub_jpeg_get_word (struct grub_jpeg_data *data) - { - grub_uint16_t r; -+ grub_ssize_t bytes_read; - - r = 0; -- grub_file_read (data->file, &r, sizeof (grub_uint16_t)); -+ bytes_read = grub_file_read (data->file, &r, sizeof (grub_uint16_t)); -+ -+ if (bytes_read != sizeof (grub_uint16_t)) -+ { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: unexpected end of data"); -+ return 0; -+ } - - return grub_be_to_cpu16 (r); - } -@@ -135,6 +151,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data) - if (data->bit_mask == 0) - { - data->bit_save = grub_jpeg_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: file read error"); -+ return 0; -+ } - if (data->bit_save == JPEG_ESC_CHAR) - { - if (grub_jpeg_get_byte (data) != 0) -@@ -143,6 +164,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data) - "jpeg: invalid 0xFF in data stream"); - return 0; - } -+ if (grub_errno != GRUB_ERR_NONE) -+ { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: file read error"); -+ return 0; -+ } - } - data->bit_mask = 0x80; - } -@@ -161,7 +187,7 @@ grub_jpeg_get_number (struct grub_jpeg_data *data, int num) - return 0; - - msb = value = grub_jpeg_get_bit (data); -- for (i = 1; i < num; i++) -+ for (i = 1; i < num && grub_errno == GRUB_ERR_NONE; i++) - value = (value << 1) + (grub_jpeg_get_bit (data) != 0); - if (!msb) - value += 1 - (1 << num); -@@ -202,6 +228,8 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data) - while (data->file->offset + sizeof (count) + 1 <= next_marker) - { - id = grub_jpeg_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - ac = (id >> 4) & 1; - id &= 0xF; - if (id > 1) -@@ -252,6 +280,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data) - - next_marker = data->file->offset; - next_marker += grub_jpeg_get_word (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - if (next_marker > data->file->size) - { -@@ -263,6 +293,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data) - <= next_marker) - { - id = grub_jpeg_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - if (id >= 0x10) /* Upper 4-bit is precision. */ - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "jpeg: only 8-bit precision is supported"); -@@ -294,6 +326,9 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data) - next_marker = data->file->offset; - next_marker += grub_jpeg_get_word (data); - -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; -+ - if (grub_jpeg_get_byte (data) != 8) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "jpeg: only 8-bit precision is supported"); -@@ -319,6 +354,8 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index"); - - ss = grub_jpeg_get_byte (data); /* Sampling factor. */ -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - if (!id) - { - grub_uint8_t vs, hs; -@@ -498,7 +535,7 @@ grub_jpeg_idct_transform (jpeg_data_unit_t du) - } - } - --static void -+static grub_err_t - grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) - { - int h1, h2, qt; -@@ -513,6 +550,9 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) - data->dc_value[id] += - grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1)); - -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; -+ - du[0] = data->dc_value[id] * (int) data->quan_table[qt][0]; - pos = 1; - while (pos < ARRAY_SIZE (data->quan_table[qt])) -@@ -527,11 +567,13 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) - num >>= 4; - pos += num; - -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; -+ - if (pos >= ARRAY_SIZE (jpeg_zigzag_order)) - { -- grub_error (GRUB_ERR_BAD_FILE_TYPE, -- "jpeg: invalid position in zigzag order!?"); -- return; -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: invalid position in zigzag order!?"); - } - - du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos]; -@@ -539,6 +581,7 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) - } - - grub_jpeg_idct_transform (du); -+ return GRUB_ERR_NONE; - } - - static void -@@ -597,7 +640,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) - data_offset += grub_jpeg_get_word (data); - - cc = grub_jpeg_get_byte (data); -- -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - if (cc != 3 && cc != 1) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "jpeg: component count must be 1 or 3"); -@@ -610,7 +654,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) - id = grub_jpeg_get_byte (data) - 1; - if ((id < 0) || (id >= 3)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index"); -- -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - ht = grub_jpeg_get_byte (data); - data->comp_index[id][1] = (ht >> 4); - data->comp_index[id][2] = (ht & 0xF) + 2; -@@ -618,11 +663,14 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) - if ((data->comp_index[id][1] < 0) || (data->comp_index[id][1] > 3) || - (data->comp_index[id][2] < 0) || (data->comp_index[id][2] > 3)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid hufftable index"); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - } - - grub_jpeg_get_byte (data); /* Skip 3 unused bytes. */ - grub_jpeg_get_word (data); -- -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - if (data->file->offset != data_offset) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos"); - -@@ -640,6 +688,7 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) - { - unsigned c1, vb, hb, nr1, nc1; - int rst = data->dri; -+ grub_err_t err = GRUB_ERR_NONE; - - vb = 8 << data->log_vs; - hb = 8 << data->log_hs; -@@ -660,17 +709,22 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) - - for (r2 = 0; r2 < (1U << data->log_vs); r2++) - for (c2 = 0; c2 < (1U << data->log_hs); c2++) -- grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]); -+ { -+ err = grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ } - - if (data->color_components >= 3) - { -- grub_jpeg_decode_du (data, 1, data->cbdu); -- grub_jpeg_decode_du (data, 2, data->crdu); -+ err = grub_jpeg_decode_du (data, 1, data->cbdu); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ err = grub_jpeg_decode_du (data, 2, data->crdu); -+ if (err != GRUB_ERR_NONE) -+ return err; - } - -- if (grub_errno) -- return grub_errno; -- - nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb; - nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb; - diff --git a/0231-net-netbuff-Block-overly-large-netbuff-allocs.patch b/0231-net-netbuff-Block-overly-large-netbuff-allocs.patch new file mode 100644 index 0000000..2e10d49 --- /dev/null +++ b/0231-net-netbuff-Block-overly-large-netbuff-allocs.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 8 Mar 2022 23:47:46 +1100 +Subject: [PATCH] net/netbuff: Block overly large netbuff allocs + +A netbuff shouldn't be too huge. It's bounded by MTU and TCP segment +reassembly. + +This helps avoid some bugs (and provides a spot to instrument to catch +them at their source). + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit ee9591103004cd13b4efadda671536090ca7fd57) +--- + grub-core/net/netbuff.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c +index dbeeefe478..d5e9e9a0d7 100644 +--- a/grub-core/net/netbuff.c ++++ b/grub-core/net/netbuff.c +@@ -79,10 +79,23 @@ grub_netbuff_alloc (grub_size_t len) + + COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0); + ++ /* ++ * The largest size of a TCP packet is 64 KiB, and everything else ++ * should be a lot smaller - most MTUs are 1500 or less. Cap data ++ * size at 64 KiB + a buffer. ++ */ ++ if (len > 0xffffUL + 0x1000UL) ++ { ++ grub_error (GRUB_ERR_BUG, ++ "attempted to allocate a packet that is too big"); ++ return NULL; ++ } ++ + if (len < NETBUFFMINLEN) + len = NETBUFFMINLEN; + + len = ALIGN_UP (len, NETBUFF_ALIGN); ++ + #ifdef GRUB_MACHINE_EMU + data = grub_malloc (len + sizeof (*nb)); + #else diff --git a/0231-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch b/0231-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch deleted file mode 100644 index 199ec32..0000000 --- a/0231-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 28 Jun 2021 14:16:58 +1000 -Subject: [PATCH] video/readers/jpeg: Do not reallocate a given huff table - -Fix a memory leak where an invalid file could cause us to reallocate -memory for a huffman table we had already allocated memory for. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit bc06e12b4de55cc6f926af9f064170c82b1403e9) ---- - grub-core/video/readers/jpeg.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c -index 10225abd53..caa211f06d 100644 ---- a/grub-core/video/readers/jpeg.c -+++ b/grub-core/video/readers/jpeg.c -@@ -245,6 +245,9 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data) - n += count[i]; - - id += ac * 2; -+ if (data->huff_value[id] != NULL) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: attempt to reallocate huffman table"); - data->huff_value[id] = grub_malloc (n); - if (grub_errno) - return grub_errno; diff --git a/0232-net-ip-Do-IP-fragment-maths-safely.patch b/0232-net-ip-Do-IP-fragment-maths-safely.patch new file mode 100644 index 0000000..118448d --- /dev/null +++ b/0232-net-ip-Do-IP-fragment-maths-safely.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 20 Dec 2021 19:41:21 +1100 +Subject: [PATCH] net/ip: Do IP fragment maths safely + +This avoids an underflow and subsequent unpleasantness. + +Fixes: CVE-2022-28733 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit eb74e5743ca7e18a5e75c392fe0b21d1549a1936) +--- + grub-core/net/ip.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c +index ce6bdc75c6..cf74f1f794 100644 +--- a/grub-core/net/ip.c ++++ b/grub-core/net/ip.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + + struct iphdr { +@@ -551,7 +552,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb, + { + rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) + + (nb->tail - nb->data)); +- rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t)); ++ ++ if (grub_sub (rsm->total_len, (iph->verhdrlen & 0xf) * sizeof (grub_uint32_t), ++ &rsm->total_len)) ++ { ++ grub_dprintf ("net", "IP reassembly size underflow\n"); ++ return GRUB_ERR_NONE; ++ } ++ + rsm->asm_netbuff = grub_netbuff_alloc (rsm->total_len); + if (!rsm->asm_netbuff) + { diff --git a/0232-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch b/0232-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch deleted file mode 100644 index 179238b..0000000 --- a/0232-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 28 Jun 2021 14:25:17 +1000 -Subject: [PATCH] video/readers/jpeg: Refuse to handle multiple start of - streams - -An invalid file could contain multiple start of stream blocks, which -would cause us to reallocate and leak our bitmap. Refuse to handle -multiple start of streams. - -Additionally, fix a grub_error() call formatting. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit f3a854def3e281b7ad4bbea730cd3046de1da52f) ---- - grub-core/video/readers/jpeg.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c -index caa211f06d..1df1171d78 100644 ---- a/grub-core/video/readers/jpeg.c -+++ b/grub-core/video/readers/jpeg.c -@@ -677,6 +677,9 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) - if (data->file->offset != data_offset) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos"); - -+ if (*data->bitmap) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: too many start of scan blocks"); -+ - if (grub_video_bitmap_create (data->bitmap, data->image_width, - data->image_height, - GRUB_VIDEO_BLIT_FORMAT_RGB_888)) -@@ -699,8 +702,8 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) - nc1 = (data->image_width + hb - 1) >> (3 + data->log_hs); - - if (data->bitmap_ptr == NULL) -- return grub_error(GRUB_ERR_BAD_FILE_TYPE, -- "jpeg: attempted to decode data before start of stream"); -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: attempted to decode data before start of stream"); - - for (; data->r1 < nr1 && (!data->dri || rst); - data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) diff --git a/0233-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch b/0233-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch new file mode 100644 index 0000000..19701b6 --- /dev/null +++ b/0233-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 16 Sep 2021 01:29:54 +1000 +Subject: [PATCH] net/dns: Fix double-free addresses on corrupt DNS response + +grub_net_dns_lookup() takes as inputs a pointer to an array of addresses +("addresses") for the given name, and pointer to a number of addresses +("naddresses"). grub_net_dns_lookup() is responsible for allocating +"addresses", and the caller is responsible for freeing it if +"naddresses" > 0. + +The DNS recv_hook will sometimes set and free the addresses array, +for example if the packet is too short: + + if (ptr + 10 >= nb->tail) + { + if (!*data->naddresses) + grub_free (*data->addresses); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + +Later on the nslookup command code unconditionally frees the "addresses" +array. Normally this is fine: the array is either populated with valid +data or is NULL. But in these sorts of error cases it is neither NULL +nor valid and we get a double-free. + +Only free "addresses" if "naddresses" > 0. + +It looks like the other use of grub_net_dns_lookup() is not affected. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit eb2e69fcf51307757e43f55ee8c9354d1ee42dd1) +--- + grub-core/net/dns.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c +index 906ec7d678..135faac035 100644 +--- a/grub-core/net/dns.c ++++ b/grub-core/net/dns.c +@@ -667,9 +667,11 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)), + grub_net_addr_to_str (&addresses[i], buf); + grub_printf ("%s\n", buf); + } +- grub_free (addresses); + if (naddresses) +- return GRUB_ERR_NONE; ++ { ++ grub_free (addresses); ++ return GRUB_ERR_NONE; ++ } + return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found")); + } + diff --git a/0233-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch b/0233-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch deleted file mode 100644 index 99eeb62..0000000 --- a/0233-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Wed, 7 Jul 2021 15:38:19 +1000 -Subject: [PATCH] video/readers/jpeg: Block int underflow -> wild pointer write - -Certain 1 px wide images caused a wild pointer write in -grub_jpeg_ycrcb_to_rgb(). This was caused because in grub_jpeg_decode_data(), -we have the following loop: - -for (; data->r1 < nr1 && (!data->dri || rst); - data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) - -We did not check if vb * width >= hb * nc1. - -On a 64-bit platform, if that turns out to be negative, it will underflow, -be interpreted as unsigned 64-bit, then be added to the 64-bit pointer, so -we see data->bitmap_ptr jump, e.g.: - -0x6180_0000_0480 to -0x6181_0000_0498 - ^ - ~--- carry has occurred and this pointer is now far away from - any object. - -On a 32-bit platform, it will decrement the pointer, creating a pointer -that won't crash but will overwrite random data. - -Catch the underflow and error out. - -Fixes: CVE-2021-3697 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 41aeb2004db9924fecd9f2dd64bc2a5a5594a4b5) ---- - grub-core/video/readers/jpeg.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c -index 1df1171d78..2da04094b3 100644 ---- a/grub-core/video/readers/jpeg.c -+++ b/grub-core/video/readers/jpeg.c -@@ -705,6 +705,10 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "jpeg: attempted to decode data before start of stream"); - -+ if (vb * data->image_width <= hb * nc1) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: cannot decode image with these dimensions"); -+ - for (; data->r1 < nr1 && (!data->dri || rst); - data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) - for (c1 = 0; c1 < nc1 && (!data->dri || rst); diff --git a/0234-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch b/0234-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch new file mode 100644 index 0000000..ab0d471 --- /dev/null +++ b/0234-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 20 Dec 2021 21:55:43 +1100 +Subject: [PATCH] net/dns: Don't read past the end of the string we're checking + against + +I don't really understand what's going on here but fuzzing found +a bug where we read past the end of check_with. That's a C string, +so use grub_strlen() to make sure we don't overread it. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 6a97b3f4b1d5173aa516edc6dedbc63de7306d21) +--- + grub-core/net/dns.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c +index 135faac035..17961a9f18 100644 +--- a/grub-core/net/dns.c ++++ b/grub-core/net/dns.c +@@ -146,11 +146,18 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, + int *length, char *set) + { + const char *readable_ptr = check_with; ++ int readable_len; + const grub_uint8_t *ptr; + char *optr = set; + int bytes_processed = 0; + if (length) + *length = 0; ++ ++ if (readable_ptr != NULL) ++ readable_len = grub_strlen (readable_ptr); ++ else ++ readable_len = 0; ++ + for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; ) + { + /* End marker. */ +@@ -172,13 +179,16 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, + ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]); + continue; + } +- if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0) ++ if (readable_ptr != NULL && (*ptr > readable_len || grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0)) + return 0; + if (grub_memchr (ptr + 1, 0, *ptr) + || grub_memchr (ptr + 1, '.', *ptr)) + return 0; + if (readable_ptr) +- readable_ptr += *ptr; ++ { ++ readable_ptr += *ptr; ++ readable_len -= *ptr; ++ } + if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0) + return 0; + bytes_processed += *ptr + 1; +@@ -192,7 +202,10 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, + if (optr) + *optr++ = '.'; + if (readable_ptr && *readable_ptr) +- readable_ptr++; ++ { ++ readable_ptr++; ++ readable_len--; ++ } + ptr += *ptr + 1; + } + return 0; diff --git a/0234-normal-charset-Fix-array-out-of-bounds-formatting-un.patch b/0234-normal-charset-Fix-array-out-of-bounds-formatting-un.patch deleted file mode 100644 index 6e64ed8..0000000 --- a/0234-normal-charset-Fix-array-out-of-bounds-formatting-un.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 13 Jul 2021 13:24:38 +1000 -Subject: [PATCH] normal/charset: Fix array out-of-bounds formatting unicode - for display - -In some cases attempting to display arbitrary binary strings leads -to ASAN splats reading the widthspec array out of bounds. - -Check the index. If it would be out of bounds, return a width of 1. -I don't know if that's strictly correct, but we're not really expecting -great display of arbitrary binary data, and it's certainly not worse than -an OOB read. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit fdf32abc7a3928852422c0f291d8cd1dd6b34a8d) ---- - grub-core/normal/charset.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c -index 4dfcc31078..7a5a7c153c 100644 ---- a/grub-core/normal/charset.c -+++ b/grub-core/normal/charset.c -@@ -395,6 +395,8 @@ grub_unicode_estimate_width (const struct grub_unicode_glyph *c) - { - if (grub_unicode_get_comb_type (c->base)) - return 0; -+ if (((unsigned long) (c->base >> 3)) >= ARRAY_SIZE (widthspec)) -+ return 1; - if (widthspec[c->base >> 3] & (1 << (c->base & 7))) - return 2; - else diff --git a/0235-net-netbuff-Block-overly-large-netbuff-allocs.patch b/0235-net-netbuff-Block-overly-large-netbuff-allocs.patch deleted file mode 100644 index 2e10d49..0000000 --- a/0235-net-netbuff-Block-overly-large-netbuff-allocs.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 8 Mar 2022 23:47:46 +1100 -Subject: [PATCH] net/netbuff: Block overly large netbuff allocs - -A netbuff shouldn't be too huge. It's bounded by MTU and TCP segment -reassembly. - -This helps avoid some bugs (and provides a spot to instrument to catch -them at their source). - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit ee9591103004cd13b4efadda671536090ca7fd57) ---- - grub-core/net/netbuff.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c -index dbeeefe478..d5e9e9a0d7 100644 ---- a/grub-core/net/netbuff.c -+++ b/grub-core/net/netbuff.c -@@ -79,10 +79,23 @@ grub_netbuff_alloc (grub_size_t len) - - COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0); - -+ /* -+ * The largest size of a TCP packet is 64 KiB, and everything else -+ * should be a lot smaller - most MTUs are 1500 or less. Cap data -+ * size at 64 KiB + a buffer. -+ */ -+ if (len > 0xffffUL + 0x1000UL) -+ { -+ grub_error (GRUB_ERR_BUG, -+ "attempted to allocate a packet that is too big"); -+ return NULL; -+ } -+ - if (len < NETBUFFMINLEN) - len = NETBUFFMINLEN; - - len = ALIGN_UP (len, NETBUFF_ALIGN); -+ - #ifdef GRUB_MACHINE_EMU - data = grub_malloc (len + sizeof (*nb)); - #else diff --git a/0235-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch b/0235-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch new file mode 100644 index 0000000..3ff7b6b --- /dev/null +++ b/0235-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch @@ -0,0 +1,112 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 20 Sep 2021 01:12:24 +1000 +Subject: [PATCH] net/tftp: Prevent a UAF and double-free from a failed seek + +A malicious tftp server can cause UAFs and a double free. + +An attempt to read from a network file is handled by grub_net_fs_read(). If +the read is at an offset other than the current offset, grub_net_seek_real() +is invoked. + +In grub_net_seek_real(), if a backwards seek cannot be satisfied from the +currently received packets, and the underlying transport does not provide +a seek method, then grub_net_seek_real() will close and reopen the network +protocol layer. + +For tftp, the ->close() call goes to tftp_close() and frees the tftp_data_t +file->data. The file->data pointer is not nulled out after the free. + +If the ->open() call fails, the file->data will not be reallocated and will +continue point to a freed memory block. This could happen from a server +refusing to send the requisite ack to the new tftp request, for example. + +The seek and the read will then fail, but the grub_file continues to exist: +the failed seek does not necessarily cause the entire file to be thrown +away (e.g. where the file is checked to see if it is gzipped/lzio/xz/etc., +a read failure is interpreted as a decompressor passing on the file, not as +an invalidation of the entire grub_file_t structure). + +This means subsequent attempts to read or seek the file will use the old +file->data after free. Eventually, the file will be close()d again and +file->data will be freed again. + +Mark a net_fs file that doesn't reopen as broken. Do not permit read() or +close() on a broken file (seek is not exposed directly to the file API - +it is only called as part of read, so this blocks seeks as well). + +As an additional defence, null out the ->data pointer if tftp_open() fails. +That would have lead to a simple null pointer dereference rather than +a mess of UAFs. + +This may affect other protocols, I haven't checked. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit dada1dda695439bb55b2848dddc2d89843552f81) +--- + grub-core/net/net.c | 11 +++++++++-- + grub-core/net/tftp.c | 1 + + include/grub/net.h | 1 + + 3 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 55aed92722..1001c611d1 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -1625,7 +1625,8 @@ grub_net_fs_close (grub_file_t file) + grub_netbuff_free (file->device->net->packs.first->nb); + grub_net_remove_packet (file->device->net->packs.first); + } +- file->device->net->protocol->close (file); ++ if (!file->device->net->broken) ++ file->device->net->protocol->close (file); + grub_free (file->device->net->name); + return GRUB_ERR_NONE; + } +@@ -1847,7 +1848,10 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) + file->device->net->stall = 0; + err = file->device->net->protocol->open (file, file->device->net->name); + if (err) +- return err; ++ { ++ file->device->net->broken = 1; ++ return err; ++ } + grub_net_fs_read_real (file, NULL, offset); + return grub_errno; + } +@@ -1856,6 +1860,9 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) + static grub_ssize_t + grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) + { ++ if (file->device->net->broken) ++ return -1; ++ + if (file->offset != file->device->net->offset) + { + grub_err_t err; +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index d54b13f09f..788ad1dc44 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -408,6 +408,7 @@ tftp_open (struct grub_file *file, const char *filename) + { + grub_net_udp_close (data->sock); + grub_free (data); ++ file->data = NULL; + return grub_errno; + } + +diff --git a/include/grub/net.h b/include/grub/net.h +index 42af7de250..9e4898cc6b 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -280,6 +280,7 @@ typedef struct grub_net + grub_fs_t fs; + int eof; + int stall; ++ int broken; + } *grub_net_t; + + extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); diff --git a/0236-net-ip-Do-IP-fragment-maths-safely.patch b/0236-net-ip-Do-IP-fragment-maths-safely.patch deleted file mode 100644 index 118448d..0000000 --- a/0236-net-ip-Do-IP-fragment-maths-safely.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 20 Dec 2021 19:41:21 +1100 -Subject: [PATCH] net/ip: Do IP fragment maths safely - -This avoids an underflow and subsequent unpleasantness. - -Fixes: CVE-2022-28733 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit eb74e5743ca7e18a5e75c392fe0b21d1549a1936) ---- - grub-core/net/ip.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c -index ce6bdc75c6..cf74f1f794 100644 ---- a/grub-core/net/ip.c -+++ b/grub-core/net/ip.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include - - struct iphdr { -@@ -551,7 +552,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb, - { - rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) - + (nb->tail - nb->data)); -- rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t)); -+ -+ if (grub_sub (rsm->total_len, (iph->verhdrlen & 0xf) * sizeof (grub_uint32_t), -+ &rsm->total_len)) -+ { -+ grub_dprintf ("net", "IP reassembly size underflow\n"); -+ return GRUB_ERR_NONE; -+ } -+ - rsm->asm_netbuff = grub_netbuff_alloc (rsm->total_len); - if (!rsm->asm_netbuff) - { diff --git a/0236-net-tftp-Avoid-a-trivial-UAF.patch b/0236-net-tftp-Avoid-a-trivial-UAF.patch new file mode 100644 index 0000000..4ec3b56 --- /dev/null +++ b/0236-net-tftp-Avoid-a-trivial-UAF.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 18 Jan 2022 14:29:20 +1100 +Subject: [PATCH] net/tftp: Avoid a trivial UAF + +Under tftp errors, we print a tftp error message from the tftp header. +However, the tftph pointer is a pointer inside nb, the netbuff. Previously, +we were freeing the nb and then dereferencing it. Don't do that, use it +and then free it later. + +This isn't really _bad_ per se, especially as we're single-threaded, but +it trips up fuzzers. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 956f4329cec23e4375182030ca9b2be631a61ba5) +--- + grub-core/net/tftp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index 788ad1dc44..a95766dcbd 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -251,9 +251,9 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), + return GRUB_ERR_NONE; + case TFTP_ERROR: + data->have_oack = 1; +- grub_netbuff_free (nb); + grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg); + grub_error_save (&data->save_err); ++ grub_netbuff_free (nb); + return GRUB_ERR_NONE; + default: + grub_netbuff_free (nb); diff --git a/0237-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch b/0237-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch deleted file mode 100644 index 19701b6..0000000 --- a/0237-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 16 Sep 2021 01:29:54 +1000 -Subject: [PATCH] net/dns: Fix double-free addresses on corrupt DNS response - -grub_net_dns_lookup() takes as inputs a pointer to an array of addresses -("addresses") for the given name, and pointer to a number of addresses -("naddresses"). grub_net_dns_lookup() is responsible for allocating -"addresses", and the caller is responsible for freeing it if -"naddresses" > 0. - -The DNS recv_hook will sometimes set and free the addresses array, -for example if the packet is too short: - - if (ptr + 10 >= nb->tail) - { - if (!*data->naddresses) - grub_free (*data->addresses); - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - -Later on the nslookup command code unconditionally frees the "addresses" -array. Normally this is fine: the array is either populated with valid -data or is NULL. But in these sorts of error cases it is neither NULL -nor valid and we get a double-free. - -Only free "addresses" if "naddresses" > 0. - -It looks like the other use of grub_net_dns_lookup() is not affected. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit eb2e69fcf51307757e43f55ee8c9354d1ee42dd1) ---- - grub-core/net/dns.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c -index 906ec7d678..135faac035 100644 ---- a/grub-core/net/dns.c -+++ b/grub-core/net/dns.c -@@ -667,9 +667,11 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)), - grub_net_addr_to_str (&addresses[i], buf); - grub_printf ("%s\n", buf); - } -- grub_free (addresses); - if (naddresses) -- return GRUB_ERR_NONE; -+ { -+ grub_free (addresses); -+ return GRUB_ERR_NONE; -+ } - return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found")); - } - diff --git a/0237-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch b/0237-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch new file mode 100644 index 0000000..186f0c3 --- /dev/null +++ b/0237-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 1 Mar 2022 23:14:15 +1100 +Subject: [PATCH] net/http: Do not tear down socket if it's already been torn + down + +It's possible for data->sock to get torn down in tcp error handling. +If we unconditionally tear it down again we will end up doing writes +to an offset of the NULL pointer when we go to tear it down again. + +Detect if it has been torn down and don't do it again. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit ec233d3ecf995293304de443579aab5c46c49e85) +--- + grub-core/net/http.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 7f878b5615..19cb8768e3 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -427,7 +427,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) + return err; + } + +- for (i = 0; !data->headers_recv && i < 100; i++) ++ for (i = 0; data->sock && !data->headers_recv && i < 100; i++) + { + grub_net_tcp_retransmit (); + grub_net_poll_cards (300, &data->headers_recv); +@@ -435,7 +435,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) + + if (!data->headers_recv) + { +- grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); ++ if (data->sock) ++ grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + if (data->err) + { + char *str = data->errmsg; diff --git a/0238-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch b/0238-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch deleted file mode 100644 index ab0d471..0000000 --- a/0238-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 20 Dec 2021 21:55:43 +1100 -Subject: [PATCH] net/dns: Don't read past the end of the string we're checking - against - -I don't really understand what's going on here but fuzzing found -a bug where we read past the end of check_with. That's a C string, -so use grub_strlen() to make sure we don't overread it. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 6a97b3f4b1d5173aa516edc6dedbc63de7306d21) ---- - grub-core/net/dns.c | 19 ++++++++++++++++--- - 1 file changed, 16 insertions(+), 3 deletions(-) - -diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c -index 135faac035..17961a9f18 100644 ---- a/grub-core/net/dns.c -+++ b/grub-core/net/dns.c -@@ -146,11 +146,18 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, - int *length, char *set) - { - const char *readable_ptr = check_with; -+ int readable_len; - const grub_uint8_t *ptr; - char *optr = set; - int bytes_processed = 0; - if (length) - *length = 0; -+ -+ if (readable_ptr != NULL) -+ readable_len = grub_strlen (readable_ptr); -+ else -+ readable_len = 0; -+ - for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; ) - { - /* End marker. */ -@@ -172,13 +179,16 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, - ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]); - continue; - } -- if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0) -+ if (readable_ptr != NULL && (*ptr > readable_len || grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0)) - return 0; - if (grub_memchr (ptr + 1, 0, *ptr) - || grub_memchr (ptr + 1, '.', *ptr)) - return 0; - if (readable_ptr) -- readable_ptr += *ptr; -+ { -+ readable_ptr += *ptr; -+ readable_len -= *ptr; -+ } - if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0) - return 0; - bytes_processed += *ptr + 1; -@@ -192,7 +202,10 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, - if (optr) - *optr++ = '.'; - if (readable_ptr && *readable_ptr) -- readable_ptr++; -+ { -+ readable_ptr++; -+ readable_len--; -+ } - ptr += *ptr + 1; - } - return 0; diff --git a/0238-net-http-Fix-OOB-write-for-split-http-headers.patch b/0238-net-http-Fix-OOB-write-for-split-http-headers.patch new file mode 100644 index 0000000..f22960b --- /dev/null +++ b/0238-net-http-Fix-OOB-write-for-split-http-headers.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 8 Mar 2022 18:17:03 +1100 +Subject: [PATCH] net/http: Fix OOB write for split http headers + +GRUB has special code for handling an http header that is split +across two packets. + +The code tracks the end of line by looking for a "\n" byte. The +code for split headers has always advanced the pointer just past the +end of the line, whereas the code that handles unsplit headers does +not advance the pointer. This extra advance causes the length to be +one greater, which breaks an assumption in parse_line(), leading to +it writing a NUL byte one byte past the end of the buffer where we +reconstruct the line from the two packets. + +It's conceivable that an attacker controlled set of packets could +cause this to zero out the first byte of the "next" pointer of the +grub_mm_region structure following the current_line buffer. + +Do not advance the pointer in the split header case. + +Fixes: CVE-2022-28734 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit e9fb459638811c12b0989dbf64e3e124974ef617) +--- + grub-core/net/http.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 19cb8768e3..58546739a2 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -193,9 +193,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), + int have_line = 1; + char *t; + ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data); +- if (ptr) +- ptr++; +- else ++ if (ptr == NULL) + { + have_line = 0; + ptr = (char *) nb->tail; diff --git a/0239-net-http-Error-out-on-headers-with-LF-without-CR.patch b/0239-net-http-Error-out-on-headers-with-LF-without-CR.patch new file mode 100644 index 0000000..b73c169 --- /dev/null +++ b/0239-net-http-Error-out-on-headers-with-LF-without-CR.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 8 Mar 2022 19:04:40 +1100 +Subject: [PATCH] net/http: Error out on headers with LF without CR + +In a similar vein to the previous patch, parse_line() would write +a NUL byte past the end of the buffer if there was an HTTP header +with a LF rather than a CRLF. + +RFC-2616 says: + + Many HTTP/1.1 header field values consist of words separated by LWS + or special characters. These special characters MUST be in a quoted + string to be used within a parameter value (as defined in section 3.6). + +We don't support quoted sections or continuation lines, etc. + +If we see an LF that's not part of a CRLF, bail out. + +Fixes: CVE-2022-28734 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit d232ad41ac4979a9de4d746e5fdff9caf0e303de) +--- + grub-core/net/http.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 58546739a2..57d2721719 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -69,7 +69,15 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len) + char *end = ptr + len; + while (end > ptr && *(end - 1) == '\r') + end--; ++ ++ /* LF without CR. */ ++ if (end == ptr + len) ++ { ++ data->errmsg = grub_strdup (_("invalid HTTP header - LF without CR")); ++ return GRUB_ERR_NONE; ++ } + *end = 0; ++ + /* Trailing CRLF. */ + if (data->in_chunk_len == 1) + { diff --git a/0239-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch b/0239-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch deleted file mode 100644 index 3ff7b6b..0000000 --- a/0239-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 20 Sep 2021 01:12:24 +1000 -Subject: [PATCH] net/tftp: Prevent a UAF and double-free from a failed seek - -A malicious tftp server can cause UAFs and a double free. - -An attempt to read from a network file is handled by grub_net_fs_read(). If -the read is at an offset other than the current offset, grub_net_seek_real() -is invoked. - -In grub_net_seek_real(), if a backwards seek cannot be satisfied from the -currently received packets, and the underlying transport does not provide -a seek method, then grub_net_seek_real() will close and reopen the network -protocol layer. - -For tftp, the ->close() call goes to tftp_close() and frees the tftp_data_t -file->data. The file->data pointer is not nulled out after the free. - -If the ->open() call fails, the file->data will not be reallocated and will -continue point to a freed memory block. This could happen from a server -refusing to send the requisite ack to the new tftp request, for example. - -The seek and the read will then fail, but the grub_file continues to exist: -the failed seek does not necessarily cause the entire file to be thrown -away (e.g. where the file is checked to see if it is gzipped/lzio/xz/etc., -a read failure is interpreted as a decompressor passing on the file, not as -an invalidation of the entire grub_file_t structure). - -This means subsequent attempts to read or seek the file will use the old -file->data after free. Eventually, the file will be close()d again and -file->data will be freed again. - -Mark a net_fs file that doesn't reopen as broken. Do not permit read() or -close() on a broken file (seek is not exposed directly to the file API - -it is only called as part of read, so this blocks seeks as well). - -As an additional defence, null out the ->data pointer if tftp_open() fails. -That would have lead to a simple null pointer dereference rather than -a mess of UAFs. - -This may affect other protocols, I haven't checked. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit dada1dda695439bb55b2848dddc2d89843552f81) ---- - grub-core/net/net.c | 11 +++++++++-- - grub-core/net/tftp.c | 1 + - include/grub/net.h | 1 + - 3 files changed, 11 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/net.c b/grub-core/net/net.c -index 55aed92722..1001c611d1 100644 ---- a/grub-core/net/net.c -+++ b/grub-core/net/net.c -@@ -1625,7 +1625,8 @@ grub_net_fs_close (grub_file_t file) - grub_netbuff_free (file->device->net->packs.first->nb); - grub_net_remove_packet (file->device->net->packs.first); - } -- file->device->net->protocol->close (file); -+ if (!file->device->net->broken) -+ file->device->net->protocol->close (file); - grub_free (file->device->net->name); - return GRUB_ERR_NONE; - } -@@ -1847,7 +1848,10 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) - file->device->net->stall = 0; - err = file->device->net->protocol->open (file, file->device->net->name); - if (err) -- return err; -+ { -+ file->device->net->broken = 1; -+ return err; -+ } - grub_net_fs_read_real (file, NULL, offset); - return grub_errno; - } -@@ -1856,6 +1860,9 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) - static grub_ssize_t - grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) - { -+ if (file->device->net->broken) -+ return -1; -+ - if (file->offset != file->device->net->offset) - { - grub_err_t err; -diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c -index d54b13f09f..788ad1dc44 100644 ---- a/grub-core/net/tftp.c -+++ b/grub-core/net/tftp.c -@@ -408,6 +408,7 @@ tftp_open (struct grub_file *file, const char *filename) - { - grub_net_udp_close (data->sock); - grub_free (data); -+ file->data = NULL; - return grub_errno; - } - -diff --git a/include/grub/net.h b/include/grub/net.h -index 42af7de250..9e4898cc6b 100644 ---- a/include/grub/net.h -+++ b/include/grub/net.h -@@ -280,6 +280,7 @@ typedef struct grub_net - grub_fs_t fs; - int eof; - int stall; -+ int broken; - } *grub_net_t; - - extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); diff --git a/0240-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch b/0240-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch new file mode 100644 index 0000000..79df1c2 --- /dev/null +++ b/0240-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +Date: Wed, 6 Apr 2022 18:03:37 +0530 +Subject: [PATCH] fs/f2fs: Do not read past the end of nat journal entries + +A corrupt f2fs file system could specify a nat journal entry count +that is beyond the maximum NAT_JOURNAL_ENTRIES. + +Check if the specified nat journal entry count before accessing the +array, and throw an error if it is too large. + +Signed-off-by: Sudhakar Kuppusamy +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit a3988cb3f0a108dd67ac127a79a4c8479d23334e) +--- + grub-core/fs/f2fs.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c +index 8a9992ca9e..63702214b0 100644 +--- a/grub-core/fs/f2fs.c ++++ b/grub-core/fs/f2fs.c +@@ -632,23 +632,27 @@ get_nat_journal (struct grub_f2fs_data *data) + return err; + } + +-static grub_uint32_t +-get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid) ++static grub_err_t ++get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid, ++ grub_uint32_t *blkaddr) + { + grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats); +- grub_uint32_t blkaddr = 0; + grub_uint16_t i; + ++ if (n >= NAT_JOURNAL_ENTRIES) ++ return grub_error (GRUB_ERR_BAD_FS, ++ "invalid number of nat journal entries"); ++ + for (i = 0; i < n; i++) + { + if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid) + { +- blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr); ++ *blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr); + break; + } + } + +- return blkaddr; ++ return GRUB_ERR_NONE; + } + + static grub_uint32_t +@@ -656,10 +660,13 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) + { + struct grub_f2fs_nat_block *nat_block; + grub_uint32_t seg_off, block_off, entry_off, block_addr; +- grub_uint32_t blkaddr; ++ grub_uint32_t blkaddr = 0; + grub_err_t err; + +- blkaddr = get_blkaddr_from_nat_journal (data, nid); ++ err = get_blkaddr_from_nat_journal (data, nid, &blkaddr); ++ if (err != GRUB_ERR_NONE) ++ return 0; ++ + if (blkaddr) + return blkaddr; + diff --git a/0240-net-tftp-Avoid-a-trivial-UAF.patch b/0240-net-tftp-Avoid-a-trivial-UAF.patch deleted file mode 100644 index 4ec3b56..0000000 --- a/0240-net-tftp-Avoid-a-trivial-UAF.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 18 Jan 2022 14:29:20 +1100 -Subject: [PATCH] net/tftp: Avoid a trivial UAF - -Under tftp errors, we print a tftp error message from the tftp header. -However, the tftph pointer is a pointer inside nb, the netbuff. Previously, -we were freeing the nb and then dereferencing it. Don't do that, use it -and then free it later. - -This isn't really _bad_ per se, especially as we're single-threaded, but -it trips up fuzzers. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 956f4329cec23e4375182030ca9b2be631a61ba5) ---- - grub-core/net/tftp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c -index 788ad1dc44..a95766dcbd 100644 ---- a/grub-core/net/tftp.c -+++ b/grub-core/net/tftp.c -@@ -251,9 +251,9 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), - return GRUB_ERR_NONE; - case TFTP_ERROR: - data->have_oack = 1; -- grub_netbuff_free (nb); - grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg); - grub_error_save (&data->save_err); -+ grub_netbuff_free (nb); - return GRUB_ERR_NONE; - default: - grub_netbuff_free (nb); diff --git a/0241-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch b/0241-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch new file mode 100644 index 0000000..855e882 --- /dev/null +++ b/0241-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch @@ -0,0 +1,132 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +Date: Wed, 6 Apr 2022 18:49:09 +0530 +Subject: [PATCH] fs/f2fs: Do not read past the end of nat bitmap + +A corrupt f2fs filesystem could have a block offset or a bitmap +offset that would cause us to read beyond the bounds of the nat +bitmap. + +Introduce the nat_bitmap_size member in grub_f2fs_data which holds +the size of nat bitmap. + +Set the size when loading the nat bitmap in nat_bitmap_ptr(), and +catch when an invalid offset would create a pointer past the end of +the allocated space. + +Check against the bitmap size in grub_f2fs_test_bit() test bit to avoid +reading past the end of the nat bitmap. + +Signed-off-by: Sudhakar Kuppusamy +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 62d63d5e38c67a6e349148bf7cb87c560e935a7e) +--- + grub-core/fs/f2fs.c | 33 +++++++++++++++++++++++++++------ + 1 file changed, 27 insertions(+), 6 deletions(-) + +diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c +index 63702214b0..8898b235e0 100644 +--- a/grub-core/fs/f2fs.c ++++ b/grub-core/fs/f2fs.c +@@ -122,6 +122,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define F2FS_INLINE_DOTS 0x10 /* File having implicit dot dentries. */ + + #define MAX_VOLUME_NAME 512 ++#define MAX_NAT_BITMAP_SIZE 3900 + + enum FILE_TYPE + { +@@ -183,7 +184,7 @@ struct grub_f2fs_checkpoint + grub_uint32_t checksum_offset; + grub_uint64_t elapsed_time; + grub_uint8_t alloc_type[MAX_ACTIVE_LOGS]; +- grub_uint8_t sit_nat_version_bitmap[3900]; ++ grub_uint8_t sit_nat_version_bitmap[MAX_NAT_BITMAP_SIZE]; + grub_uint32_t checksum; + } GRUB_PACKED; + +@@ -302,6 +303,7 @@ struct grub_f2fs_data + + struct grub_f2fs_nat_journal nat_j; + char *nat_bitmap; ++ grub_uint32_t nat_bitmap_size; + + grub_disk_t disk; + struct grub_f2fs_node *inode; +@@ -377,15 +379,20 @@ sum_blk_addr (struct grub_f2fs_data *data, int base, int type) + } + + static void * +-nat_bitmap_ptr (struct grub_f2fs_data *data) ++nat_bitmap_ptr (struct grub_f2fs_data *data, grub_uint32_t *nat_bitmap_size) + { + struct grub_f2fs_checkpoint *ckpt = &data->ckpt; + grub_uint32_t offset; ++ *nat_bitmap_size = MAX_NAT_BITMAP_SIZE; + + if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0) + return ckpt->sit_nat_version_bitmap; + + offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize); ++ if (offset >= MAX_NAT_BITMAP_SIZE) ++ return NULL; ++ ++ *nat_bitmap_size = *nat_bitmap_size - offset; + + return ckpt->sit_nat_version_bitmap + offset; + } +@@ -438,11 +445,15 @@ grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len) + } + + static int +-grub_f2fs_test_bit (grub_uint32_t nr, const char *p) ++grub_f2fs_test_bit (grub_uint32_t nr, const char *p, grub_uint32_t len) + { + int mask; ++ grub_uint32_t shifted_nr = (nr >> 3); + +- p += (nr >> 3); ++ if (shifted_nr >= len) ++ return -1; ++ ++ p += shifted_nr; + mask = 1 << (7 - (nr & 0x07)); + + return mask & *p; +@@ -662,6 +673,7 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) + grub_uint32_t seg_off, block_off, entry_off, block_addr; + grub_uint32_t blkaddr = 0; + grub_err_t err; ++ int result_bit; + + err = get_blkaddr_from_nat_journal (data, nid, &blkaddr); + if (err != GRUB_ERR_NONE) +@@ -682,8 +694,15 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) + ((seg_off * data->blocks_per_seg) << 1) + + (block_off & (data->blocks_per_seg - 1)); + +- if (grub_f2fs_test_bit (block_off, data->nat_bitmap)) ++ result_bit = grub_f2fs_test_bit (block_off, data->nat_bitmap, ++ data->nat_bitmap_size); ++ if (result_bit > 0) + block_addr += data->blocks_per_seg; ++ else if (result_bit == -1) ++ { ++ grub_free (nat_block); ++ return 0; ++ } + + err = grub_f2fs_block_read (data, block_addr, nat_block); + if (err) +@@ -833,7 +852,9 @@ grub_f2fs_mount (grub_disk_t disk) + if (err) + goto fail; + +- data->nat_bitmap = nat_bitmap_ptr (data); ++ data->nat_bitmap = nat_bitmap_ptr (data, &data->nat_bitmap_size); ++ if (data->nat_bitmap == NULL) ++ goto fail; + + err = get_nat_journal (data); + if (err) diff --git a/0241-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch b/0241-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch deleted file mode 100644 index 186f0c3..0000000 --- a/0241-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 1 Mar 2022 23:14:15 +1100 -Subject: [PATCH] net/http: Do not tear down socket if it's already been torn - down - -It's possible for data->sock to get torn down in tcp error handling. -If we unconditionally tear it down again we will end up doing writes -to an offset of the NULL pointer when we go to tear it down again. - -Detect if it has been torn down and don't do it again. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit ec233d3ecf995293304de443579aab5c46c49e85) ---- - grub-core/net/http.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/http.c b/grub-core/net/http.c -index 7f878b5615..19cb8768e3 100644 ---- a/grub-core/net/http.c -+++ b/grub-core/net/http.c -@@ -427,7 +427,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) - return err; - } - -- for (i = 0; !data->headers_recv && i < 100; i++) -+ for (i = 0; data->sock && !data->headers_recv && i < 100; i++) - { - grub_net_tcp_retransmit (); - grub_net_poll_cards (300, &data->headers_recv); -@@ -435,7 +435,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) - - if (!data->headers_recv) - { -- grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); -+ if (data->sock) -+ grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); - if (data->err) - { - char *str = data->errmsg; diff --git a/0242-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch b/0242-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch new file mode 100644 index 0000000..0553d60 --- /dev/null +++ b/0242-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +Date: Wed, 6 Apr 2022 18:17:43 +0530 +Subject: [PATCH] fs/f2fs: Do not copy file names that are too long + +A corrupt f2fs file system might specify a name length which is greater +than the maximum name length supported by the GRUB f2fs driver. + +We will allocate enough memory to store the overly long name, but there +are only F2FS_NAME_LEN bytes in the source, so we would read past the end +of the source. + +While checking directory entries, do not copy a file name with an invalid +length. + +Signed-off-by: Sudhakar Kuppusamy +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 9a891f638509e031d322c94e3cbcf38d36f3993a) +--- + grub-core/fs/f2fs.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c +index 8898b235e0..df6beb544c 100644 +--- a/grub-core/fs/f2fs.c ++++ b/grub-core/fs/f2fs.c +@@ -1003,6 +1003,10 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx) + + ftype = ctx->dentry[i].file_type; + name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len); ++ ++ if (name_len >= F2FS_NAME_LEN) ++ return 0; ++ + filename = grub_malloc (name_len + 1); + if (!filename) + return 0; diff --git a/0242-net-http-Fix-OOB-write-for-split-http-headers.patch b/0242-net-http-Fix-OOB-write-for-split-http-headers.patch deleted file mode 100644 index f22960b..0000000 --- a/0242-net-http-Fix-OOB-write-for-split-http-headers.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 8 Mar 2022 18:17:03 +1100 -Subject: [PATCH] net/http: Fix OOB write for split http headers - -GRUB has special code for handling an http header that is split -across two packets. - -The code tracks the end of line by looking for a "\n" byte. The -code for split headers has always advanced the pointer just past the -end of the line, whereas the code that handles unsplit headers does -not advance the pointer. This extra advance causes the length to be -one greater, which breaks an assumption in parse_line(), leading to -it writing a NUL byte one byte past the end of the buffer where we -reconstruct the line from the two packets. - -It's conceivable that an attacker controlled set of packets could -cause this to zero out the first byte of the "next" pointer of the -grub_mm_region structure following the current_line buffer. - -Do not advance the pointer in the split header case. - -Fixes: CVE-2022-28734 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit e9fb459638811c12b0989dbf64e3e124974ef617) ---- - grub-core/net/http.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/grub-core/net/http.c b/grub-core/net/http.c -index 19cb8768e3..58546739a2 100644 ---- a/grub-core/net/http.c -+++ b/grub-core/net/http.c -@@ -193,9 +193,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), - int have_line = 1; - char *t; - ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data); -- if (ptr) -- ptr++; -- else -+ if (ptr == NULL) - { - have_line = 0; - ptr = (char *) nb->tail; diff --git a/0243-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch b/0243-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch new file mode 100644 index 0000000..7ff5821 --- /dev/null +++ b/0243-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darren Kenny +Date: Tue, 29 Mar 2022 10:49:56 +0000 +Subject: [PATCH] fs/btrfs: Fix several fuzz issues with invalid dir item + sizing + +According to the btrfs code in Linux, the structure of a directory item +leaf should be of the form: + + |struct btrfs_dir_item|name|data| + +in GRUB the name len and data len are in the grub_btrfs_dir_item +structure's n and m fields respectively. + +The combined size of the structure, name and data should be less than +the allocated memory, a difference to the Linux kernel's struct +btrfs_dir_item is that the grub_btrfs_dir_item has an extra field for +where the name is stored, so we adjust for that too. + +Signed-off-by: Darren Kenny +Reviewed-by: Daniel Kiper +(cherry picked from commit 6d3f06c0b6a8992b9b1bb0e62af93ac5ff2781f0) +[rharwood: we've an extra variable here] +Signed-off-by: Robbie Harwood +--- + grub-core/fs/btrfs.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 07c0ff874b..2fcfb738fe 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -2254,6 +2254,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, + grub_uint64_t tree; + grub_uint8_t type; + char *new_path = NULL; ++ grub_size_t est_size = 0; + + if (!data) + return grub_errno; +@@ -2320,6 +2321,18 @@ grub_btrfs_dir (grub_device_t device, const char *path, + break; + } + ++ if (direl == NULL || ++ grub_add (grub_le_to_cpu16 (direl->n), ++ grub_le_to_cpu16 (direl->m), &est_size) || ++ grub_add (est_size, sizeof (*direl), &est_size) || ++ grub_sub (est_size, sizeof (direl->name), &est_size) || ++ est_size > allocated) ++ { ++ grub_errno = GRUB_ERR_OUT_OF_RANGE; ++ r = -grub_errno; ++ goto out; ++ } ++ + for (cdirel = direl; + (grub_uint8_t *) cdirel - (grub_uint8_t *) direl + < (grub_ssize_t) elemsize; +@@ -2330,6 +2343,19 @@ grub_btrfs_dir (grub_device_t device, const char *path, + char c; + struct grub_btrfs_inode inode; + struct grub_dirhook_info info; ++ ++ if (cdirel == NULL || ++ grub_add (grub_le_to_cpu16 (cdirel->n), ++ grub_le_to_cpu16 (cdirel->m), &est_size) || ++ grub_add (est_size, sizeof (*cdirel), &est_size) || ++ grub_sub (est_size, sizeof (cdirel->name), &est_size) || ++ est_size > allocated) ++ { ++ grub_errno = GRUB_ERR_OUT_OF_RANGE; ++ r = -grub_errno; ++ goto out; ++ } ++ + err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id, + tree); + grub_memset (&info, 0, sizeof (info)); diff --git a/0243-net-http-Error-out-on-headers-with-LF-without-CR.patch b/0243-net-http-Error-out-on-headers-with-LF-without-CR.patch deleted file mode 100644 index b73c169..0000000 --- a/0243-net-http-Error-out-on-headers-with-LF-without-CR.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 8 Mar 2022 19:04:40 +1100 -Subject: [PATCH] net/http: Error out on headers with LF without CR - -In a similar vein to the previous patch, parse_line() would write -a NUL byte past the end of the buffer if there was an HTTP header -with a LF rather than a CRLF. - -RFC-2616 says: - - Many HTTP/1.1 header field values consist of words separated by LWS - or special characters. These special characters MUST be in a quoted - string to be used within a parameter value (as defined in section 3.6). - -We don't support quoted sections or continuation lines, etc. - -If we see an LF that's not part of a CRLF, bail out. - -Fixes: CVE-2022-28734 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit d232ad41ac4979a9de4d746e5fdff9caf0e303de) ---- - grub-core/net/http.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/grub-core/net/http.c b/grub-core/net/http.c -index 58546739a2..57d2721719 100644 ---- a/grub-core/net/http.c -+++ b/grub-core/net/http.c -@@ -69,7 +69,15 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len) - char *end = ptr + len; - while (end > ptr && *(end - 1) == '\r') - end--; -+ -+ /* LF without CR. */ -+ if (end == ptr + len) -+ { -+ data->errmsg = grub_strdup (_("invalid HTTP header - LF without CR")); -+ return GRUB_ERR_NONE; -+ } - *end = 0; -+ - /* Trailing CRLF. */ - if (data->in_chunk_len == 1) - { diff --git a/0244-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch b/0244-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch new file mode 100644 index 0000000..d638c11 --- /dev/null +++ b/0244-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darren Kenny +Date: Tue, 29 Mar 2022 15:52:46 +0000 +Subject: [PATCH] fs/btrfs: Fix more ASAN and SEGV issues found with fuzzing + +The fuzzer is generating btrfs file systems that have chunks with +invalid combinations of stripes and substripes for the given RAID +configurations. + +After examining the Linux kernel fs/btrfs/tree-checker.c code, it +appears that sub-stripes should only be applied to RAID10, and in that +case there should only ever be 2 of them. + +Similarly, RAID single should only have 1 stripe, and RAID1/1C3/1C4 +should have 2. 3 or 4 stripes respectively, which is what redundancy +corresponds. + +Some of the chunks ended up with a size of 0, which grub_malloc() still +returned memory for and in turn generated ASAN errors later when +accessed. + +While it would be possible to specifically limit the number of stripes, +a more correct test was on the combination of the chunk item, and the +number of stripes by the size of the chunk stripe structure in +comparison to the size of the chunk itself. + +Signed-off-by: Darren Kenny +Reviewed-by: Daniel Kiper +(cherry picked from commit 3849647b4b98a4419366708fc4b7f339c6f55ec7) +--- + grub-core/fs/btrfs.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 55 insertions(+) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 2fcfb738fe..0e9b450413 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -941,6 +941,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + return grub_error (GRUB_ERR_BAD_FS, + "couldn't find the chunk descriptor"); + ++ if (!chsize) ++ { ++ grub_dprintf ("btrfs", "zero-size chunk\n"); ++ return grub_error (GRUB_ERR_BAD_FS, ++ "got an invalid zero-size chunk"); ++ } + chunk = grub_malloc (chsize); + if (!chunk) + return grub_errno; +@@ -999,6 +1005,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size), + nstripes, + NULL); ++ ++ /* For single, there should be exactly 1 stripe. */ ++ if (grub_le_to_cpu16 (chunk->nstripes) != 1) ++ { ++ grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 (%u)\n", ++ grub_le_to_cpu16 (chunk->nstripes)); ++ return grub_error (GRUB_ERR_BAD_FS, ++ "invalid RAID_SINGLE: nstripes != 1 (%u)", ++ grub_le_to_cpu16 (chunk->nstripes)); ++ } + if (stripe_length == 0) + stripe_length = 512; + stripen = grub_divmod64 (off, stripe_length, &stripe_offset); +@@ -1018,6 +1034,19 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + stripen = 0; + stripe_offset = off; + csize = grub_le_to_cpu64 (chunk->size) - off; ++ ++ /* ++ * Redundancy, and substripes only apply to RAID10, and there ++ * should be exactly 2 sub-stripes. ++ */ ++ if (grub_le_to_cpu16 (chunk->nstripes) != redundancy) ++ { ++ grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n", ++ redundancy, grub_le_to_cpu16 (chunk->nstripes)); ++ return grub_error (GRUB_ERR_BAD_FS, ++ "invalid RAID1: nstripes != %u (%u)", ++ redundancy, grub_le_to_cpu16 (chunk->nstripes)); ++ } + break; + } + case GRUB_BTRFS_CHUNK_TYPE_RAID0: +@@ -1054,6 +1083,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + stripe_offset = low + chunk_stripe_length + * high; + csize = chunk_stripe_length - low; ++ ++ /* ++ * Substripes only apply to RAID10, and there ++ * should be exactly 2 sub-stripes. ++ */ ++ if (grub_le_to_cpu16 (chunk->nsubstripes) != 2) ++ { ++ grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 (%u)", ++ grub_le_to_cpu16 (chunk->nsubstripes)); ++ return grub_error (GRUB_ERR_BAD_FS, ++ "invalid RAID10: nsubstripes != 2 (%u)", ++ grub_le_to_cpu16 (chunk->nsubstripes)); ++ } ++ + break; + } + case GRUB_BTRFS_CHUNK_TYPE_RAID5: +@@ -1153,6 +1196,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + + for (j = 0; j < 2; j++) + { ++ grub_size_t est_chunk_alloc = 0; ++ + grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T + "+0x%" PRIxGRUB_UINT64_T + " (%d stripes (%d substripes) of %" +@@ -1165,6 +1210,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n", + addr); + ++ if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe), ++ grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) || ++ grub_add (est_chunk_alloc, ++ sizeof (struct grub_btrfs_chunk_item), &est_chunk_alloc) || ++ est_chunk_alloc > chunk->size) ++ { ++ err = GRUB_ERR_BAD_FS; ++ break; ++ } ++ + if (is_raid56) + { + err = btrfs_read_from_chunk (data, chunk, stripen, diff --git a/0244-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch b/0244-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch deleted file mode 100644 index 79df1c2..0000000 --- a/0244-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudhakar Kuppusamy -Date: Wed, 6 Apr 2022 18:03:37 +0530 -Subject: [PATCH] fs/f2fs: Do not read past the end of nat journal entries - -A corrupt f2fs file system could specify a nat journal entry count -that is beyond the maximum NAT_JOURNAL_ENTRIES. - -Check if the specified nat journal entry count before accessing the -array, and throw an error if it is too large. - -Signed-off-by: Sudhakar Kuppusamy -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit a3988cb3f0a108dd67ac127a79a4c8479d23334e) ---- - grub-core/fs/f2fs.c | 21 ++++++++++++++------- - 1 file changed, 14 insertions(+), 7 deletions(-) - -diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c -index 8a9992ca9e..63702214b0 100644 ---- a/grub-core/fs/f2fs.c -+++ b/grub-core/fs/f2fs.c -@@ -632,23 +632,27 @@ get_nat_journal (struct grub_f2fs_data *data) - return err; - } - --static grub_uint32_t --get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid) -+static grub_err_t -+get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid, -+ grub_uint32_t *blkaddr) - { - grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats); -- grub_uint32_t blkaddr = 0; - grub_uint16_t i; - -+ if (n >= NAT_JOURNAL_ENTRIES) -+ return grub_error (GRUB_ERR_BAD_FS, -+ "invalid number of nat journal entries"); -+ - for (i = 0; i < n; i++) - { - if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid) - { -- blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr); -+ *blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr); - break; - } - } - -- return blkaddr; -+ return GRUB_ERR_NONE; - } - - static grub_uint32_t -@@ -656,10 +660,13 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) - { - struct grub_f2fs_nat_block *nat_block; - grub_uint32_t seg_off, block_off, entry_off, block_addr; -- grub_uint32_t blkaddr; -+ grub_uint32_t blkaddr = 0; - grub_err_t err; - -- blkaddr = get_blkaddr_from_nat_journal (data, nid); -+ err = get_blkaddr_from_nat_journal (data, nid, &blkaddr); -+ if (err != GRUB_ERR_NONE) -+ return 0; -+ - if (blkaddr) - return blkaddr; - diff --git a/0245-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch b/0245-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch new file mode 100644 index 0000000..2e5145f --- /dev/null +++ b/0245-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darren Kenny +Date: Thu, 7 Apr 2022 15:18:12 +0000 +Subject: [PATCH] fs/btrfs: Fix more fuzz issues related to chunks + +The corpus we generating issues in grub_btrfs_read_logical() when +attempting to iterate over nstripes entries in the boot mapping. + +In most cases the reason for the failure was that the number of strips +exceeded the possible space statically allocated in superblock bootmapping +space. Each stripe entry in the bootmapping block consists of +a grub_btrfs_key followed by a grub_btrfs_chunk_stripe. + +Another issue that came up was that while calculating the chunk size, +in an earlier piece of code in that function, depending on the data +provided in the btrfs file system, it would end up calculating a size +that was too small to contain even 1 grub_btrfs_chunk_item, which is +obviously invalid too. + +Signed-off-by: Darren Kenny +Reviewed-by: Daniel Kiper +(cherry picked from commit e00cd76cbadcc897a9cc4087cb2fcb5dbe15e596) +--- + grub-core/fs/btrfs.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 0e9b450413..47325f6ad7 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -947,6 +947,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + return grub_error (GRUB_ERR_BAD_FS, + "got an invalid zero-size chunk"); + } ++ ++ /* ++ * The space being allocated for a chunk should at least be able to ++ * contain one chunk item. ++ */ ++ if (chsize < sizeof (struct grub_btrfs_chunk_item)) ++ { ++ grub_dprintf ("btrfs", "chunk-size too small\n"); ++ return grub_error (GRUB_ERR_BAD_FS, ++ "got an invalid chunk size"); ++ } + chunk = grub_malloc (chsize); + if (!chunk) + return grub_errno; +@@ -1194,6 +1205,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + if (csize > (grub_uint64_t) size) + csize = size; + ++ /* ++ * The space for a chunk stripe is limited to the space provide in the super-block's ++ * bootstrap mapping with an initial btrfs key at the start of each chunk. ++ */ ++ grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) / ++ (sizeof (struct grub_btrfs_key) + sizeof (struct grub_btrfs_chunk_stripe)); ++ + for (j = 0; j < 2; j++) + { + grub_size_t est_chunk_alloc = 0; +@@ -1220,6 +1238,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + break; + } + ++ if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes) ++ { ++ err = GRUB_ERR_BAD_FS; ++ break; ++ } ++ + if (is_raid56) + { + err = btrfs_read_from_chunk (data, chunk, stripen, diff --git a/0245-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch b/0245-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch deleted file mode 100644 index 855e882..0000000 --- a/0245-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudhakar Kuppusamy -Date: Wed, 6 Apr 2022 18:49:09 +0530 -Subject: [PATCH] fs/f2fs: Do not read past the end of nat bitmap - -A corrupt f2fs filesystem could have a block offset or a bitmap -offset that would cause us to read beyond the bounds of the nat -bitmap. - -Introduce the nat_bitmap_size member in grub_f2fs_data which holds -the size of nat bitmap. - -Set the size when loading the nat bitmap in nat_bitmap_ptr(), and -catch when an invalid offset would create a pointer past the end of -the allocated space. - -Check against the bitmap size in grub_f2fs_test_bit() test bit to avoid -reading past the end of the nat bitmap. - -Signed-off-by: Sudhakar Kuppusamy -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 62d63d5e38c67a6e349148bf7cb87c560e935a7e) ---- - grub-core/fs/f2fs.c | 33 +++++++++++++++++++++++++++------ - 1 file changed, 27 insertions(+), 6 deletions(-) - -diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c -index 63702214b0..8898b235e0 100644 ---- a/grub-core/fs/f2fs.c -+++ b/grub-core/fs/f2fs.c -@@ -122,6 +122,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); - #define F2FS_INLINE_DOTS 0x10 /* File having implicit dot dentries. */ - - #define MAX_VOLUME_NAME 512 -+#define MAX_NAT_BITMAP_SIZE 3900 - - enum FILE_TYPE - { -@@ -183,7 +184,7 @@ struct grub_f2fs_checkpoint - grub_uint32_t checksum_offset; - grub_uint64_t elapsed_time; - grub_uint8_t alloc_type[MAX_ACTIVE_LOGS]; -- grub_uint8_t sit_nat_version_bitmap[3900]; -+ grub_uint8_t sit_nat_version_bitmap[MAX_NAT_BITMAP_SIZE]; - grub_uint32_t checksum; - } GRUB_PACKED; - -@@ -302,6 +303,7 @@ struct grub_f2fs_data - - struct grub_f2fs_nat_journal nat_j; - char *nat_bitmap; -+ grub_uint32_t nat_bitmap_size; - - grub_disk_t disk; - struct grub_f2fs_node *inode; -@@ -377,15 +379,20 @@ sum_blk_addr (struct grub_f2fs_data *data, int base, int type) - } - - static void * --nat_bitmap_ptr (struct grub_f2fs_data *data) -+nat_bitmap_ptr (struct grub_f2fs_data *data, grub_uint32_t *nat_bitmap_size) - { - struct grub_f2fs_checkpoint *ckpt = &data->ckpt; - grub_uint32_t offset; -+ *nat_bitmap_size = MAX_NAT_BITMAP_SIZE; - - if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0) - return ckpt->sit_nat_version_bitmap; - - offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize); -+ if (offset >= MAX_NAT_BITMAP_SIZE) -+ return NULL; -+ -+ *nat_bitmap_size = *nat_bitmap_size - offset; - - return ckpt->sit_nat_version_bitmap + offset; - } -@@ -438,11 +445,15 @@ grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len) - } - - static int --grub_f2fs_test_bit (grub_uint32_t nr, const char *p) -+grub_f2fs_test_bit (grub_uint32_t nr, const char *p, grub_uint32_t len) - { - int mask; -+ grub_uint32_t shifted_nr = (nr >> 3); - -- p += (nr >> 3); -+ if (shifted_nr >= len) -+ return -1; -+ -+ p += shifted_nr; - mask = 1 << (7 - (nr & 0x07)); - - return mask & *p; -@@ -662,6 +673,7 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) - grub_uint32_t seg_off, block_off, entry_off, block_addr; - grub_uint32_t blkaddr = 0; - grub_err_t err; -+ int result_bit; - - err = get_blkaddr_from_nat_journal (data, nid, &blkaddr); - if (err != GRUB_ERR_NONE) -@@ -682,8 +694,15 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) - ((seg_off * data->blocks_per_seg) << 1) + - (block_off & (data->blocks_per_seg - 1)); - -- if (grub_f2fs_test_bit (block_off, data->nat_bitmap)) -+ result_bit = grub_f2fs_test_bit (block_off, data->nat_bitmap, -+ data->nat_bitmap_size); -+ if (result_bit > 0) - block_addr += data->blocks_per_seg; -+ else if (result_bit == -1) -+ { -+ grub_free (nat_block); -+ return 0; -+ } - - err = grub_f2fs_block_read (data, block_addr, nat_block); - if (err) -@@ -833,7 +852,9 @@ grub_f2fs_mount (grub_disk_t disk) - if (err) - goto fail; - -- data->nat_bitmap = nat_bitmap_ptr (data); -+ data->nat_bitmap = nat_bitmap_ptr (data, &data->nat_bitmap_size); -+ if (data->nat_bitmap == NULL) -+ goto fail; - - err = get_nat_journal (data); - if (err) diff --git a/0246-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch b/0246-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch deleted file mode 100644 index 0553d60..0000000 --- a/0246-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudhakar Kuppusamy -Date: Wed, 6 Apr 2022 18:17:43 +0530 -Subject: [PATCH] fs/f2fs: Do not copy file names that are too long - -A corrupt f2fs file system might specify a name length which is greater -than the maximum name length supported by the GRUB f2fs driver. - -We will allocate enough memory to store the overly long name, but there -are only F2FS_NAME_LEN bytes in the source, so we would read past the end -of the source. - -While checking directory entries, do not copy a file name with an invalid -length. - -Signed-off-by: Sudhakar Kuppusamy -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 9a891f638509e031d322c94e3cbcf38d36f3993a) ---- - grub-core/fs/f2fs.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c -index 8898b235e0..df6beb544c 100644 ---- a/grub-core/fs/f2fs.c -+++ b/grub-core/fs/f2fs.c -@@ -1003,6 +1003,10 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx) - - ftype = ctx->dentry[i].file_type; - name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len); -+ -+ if (name_len >= F2FS_NAME_LEN) -+ return 0; -+ - filename = grub_malloc (name_len + 1); - if (!filename) - return 0; diff --git a/0246-misc-Make-grub_min-and-grub_max-more-resilient.patch b/0246-misc-Make-grub_min-and-grub_max-more-resilient.patch new file mode 100644 index 0000000..eb2e8fd --- /dev/null +++ b/0246-misc-Make-grub_min-and-grub_max-more-resilient.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 21 Mar 2022 16:06:10 -0400 +Subject: [PATCH] misc: Make grub_min() and grub_max() more resilient. + +grub_min(a,b) and grub_max(a,b) use a relatively naive implementation +which leads to several problems: +- they evaluate their parameters more than once +- the naive way to address this, to declare temporary variables in a + statement-expression, isn't resilient against nested uses, because + MIN(a,MIN(b,c)) results in the temporary variables being declared in + two nested scopes, which may result in a build warning depending on + your build options. + +This patch changes our implementation to use a statement-expression +inside a helper macro, and creates the symbols for the temporary +variables with __COUNTER__ (A GNU C cpp extension) and token pasting to +create uniquely named internal variables. + +Signed-off-by: Peter Jones +--- + grub-core/loader/multiboot_elfxx.c | 4 +--- + include/grub/misc.h | 25 +++++++++++++++++++++++-- + 2 files changed, 24 insertions(+), 5 deletions(-) + +diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c +index f2318e0d16..87f6e31aa6 100644 +--- a/grub-core/loader/multiboot_elfxx.c ++++ b/grub-core/loader/multiboot_elfxx.c +@@ -35,9 +35,7 @@ + #endif + + #include +- +-#define CONCAT(a,b) CONCAT_(a, b) +-#define CONCAT_(a,b) a ## b ++#include + + #pragma GCC diagnostic ignored "-Wcast-align" + +diff --git a/include/grub/misc.h b/include/grub/misc.h +index 6c4aa85ac5..cf84aec1db 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -35,6 +35,14 @@ + #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) + #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; } + ++#ifndef CONCAT_ ++#define CONCAT_(a, b) a ## b ++#endif ++ ++#ifndef CONCAT ++#define CONCAT(a, b) CONCAT_(a, b) ++#endif ++ + #define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, __VA_ARGS__) + + void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n); +@@ -498,8 +506,21 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file, + #define grub_boot_time(...) + #endif + +-#define grub_max(a, b) (((a) > (b)) ? (a) : (b)) +-#define grub_min(a, b) (((a) < (b)) ? (a) : (b)) ++#define _grub_min(a, b, _a, _b) \ ++ ({ typeof (a) _a = (a); \ ++ typeof (b) _b = (b); \ ++ _a < _b ? _a : _b; }) ++#define grub_min(a, b) _grub_min(a, b, \ ++ CONCAT(_a_,__COUNTER__), \ ++ CONCAT(_b_,__COUNTER__)) ++ ++#define _grub_max(a, b, _a, _b) \ ++ ({ typeof (a) _a = (a); \ ++ typeof (b) _b = (b); \ ++ _a > _b ? _a : _b; }) ++#define grub_max(a, b) _grub_max(a, b, \ ++ CONCAT(_a_,__COUNTER__), \ ++ CONCAT(_b_,__COUNTER__)) + + #define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) - __builtin_clzll (n) - 1) + diff --git a/0247-ReiserFS-switch-to-using-grub_min-grub_max.patch b/0247-ReiserFS-switch-to-using-grub_min-grub_max.patch new file mode 100644 index 0000000..0707af3 --- /dev/null +++ b/0247-ReiserFS-switch-to-using-grub_min-grub_max.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 21 Apr 2022 16:31:17 -0400 +Subject: [PATCH] ReiserFS: switch to using grub_min()/grub_max() + +This is a minor cleanup patch to remove the bespoke MIN() and MAX() +definitions from the reiserfs driver, and uses grub_min() / grub_max() +instead. + +Signed-off-by: Peter Jones +--- + grub-core/fs/reiserfs.c | 28 +++++++++------------------- + 1 file changed, 9 insertions(+), 19 deletions(-) + +diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c +index af6a226a7f..b8253da7fe 100644 +--- a/grub-core/fs/reiserfs.c ++++ b/grub-core/fs/reiserfs.c +@@ -42,16 +42,6 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + +-#define MIN(a, b) \ +- ({ typeof (a) _a = (a); \ +- typeof (b) _b = (b); \ +- _a < _b ? _a : _b; }) +- +-#define MAX(a, b) \ +- ({ typeof (a) _a = (a); \ +- typeof (b) _b = (b); \ +- _a > _b ? _a : _b; }) +- + #define REISERFS_SUPER_BLOCK_OFFSET 0x10000 + #define REISERFS_MAGIC_LEN 12 + #define REISERFS_MAGIC_STRING "ReIsEr" +@@ -1076,7 +1066,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, + grub_reiserfs_set_key_type (&key, GRUB_REISERFS_ANY, 2); + initial_position = off; + current_position = 0; +- final_position = MIN (len + initial_position, node->size); ++ final_position = grub_min (len + initial_position, node->size); + grub_dprintf ("reiserfs", + "Reading from %lld to %lld (%lld instead of requested %ld)\n", + (unsigned long long) initial_position, +@@ -1115,8 +1105,8 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, + grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block); + if (initial_position < current_position + item_size) + { +- offset = MAX ((signed) (initial_position - current_position), 0); +- length = (MIN (item_size, final_position - current_position) ++ offset = grub_max ((signed) (initial_position - current_position), 0); ++ length = (grub_min (item_size, final_position - current_position) + - offset); + grub_dprintf ("reiserfs", + "Reading direct block %u from %u to %u...\n", +@@ -1161,9 +1151,9 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, + grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block); + if (current_position + block_size >= initial_position) + { +- offset = MAX ((signed) (initial_position - current_position), +- 0); +- length = (MIN (block_size, final_position - current_position) ++ offset = grub_max ((signed) (initial_position - current_position), ++ 0); ++ length = (grub_min (block_size, final_position - current_position) + - offset); + grub_dprintf ("reiserfs", + "Reading indirect block %u from %u to %u...\n", +@@ -1205,7 +1195,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, + switch (found.type) + { + case GRUB_REISERFS_DIRECT: +- read_length = MIN (len, item_size - file->offset); ++ read_length = grub_min (len, item_size - file->offset); + grub_disk_read (found.data->disk, + (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE, + grub_le_to_cpu16 (found.header.item_location) + file->offset, +@@ -1224,12 +1214,12 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, + item_size, (char *) indirect_block_ptr); + if (grub_errno) + goto fail; +- len = MIN (len, file->size - file->offset); ++ len = grub_min (len, file->size - file->offset); + for (indirect_block = file->offset / block_size; + indirect_block < indirect_block_count && read_length < len; + indirect_block++) + { +- read = MIN (block_size, len - read_length); ++ read = grub_min (block_size, len - read_length); + grub_disk_read (found.data->disk, + (grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) * block_size) / GRUB_DISK_SECTOR_SIZE, + file->offset % block_size, read, diff --git a/0247-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch b/0247-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch deleted file mode 100644 index 7ff5821..0000000 --- a/0247-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Darren Kenny -Date: Tue, 29 Mar 2022 10:49:56 +0000 -Subject: [PATCH] fs/btrfs: Fix several fuzz issues with invalid dir item - sizing - -According to the btrfs code in Linux, the structure of a directory item -leaf should be of the form: - - |struct btrfs_dir_item|name|data| - -in GRUB the name len and data len are in the grub_btrfs_dir_item -structure's n and m fields respectively. - -The combined size of the structure, name and data should be less than -the allocated memory, a difference to the Linux kernel's struct -btrfs_dir_item is that the grub_btrfs_dir_item has an extra field for -where the name is stored, so we adjust for that too. - -Signed-off-by: Darren Kenny -Reviewed-by: Daniel Kiper -(cherry picked from commit 6d3f06c0b6a8992b9b1bb0e62af93ac5ff2781f0) -[rharwood: we've an extra variable here] -Signed-off-by: Robbie Harwood ---- - grub-core/fs/btrfs.c | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index 07c0ff874b..2fcfb738fe 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -2254,6 +2254,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, - grub_uint64_t tree; - grub_uint8_t type; - char *new_path = NULL; -+ grub_size_t est_size = 0; - - if (!data) - return grub_errno; -@@ -2320,6 +2321,18 @@ grub_btrfs_dir (grub_device_t device, const char *path, - break; - } - -+ if (direl == NULL || -+ grub_add (grub_le_to_cpu16 (direl->n), -+ grub_le_to_cpu16 (direl->m), &est_size) || -+ grub_add (est_size, sizeof (*direl), &est_size) || -+ grub_sub (est_size, sizeof (direl->name), &est_size) || -+ est_size > allocated) -+ { -+ grub_errno = GRUB_ERR_OUT_OF_RANGE; -+ r = -grub_errno; -+ goto out; -+ } -+ - for (cdirel = direl; - (grub_uint8_t *) cdirel - (grub_uint8_t *) direl - < (grub_ssize_t) elemsize; -@@ -2330,6 +2343,19 @@ grub_btrfs_dir (grub_device_t device, const char *path, - char c; - struct grub_btrfs_inode inode; - struct grub_dirhook_info info; -+ -+ if (cdirel == NULL || -+ grub_add (grub_le_to_cpu16 (cdirel->n), -+ grub_le_to_cpu16 (cdirel->m), &est_size) || -+ grub_add (est_size, sizeof (*cdirel), &est_size) || -+ grub_sub (est_size, sizeof (cdirel->name), &est_size) || -+ est_size > allocated) -+ { -+ grub_errno = GRUB_ERR_OUT_OF_RANGE; -+ r = -grub_errno; -+ goto out; -+ } -+ - err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id, - tree); - grub_memset (&info, 0, sizeof (info)); diff --git a/0248-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch b/0248-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch deleted file mode 100644 index d638c11..0000000 --- a/0248-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Darren Kenny -Date: Tue, 29 Mar 2022 15:52:46 +0000 -Subject: [PATCH] fs/btrfs: Fix more ASAN and SEGV issues found with fuzzing - -The fuzzer is generating btrfs file systems that have chunks with -invalid combinations of stripes and substripes for the given RAID -configurations. - -After examining the Linux kernel fs/btrfs/tree-checker.c code, it -appears that sub-stripes should only be applied to RAID10, and in that -case there should only ever be 2 of them. - -Similarly, RAID single should only have 1 stripe, and RAID1/1C3/1C4 -should have 2. 3 or 4 stripes respectively, which is what redundancy -corresponds. - -Some of the chunks ended up with a size of 0, which grub_malloc() still -returned memory for and in turn generated ASAN errors later when -accessed. - -While it would be possible to specifically limit the number of stripes, -a more correct test was on the combination of the chunk item, and the -number of stripes by the size of the chunk stripe structure in -comparison to the size of the chunk itself. - -Signed-off-by: Darren Kenny -Reviewed-by: Daniel Kiper -(cherry picked from commit 3849647b4b98a4419366708fc4b7f339c6f55ec7) ---- - grub-core/fs/btrfs.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 55 insertions(+) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index 2fcfb738fe..0e9b450413 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -941,6 +941,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - return grub_error (GRUB_ERR_BAD_FS, - "couldn't find the chunk descriptor"); - -+ if (!chsize) -+ { -+ grub_dprintf ("btrfs", "zero-size chunk\n"); -+ return grub_error (GRUB_ERR_BAD_FS, -+ "got an invalid zero-size chunk"); -+ } - chunk = grub_malloc (chsize); - if (!chunk) - return grub_errno; -@@ -999,6 +1005,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size), - nstripes, - NULL); -+ -+ /* For single, there should be exactly 1 stripe. */ -+ if (grub_le_to_cpu16 (chunk->nstripes) != 1) -+ { -+ grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 (%u)\n", -+ grub_le_to_cpu16 (chunk->nstripes)); -+ return grub_error (GRUB_ERR_BAD_FS, -+ "invalid RAID_SINGLE: nstripes != 1 (%u)", -+ grub_le_to_cpu16 (chunk->nstripes)); -+ } - if (stripe_length == 0) - stripe_length = 512; - stripen = grub_divmod64 (off, stripe_length, &stripe_offset); -@@ -1018,6 +1034,19 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - stripen = 0; - stripe_offset = off; - csize = grub_le_to_cpu64 (chunk->size) - off; -+ -+ /* -+ * Redundancy, and substripes only apply to RAID10, and there -+ * should be exactly 2 sub-stripes. -+ */ -+ if (grub_le_to_cpu16 (chunk->nstripes) != redundancy) -+ { -+ grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n", -+ redundancy, grub_le_to_cpu16 (chunk->nstripes)); -+ return grub_error (GRUB_ERR_BAD_FS, -+ "invalid RAID1: nstripes != %u (%u)", -+ redundancy, grub_le_to_cpu16 (chunk->nstripes)); -+ } - break; - } - case GRUB_BTRFS_CHUNK_TYPE_RAID0: -@@ -1054,6 +1083,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - stripe_offset = low + chunk_stripe_length - * high; - csize = chunk_stripe_length - low; -+ -+ /* -+ * Substripes only apply to RAID10, and there -+ * should be exactly 2 sub-stripes. -+ */ -+ if (grub_le_to_cpu16 (chunk->nsubstripes) != 2) -+ { -+ grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 (%u)", -+ grub_le_to_cpu16 (chunk->nsubstripes)); -+ return grub_error (GRUB_ERR_BAD_FS, -+ "invalid RAID10: nsubstripes != 2 (%u)", -+ grub_le_to_cpu16 (chunk->nsubstripes)); -+ } -+ - break; - } - case GRUB_BTRFS_CHUNK_TYPE_RAID5: -@@ -1153,6 +1196,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - - for (j = 0; j < 2; j++) - { -+ grub_size_t est_chunk_alloc = 0; -+ - grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T - "+0x%" PRIxGRUB_UINT64_T - " (%d stripes (%d substripes) of %" -@@ -1165,6 +1210,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n", - addr); - -+ if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe), -+ grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) || -+ grub_add (est_chunk_alloc, -+ sizeof (struct grub_btrfs_chunk_item), &est_chunk_alloc) || -+ est_chunk_alloc > chunk->size) -+ { -+ err = GRUB_ERR_BAD_FS; -+ break; -+ } -+ - if (is_raid56) - { - err = btrfs_read_from_chunk (data, chunk, stripen, diff --git a/0248-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch b/0248-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch new file mode 100644 index 0000000..a7ac6f2 --- /dev/null +++ b/0248-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 24 Mar 2022 14:40:01 -0400 +Subject: [PATCH] misc: make grub_boot_time() also call + grub_dprintf("boot",...) + +Currently grub_boot_time() includes valuable debugging messages, but if +you build without BOOT_TIME_STATS enabled, they are silently and +confusingly compiled away. + +This patch changes grub_boot_time() to also log when "boot" is enabled +in DEBUG, regardless of BOOT_TIME_STATS. + +Signed-off-by: Peter Jones +--- + grub-core/kern/misc.c | 3 ++- + include/grub/misc.h | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index a186ad3dd4..cb45461402 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -1334,7 +1334,8 @@ grub_real_boot_time (const char *file, + n->next = 0; + + va_start (args, fmt); +- n->msg = grub_xvasprintf (fmt, args); ++ n->msg = grub_xvasprintf (fmt, args); ++ grub_dprintf ("boot", "%s\n", n->msg); + va_end (args); + + *boot_time_last = n; +diff --git a/include/grub/misc.h b/include/grub/misc.h +index cf84aec1db..faae0ae860 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -503,7 +503,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file, + const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 3, 4))); + #define grub_boot_time(...) grub_real_boot_time(GRUB_FILE, __LINE__, __VA_ARGS__) + #else +-#define grub_boot_time(...) ++#define grub_boot_time(fmt, ...) grub_dprintf("boot", fmt "\n", ##__VA_ARGS__) + #endif + + #define _grub_min(a, b, _a, _b) \ diff --git a/0249-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch b/0249-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch deleted file mode 100644 index 2e5145f..0000000 --- a/0249-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Darren Kenny -Date: Thu, 7 Apr 2022 15:18:12 +0000 -Subject: [PATCH] fs/btrfs: Fix more fuzz issues related to chunks - -The corpus we generating issues in grub_btrfs_read_logical() when -attempting to iterate over nstripes entries in the boot mapping. - -In most cases the reason for the failure was that the number of strips -exceeded the possible space statically allocated in superblock bootmapping -space. Each stripe entry in the bootmapping block consists of -a grub_btrfs_key followed by a grub_btrfs_chunk_stripe. - -Another issue that came up was that while calculating the chunk size, -in an earlier piece of code in that function, depending on the data -provided in the btrfs file system, it would end up calculating a size -that was too small to contain even 1 grub_btrfs_chunk_item, which is -obviously invalid too. - -Signed-off-by: Darren Kenny -Reviewed-by: Daniel Kiper -(cherry picked from commit e00cd76cbadcc897a9cc4087cb2fcb5dbe15e596) ---- - grub-core/fs/btrfs.c | 24 ++++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index 0e9b450413..47325f6ad7 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -947,6 +947,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - return grub_error (GRUB_ERR_BAD_FS, - "got an invalid zero-size chunk"); - } -+ -+ /* -+ * The space being allocated for a chunk should at least be able to -+ * contain one chunk item. -+ */ -+ if (chsize < sizeof (struct grub_btrfs_chunk_item)) -+ { -+ grub_dprintf ("btrfs", "chunk-size too small\n"); -+ return grub_error (GRUB_ERR_BAD_FS, -+ "got an invalid chunk size"); -+ } - chunk = grub_malloc (chsize); - if (!chunk) - return grub_errno; -@@ -1194,6 +1205,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - if (csize > (grub_uint64_t) size) - csize = size; - -+ /* -+ * The space for a chunk stripe is limited to the space provide in the super-block's -+ * bootstrap mapping with an initial btrfs key at the start of each chunk. -+ */ -+ grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) / -+ (sizeof (struct grub_btrfs_key) + sizeof (struct grub_btrfs_chunk_stripe)); -+ - for (j = 0; j < 2; j++) - { - grub_size_t est_chunk_alloc = 0; -@@ -1220,6 +1238,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - break; - } - -+ if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes) -+ { -+ err = GRUB_ERR_BAD_FS; -+ break; -+ } -+ - if (is_raid56) - { - err = btrfs_read_from_chunk (data, chunk, stripen, diff --git a/0249-modules-make-.module_license-read-only.patch b/0249-modules-make-.module_license-read-only.patch new file mode 100644 index 0000000..ba3b313 --- /dev/null +++ b/0249-modules-make-.module_license-read-only.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 24 Feb 2022 16:32:51 -0500 +Subject: [PATCH] modules: make .module_license read-only + +Currently .module_license is set writable (that is, the section has the +SHF_WRITE flag set) in the module's ELF headers. This probably never +actually matters, but it can't possibly be correct. + +This patch sets that data as "const", which causes that flag not to be +set. + +Signed-off-by: Peter Jones +--- + include/grub/dl.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/grub/dl.h b/include/grub/dl.h +index 20d870f2a4..618ae6f474 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -121,7 +121,7 @@ grub_mod_fini (void) + #define ATTRIBUTE_USED __unused__ + #endif + #define GRUB_MOD_LICENSE(license) \ +- static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license; ++ static const char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license; + #define GRUB_MOD_DEP(name) \ + static const char grub_module_depend_##name[] \ + __attribute__((section(GRUB_MOD_SECTION(moddeps)), ATTRIBUTE_USED)) = #name diff --git a/0250-misc-Make-grub_min-and-grub_max-more-resilient.patch b/0250-misc-Make-grub_min-and-grub_max-more-resilient.patch deleted file mode 100644 index eb2e8fd..0000000 --- a/0250-misc-Make-grub_min-and-grub_max-more-resilient.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 21 Mar 2022 16:06:10 -0400 -Subject: [PATCH] misc: Make grub_min() and grub_max() more resilient. - -grub_min(a,b) and grub_max(a,b) use a relatively naive implementation -which leads to several problems: -- they evaluate their parameters more than once -- the naive way to address this, to declare temporary variables in a - statement-expression, isn't resilient against nested uses, because - MIN(a,MIN(b,c)) results in the temporary variables being declared in - two nested scopes, which may result in a build warning depending on - your build options. - -This patch changes our implementation to use a statement-expression -inside a helper macro, and creates the symbols for the temporary -variables with __COUNTER__ (A GNU C cpp extension) and token pasting to -create uniquely named internal variables. - -Signed-off-by: Peter Jones ---- - grub-core/loader/multiboot_elfxx.c | 4 +--- - include/grub/misc.h | 25 +++++++++++++++++++++++-- - 2 files changed, 24 insertions(+), 5 deletions(-) - -diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c -index f2318e0d16..87f6e31aa6 100644 ---- a/grub-core/loader/multiboot_elfxx.c -+++ b/grub-core/loader/multiboot_elfxx.c -@@ -35,9 +35,7 @@ - #endif - - #include -- --#define CONCAT(a,b) CONCAT_(a, b) --#define CONCAT_(a,b) a ## b -+#include - - #pragma GCC diagnostic ignored "-Wcast-align" - -diff --git a/include/grub/misc.h b/include/grub/misc.h -index 6c4aa85ac5..cf84aec1db 100644 ---- a/include/grub/misc.h -+++ b/include/grub/misc.h -@@ -35,6 +35,14 @@ - #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) - #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; } - -+#ifndef CONCAT_ -+#define CONCAT_(a, b) a ## b -+#endif -+ -+#ifndef CONCAT -+#define CONCAT(a, b) CONCAT_(a, b) -+#endif -+ - #define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, __VA_ARGS__) - - void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n); -@@ -498,8 +506,21 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file, - #define grub_boot_time(...) - #endif - --#define grub_max(a, b) (((a) > (b)) ? (a) : (b)) --#define grub_min(a, b) (((a) < (b)) ? (a) : (b)) -+#define _grub_min(a, b, _a, _b) \ -+ ({ typeof (a) _a = (a); \ -+ typeof (b) _b = (b); \ -+ _a < _b ? _a : _b; }) -+#define grub_min(a, b) _grub_min(a, b, \ -+ CONCAT(_a_,__COUNTER__), \ -+ CONCAT(_b_,__COUNTER__)) -+ -+#define _grub_max(a, b, _a, _b) \ -+ ({ typeof (a) _a = (a); \ -+ typeof (b) _b = (b); \ -+ _a > _b ? _a : _b; }) -+#define grub_max(a, b) _grub_max(a, b, \ -+ CONCAT(_a_,__COUNTER__), \ -+ CONCAT(_b_,__COUNTER__)) - - #define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) - __builtin_clzll (n) - 1) - diff --git a/0250-modules-strip-.llvm_addrsig-sections-and-similar.patch b/0250-modules-strip-.llvm_addrsig-sections-and-similar.patch new file mode 100644 index 0000000..9f26115 --- /dev/null +++ b/0250-modules-strip-.llvm_addrsig-sections-and-similar.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 24 Feb 2022 16:40:11 -0500 +Subject: [PATCH] modules: strip .llvm_addrsig sections and similar. + +Currently grub modules built with clang or gcc have several sections +which we don't actually need or support. + +We already have a list of section to skip in genmod.sh, and this patch +adds the following sections to that list (as well as a few newlines): + +.note.gnu.property +.llvm* + +Note that the glob there won't work without a new enough linker, but the +failure is just reversion to the status quo, so that's not a big problem. + +Signed-off-by: Peter Jones +--- + grub-core/genmod.sh.in | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in +index 1250589b3f..c2c5280d75 100644 +--- a/grub-core/genmod.sh.in ++++ b/grub-core/genmod.sh.in +@@ -57,8 +57,11 @@ if test x@TARGET_APPLE_LINKER@ != x1; then + @TARGET_STRIP@ --strip-unneeded \ + -K grub_mod_init -K grub_mod_fini \ + -K _grub_mod_init -K _grub_mod_fini \ +- -R .note.gnu.gold-version -R .note.GNU-stack \ ++ -R .note.GNU-stack \ ++ -R .note.gnu.gold-version \ ++ -R .note.gnu.property \ + -R .gnu.build.attributes \ ++ -R '.llvm*' \ + -R .rel.gnu.build.attributes \ + -R .rela.gnu.build.attributes \ + -R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \ diff --git a/0251-ReiserFS-switch-to-using-grub_min-grub_max.patch b/0251-ReiserFS-switch-to-using-grub_min-grub_max.patch deleted file mode 100644 index 0707af3..0000000 --- a/0251-ReiserFS-switch-to-using-grub_min-grub_max.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 21 Apr 2022 16:31:17 -0400 -Subject: [PATCH] ReiserFS: switch to using grub_min()/grub_max() - -This is a minor cleanup patch to remove the bespoke MIN() and MAX() -definitions from the reiserfs driver, and uses grub_min() / grub_max() -instead. - -Signed-off-by: Peter Jones ---- - grub-core/fs/reiserfs.c | 28 +++++++++------------------- - 1 file changed, 9 insertions(+), 19 deletions(-) - -diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c -index af6a226a7f..b8253da7fe 100644 ---- a/grub-core/fs/reiserfs.c -+++ b/grub-core/fs/reiserfs.c -@@ -42,16 +42,6 @@ - - GRUB_MOD_LICENSE ("GPLv3+"); - --#define MIN(a, b) \ -- ({ typeof (a) _a = (a); \ -- typeof (b) _b = (b); \ -- _a < _b ? _a : _b; }) -- --#define MAX(a, b) \ -- ({ typeof (a) _a = (a); \ -- typeof (b) _b = (b); \ -- _a > _b ? _a : _b; }) -- - #define REISERFS_SUPER_BLOCK_OFFSET 0x10000 - #define REISERFS_MAGIC_LEN 12 - #define REISERFS_MAGIC_STRING "ReIsEr" -@@ -1076,7 +1066,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, - grub_reiserfs_set_key_type (&key, GRUB_REISERFS_ANY, 2); - initial_position = off; - current_position = 0; -- final_position = MIN (len + initial_position, node->size); -+ final_position = grub_min (len + initial_position, node->size); - grub_dprintf ("reiserfs", - "Reading from %lld to %lld (%lld instead of requested %ld)\n", - (unsigned long long) initial_position, -@@ -1115,8 +1105,8 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, - grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block); - if (initial_position < current_position + item_size) - { -- offset = MAX ((signed) (initial_position - current_position), 0); -- length = (MIN (item_size, final_position - current_position) -+ offset = grub_max ((signed) (initial_position - current_position), 0); -+ length = (grub_min (item_size, final_position - current_position) - - offset); - grub_dprintf ("reiserfs", - "Reading direct block %u from %u to %u...\n", -@@ -1161,9 +1151,9 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, - grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block); - if (current_position + block_size >= initial_position) - { -- offset = MAX ((signed) (initial_position - current_position), -- 0); -- length = (MIN (block_size, final_position - current_position) -+ offset = grub_max ((signed) (initial_position - current_position), -+ 0); -+ length = (grub_min (block_size, final_position - current_position) - - offset); - grub_dprintf ("reiserfs", - "Reading indirect block %u from %u to %u...\n", -@@ -1205,7 +1195,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, - switch (found.type) - { - case GRUB_REISERFS_DIRECT: -- read_length = MIN (len, item_size - file->offset); -+ read_length = grub_min (len, item_size - file->offset); - grub_disk_read (found.data->disk, - (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE, - grub_le_to_cpu16 (found.header.item_location) + file->offset, -@@ -1224,12 +1214,12 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, - item_size, (char *) indirect_block_ptr); - if (grub_errno) - goto fail; -- len = MIN (len, file->size - file->offset); -+ len = grub_min (len, file->size - file->offset); - for (indirect_block = file->offset / block_size; - indirect_block < indirect_block_count && read_length < len; - indirect_block++) - { -- read = MIN (block_size, len - read_length); -+ read = grub_min (block_size, len - read_length); - grub_disk_read (found.data->disk, - (grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) * block_size) / GRUB_DISK_SECTOR_SIZE, - file->offset % block_size, read, diff --git a/0251-modules-Don-t-allocate-space-for-non-allocable-secti.patch b/0251-modules-Don-t-allocate-space-for-non-allocable-secti.patch new file mode 100644 index 0000000..d07d838 --- /dev/null +++ b/0251-modules-Don-t-allocate-space-for-non-allocable-secti.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 21 Mar 2022 16:56:10 -0400 +Subject: [PATCH] modules: Don't allocate space for non-allocable sections. + +Currently when loading grub modules, we allocate space for all sections, +including those without SHF_ALLOC set. We then copy the sections that +/do/ have SHF_ALLOC set into the allocated memory, leaving some of our +allocation untouched forever. Additionally, on platforms with GOT +fixups and trampolines, we currently compute alignment round-ups for the +sections and sections with sh_size = 0. + +This patch removes the extra space from the allocation computation, and +makes the allocation computation loop skip empty sections as the loading +loop does. + +Signed-off-by: Peter Jones +--- + grub-core/kern/dl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index f304494574..aef8af8aa7 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -289,6 +289,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + i < e->e_shnum; + i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) + { ++ if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) ++ continue; ++ + tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; + if (talign < s->sh_addralign) + talign = s->sh_addralign; diff --git a/0252-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch b/0252-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch deleted file mode 100644 index a7ac6f2..0000000 --- a/0252-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 24 Mar 2022 14:40:01 -0400 -Subject: [PATCH] misc: make grub_boot_time() also call - grub_dprintf("boot",...) - -Currently grub_boot_time() includes valuable debugging messages, but if -you build without BOOT_TIME_STATS enabled, they are silently and -confusingly compiled away. - -This patch changes grub_boot_time() to also log when "boot" is enabled -in DEBUG, regardless of BOOT_TIME_STATS. - -Signed-off-by: Peter Jones ---- - grub-core/kern/misc.c | 3 ++- - include/grub/misc.h | 2 +- - 2 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c -index a186ad3dd4..cb45461402 100644 ---- a/grub-core/kern/misc.c -+++ b/grub-core/kern/misc.c -@@ -1334,7 +1334,8 @@ grub_real_boot_time (const char *file, - n->next = 0; - - va_start (args, fmt); -- n->msg = grub_xvasprintf (fmt, args); -+ n->msg = grub_xvasprintf (fmt, args); -+ grub_dprintf ("boot", "%s\n", n->msg); - va_end (args); - - *boot_time_last = n; -diff --git a/include/grub/misc.h b/include/grub/misc.h -index cf84aec1db..faae0ae860 100644 ---- a/include/grub/misc.h -+++ b/include/grub/misc.h -@@ -503,7 +503,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file, - const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 3, 4))); - #define grub_boot_time(...) grub_real_boot_time(GRUB_FILE, __LINE__, __VA_ARGS__) - #else --#define grub_boot_time(...) -+#define grub_boot_time(fmt, ...) grub_dprintf("boot", fmt "\n", ##__VA_ARGS__) - #endif - - #define _grub_min(a, b, _a, _b) \ diff --git a/0252-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch b/0252-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch new file mode 100644 index 0000000..ef51214 --- /dev/null +++ b/0252-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 25 Mar 2022 15:40:12 -0400 +Subject: [PATCH] pe: add the DOS header struct and fix some bad naming. + +In order to properly validate a loaded kernel's support for being loaded +without a writable stack or executable, we need to be able to properly +parse arbitrary PE headers. + +Currently, pe32.h is written in such a way that the MS-DOS header that +tells us where to find the PE header in the binary can't be accessed. +Further, for some reason it calls the DOS MZ magic "GRUB_PE32_MAGIC". + +This patch adds the structure for the DOS header, renames the DOS magic +define, and adds defines for the actual PE magic. + +Signed-off-by: Peter Jones +--- + grub-core/loader/arm64/linux.c | 2 +- + include/grub/efi/pe32.h | 28 ++++++++++++++++++++++++++-- + 2 files changed, 27 insertions(+), 3 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index d2af47c2c0..cc67f43906 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -58,7 +58,7 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) + if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE) + return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); + +- if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC) ++ if ((lh->code0 & 0xffff) != GRUB_DOS_MAGIC) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); + +diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h +index a43adf2746..2a5e1ee003 100644 +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -46,7 +46,30 @@ + + #define GRUB_PE32_MSDOS_STUB_SIZE 0x80 + +-#define GRUB_PE32_MAGIC 0x5a4d ++#define GRUB_DOS_MAGIC 0x5a4d ++ ++struct grub_dos_header ++{ ++ grub_uint16_t magic; ++ grub_uint16_t cblp; ++ grub_uint16_t cp; ++ grub_uint16_t crlc; ++ grub_uint16_t cparhdr; ++ grub_uint16_t minalloc; ++ grub_uint16_t maxalloc; ++ grub_uint16_t ss; ++ grub_uint16_t sp; ++ grub_uint16_t csum; ++ grub_uint16_t ip; ++ grub_uint16_t cs; ++ grub_uint16_t lfarlc; ++ grub_uint16_t ovno; ++ grub_uint16_t res0[4]; ++ grub_uint16_t oemid; ++ grub_uint16_t oeminfo; ++ grub_uint16_t res1[10]; ++ grub_uint32_t lfanew; ++}; + + /* According to the spec, the minimal alignment is 512 bytes... + But some examples (such as EFI drivers in the Intel +@@ -280,7 +303,8 @@ struct grub_pe32_section_table + + + +-#define GRUB_PE32_SIGNATURE_SIZE 4 ++#define GRUB_PE32_SIGNATURE_SIZE 4 ++#define GRUB_PE32_SIGNATURE "PE\0\0" + + struct grub_pe32_header + { diff --git a/0253-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch b/0253-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch new file mode 100644 index 0000000..c6688cd --- /dev/null +++ b/0253-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 9 Feb 2022 16:08:20 -0500 +Subject: [PATCH] EFI: allocate kernel in EFI_RUNTIME_SERVICES_CODE instead of + EFI_LOADER_DATA. + +On some of the firmwares with more security mitigations, EFI_LOADER_DATA +doesn't get you executable memory, and we take a fault and reboot when +we enter kernel. + +This patch correctly allocates the kernel code as EFI_RUNTIME_SERVICES_CODE +rather than EFI_LOADER_DATA. + +Signed-off-by: Peter Jones +[rharwood: use kernel_size] +Signed-off-by: Robbie Harwood +--- + grub-core/loader/i386/efi/linux.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 9e5c11ac69..92b2fb5091 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -86,7 +86,9 @@ kernel_free(void *addr, grub_efi_uintn_t size) + } + + static void * +-kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) ++kernel_alloc(grub_efi_uintn_t size, ++ grub_efi_memory_type_t memtype, ++ const char * const errmsg) + { + void *addr = 0; + unsigned int i; +@@ -112,7 +114,7 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) + prev_max = max; + addr = grub_efi_allocate_pages_real (max, pages, + max_addresses[i].alloc_type, +- GRUB_EFI_LOADER_DATA); ++ memtype); + if (addr) + grub_dprintf ("linux", "Allocated at %p\n", addr); + } +@@ -242,7 +244,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + } + } + +- initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); ++ initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA, ++ N_("can't allocate initrd")); + if (initrd_mem == NULL) + goto fail; + grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); +@@ -393,7 +396,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + #endif + +- params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters"); ++ params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA, ++ "cannot allocate kernel parameters"); + if (!params) + goto fail; + grub_dprintf ("linux", "params = %p\n", params); +@@ -415,7 +419,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "new lh is at %p\n", lh); + + grub_dprintf ("linux", "setting up cmdline\n"); +- cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); ++ cmdline = kernel_alloc (lh->cmdline_size + 1, ++ GRUB_EFI_RUNTIME_SERVICES_DATA, ++ N_("can't allocate cmdline")); + if (!cmdline) + goto fail; + grub_dprintf ("linux", "cmdline = %p\n", cmdline); +@@ -461,7 +467,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + kernel_size = lh->init_size; +- kernel_mem = kernel_alloc (kernel_size, N_("can't allocate kernel")); ++ kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, ++ N_("can't allocate kernel")); + restore_addresses(); + if (!kernel_mem) + goto fail; diff --git a/0253-modules-make-.module_license-read-only.patch b/0253-modules-make-.module_license-read-only.patch deleted file mode 100644 index ba3b313..0000000 --- a/0253-modules-make-.module_license-read-only.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 24 Feb 2022 16:32:51 -0500 -Subject: [PATCH] modules: make .module_license read-only - -Currently .module_license is set writable (that is, the section has the -SHF_WRITE flag set) in the module's ELF headers. This probably never -actually matters, but it can't possibly be correct. - -This patch sets that data as "const", which causes that flag not to be -set. - -Signed-off-by: Peter Jones ---- - include/grub/dl.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/grub/dl.h b/include/grub/dl.h -index 20d870f2a4..618ae6f474 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -121,7 +121,7 @@ grub_mod_fini (void) - #define ATTRIBUTE_USED __unused__ - #endif - #define GRUB_MOD_LICENSE(license) \ -- static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license; -+ static const char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license; - #define GRUB_MOD_DEP(name) \ - static const char grub_module_depend_##name[] \ - __attribute__((section(GRUB_MOD_SECTION(moddeps)), ATTRIBUTE_USED)) = #name diff --git a/0254-modules-load-module-sections-at-page-aligned-address.patch b/0254-modules-load-module-sections-at-page-aligned-address.patch new file mode 100644 index 0000000..eb171f5 --- /dev/null +++ b/0254-modules-load-module-sections-at-page-aligned-address.patch @@ -0,0 +1,378 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 21 Mar 2022 17:45:40 -0400 +Subject: [PATCH] modules: load module sections at page-aligned addresses + +Currently we load module sections at whatever alignment gcc+ld happened +to dump into the ELF section header, which is often pretty useless. For +example, by default time.mod has these sections on a current x86_64 +build: + +$ eu-readelf -a grub-core/time.mod |& grep ^Section -A13 +Section Headers: +[Nr] Name Type Addr Off Size ES Flags Lk Inf Al +[ 0] NULL 0 00000000 00000000 0 0 0 0 +[ 1] .text PROGBITS 0 00000040 0000015e 0 AX 0 0 1 +[ 2] .rela.text RELA 0 00000458 000001e0 24 I 8 1 8 +[ 3] .rodata.str1.1 PROGBITS 0 0000019e 000000a1 1 AMS 0 0 1 +[ 4] .module_license PROGBITS 0 00000240 0000000f 0 A 0 0 8 +[ 5] .data PROGBITS 0 0000024f 00000000 0 WA 0 0 1 +[ 6] .bss NOBITS 0 00000250 00000008 0 WA 0 0 8 +[ 7] .modname PROGBITS 0 00000250 00000005 0 0 0 1 +[ 8] .symtab SYMTAB 0 00000258 00000150 24 9 6 8 +[ 9] .strtab STRTAB 0 000003a8 000000ab 0 0 0 1 +[10] .shstrtab STRTAB 0 00000638 00000059 0 0 0 1 + +With NX protections being page based, loading sections with either a 1 +or 8 *byte* alignment does absolutely nothing to help us out. + +This patch switches most EFI platforms to load module sections at 4kB +page-aligned addresses. To do so, it adds an new per-arch function, +grub_arch_dl_min_alignment(), which returns the alignment needed for +dynamically loaded sections (in bytes). Currently it sets it to 4096 +when GRUB_MACHINE_EFI is true on x86_64, i386, arm, arm64, and emu, and +1-byte alignment on everything else. + +It then changes the allocation size computation and the loader code in +grub_dl_load_segments() to align the locations and sizes up to these +boundaries, and fills any added padding with zeros. + +All of this happens before relocations are applied, so the relocations +factor that in with no change. + +As an aside, initially Daniel Kiper and I thought that it might be a +better idea to split the modules up into top-level sections as +.text.modules, .rodata.modules, .data.modules, etc., so that their page +permissions would get set by the loader that's loading grub itself. +This turns out to have two significant downsides: 1) either in mkimage +or in grub_dl_relocate_symbols(), you wind up having to dynamically +process the relocations to accommodate the moved module sections, and 2) +you then need to change the permissions on the modules and change them +back while relocating them in grub_dl_relocate_symbols(), which means +that any loader that /does/ honor the section flags but does /not/ +generally support NX with the memory attributes API will cause grub to +fail. + +Signed-off-by: Peter Jones +--- + grub-core/kern/arm/dl.c | 13 +++++++++++++ + grub-core/kern/arm64/dl.c | 13 +++++++++++++ + grub-core/kern/dl.c | 29 +++++++++++++++++++++-------- + grub-core/kern/emu/full.c | 13 +++++++++++++ + grub-core/kern/i386/dl.c | 13 +++++++++++++ + grub-core/kern/ia64/dl.c | 9 +++++++++ + grub-core/kern/mips/dl.c | 8 ++++++++ + grub-core/kern/powerpc/dl.c | 9 +++++++++ + grub-core/kern/riscv/dl.c | 13 +++++++++++++ + grub-core/kern/sparc64/dl.c | 9 +++++++++ + grub-core/kern/x86_64/dl.c | 13 +++++++++++++ + include/grub/dl.h | 2 ++ + docs/grub-dev.texi | 6 +++--- + 13 files changed, 139 insertions(+), 11 deletions(-) + +diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c +index eab9d17ff2..9260737936 100644 +--- a/grub-core/kern/arm/dl.c ++++ b/grub-core/kern/arm/dl.c +@@ -278,3 +278,16 @@ grub_arch_dl_check_header (void *ehdr) + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c +index 512e5a80b0..0d4a26857f 100644 +--- a/grub-core/kern/arm64/dl.c ++++ b/grub-core/kern/arm64/dl.c +@@ -196,3 +196,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index aef8af8aa7..8c7aacef39 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -277,7 +277,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + { + unsigned i; + const Elf_Shdr *s; +- grub_size_t tsize = 0, talign = 1; ++ grub_size_t tsize = 0, talign = 1, arch_addralign = 1; + #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) + grub_size_t tramp; + grub_size_t got; +@@ -285,16 +285,24 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + #endif + char *ptr; + ++ arch_addralign = grub_arch_dl_min_alignment (); ++ + for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) + { ++ grub_size_t sh_addralign; ++ grub_size_t sh_size; ++ + if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) + continue; + +- tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; +- if (talign < s->sh_addralign) +- talign = s->sh_addralign; ++ sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign); ++ sh_size = ALIGN_UP(s->sh_size, sh_addralign); ++ ++ tsize = ALIGN_UP (tsize, sh_addralign) + sh_size; ++ if (talign < sh_addralign) ++ talign = sh_addralign; + } + + #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) +@@ -323,6 +331,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + i < e->e_shnum; + i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) + { ++ grub_size_t sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign); ++ grub_size_t sh_size = ALIGN_UP(s->sh_size, sh_addralign); ++ + if (s->sh_flags & SHF_ALLOC) + { + grub_dl_segment_t seg; +@@ -335,17 +346,19 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + { + void *addr; + +- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign); ++ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, sh_addralign); + addr = ptr; +- ptr += s->sh_size; ++ ptr += sh_size; + + switch (s->sh_type) + { + case SHT_PROGBITS: + grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size); ++ grub_memset ((char *)addr + s->sh_size, 0, ++ sh_size - s->sh_size); + break; + case SHT_NOBITS: +- grub_memset (addr, 0, s->sh_size); ++ grub_memset (addr, 0, sh_size); + break; + } + +@@ -354,7 +367,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + else + seg->addr = 0; + +- seg->size = s->sh_size; ++ seg->size = sh_size; + seg->section = i; + seg->next = mod->segment; + mod->segment = seg; +diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c +index e8d63b1f5f..1de1c28eb0 100644 +--- a/grub-core/kern/emu/full.c ++++ b/grub-core/kern/emu/full.c +@@ -67,3 +67,16 @@ grub_arch_dl_init_linker (void) + } + #endif + ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/grub-core/kern/i386/dl.c b/grub-core/kern/i386/dl.c +index 1346da5cc9..d6b4681fc9 100644 +--- a/grub-core/kern/i386/dl.c ++++ b/grub-core/kern/i386/dl.c +@@ -79,3 +79,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c +index db59300fea..92d82c5750 100644 +--- a/grub-core/kern/ia64/dl.c ++++ b/grub-core/kern/ia64/dl.c +@@ -148,3 +148,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + } + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++ return 1; ++} +diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c +index 5d7d299c74..6d83bd71e9 100644 +--- a/grub-core/kern/mips/dl.c ++++ b/grub-core/kern/mips/dl.c +@@ -272,3 +272,11 @@ grub_arch_dl_init_linker (void) + grub_dl_register_symbol ("_gp_disp", &_gp_disp_dummy, 0, 0); + } + ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++ return 1; ++} +diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c +index cdd61b305f..5d9ba2e158 100644 +--- a/grub-core/kern/powerpc/dl.c ++++ b/grub-core/kern/powerpc/dl.c +@@ -167,3 +167,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++ return 1; ++} +diff --git a/grub-core/kern/riscv/dl.c b/grub-core/kern/riscv/dl.c +index f26b12aaa4..aa18f9e990 100644 +--- a/grub-core/kern/riscv/dl.c ++++ b/grub-core/kern/riscv/dl.c +@@ -343,3 +343,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/grub-core/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c +index f3d960186b..f054f08241 100644 +--- a/grub-core/kern/sparc64/dl.c ++++ b/grub-core/kern/sparc64/dl.c +@@ -189,3 +189,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++ return 1; ++} +diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c +index e5a8bdcf4f..a105dc50ce 100644 +--- a/grub-core/kern/x86_64/dl.c ++++ b/grub-core/kern/x86_64/dl.c +@@ -119,3 +119,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/include/grub/dl.h b/include/grub/dl.h +index 618ae6f474..f36ed5cb17 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -280,6 +280,8 @@ grub_err_t grub_arch_dl_check_header (void *ehdr); + grub_err_t + grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg); ++grub_size_t ++grub_arch_dl_min_alignment (void); + #endif + + #if defined (_mips) +diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi +index 19f708ee66..7b2455a8fe 100644 +--- a/docs/grub-dev.texi ++++ b/docs/grub-dev.texi +@@ -755,9 +755,9 @@ declare startup asm file ($cpu_$platform_startup) as well as any other files + (e.g. init.c and callwrap.S) (e.g. $cpu_$platform = kern/$cpu/$platform/init.c). + At this stage you will also need to add dummy dl.c and cache.S with functions + grub_err_t grub_arch_dl_check_header (void *ehdr), grub_err_t +-grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c) and +-void grub_arch_sync_caches (void *address, grub_size_t len) (cache.S). They +-won't be used for now. ++grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c), grub_uint32_t ++grub_arch_dl_min_alignment (void), and void grub_arch_sync_caches (void ++*address, grub_size_t len) (cache.S). They won't be used for now. + + You will need to create directory include/$cpu/$platform and a file + include/$cpu/types.h. The later folowing this template: diff --git a/0254-modules-strip-.llvm_addrsig-sections-and-similar.patch b/0254-modules-strip-.llvm_addrsig-sections-and-similar.patch deleted file mode 100644 index 9f26115..0000000 --- a/0254-modules-strip-.llvm_addrsig-sections-and-similar.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 24 Feb 2022 16:40:11 -0500 -Subject: [PATCH] modules: strip .llvm_addrsig sections and similar. - -Currently grub modules built with clang or gcc have several sections -which we don't actually need or support. - -We already have a list of section to skip in genmod.sh, and this patch -adds the following sections to that list (as well as a few newlines): - -.note.gnu.property -.llvm* - -Note that the glob there won't work without a new enough linker, but the -failure is just reversion to the status quo, so that's not a big problem. - -Signed-off-by: Peter Jones ---- - grub-core/genmod.sh.in | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in -index 1250589b3f..c2c5280d75 100644 ---- a/grub-core/genmod.sh.in -+++ b/grub-core/genmod.sh.in -@@ -57,8 +57,11 @@ if test x@TARGET_APPLE_LINKER@ != x1; then - @TARGET_STRIP@ --strip-unneeded \ - -K grub_mod_init -K grub_mod_fini \ - -K _grub_mod_init -K _grub_mod_fini \ -- -R .note.gnu.gold-version -R .note.GNU-stack \ -+ -R .note.GNU-stack \ -+ -R .note.gnu.gold-version \ -+ -R .note.gnu.property \ - -R .gnu.build.attributes \ -+ -R '.llvm*' \ - -R .rel.gnu.build.attributes \ - -R .rela.gnu.build.attributes \ - -R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \ diff --git a/0255-modules-Don-t-allocate-space-for-non-allocable-secti.patch b/0255-modules-Don-t-allocate-space-for-non-allocable-secti.patch deleted file mode 100644 index d07d838..0000000 --- a/0255-modules-Don-t-allocate-space-for-non-allocable-secti.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 21 Mar 2022 16:56:10 -0400 -Subject: [PATCH] modules: Don't allocate space for non-allocable sections. - -Currently when loading grub modules, we allocate space for all sections, -including those without SHF_ALLOC set. We then copy the sections that -/do/ have SHF_ALLOC set into the allocated memory, leaving some of our -allocation untouched forever. Additionally, on platforms with GOT -fixups and trampolines, we currently compute alignment round-ups for the -sections and sections with sh_size = 0. - -This patch removes the extra space from the allocation computation, and -makes the allocation computation loop skip empty sections as the loading -loop does. - -Signed-off-by: Peter Jones ---- - grub-core/kern/dl.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index f304494574..aef8af8aa7 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -289,6 +289,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - i < e->e_shnum; - i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) - { -+ if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) -+ continue; -+ - tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; - if (talign < s->sh_addralign) - talign = s->sh_addralign; diff --git a/0255-nx-add-memory-attribute-get-set-API.patch b/0255-nx-add-memory-attribute-get-set-API.patch new file mode 100644 index 0000000..91c9d2f --- /dev/null +++ b/0255-nx-add-memory-attribute-get-set-API.patch @@ -0,0 +1,317 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 22 Mar 2022 10:56:21 -0400 +Subject: [PATCH] nx: add memory attribute get/set API + +For NX, we need to set the page access permission attributes for write +and execute permissions. + +This patch adds two new primitives, grub_set_mem_attrs() and +grub_clear_mem_attrs(), and associated constant definitions, to be used +for that purpose. + +For most platforms, it adds a dummy implementation that returns +GRUB_ERR_NONE. On EFI platforms, it adds a common helper function, +grub_efi_status_to_err(), which translates EFI error codes to grub error +codes, adds headers for the EFI Memory Attribute Protocol (still pending +standardization), and an implementation of the grub nx primitives using +it. + +Signed-off-by: Peter Jones +[rharwood: add pjones's none/nyi fixup] +Signed-off-by: Robbie Harwood +--- + grub-core/kern/efi/efi.c | 36 +++++++++++++ + grub-core/kern/efi/mm.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++ + include/grub/efi/api.h | 25 +++++++++ + include/grub/efi/efi.h | 2 + + include/grub/mm.h | 32 ++++++++++++ + 5 files changed, 226 insertions(+) + +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 7fcca69c17..4ac2b2754e 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -1096,3 +1096,39 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, + + return 0; + } ++ ++grub_err_t ++grub_efi_status_to_err (grub_efi_status_t status) ++{ ++ grub_err_t err; ++ switch (status) ++ { ++ case GRUB_EFI_SUCCESS: ++ err = GRUB_ERR_NONE; ++ break; ++ case GRUB_EFI_INVALID_PARAMETER: ++ default: ++ err = GRUB_ERR_BAD_ARGUMENT; ++ break; ++ case GRUB_EFI_OUT_OF_RESOURCES: ++ err = GRUB_ERR_OUT_OF_MEMORY; ++ break; ++ case GRUB_EFI_DEVICE_ERROR: ++ err = GRUB_ERR_IO; ++ break; ++ case GRUB_EFI_WRITE_PROTECTED: ++ err = GRUB_ERR_WRITE_ERROR; ++ break; ++ case GRUB_EFI_SECURITY_VIOLATION: ++ err = GRUB_ERR_ACCESS_DENIED; ++ break; ++ case GRUB_EFI_NOT_FOUND: ++ err = GRUB_ERR_FILE_NOT_FOUND; ++ break; ++ case GRUB_EFI_ABORTED: ++ err = GRUB_ERR_WAIT; ++ break; ++ } ++ ++ return err; ++} +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index e84961d078..2c33758ed7 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -738,3 +738,134 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) + return GRUB_ERR_NONE; + } + #endif ++ ++static inline grub_uint64_t ++grub_mem_attrs_to_uefi_mem_attrs (grub_uint64_t attrs) ++{ ++ grub_uint64_t ret = GRUB_EFI_MEMORY_RP | ++ GRUB_EFI_MEMORY_RO | ++ GRUB_EFI_MEMORY_XP; ++ ++ if (attrs & GRUB_MEM_ATTR_R) ++ ret &= ~GRUB_EFI_MEMORY_RP; ++ ++ if (attrs & GRUB_MEM_ATTR_W) ++ ret &= ~GRUB_EFI_MEMORY_RO; ++ ++ if (attrs & GRUB_MEM_ATTR_X) ++ ret &= ~GRUB_EFI_MEMORY_XP; ++ ++ return ret; ++} ++ ++static inline grub_uint64_t ++uefi_mem_attrs_to_grub_mem_attrs (grub_uint64_t attrs) ++{ ++ grub_uint64_t ret = GRUB_MEM_ATTR_R | ++ GRUB_MEM_ATTR_W | ++ GRUB_MEM_ATTR_X; ++ ++ if (attrs & GRUB_EFI_MEMORY_RP) ++ ret &= ~GRUB_MEM_ATTR_R; ++ ++ if (attrs & GRUB_EFI_MEMORY_RO) ++ ret &= ~GRUB_MEM_ATTR_W; ++ ++ if (attrs & GRUB_EFI_MEMORY_XP) ++ ret &= ~GRUB_MEM_ATTR_X; ++ ++ return ret; ++} ++ ++grub_err_t ++grub_get_mem_attrs (grub_addr_t addr, grub_size_t size, grub_uint64_t *attrs) ++{ ++ grub_efi_memory_attribute_protocol_t *proto; ++ grub_efi_physical_address_t physaddr = addr; ++ grub_efi_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; ++ grub_efi_status_t efi_status; ++ ++ proto = grub_efi_locate_protocol (&protocol_guid, 0); ++ if (!proto) ++ return GRUB_ERR_NOT_IMPLEMENTED_YET; ++ ++ if (physaddr & 0xfff || size & 0xfff || size == 0 || attrs == NULL) ++ { ++ grub_dprintf ("nx", "%s called on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" and attrs %p\n", ++ __func__, physaddr, physaddr+size-1, attrs); ++ return 0; ++ } ++ ++ efi_status = efi_call_4(proto->get_memory_attributes, ++ proto, physaddr, size, attrs); ++ *attrs = uefi_mem_attrs_to_grub_mem_attrs (*attrs); ++ ++ return grub_efi_status_to_err (efi_status); ++} ++ ++grub_err_t ++grub_update_mem_attrs (grub_addr_t addr, grub_size_t size, ++ grub_uint64_t set_attrs, grub_uint64_t clear_attrs) ++{ ++ grub_efi_memory_attribute_protocol_t *proto; ++ grub_efi_physical_address_t physaddr = addr; ++ grub_efi_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; ++ grub_efi_status_t efi_status = GRUB_EFI_SUCCESS; ++ grub_uint64_t before = 0, after = 0, uefi_set_attrs, uefi_clear_attrs; ++ grub_err_t err; ++ ++ proto = grub_efi_locate_protocol (&protocol_guid, 0); ++ if (!proto) ++ return GRUB_ERR_NONE; ++ ++ err = grub_get_mem_attrs (addr, size, &before); ++ if (err) ++ grub_dprintf ("nx", "grub_get_mem_attrs(0x%"PRIxGRUB_ADDR", %"PRIuGRUB_SIZE", %p) -> 0x%x\n", ++ addr, size, &before, err); ++ ++ if (physaddr & 0xfff || size & 0xfff || size == 0) ++ { ++ grub_dprintf ("nx", "%s called on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" +%s%s%s -%s%s%s\n", ++ __func__, physaddr, physaddr + size - 1, ++ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "", ++ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : ""); ++ return 0; ++ } ++ ++ uefi_set_attrs = grub_mem_attrs_to_uefi_mem_attrs (set_attrs); ++ grub_dprintf ("nx", "translating set_attrs from 0x%lx to 0x%lx\n", set_attrs, uefi_set_attrs); ++ uefi_clear_attrs = grub_mem_attrs_to_uefi_mem_attrs (clear_attrs); ++ grub_dprintf ("nx", "translating clear_attrs from 0x%lx to 0x%lx\n", clear_attrs, uefi_clear_attrs); ++ if (uefi_set_attrs) ++ efi_status = efi_call_4(proto->set_memory_attributes, ++ proto, physaddr, size, uefi_set_attrs); ++ if (efi_status == GRUB_EFI_SUCCESS && uefi_clear_attrs) ++ efi_status = efi_call_4(proto->clear_memory_attributes, ++ proto, physaddr, size, uefi_clear_attrs); ++ ++ err = grub_get_mem_attrs (addr, size, &after); ++ if (err) ++ grub_dprintf ("nx", "grub_get_mem_attrs(0x%"PRIxGRUB_ADDR", %"PRIuGRUB_SIZE", %p) -> 0x%x\n", ++ addr, size, &after, err); ++ ++ grub_dprintf ("nx", "set +%s%s%s -%s%s%s on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" before:%c%c%c after:%c%c%c\n", ++ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "", ++ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "", ++ addr, addr + size - 1, ++ (before & GRUB_MEM_ATTR_R) ? 'r' : '-', ++ (before & GRUB_MEM_ATTR_W) ? 'w' : '-', ++ (before & GRUB_MEM_ATTR_X) ? 'x' : '-', ++ (after & GRUB_MEM_ATTR_R) ? 'r' : '-', ++ (after & GRUB_MEM_ATTR_W) ? 'w' : '-', ++ (after & GRUB_MEM_ATTR_X) ? 'x' : '-'); ++ ++ return grub_efi_status_to_err (efi_status); ++} +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index f431f49973..464842ba37 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -363,6 +363,11 @@ + { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \ + } + ++#define GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID \ ++ { 0xf4560cf6, 0x40ec, 0x4b4a, \ ++ { 0xa1, 0x92, 0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89 } \ ++ } ++ + struct grub_efi_sal_system_table + { + grub_uint32_t signature; +@@ -2102,6 +2107,26 @@ struct grub_efi_ip6_config_manual_address { + }; + typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t; + ++struct grub_efi_memory_attribute_protocol ++{ ++ grub_efi_status_t (*get_memory_attributes) ( ++ struct grub_efi_memory_attribute_protocol *this, ++ grub_efi_physical_address_t base_address, ++ grub_efi_uint64_t length, ++ grub_efi_uint64_t *attributes); ++ grub_efi_status_t (*set_memory_attributes) ( ++ struct grub_efi_memory_attribute_protocol *this, ++ grub_efi_physical_address_t base_address, ++ grub_efi_uint64_t length, ++ grub_efi_uint64_t attributes); ++ grub_efi_status_t (*clear_memory_attributes) ( ++ struct grub_efi_memory_attribute_protocol *this, ++ grub_efi_physical_address_t base_address, ++ grub_efi_uint64_t length, ++ grub_efi_uint64_t attributes); ++}; ++typedef struct grub_efi_memory_attribute_protocol grub_efi_memory_attribute_protocol_t; ++ + #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ + || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ + || defined(__riscv) +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index ec52083c49..34825c4adc 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -164,4 +164,6 @@ struct grub_net_card; + grub_efi_handle_t + grub_efinet_get_device_handle (struct grub_net_card *card); + ++grub_err_t EXPORT_FUNC(grub_efi_status_to_err) (grub_efi_status_t status); ++ + #endif /* ! GRUB_EFI_EFI_HEADER */ +diff --git a/include/grub/mm.h b/include/grub/mm.h +index 9c38dd3ca5..d81623d226 100644 +--- a/include/grub/mm.h ++++ b/include/grub/mm.h +@@ -22,6 +22,7 @@ + + #include + #include ++#include + #include + + #ifndef NULL +@@ -38,6 +39,37 @@ void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size); + void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size); + #endif + ++#define GRUB_MEM_ATTR_R 0x0000000000000004LLU ++#define GRUB_MEM_ATTR_W 0x0000000000000002LLU ++#define GRUB_MEM_ATTR_X 0x0000000000000001LLU ++ ++#ifdef GRUB_MACHINE_EFI ++grub_err_t EXPORT_FUNC(grub_get_mem_attrs) (grub_addr_t addr, ++ grub_size_t size, ++ grub_uint64_t *attrs); ++grub_err_t EXPORT_FUNC(grub_update_mem_attrs) (grub_addr_t addr, ++ grub_size_t size, ++ grub_uint64_t set_attrs, ++ grub_uint64_t clear_attrs); ++#else /* !GRUB_MACHINE_EFI */ ++static inline grub_err_t ++grub_get_mem_attrs (grub_addr_t addr __attribute__((__unused__)), ++ grub_size_t size __attribute__((__unused__)), ++ grub_uint64_t *attrs __attribute__((__unused__))) ++{ ++ return GRUB_ERR_NONE; ++} ++ ++static inline grub_err_t ++grub_update_mem_attrs (grub_addr_t addr __attribute__((__unused__)), ++ grub_size_t size __attribute__((__unused__)), ++ grub_uint64_t set_attrs __attribute__((__unused__)), ++ grub_uint64_t clear_attrs __attribute__((__unused__))) ++{ ++ return GRUB_ERR_NONE; ++} ++#endif /* GRUB_MACHINE_EFI */ ++ + void grub_mm_check_real (const char *file, int line); + #define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__); + diff --git a/0256-nx-set-page-permissions-for-loaded-modules.patch b/0256-nx-set-page-permissions-for-loaded-modules.patch new file mode 100644 index 0000000..9e0aebb --- /dev/null +++ b/0256-nx-set-page-permissions-for-loaded-modules.patch @@ -0,0 +1,263 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 21 Mar 2022 17:46:35 -0400 +Subject: [PATCH] nx: set page permissions for loaded modules. + +For NX, we need to set write and executable permissions on the sections +of grub modules when we load them. + +On sections with SHF_ALLOC set, which is typically everything except +.modname and the symbol and string tables, this patch clears the Read +Only flag on sections that have the ELF flag SHF_WRITE set, and clears +the No eXecute flag on sections with SHF_EXECINSTR set. In all other +cases it sets both flags. + +Signed-off-by: Peter Jones +[rharwood: arm tgptr -> tgaddr] +Signed-off-by: Robbie Harwood +--- + grub-core/kern/dl.c | 120 +++++++++++++++++++++++++++++++++++++++------------- + include/grub/dl.h | 44 +++++++++++++++++++ + 2 files changed, 134 insertions(+), 30 deletions(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index 8c7aacef39..d5de80186f 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -285,6 +285,8 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + #endif + char *ptr; + ++ grub_dprintf ("modules", "loading segments for \"%s\"\n", mod->name); ++ + arch_addralign = grub_arch_dl_min_alignment (); + + for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); +@@ -384,6 +386,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + ptr += got; + #endif + ++ grub_dprintf ("modules", "done loading segments for \"%s\"\n", mod->name); + return GRUB_ERR_NONE; + } + +@@ -517,23 +520,6 @@ grub_dl_find_section (Elf_Ehdr *e, const char *name) + return s; + return NULL; + } +-static long +-grub_dl_find_section_index (Elf_Ehdr *e, const char *name) +-{ +- Elf_Shdr *s; +- const char *str; +- unsigned i; +- +- s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); +- str = (char *) e + s->sh_offset; +- +- for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); +- i < e->e_shnum; +- i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) +- if (grub_strcmp (str + s->sh_name, name) == 0) +- return (long)i; +- return -1; +-} + + /* Me, Vladimir Serbinenko, hereby I add this module check as per new + GNU module policy. Note that this license check is informative only. +@@ -662,6 +648,7 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) + Elf_Shdr *s; + unsigned i; + ++ grub_dprintf ("modules", "relocating symbols for \"%s\"\n", mod->name); + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) +@@ -670,24 +657,95 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) + grub_dl_segment_t seg; + grub_err_t err; + +- /* Find the target segment. */ +- for (seg = mod->segment; seg; seg = seg->next) +- if (seg->section == s->sh_info) +- break; ++ seg = grub_dl_find_segment(mod, s->sh_info); ++ if (!seg) ++ continue; + +- if (seg) +- { +- if (!mod->symtab) +- return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); ++ if (!mod->symtab) ++ return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); + +- err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); +- if (err) +- return err; +- } ++ err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); ++ if (err) ++ return err; + } + ++ grub_dprintf ("modules", "done relocating symbols for \"%s\"\n", mod->name); + return GRUB_ERR_NONE; + } ++ ++static grub_err_t ++grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr) ++{ ++ unsigned i; ++ const Elf_Shdr *s; ++ const Elf_Ehdr *e = ehdr; ++#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) ++ grub_size_t arch_addralign = grub_arch_dl_min_alignment (); ++ grub_addr_t tgaddr; ++ grub_uint64_t tgsz; ++#endif ++ ++ grub_dprintf ("modules", "updating memory attributes for \"%s\"\n", ++ mod->name); ++ for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); ++ i < e->e_shnum; ++ i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) ++ { ++ grub_dl_segment_t seg; ++ grub_uint64_t set_attrs = GRUB_MEM_ATTR_R; ++ grub_uint64_t clear_attrs = GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X; ++ ++ seg = grub_dl_find_segment(mod, i); ++ if (!seg) ++ continue; ++ ++ if (seg->size == 0 || !(s->sh_flags & SHF_ALLOC)) ++ continue; ++ ++ if (s->sh_flags & SHF_WRITE) ++ { ++ set_attrs |= GRUB_MEM_ATTR_W; ++ clear_attrs &= ~GRUB_MEM_ATTR_W; ++ } ++ ++ if (s->sh_flags & SHF_EXECINSTR) ++ { ++ set_attrs |= GRUB_MEM_ATTR_X; ++ clear_attrs &= ~GRUB_MEM_ATTR_X; ++ } ++ ++ grub_dprintf ("modules", "setting memory attrs for section \"%s\" to -%s%s%s+%s%s%s\n", ++ grub_dl_get_section_name(e, s), ++ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "", ++ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : ""); ++ grub_update_mem_attrs ((grub_addr_t)(seg->addr), seg->size, set_attrs, clear_attrs); ++ } ++ ++#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) ++ tgaddr = grub_min((grub_addr_t)mod->tramp, (grub_addr_t)mod->got); ++ tgsz = grub_max((grub_addr_t)mod->trampptr, (grub_addr_t)mod->gotptr) - tgaddr; ++ ++ if (tgsz) ++ { ++ tgsz = ALIGN_UP(tgsz, arch_addralign); ++ ++ grub_dprintf ("modules", "updating attributes for GOT and trampolines\n", ++ mod->name); ++ grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_X, ++ GRUB_MEM_ATTR_W); ++ } ++#endif ++ ++ grub_dprintf ("modules", "done updating module memory attributes for \"%s\"\n", ++ mod->name); ++ ++ return GRUB_ERR_NONE; ++} ++ + static void + grub_dl_print_gdb_info (grub_dl_t mod, Elf_Ehdr *e) + { +@@ -753,6 +811,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) + mod->ref_count = 1; + + grub_dprintf ("modules", "relocating to %p\n", mod); ++ + /* Me, Vladimir Serbinenko, hereby I add this module check as per new + GNU module policy. Note that this license check is informative only. + Modules have to be licensed under GPLv3 or GPLv3+ (optionally +@@ -766,7 +825,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) + || grub_dl_resolve_dependencies (mod, e) + || grub_dl_load_segments (mod, e) + || grub_dl_resolve_symbols (mod, e) +- || grub_dl_relocate_symbols (mod, e)) ++ || grub_dl_relocate_symbols (mod, e) ++ || grub_dl_set_mem_attrs (mod, e)) + { + mod->fini = 0; + grub_dl_unload (mod); +diff --git a/include/grub/dl.h b/include/grub/dl.h +index f36ed5cb17..45ac8e339f 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #endif + + /* +@@ -268,6 +269,49 @@ grub_dl_is_persistent (grub_dl_t mod) + return mod->persistent; + } + ++static inline const char * ++grub_dl_get_section_name (const Elf_Ehdr *e, const Elf_Shdr *s) ++{ ++ Elf_Shdr *str_s; ++ const char *str; ++ ++ str_s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); ++ str = (char *) e + str_s->sh_offset; ++ ++ return str + s->sh_name; ++} ++ ++static inline long ++grub_dl_find_section_index (Elf_Ehdr *e, const char *name) ++{ ++ Elf_Shdr *s; ++ const char *str; ++ unsigned i; ++ ++ s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); ++ str = (char *) e + s->sh_offset; ++ ++ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); ++ i < e->e_shnum; ++ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) ++ if (grub_strcmp (str + s->sh_name, name) == 0) ++ return (long)i; ++ return -1; ++} ++ ++/* Return the segment for a section of index N */ ++static inline grub_dl_segment_t ++grub_dl_find_segment (grub_dl_t mod, unsigned n) ++{ ++ grub_dl_segment_t seg; ++ ++ for (seg = mod->segment; seg; seg = seg->next) ++ if (seg->section == n) ++ return seg; ++ ++ return NULL; ++} ++ + #endif + + void * EXPORT_FUNC(grub_resolve_symbol) (const char *name); diff --git a/0256-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch b/0256-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch deleted file mode 100644 index ef51214..0000000 --- a/0256-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 25 Mar 2022 15:40:12 -0400 -Subject: [PATCH] pe: add the DOS header struct and fix some bad naming. - -In order to properly validate a loaded kernel's support for being loaded -without a writable stack or executable, we need to be able to properly -parse arbitrary PE headers. - -Currently, pe32.h is written in such a way that the MS-DOS header that -tells us where to find the PE header in the binary can't be accessed. -Further, for some reason it calls the DOS MZ magic "GRUB_PE32_MAGIC". - -This patch adds the structure for the DOS header, renames the DOS magic -define, and adds defines for the actual PE magic. - -Signed-off-by: Peter Jones ---- - grub-core/loader/arm64/linux.c | 2 +- - include/grub/efi/pe32.h | 28 ++++++++++++++++++++++++++-- - 2 files changed, 27 insertions(+), 3 deletions(-) - -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index d2af47c2c0..cc67f43906 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -58,7 +58,7 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) - if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE) - return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); - -- if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC) -+ if ((lh->code0 & 0xffff) != GRUB_DOS_MAGIC) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); - -diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h -index a43adf2746..2a5e1ee003 100644 ---- a/include/grub/efi/pe32.h -+++ b/include/grub/efi/pe32.h -@@ -46,7 +46,30 @@ - - #define GRUB_PE32_MSDOS_STUB_SIZE 0x80 - --#define GRUB_PE32_MAGIC 0x5a4d -+#define GRUB_DOS_MAGIC 0x5a4d -+ -+struct grub_dos_header -+{ -+ grub_uint16_t magic; -+ grub_uint16_t cblp; -+ grub_uint16_t cp; -+ grub_uint16_t crlc; -+ grub_uint16_t cparhdr; -+ grub_uint16_t minalloc; -+ grub_uint16_t maxalloc; -+ grub_uint16_t ss; -+ grub_uint16_t sp; -+ grub_uint16_t csum; -+ grub_uint16_t ip; -+ grub_uint16_t cs; -+ grub_uint16_t lfarlc; -+ grub_uint16_t ovno; -+ grub_uint16_t res0[4]; -+ grub_uint16_t oemid; -+ grub_uint16_t oeminfo; -+ grub_uint16_t res1[10]; -+ grub_uint32_t lfanew; -+}; - - /* According to the spec, the minimal alignment is 512 bytes... - But some examples (such as EFI drivers in the Intel -@@ -280,7 +303,8 @@ struct grub_pe32_section_table - - - --#define GRUB_PE32_SIGNATURE_SIZE 4 -+#define GRUB_PE32_SIGNATURE_SIZE 4 -+#define GRUB_PE32_SIGNATURE "PE\0\0" - - struct grub_pe32_header - { diff --git a/0257-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch b/0257-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch deleted file mode 100644 index c6688cd..0000000 --- a/0257-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 9 Feb 2022 16:08:20 -0500 -Subject: [PATCH] EFI: allocate kernel in EFI_RUNTIME_SERVICES_CODE instead of - EFI_LOADER_DATA. - -On some of the firmwares with more security mitigations, EFI_LOADER_DATA -doesn't get you executable memory, and we take a fault and reboot when -we enter kernel. - -This patch correctly allocates the kernel code as EFI_RUNTIME_SERVICES_CODE -rather than EFI_LOADER_DATA. - -Signed-off-by: Peter Jones -[rharwood: use kernel_size] -Signed-off-by: Robbie Harwood ---- - grub-core/loader/i386/efi/linux.c | 19 +++++++++++++------ - 1 file changed, 13 insertions(+), 6 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 9e5c11ac69..92b2fb5091 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -86,7 +86,9 @@ kernel_free(void *addr, grub_efi_uintn_t size) - } - - static void * --kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) -+kernel_alloc(grub_efi_uintn_t size, -+ grub_efi_memory_type_t memtype, -+ const char * const errmsg) - { - void *addr = 0; - unsigned int i; -@@ -112,7 +114,7 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) - prev_max = max; - addr = grub_efi_allocate_pages_real (max, pages, - max_addresses[i].alloc_type, -- GRUB_EFI_LOADER_DATA); -+ memtype); - if (addr) - grub_dprintf ("linux", "Allocated at %p\n", addr); - } -@@ -242,7 +244,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - } - } - -- initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -+ initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA, -+ N_("can't allocate initrd")); - if (initrd_mem == NULL) - goto fail; - grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); -@@ -393,7 +396,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -- params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters"); -+ params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA, -+ "cannot allocate kernel parameters"); - if (!params) - goto fail; - grub_dprintf ("linux", "params = %p\n", params); -@@ -415,7 +419,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "new lh is at %p\n", lh); - - grub_dprintf ("linux", "setting up cmdline\n"); -- cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); -+ cmdline = kernel_alloc (lh->cmdline_size + 1, -+ GRUB_EFI_RUNTIME_SERVICES_DATA, -+ N_("can't allocate cmdline")); - if (!cmdline) - goto fail; - grub_dprintf ("linux", "cmdline = %p\n", cmdline); -@@ -461,7 +467,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - kernel_size = lh->init_size; -- kernel_mem = kernel_alloc (kernel_size, N_("can't allocate kernel")); -+ kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, -+ N_("can't allocate kernel")); - restore_addresses(); - if (!kernel_mem) - goto fail; diff --git a/0257-nx-set-attrs-in-our-kernel-loaders.patch b/0257-nx-set-attrs-in-our-kernel-loaders.patch new file mode 100644 index 0000000..514df1f --- /dev/null +++ b/0257-nx-set-attrs-in-our-kernel-loaders.patch @@ -0,0 +1,565 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 22 Mar 2022 10:57:07 -0400 +Subject: [PATCH] nx: set attrs in our kernel loaders + +For NX, our kernel loaders need to set write and execute page +permissions on allocated pages and the stack. + +This patch adds those calls. + +Signed-off-by: Peter Jones +[rharwood: fix stack_attrs undefined, fix aarch64 callsites] +Signed-off-by: Robbie Harwood +--- + grub-core/kern/efi/mm.c | 77 +++++++++++++++++ + grub-core/loader/arm64/linux.c | 16 +++- + grub-core/loader/arm64/xen_boot.c | 4 +- + grub-core/loader/efi/chainloader.c | 11 +++ + grub-core/loader/efi/linux.c | 164 ++++++++++++++++++++++++++++++++++++- + grub-core/loader/i386/efi/linux.c | 26 +++++- + grub-core/loader/i386/linux.c | 5 ++ + include/grub/efi/efi.h | 6 +- + include/grub/efi/linux.h | 16 +++- + include/grub/efi/pe32.h | 2 + + 10 files changed, 312 insertions(+), 15 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 2c33758ed7..e460b072e6 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -610,6 +610,81 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map, + } + #endif + ++grub_addr_t grub_stack_addr = (grub_addr_t)-1ll; ++grub_size_t grub_stack_size = 0; ++ ++static void ++grub_nx_init (void) ++{ ++ grub_uint64_t attrs, stack_attrs; ++ grub_err_t err; ++ grub_addr_t stack_current, stack_end; ++ const grub_uint64_t page_size = 4096; ++ const grub_uint64_t page_mask = ~(page_size - 1); ++ ++ /* ++ * These are to confirm that the flags are working as expected when ++ * debugging. ++ */ ++ attrs = 0; ++ stack_current = (grub_addr_t)grub_nx_init & page_mask; ++ err = grub_get_mem_attrs (stack_current, page_size, &attrs); ++ if (err) ++ { ++ grub_dprintf ("nx", ++ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", ++ stack_current, err); ++ grub_error_pop (); ++ } ++ else ++ grub_dprintf ("nx", "page attrs for grub_nx_init (%p) are %c%c%c\n", ++ grub_dl_load_core, ++ (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', ++ (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-', ++ (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-'); ++ ++ stack_current = (grub_addr_t)&stack_current & page_mask; ++ err = grub_get_mem_attrs (stack_current, page_size, &stack_attrs); ++ if (err) ++ { ++ grub_dprintf ("nx", ++ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", ++ stack_current, err); ++ grub_error_pop (); ++ } ++ else ++ { ++ attrs = stack_attrs; ++ grub_dprintf ("nx", "page attrs for stack (%p) are %c%c%c\n", ++ &attrs, ++ (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', ++ (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-', ++ (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-'); ++ } ++ for (stack_end = stack_current + page_size ; ++ !(attrs & GRUB_MEM_ATTR_R); ++ stack_end += page_size) ++ { ++ err = grub_get_mem_attrs (stack_current, page_size, &attrs); ++ if (err) ++ { ++ grub_dprintf ("nx", ++ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", ++ stack_current, err); ++ grub_error_pop (); ++ break; ++ } ++ } ++ if (stack_end > stack_current) ++ { ++ grub_stack_addr = stack_current; ++ grub_stack_size = stack_end - stack_current; ++ grub_dprintf ("nx", ++ "detected stack from 0x%"PRIxGRUB_ADDR" to 0x%"PRIxGRUB_ADDR"\n", ++ grub_stack_addr, grub_stack_addr + grub_stack_size - 1); ++ } ++} ++ + void + grub_efi_mm_init (void) + { +@@ -623,6 +698,8 @@ grub_efi_mm_init (void) + grub_efi_uint64_t required_pages; + int mm_status; + ++ grub_nx_init (); ++ + /* Prepare a memory region to store two memory maps. */ + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + if (! memory_map) +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index cc67f43906..de85583487 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -172,7 +172,8 @@ free_params (void) + } + + grub_err_t +-grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) ++grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args, ++ int nx_supported) + { + grub_err_t retval; + +@@ -182,7 +183,8 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) + + grub_dprintf ("linux", "linux command line: '%s'\n", args); + +- retval = grub_efi_linux_boot ((char *)addr, handover_offset, (void *)addr); ++ retval = grub_efi_linux_boot (addr, size, handover_offset, ++ (void *)addr, nx_supported); + + /* Never reached... */ + free_params(); +@@ -192,7 +194,10 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) + static grub_err_t + grub_linux_boot (void) + { +- return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, linux_args)); ++ return grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, ++ (grub_size_t)kernel_size, ++ linux_args, ++ 0); + } + + static grub_err_t +@@ -340,6 +345,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_off_t filelen; + grub_uint32_t align; + void *kernel = NULL; ++ int nx_supported = 1; + + grub_dl_ref (my_mod); + +@@ -376,6 +382,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); + grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); + ++ err = grub_efi_check_nx_image_support((grub_addr_t)kernel, filelen, &nx_supported); ++ if (err != GRUB_ERR_NONE) ++ goto fail; ++ + grub_loader_unset(); + + kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); +diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c +index d9b7a9ba40..6e7e920416 100644 +--- a/grub-core/loader/arm64/xen_boot.c ++++ b/grub-core/loader/arm64/xen_boot.c +@@ -266,7 +266,9 @@ xen_boot (void) + return err; + + return grub_arch_efi_linux_boot_image (xen_hypervisor->start, +- xen_hypervisor->cmdline); ++ xen_hypervisor->size, ++ xen_hypervisor->cmdline, ++ 0); + } + + static void +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index fb874f1855..dd31ac9bb3 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -1070,6 +1070,17 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + ++ /* ++ * The OS kernel is going to set its own permissions when it takes over ++ * paging a few million instructions from now, and load_image() will set up ++ * anything that's needed based on the section headers, so there's no point ++ * in doing anything but clearing the protection bits here. ++ */ ++ grub_dprintf("nx", "setting attributes for %p (%lu bytes) to %llx\n", ++ (void *)(grub_addr_t)address, fsize, 0llu); ++ grub_update_mem_attrs (address, fsize, ++ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X, 0); ++ + #if defined (__i386__) || defined (__x86_64__) + if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header)) + { +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index 9265cf4200..277f352e0c 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -26,16 +26,127 @@ + + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" ++#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" ++ ++grub_err_t ++grub_efi_check_nx_image_support (grub_addr_t kernel_addr, ++ grub_size_t kernel_size, ++ int *nx_supported) ++{ ++ struct grub_dos_header *doshdr; ++ grub_size_t sz = sizeof (*doshdr); ++ ++ struct grub_pe32_header_32 *pe32; ++ struct grub_pe32_header_64 *pe64; ++ ++ int image_is_compatible = 0; ++ int is_64_bit; ++ ++ if (kernel_size < sz) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); ++ ++ doshdr = (void *)kernel_addr; ++ ++ if ((doshdr->magic & 0xffff) != GRUB_DOS_MAGIC) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel DOS magic is invalid")); ++ ++ sz = doshdr->lfanew + sizeof (*pe32); ++ if (kernel_size < sz) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); ++ ++ pe32 = (struct grub_pe32_header_32 *)(kernel_addr + doshdr->lfanew); ++ pe64 = (struct grub_pe32_header_64 *)pe32; ++ ++ if (grub_memcmp (pe32->signature, GRUB_PE32_SIGNATURE, ++ GRUB_PE32_SIGNATURE_SIZE) != 0) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel PE magic is invalid")); ++ ++ switch (pe32->coff_header.machine) ++ { ++ case GRUB_PE32_MACHINE_ARMTHUMB_MIXED: ++ case GRUB_PE32_MACHINE_I386: ++ case GRUB_PE32_MACHINE_RISCV32: ++ is_64_bit = 0; ++ break; ++ case GRUB_PE32_MACHINE_ARM64: ++ case GRUB_PE32_MACHINE_IA64: ++ case GRUB_PE32_MACHINE_RISCV64: ++ case GRUB_PE32_MACHINE_X86_64: ++ is_64_bit = 1; ++ break; ++ default: ++ return grub_error (GRUB_ERR_BAD_OS, N_("PE machine type 0x%04hx unknown"), ++ pe32->coff_header.machine); ++ } ++ ++ if (is_64_bit) ++ { ++ sz = doshdr->lfanew + sizeof (*pe64); ++ if (kernel_size < sz) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); ++ ++ if (pe64->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT) ++ image_is_compatible = 1; ++ } ++ else ++ { ++ if (pe32->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT) ++ image_is_compatible = 1; ++ } ++ ++ *nx_supported = image_is_compatible; ++ return GRUB_ERR_NONE; ++} ++ ++grub_err_t ++grub_efi_check_nx_required (int *nx_required) ++{ ++ grub_efi_status_t status; ++ grub_efi_guid_t guid = GRUB_EFI_SHIM_LOCK_GUID; ++ grub_size_t mok_policy_sz = 0; ++ char *mok_policy = NULL; ++ grub_uint32_t mok_policy_attrs = 0; ++ ++ status = grub_efi_get_variable_with_attributes ("MokPolicy", &guid, ++ &mok_policy_sz, ++ (void **)&mok_policy, ++ &mok_policy_attrs); ++ if (status == GRUB_EFI_NOT_FOUND || ++ mok_policy_sz == 0 || ++ mok_policy == NULL) ++ { ++ *nx_required = 0; ++ return GRUB_ERR_NONE; ++ } ++ ++ *nx_required = 0; ++ if (mok_policy_sz < 1 || ++ mok_policy_attrs != (GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | ++ GRUB_EFI_VARIABLE_RUNTIME_ACCESS) || ++ (mok_policy[mok_policy_sz-1] & GRUB_MOK_POLICY_NX_REQUIRED)) ++ *nx_required = 1; ++ ++ return GRUB_ERR_NONE; ++} + + typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); + + grub_err_t +-grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, +- void *kernel_params) ++grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size, ++ grub_off_t handover_offset, void *kernel_params, ++ int nx_supported) + { + grub_efi_loaded_image_t *loaded_image = NULL; + handover_func hf; + int offset = 0; ++ grub_uint64_t stack_set_attrs = GRUB_MEM_ATTR_R | ++ GRUB_MEM_ATTR_W | ++ GRUB_MEM_ATTR_X; ++ grub_uint64_t stack_clear_attrs = 0; ++ grub_uint64_t kernel_set_attrs = stack_set_attrs; ++ grub_uint64_t kernel_clear_attrs = stack_clear_attrs; ++ grub_uint64_t attrs; ++ int nx_required = 0; + + #ifdef __x86_64__ + offset = 512; +@@ -48,12 +159,57 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, + */ + loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); + if (loaded_image) +- loaded_image->image_base = kernel_addr; ++ loaded_image->image_base = (void *)kernel_addr; + else + grub_dprintf ("linux", "Loaded Image base address could not be set\n"); + + grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n", +- kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params); ++ (void *)kernel_addr, (void *)handover_offset, kernel_params); ++ ++ ++ if (nx_required && !nx_supported) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel does not support NX loading required by policy")); ++ ++ if (nx_supported) ++ { ++ kernel_set_attrs &= ~GRUB_MEM_ATTR_W; ++ kernel_clear_attrs |= GRUB_MEM_ATTR_W; ++ stack_set_attrs &= ~GRUB_MEM_ATTR_X; ++ stack_clear_attrs |= GRUB_MEM_ATTR_X; ++ } ++ ++ grub_dprintf ("nx", "Setting attributes for 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to r%cx\n", ++ kernel_addr, kernel_addr + kernel_size - 1, ++ (kernel_set_attrs & GRUB_MEM_ATTR_W) ? 'w' : '-'); ++ grub_update_mem_attrs (kernel_addr, kernel_size, ++ kernel_set_attrs, kernel_clear_attrs); ++ ++ grub_get_mem_attrs (kernel_addr, 4096, &attrs); ++ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n", ++ (grub_addr_t)kernel_addr, ++ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-", ++ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-", ++ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-"); ++ if (grub_stack_addr != (grub_addr_t)-1ll) ++ { ++ grub_dprintf ("nx", "Setting attributes for stack at 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to rw%c\n", ++ grub_stack_addr, grub_stack_addr + grub_stack_size - 1, ++ (stack_set_attrs & GRUB_MEM_ATTR_X) ? 'x' : '-'); ++ grub_update_mem_attrs (grub_stack_addr, grub_stack_size, ++ stack_set_attrs, stack_clear_attrs); ++ ++ grub_get_mem_attrs (grub_stack_addr, 4096, &attrs); ++ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n", ++ grub_stack_addr, ++ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-", ++ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-", ++ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-"); ++ } ++ ++#if defined(__i386__) || defined(__x86_64__) ++ asm volatile ("cli"); ++#endif ++ + hf = (handover_func)((char *)kernel_addr + handover_offset + offset); + hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 92b2fb5091..91ae274299 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -44,7 +44,7 @@ struct grub_linuxefi_context { + grub_uint32_t handover_offset; + struct linux_kernel_params *params; + char *cmdline; +- ++ int nx_supported; + void *initrd_mem; + }; + +@@ -110,13 +110,19 @@ kernel_alloc(grub_efi_uintn_t size, + pages = BYTES_TO_PAGES(size); + grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n", + (unsigned long)pages, (void *)(unsigned long)max); ++ size = pages * GRUB_EFI_PAGE_SIZE; + + prev_max = max; + addr = grub_efi_allocate_pages_real (max, pages, + max_addresses[i].alloc_type, + memtype); + if (addr) +- grub_dprintf ("linux", "Allocated at %p\n", addr); ++ { ++ grub_dprintf ("linux", "Allocated at %p\n", addr); ++ grub_update_mem_attrs ((grub_addr_t)addr, size, ++ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, ++ GRUB_MEM_ATTR_X); ++ } + } + + while (grub_error_pop ()) +@@ -137,9 +143,11 @@ grub_linuxefi_boot (void *data) + + asm volatile ("cli"); + +- return grub_efi_linux_boot ((char *)context->kernel_mem, ++ return grub_efi_linux_boot ((grub_addr_t)context->kernel_mem, ++ context->kernel_size, + context->handover_offset, +- context->params); ++ context->params, ++ context->nx_supported); + } + + static grub_err_t +@@ -304,7 +312,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_uint32_t handover_offset; + struct linux_kernel_params *params = 0; + char *cmdline = 0; ++ int nx_supported = 1; + struct grub_linuxefi_context *context = 0; ++ grub_err_t err; + + grub_dl_ref (my_mod); + +@@ -334,6 +344,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + ++ err = grub_efi_check_nx_image_support ((grub_addr_t)kernel, filelen, ++ &nx_supported); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ grub_dprintf ("linux", "nx is%s supported by this kernel\n", ++ nx_supported ? "" : " not"); ++ + lh = (struct linux_i386_kernel_header *)kernel; + grub_dprintf ("linux", "original lh is at %p\n", kernel); + +@@ -498,6 +515,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + context->handover_offset = handover_offset; + context->params = params; + context->cmdline = cmdline; ++ context->nx_supported = nx_supported; + + grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0); + +diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index 4aeb0e4b9a..3c1ff64763 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -805,6 +805,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + kernel_offset += len; + } + ++ grub_dprintf("efi", "setting attributes for %p (%zu bytes) to +rw-x\n", ++ &linux_params, sizeof (lh) + len); ++ grub_update_mem_attrs ((grub_addr_t)&linux_params, sizeof (lh) + len, ++ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, GRUB_MEM_ATTR_X); ++ + linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR; + linux_params.kernel_alignment = (1 << align); + linux_params.ps_mouse = linux_params.padding11 = 0; +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 34825c4adc..449e55269f 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -140,12 +140,16 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, + char **device, + char **path); + ++extern grub_addr_t EXPORT_VAR(grub_stack_addr); ++extern grub_size_t EXPORT_VAR(grub_stack_size); ++ + #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) + void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); + grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); + #include + grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh); +-grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, char *args); ++grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size, ++ char *args, int nx_enabled); + #endif + + grub_addr_t grub_efi_section_addr (const char *section); +diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h +index 887b02fd9f..b82f71006a 100644 +--- a/include/grub/efi/linux.h ++++ b/include/grub/efi/linux.h +@@ -22,8 +22,20 @@ + #include + #include + ++#define GRUB_MOK_POLICY_NX_REQUIRED 0x1 ++ + grub_err_t +-EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, +- void *kernel_param); ++EXPORT_FUNC(grub_efi_linux_boot) (grub_addr_t kernel_address, ++ grub_size_t kernel_size, ++ grub_off_t handover_offset, ++ void *kernel_param, int nx_enabled); ++ ++grub_err_t ++EXPORT_FUNC(grub_efi_check_nx_image_support) (grub_addr_t kernel_addr, ++ grub_size_t kernel_size, ++ int *nx_supported); ++ ++grub_err_t ++EXPORT_FUNC(grub_efi_check_nx_required) (int *nx_required); + + #endif /* ! GRUB_EFI_LINUX_HEADER */ +diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h +index 2a5e1ee003..a5e623eb04 100644 +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -181,6 +181,8 @@ struct grub_pe32_optional_header + struct grub_pe32_data_directory reserved_entry; + }; + ++#define GRUB_PE32_NX_COMPAT 0x0100 ++ + struct grub_pe64_optional_header + { + grub_uint16_t magic; diff --git a/0258-modules-load-module-sections-at-page-aligned-address.patch b/0258-modules-load-module-sections-at-page-aligned-address.patch deleted file mode 100644 index 9a5048c..0000000 --- a/0258-modules-load-module-sections-at-page-aligned-address.patch +++ /dev/null @@ -1,378 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 21 Mar 2022 17:45:40 -0400 -Subject: [PATCH] modules: load module sections at page-aligned addresses - -Currently we load module sections at whatever alignment gcc+ld happened -to dump into the ELF section header, which is often pretty useless. For -example, by default time.mod has these sections on a current x86_64 -build: - -$ eu-readelf -a grub-core/time.mod |& grep ^Section -A13 -Section Headers: -[Nr] Name Type Addr Off Size ES Flags Lk Inf Al -[ 0] NULL 0 00000000 00000000 0 0 0 0 -[ 1] .text PROGBITS 0 00000040 0000015e 0 AX 0 0 1 -[ 2] .rela.text RELA 0 00000458 000001e0 24 I 8 1 8 -[ 3] .rodata.str1.1 PROGBITS 0 0000019e 000000a1 1 AMS 0 0 1 -[ 4] .module_license PROGBITS 0 00000240 0000000f 0 A 0 0 8 -[ 5] .data PROGBITS 0 0000024f 00000000 0 WA 0 0 1 -[ 6] .bss NOBITS 0 00000250 00000008 0 WA 0 0 8 -[ 7] .modname PROGBITS 0 00000250 00000005 0 0 0 1 -[ 8] .symtab SYMTAB 0 00000258 00000150 24 9 6 8 -[ 9] .strtab STRTAB 0 000003a8 000000ab 0 0 0 1 -[10] .shstrtab STRTAB 0 00000638 00000059 0 0 0 1 - -With NX protections being page based, loading sections with either a 1 -or 8 *byte* alignment does absolutely nothing to help us out. - -This patch switches most EFI platforms to load module sections at 4kB -page-aligned addresses. To do so, it adds an new per-arch function, -grub_arch_dl_min_alignment(), which returns the alignment needed for -dynamically loaded sections (in bytes). Currently it sets it to 4096 -when GRUB_MACHINE_EFI is true on x86_64, i386, arm, arm64, and emu, and -1-byte alignment on everything else. - -It then changes the allocation size computation and the loader code in -grub_dl_load_segments() to align the locations and sizes up to these -boundaries, and fills any added padding with zeros. - -All of this happens before relocations are applied, so the relocations -factor that in with no change. - -As an aside, initially Daniel Kiper and I thought that it might be a -better idea to split the modules up into top-level sections as -.text.modules, .rodata.modules, .data.modules, etc., so that their page -permissions would get set by the loader that's loading grub itself. -This turns out to have two significant downsides: 1) either in mkimage -or in grub_dl_relocate_symbols(), you wind up having to dynamically -process the relocations to accommodate the moved module sections, and 2) -you then need to change the permissions on the modules and change them -back while relocating them in grub_dl_relocate_symbols(), which means -that any loader that /does/ honor the section flags but does /not/ -generally support NX with the memory attributes API will cause grub to -fail. - -Signed-off-by: Peter Jones ---- - grub-core/kern/arm/dl.c | 13 +++++++++++++ - grub-core/kern/arm64/dl.c | 13 +++++++++++++ - grub-core/kern/dl.c | 29 +++++++++++++++++++++-------- - grub-core/kern/emu/full.c | 13 +++++++++++++ - grub-core/kern/i386/dl.c | 13 +++++++++++++ - grub-core/kern/ia64/dl.c | 9 +++++++++ - grub-core/kern/mips/dl.c | 8 ++++++++ - grub-core/kern/powerpc/dl.c | 9 +++++++++ - grub-core/kern/riscv/dl.c | 13 +++++++++++++ - grub-core/kern/sparc64/dl.c | 9 +++++++++ - grub-core/kern/x86_64/dl.c | 13 +++++++++++++ - include/grub/dl.h | 2 ++ - docs/grub-dev.texi | 6 +++--- - 13 files changed, 139 insertions(+), 11 deletions(-) - -diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c -index eab9d17ff2..9260737936 100644 ---- a/grub-core/kern/arm/dl.c -+++ b/grub-core/kern/arm/dl.c -@@ -278,3 +278,16 @@ grub_arch_dl_check_header (void *ehdr) - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c -index 512e5a80b0..0d4a26857f 100644 ---- a/grub-core/kern/arm64/dl.c -+++ b/grub-core/kern/arm64/dl.c -@@ -196,3 +196,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index aef8af8aa7..8c7aacef39 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -277,7 +277,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - { - unsigned i; - const Elf_Shdr *s; -- grub_size_t tsize = 0, talign = 1; -+ grub_size_t tsize = 0, talign = 1, arch_addralign = 1; - #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) - grub_size_t tramp; - grub_size_t got; -@@ -285,16 +285,24 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - #endif - char *ptr; - -+ arch_addralign = grub_arch_dl_min_alignment (); -+ - for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) - { -+ grub_size_t sh_addralign; -+ grub_size_t sh_size; -+ - if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) - continue; - -- tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; -- if (talign < s->sh_addralign) -- talign = s->sh_addralign; -+ sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign); -+ sh_size = ALIGN_UP(s->sh_size, sh_addralign); -+ -+ tsize = ALIGN_UP (tsize, sh_addralign) + sh_size; -+ if (talign < sh_addralign) -+ talign = sh_addralign; - } - - #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) -@@ -323,6 +331,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - i < e->e_shnum; - i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) - { -+ grub_size_t sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign); -+ grub_size_t sh_size = ALIGN_UP(s->sh_size, sh_addralign); -+ - if (s->sh_flags & SHF_ALLOC) - { - grub_dl_segment_t seg; -@@ -335,17 +346,19 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - { - void *addr; - -- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign); -+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, sh_addralign); - addr = ptr; -- ptr += s->sh_size; -+ ptr += sh_size; - - switch (s->sh_type) - { - case SHT_PROGBITS: - grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size); -+ grub_memset ((char *)addr + s->sh_size, 0, -+ sh_size - s->sh_size); - break; - case SHT_NOBITS: -- grub_memset (addr, 0, s->sh_size); -+ grub_memset (addr, 0, sh_size); - break; - } - -@@ -354,7 +367,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - else - seg->addr = 0; - -- seg->size = s->sh_size; -+ seg->size = sh_size; - seg->section = i; - seg->next = mod->segment; - mod->segment = seg; -diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c -index e8d63b1f5f..1de1c28eb0 100644 ---- a/grub-core/kern/emu/full.c -+++ b/grub-core/kern/emu/full.c -@@ -67,3 +67,16 @@ grub_arch_dl_init_linker (void) - } - #endif - -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/grub-core/kern/i386/dl.c b/grub-core/kern/i386/dl.c -index 1346da5cc9..d6b4681fc9 100644 ---- a/grub-core/kern/i386/dl.c -+++ b/grub-core/kern/i386/dl.c -@@ -79,3 +79,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c -index db59300fea..92d82c5750 100644 ---- a/grub-core/kern/ia64/dl.c -+++ b/grub-core/kern/ia64/dl.c -@@ -148,3 +148,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - } - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+ return 1; -+} -diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c -index 5d7d299c74..6d83bd71e9 100644 ---- a/grub-core/kern/mips/dl.c -+++ b/grub-core/kern/mips/dl.c -@@ -272,3 +272,11 @@ grub_arch_dl_init_linker (void) - grub_dl_register_symbol ("_gp_disp", &_gp_disp_dummy, 0, 0); - } - -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+ return 1; -+} -diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c -index cdd61b305f..5d9ba2e158 100644 ---- a/grub-core/kern/powerpc/dl.c -+++ b/grub-core/kern/powerpc/dl.c -@@ -167,3 +167,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+ return 1; -+} -diff --git a/grub-core/kern/riscv/dl.c b/grub-core/kern/riscv/dl.c -index f26b12aaa4..aa18f9e990 100644 ---- a/grub-core/kern/riscv/dl.c -+++ b/grub-core/kern/riscv/dl.c -@@ -343,3 +343,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/grub-core/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c -index f3d960186b..f054f08241 100644 ---- a/grub-core/kern/sparc64/dl.c -+++ b/grub-core/kern/sparc64/dl.c -@@ -189,3 +189,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+ return 1; -+} -diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c -index e5a8bdcf4f..a105dc50ce 100644 ---- a/grub-core/kern/x86_64/dl.c -+++ b/grub-core/kern/x86_64/dl.c -@@ -119,3 +119,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/include/grub/dl.h b/include/grub/dl.h -index 618ae6f474..f36ed5cb17 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -280,6 +280,8 @@ grub_err_t grub_arch_dl_check_header (void *ehdr); - grub_err_t - grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - Elf_Shdr *s, grub_dl_segment_t seg); -+grub_size_t -+grub_arch_dl_min_alignment (void); - #endif - - #if defined (_mips) -diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi -index 90083772c8..c23ba313dc 100644 ---- a/docs/grub-dev.texi -+++ b/docs/grub-dev.texi -@@ -755,9 +755,9 @@ declare startup asm file ($cpu_$platform_startup) as well as any other files - (e.g. init.c and callwrap.S) (e.g. $cpu_$platform = kern/$cpu/$platform/init.c). - At this stage you will also need to add dummy dl.c and cache.S with functions - grub_err_t grub_arch_dl_check_header (void *ehdr), grub_err_t --grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c) and --void grub_arch_sync_caches (void *address, grub_size_t len) (cache.S). They --won't be used for now. -+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c), grub_uint32_t -+grub_arch_dl_min_alignment (void), and void grub_arch_sync_caches (void -+*address, grub_size_t len) (cache.S). They won't be used for now. - - You will need to create directory include/$cpu/$platform and a file - include/$cpu/types.h. The later folowing this template: diff --git a/0258-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch b/0258-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch new file mode 100644 index 0000000..7da75a8 --- /dev/null +++ b/0258-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 22 Mar 2022 10:57:20 -0400 +Subject: [PATCH] nx: set the nx compatible flag in EFI grub images + +For NX, we need the grub binary to announce that it is compatible with +the NX feature. This implies that when loading the executable grub +image, several attributes are true: + +- the binary doesn't need an executable stack +- the binary doesn't need sections to be both executable and writable +- the binary knows how to use the EFI Memory Attributes protocol on code + it is loading. + +This patch adds a definition for the PE DLL Characteristics flag +GRUB_PE32_NX_COMPAT, and changes grub-mkimage to set that flag. + +Signed-off-by: Peter Jones +--- + util/mkimage.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/util/mkimage.c b/util/mkimage.c +index 8319e8dfbd..c3d33aaac8 100644 +--- a/util/mkimage.c ++++ b/util/mkimage.c +@@ -1418,6 +1418,7 @@ grub_install_generate_image (const char *dir, const char *prefix, + section = (struct grub_pe32_section_table *)(o64 + 1); + } + ++ PE_OHDR (o32, o64, dll_characteristics) = grub_host_to_target16 (GRUB_PE32_NX_COMPAT); + PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size); + PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address); + PE_OHDR (o32, o64, image_base) = 0; diff --git a/0259-grub-probe-document-the-behavior-of-multiple-v.patch b/0259-grub-probe-document-the-behavior-of-multiple-v.patch new file mode 100644 index 0000000..4e9d7cc --- /dev/null +++ b/0259-grub-probe-document-the-behavior-of-multiple-v.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 15 Jul 2022 15:49:25 -0400 +Subject: [PATCH] grub-probe: document the behavior of multiple -v + +Signed-off-by: Robbie Harwood +(cherry picked from commit 51a55233eed08f7f12276afd6b3724b807a0b680) +--- + util/grub-probe.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/util/grub-probe.c b/util/grub-probe.c +index c6fac732b4..ba867319a7 100644 +--- a/util/grub-probe.c ++++ b/util/grub-probe.c +@@ -732,7 +732,8 @@ static struct argp_option options[] = { + {"device-map", 'm', N_("FILE"), 0, + N_("use FILE as the device map [default=%s]"), 0}, + {"target", 't', N_("TARGET"), 0, 0, 0}, +- {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, ++ {"verbose", 'v', 0, 0, ++ N_("print verbose messages (pass twice to enable debug printing)."), 0}, + {0, '0', 0, 0, N_("separate items in output using ASCII NUL characters"), 0}, + { 0, 0, 0, 0, 0, 0 } + }; diff --git a/0259-nx-add-memory-attribute-get-set-API.patch b/0259-nx-add-memory-attribute-get-set-API.patch deleted file mode 100644 index 91c9d2f..0000000 --- a/0259-nx-add-memory-attribute-get-set-API.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 22 Mar 2022 10:56:21 -0400 -Subject: [PATCH] nx: add memory attribute get/set API - -For NX, we need to set the page access permission attributes for write -and execute permissions. - -This patch adds two new primitives, grub_set_mem_attrs() and -grub_clear_mem_attrs(), and associated constant definitions, to be used -for that purpose. - -For most platforms, it adds a dummy implementation that returns -GRUB_ERR_NONE. On EFI platforms, it adds a common helper function, -grub_efi_status_to_err(), which translates EFI error codes to grub error -codes, adds headers for the EFI Memory Attribute Protocol (still pending -standardization), and an implementation of the grub nx primitives using -it. - -Signed-off-by: Peter Jones -[rharwood: add pjones's none/nyi fixup] -Signed-off-by: Robbie Harwood ---- - grub-core/kern/efi/efi.c | 36 +++++++++++++ - grub-core/kern/efi/mm.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++ - include/grub/efi/api.h | 25 +++++++++ - include/grub/efi/efi.h | 2 + - include/grub/mm.h | 32 ++++++++++++ - 5 files changed, 226 insertions(+) - -diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c -index 7fcca69c17..4ac2b2754e 100644 ---- a/grub-core/kern/efi/efi.c -+++ b/grub-core/kern/efi/efi.c -@@ -1096,3 +1096,39 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, - - return 0; - } -+ -+grub_err_t -+grub_efi_status_to_err (grub_efi_status_t status) -+{ -+ grub_err_t err; -+ switch (status) -+ { -+ case GRUB_EFI_SUCCESS: -+ err = GRUB_ERR_NONE; -+ break; -+ case GRUB_EFI_INVALID_PARAMETER: -+ default: -+ err = GRUB_ERR_BAD_ARGUMENT; -+ break; -+ case GRUB_EFI_OUT_OF_RESOURCES: -+ err = GRUB_ERR_OUT_OF_MEMORY; -+ break; -+ case GRUB_EFI_DEVICE_ERROR: -+ err = GRUB_ERR_IO; -+ break; -+ case GRUB_EFI_WRITE_PROTECTED: -+ err = GRUB_ERR_WRITE_ERROR; -+ break; -+ case GRUB_EFI_SECURITY_VIOLATION: -+ err = GRUB_ERR_ACCESS_DENIED; -+ break; -+ case GRUB_EFI_NOT_FOUND: -+ err = GRUB_ERR_FILE_NOT_FOUND; -+ break; -+ case GRUB_EFI_ABORTED: -+ err = GRUB_ERR_WAIT; -+ break; -+ } -+ -+ return err; -+} -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index e84961d078..2c33758ed7 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -738,3 +738,134 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) - return GRUB_ERR_NONE; - } - #endif -+ -+static inline grub_uint64_t -+grub_mem_attrs_to_uefi_mem_attrs (grub_uint64_t attrs) -+{ -+ grub_uint64_t ret = GRUB_EFI_MEMORY_RP | -+ GRUB_EFI_MEMORY_RO | -+ GRUB_EFI_MEMORY_XP; -+ -+ if (attrs & GRUB_MEM_ATTR_R) -+ ret &= ~GRUB_EFI_MEMORY_RP; -+ -+ if (attrs & GRUB_MEM_ATTR_W) -+ ret &= ~GRUB_EFI_MEMORY_RO; -+ -+ if (attrs & GRUB_MEM_ATTR_X) -+ ret &= ~GRUB_EFI_MEMORY_XP; -+ -+ return ret; -+} -+ -+static inline grub_uint64_t -+uefi_mem_attrs_to_grub_mem_attrs (grub_uint64_t attrs) -+{ -+ grub_uint64_t ret = GRUB_MEM_ATTR_R | -+ GRUB_MEM_ATTR_W | -+ GRUB_MEM_ATTR_X; -+ -+ if (attrs & GRUB_EFI_MEMORY_RP) -+ ret &= ~GRUB_MEM_ATTR_R; -+ -+ if (attrs & GRUB_EFI_MEMORY_RO) -+ ret &= ~GRUB_MEM_ATTR_W; -+ -+ if (attrs & GRUB_EFI_MEMORY_XP) -+ ret &= ~GRUB_MEM_ATTR_X; -+ -+ return ret; -+} -+ -+grub_err_t -+grub_get_mem_attrs (grub_addr_t addr, grub_size_t size, grub_uint64_t *attrs) -+{ -+ grub_efi_memory_attribute_protocol_t *proto; -+ grub_efi_physical_address_t physaddr = addr; -+ grub_efi_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; -+ grub_efi_status_t efi_status; -+ -+ proto = grub_efi_locate_protocol (&protocol_guid, 0); -+ if (!proto) -+ return GRUB_ERR_NOT_IMPLEMENTED_YET; -+ -+ if (physaddr & 0xfff || size & 0xfff || size == 0 || attrs == NULL) -+ { -+ grub_dprintf ("nx", "%s called on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" and attrs %p\n", -+ __func__, physaddr, physaddr+size-1, attrs); -+ return 0; -+ } -+ -+ efi_status = efi_call_4(proto->get_memory_attributes, -+ proto, physaddr, size, attrs); -+ *attrs = uefi_mem_attrs_to_grub_mem_attrs (*attrs); -+ -+ return grub_efi_status_to_err (efi_status); -+} -+ -+grub_err_t -+grub_update_mem_attrs (grub_addr_t addr, grub_size_t size, -+ grub_uint64_t set_attrs, grub_uint64_t clear_attrs) -+{ -+ grub_efi_memory_attribute_protocol_t *proto; -+ grub_efi_physical_address_t physaddr = addr; -+ grub_efi_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; -+ grub_efi_status_t efi_status = GRUB_EFI_SUCCESS; -+ grub_uint64_t before = 0, after = 0, uefi_set_attrs, uefi_clear_attrs; -+ grub_err_t err; -+ -+ proto = grub_efi_locate_protocol (&protocol_guid, 0); -+ if (!proto) -+ return GRUB_ERR_NONE; -+ -+ err = grub_get_mem_attrs (addr, size, &before); -+ if (err) -+ grub_dprintf ("nx", "grub_get_mem_attrs(0x%"PRIxGRUB_ADDR", %"PRIuGRUB_SIZE", %p) -> 0x%x\n", -+ addr, size, &before, err); -+ -+ if (physaddr & 0xfff || size & 0xfff || size == 0) -+ { -+ grub_dprintf ("nx", "%s called on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" +%s%s%s -%s%s%s\n", -+ __func__, physaddr, physaddr + size - 1, -+ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "", -+ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : ""); -+ return 0; -+ } -+ -+ uefi_set_attrs = grub_mem_attrs_to_uefi_mem_attrs (set_attrs); -+ grub_dprintf ("nx", "translating set_attrs from 0x%lx to 0x%lx\n", set_attrs, uefi_set_attrs); -+ uefi_clear_attrs = grub_mem_attrs_to_uefi_mem_attrs (clear_attrs); -+ grub_dprintf ("nx", "translating clear_attrs from 0x%lx to 0x%lx\n", clear_attrs, uefi_clear_attrs); -+ if (uefi_set_attrs) -+ efi_status = efi_call_4(proto->set_memory_attributes, -+ proto, physaddr, size, uefi_set_attrs); -+ if (efi_status == GRUB_EFI_SUCCESS && uefi_clear_attrs) -+ efi_status = efi_call_4(proto->clear_memory_attributes, -+ proto, physaddr, size, uefi_clear_attrs); -+ -+ err = grub_get_mem_attrs (addr, size, &after); -+ if (err) -+ grub_dprintf ("nx", "grub_get_mem_attrs(0x%"PRIxGRUB_ADDR", %"PRIuGRUB_SIZE", %p) -> 0x%x\n", -+ addr, size, &after, err); -+ -+ grub_dprintf ("nx", "set +%s%s%s -%s%s%s on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" before:%c%c%c after:%c%c%c\n", -+ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "", -+ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "", -+ addr, addr + size - 1, -+ (before & GRUB_MEM_ATTR_R) ? 'r' : '-', -+ (before & GRUB_MEM_ATTR_W) ? 'w' : '-', -+ (before & GRUB_MEM_ATTR_X) ? 'x' : '-', -+ (after & GRUB_MEM_ATTR_R) ? 'r' : '-', -+ (after & GRUB_MEM_ATTR_W) ? 'w' : '-', -+ (after & GRUB_MEM_ATTR_X) ? 'x' : '-'); -+ -+ return grub_efi_status_to_err (efi_status); -+} -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index f431f49973..464842ba37 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -363,6 +363,11 @@ - { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \ - } - -+#define GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID \ -+ { 0xf4560cf6, 0x40ec, 0x4b4a, \ -+ { 0xa1, 0x92, 0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89 } \ -+ } -+ - struct grub_efi_sal_system_table - { - grub_uint32_t signature; -@@ -2102,6 +2107,26 @@ struct grub_efi_ip6_config_manual_address { - }; - typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t; - -+struct grub_efi_memory_attribute_protocol -+{ -+ grub_efi_status_t (*get_memory_attributes) ( -+ struct grub_efi_memory_attribute_protocol *this, -+ grub_efi_physical_address_t base_address, -+ grub_efi_uint64_t length, -+ grub_efi_uint64_t *attributes); -+ grub_efi_status_t (*set_memory_attributes) ( -+ struct grub_efi_memory_attribute_protocol *this, -+ grub_efi_physical_address_t base_address, -+ grub_efi_uint64_t length, -+ grub_efi_uint64_t attributes); -+ grub_efi_status_t (*clear_memory_attributes) ( -+ struct grub_efi_memory_attribute_protocol *this, -+ grub_efi_physical_address_t base_address, -+ grub_efi_uint64_t length, -+ grub_efi_uint64_t attributes); -+}; -+typedef struct grub_efi_memory_attribute_protocol grub_efi_memory_attribute_protocol_t; -+ - #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ - || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ - || defined(__riscv) -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index ec52083c49..34825c4adc 100644 ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -164,4 +164,6 @@ struct grub_net_card; - grub_efi_handle_t - grub_efinet_get_device_handle (struct grub_net_card *card); - -+grub_err_t EXPORT_FUNC(grub_efi_status_to_err) (grub_efi_status_t status); -+ - #endif /* ! GRUB_EFI_EFI_HEADER */ -diff --git a/include/grub/mm.h b/include/grub/mm.h -index 9c38dd3ca5..d81623d226 100644 ---- a/include/grub/mm.h -+++ b/include/grub/mm.h -@@ -22,6 +22,7 @@ - - #include - #include -+#include - #include - - #ifndef NULL -@@ -38,6 +39,37 @@ void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size); - void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size); - #endif - -+#define GRUB_MEM_ATTR_R 0x0000000000000004LLU -+#define GRUB_MEM_ATTR_W 0x0000000000000002LLU -+#define GRUB_MEM_ATTR_X 0x0000000000000001LLU -+ -+#ifdef GRUB_MACHINE_EFI -+grub_err_t EXPORT_FUNC(grub_get_mem_attrs) (grub_addr_t addr, -+ grub_size_t size, -+ grub_uint64_t *attrs); -+grub_err_t EXPORT_FUNC(grub_update_mem_attrs) (grub_addr_t addr, -+ grub_size_t size, -+ grub_uint64_t set_attrs, -+ grub_uint64_t clear_attrs); -+#else /* !GRUB_MACHINE_EFI */ -+static inline grub_err_t -+grub_get_mem_attrs (grub_addr_t addr __attribute__((__unused__)), -+ grub_size_t size __attribute__((__unused__)), -+ grub_uint64_t *attrs __attribute__((__unused__))) -+{ -+ return GRUB_ERR_NONE; -+} -+ -+static inline grub_err_t -+grub_update_mem_attrs (grub_addr_t addr __attribute__((__unused__)), -+ grub_size_t size __attribute__((__unused__)), -+ grub_uint64_t set_attrs __attribute__((__unused__)), -+ grub_uint64_t clear_attrs __attribute__((__unused__))) -+{ -+ return GRUB_ERR_NONE; -+} -+#endif /* GRUB_MACHINE_EFI */ -+ - void grub_mm_check_real (const char *file, int line); - #define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__); - diff --git a/0260-grub_fs_probe-dprint-errors-from-filesystems.patch b/0260-grub_fs_probe-dprint-errors-from-filesystems.patch new file mode 100644 index 0000000..1455ae4 --- /dev/null +++ b/0260-grub_fs_probe-dprint-errors-from-filesystems.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 15 Jul 2022 15:39:41 -0400 +Subject: [PATCH] grub_fs_probe(): dprint errors from filesystems + +When filesystem detection fails, all that's currently debug-logged is a +series of messages like: + + grub-core/kern/fs.c:56:fs: Detecting ntfs... + grub-core/kern/fs.c:76:fs: ntfs detection failed. + +repeated for each filesystem. Any messages provided to grub_error() by +the filesystem are lost, and one has to break out gdb to figure out what +went wrong. + +With this change, one instead sees: + + grub-core/kern/fs.c:56:fs: Detecting fat... + grub-core/osdep/hostdisk.c:357:hostdisk: reusing open device + `/path/to/device' + grub-core/kern/fs.c:77:fs: error: invalid modification timestamp for /. + grub-core/kern/fs.c:79:fs: fat detection failed. + +in the debug prints. + +Signed-off-by: Robbie Harwood +(cherry picked from commit 838c79d658797d0662ee7f9e033e38ee88059e02) +--- + grub-core/kern/fs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c +index c698295bcb..b58e2ae1d2 100644 +--- a/grub-core/kern/fs.c ++++ b/grub-core/kern/fs.c +@@ -74,6 +74,7 @@ grub_fs_probe (grub_device_t device) + if (grub_errno == GRUB_ERR_NONE) + return p; + ++ grub_dprintf ("fs", _("error: %s.\n"), grub_errmsg); + grub_error_push (); + grub_dprintf ("fs", "%s detection failed.\n", p->name); + grub_error_pop (); diff --git a/0260-nx-set-page-permissions-for-loaded-modules.patch b/0260-nx-set-page-permissions-for-loaded-modules.patch deleted file mode 100644 index 9e0aebb..0000000 --- a/0260-nx-set-page-permissions-for-loaded-modules.patch +++ /dev/null @@ -1,263 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 21 Mar 2022 17:46:35 -0400 -Subject: [PATCH] nx: set page permissions for loaded modules. - -For NX, we need to set write and executable permissions on the sections -of grub modules when we load them. - -On sections with SHF_ALLOC set, which is typically everything except -.modname and the symbol and string tables, this patch clears the Read -Only flag on sections that have the ELF flag SHF_WRITE set, and clears -the No eXecute flag on sections with SHF_EXECINSTR set. In all other -cases it sets both flags. - -Signed-off-by: Peter Jones -[rharwood: arm tgptr -> tgaddr] -Signed-off-by: Robbie Harwood ---- - grub-core/kern/dl.c | 120 +++++++++++++++++++++++++++++++++++++++------------- - include/grub/dl.h | 44 +++++++++++++++++++ - 2 files changed, 134 insertions(+), 30 deletions(-) - -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index 8c7aacef39..d5de80186f 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -285,6 +285,8 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - #endif - char *ptr; - -+ grub_dprintf ("modules", "loading segments for \"%s\"\n", mod->name); -+ - arch_addralign = grub_arch_dl_min_alignment (); - - for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); -@@ -384,6 +386,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - ptr += got; - #endif - -+ grub_dprintf ("modules", "done loading segments for \"%s\"\n", mod->name); - return GRUB_ERR_NONE; - } - -@@ -517,23 +520,6 @@ grub_dl_find_section (Elf_Ehdr *e, const char *name) - return s; - return NULL; - } --static long --grub_dl_find_section_index (Elf_Ehdr *e, const char *name) --{ -- Elf_Shdr *s; -- const char *str; -- unsigned i; -- -- s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); -- str = (char *) e + s->sh_offset; -- -- for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); -- i < e->e_shnum; -- i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) -- if (grub_strcmp (str + s->sh_name, name) == 0) -- return (long)i; -- return -1; --} - - /* Me, Vladimir Serbinenko, hereby I add this module check as per new - GNU module policy. Note that this license check is informative only. -@@ -662,6 +648,7 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) - Elf_Shdr *s; - unsigned i; - -+ grub_dprintf ("modules", "relocating symbols for \"%s\"\n", mod->name); - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) -@@ -670,24 +657,95 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) - grub_dl_segment_t seg; - grub_err_t err; - -- /* Find the target segment. */ -- for (seg = mod->segment; seg; seg = seg->next) -- if (seg->section == s->sh_info) -- break; -+ seg = grub_dl_find_segment(mod, s->sh_info); -+ if (!seg) -+ continue; - -- if (seg) -- { -- if (!mod->symtab) -- return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); -+ if (!mod->symtab) -+ return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); - -- err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); -- if (err) -- return err; -- } -+ err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); -+ if (err) -+ return err; - } - -+ grub_dprintf ("modules", "done relocating symbols for \"%s\"\n", mod->name); - return GRUB_ERR_NONE; - } -+ -+static grub_err_t -+grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr) -+{ -+ unsigned i; -+ const Elf_Shdr *s; -+ const Elf_Ehdr *e = ehdr; -+#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) -+ grub_size_t arch_addralign = grub_arch_dl_min_alignment (); -+ grub_addr_t tgaddr; -+ grub_uint64_t tgsz; -+#endif -+ -+ grub_dprintf ("modules", "updating memory attributes for \"%s\"\n", -+ mod->name); -+ for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); -+ i < e->e_shnum; -+ i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) -+ { -+ grub_dl_segment_t seg; -+ grub_uint64_t set_attrs = GRUB_MEM_ATTR_R; -+ grub_uint64_t clear_attrs = GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X; -+ -+ seg = grub_dl_find_segment(mod, i); -+ if (!seg) -+ continue; -+ -+ if (seg->size == 0 || !(s->sh_flags & SHF_ALLOC)) -+ continue; -+ -+ if (s->sh_flags & SHF_WRITE) -+ { -+ set_attrs |= GRUB_MEM_ATTR_W; -+ clear_attrs &= ~GRUB_MEM_ATTR_W; -+ } -+ -+ if (s->sh_flags & SHF_EXECINSTR) -+ { -+ set_attrs |= GRUB_MEM_ATTR_X; -+ clear_attrs &= ~GRUB_MEM_ATTR_X; -+ } -+ -+ grub_dprintf ("modules", "setting memory attrs for section \"%s\" to -%s%s%s+%s%s%s\n", -+ grub_dl_get_section_name(e, s), -+ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "", -+ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : ""); -+ grub_update_mem_attrs ((grub_addr_t)(seg->addr), seg->size, set_attrs, clear_attrs); -+ } -+ -+#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) -+ tgaddr = grub_min((grub_addr_t)mod->tramp, (grub_addr_t)mod->got); -+ tgsz = grub_max((grub_addr_t)mod->trampptr, (grub_addr_t)mod->gotptr) - tgaddr; -+ -+ if (tgsz) -+ { -+ tgsz = ALIGN_UP(tgsz, arch_addralign); -+ -+ grub_dprintf ("modules", "updating attributes for GOT and trampolines\n", -+ mod->name); -+ grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_X, -+ GRUB_MEM_ATTR_W); -+ } -+#endif -+ -+ grub_dprintf ("modules", "done updating module memory attributes for \"%s\"\n", -+ mod->name); -+ -+ return GRUB_ERR_NONE; -+} -+ - static void - grub_dl_print_gdb_info (grub_dl_t mod, Elf_Ehdr *e) - { -@@ -753,6 +811,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) - mod->ref_count = 1; - - grub_dprintf ("modules", "relocating to %p\n", mod); -+ - /* Me, Vladimir Serbinenko, hereby I add this module check as per new - GNU module policy. Note that this license check is informative only. - Modules have to be licensed under GPLv3 or GPLv3+ (optionally -@@ -766,7 +825,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) - || grub_dl_resolve_dependencies (mod, e) - || grub_dl_load_segments (mod, e) - || grub_dl_resolve_symbols (mod, e) -- || grub_dl_relocate_symbols (mod, e)) -+ || grub_dl_relocate_symbols (mod, e) -+ || grub_dl_set_mem_attrs (mod, e)) - { - mod->fini = 0; - grub_dl_unload (mod); -diff --git a/include/grub/dl.h b/include/grub/dl.h -index f36ed5cb17..45ac8e339f 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #endif - - /* -@@ -268,6 +269,49 @@ grub_dl_is_persistent (grub_dl_t mod) - return mod->persistent; - } - -+static inline const char * -+grub_dl_get_section_name (const Elf_Ehdr *e, const Elf_Shdr *s) -+{ -+ Elf_Shdr *str_s; -+ const char *str; -+ -+ str_s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); -+ str = (char *) e + str_s->sh_offset; -+ -+ return str + s->sh_name; -+} -+ -+static inline long -+grub_dl_find_section_index (Elf_Ehdr *e, const char *name) -+{ -+ Elf_Shdr *s; -+ const char *str; -+ unsigned i; -+ -+ s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); -+ str = (char *) e + s->sh_offset; -+ -+ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); -+ i < e->e_shnum; -+ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) -+ if (grub_strcmp (str + s->sh_name, name) == 0) -+ return (long)i; -+ return -1; -+} -+ -+/* Return the segment for a section of index N */ -+static inline grub_dl_segment_t -+grub_dl_find_segment (grub_dl_t mod, unsigned n) -+{ -+ grub_dl_segment_t seg; -+ -+ for (seg = mod->segment; seg; seg = seg->next) -+ if (seg->section == n) -+ return seg; -+ -+ return NULL; -+} -+ - #endif - - void * EXPORT_FUNC(grub_resolve_symbol) (const char *name); diff --git a/0261-fs-fat-don-t-error-when-mtime-is-0.patch b/0261-fs-fat-don-t-error-when-mtime-is-0.patch new file mode 100644 index 0000000..f014f6c --- /dev/null +++ b/0261-fs-fat-don-t-error-when-mtime-is-0.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 15 Jul 2022 15:42:41 -0400 +Subject: [PATCH] fs/fat: don't error when mtime is 0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In the wild, we occasionally see valid ESPs where some file modification times +are 0. For instance: + + ├── [Dec 31 1979] EFI + │ ├── [Dec 31 1979] BOOT + │ │ ├── [Dec 31 1979] BOOTX64.EFI + │ │ └── [Dec 31 1979] fbx64.efi + │ └── [Jun 27 02:41] fedora + │ ├── [Dec 31 1979] BOOTX64.CSV + │ ├── [Dec 31 1979] fonts + │ ├── [Mar 14 03:35] fw + │ │ ├── [Mar 14 03:35] fwupd-359c1169-abd6-4a0d-8bce-e4d4713335c1.cap + │ │ ├── [Mar 14 03:34] fwupd-9d255c4b-2d88-4861-860d-7ee52ade9463.cap + │ │ └── [Mar 14 03:34] fwupd-b36438d8-9128-49d2-b280-487be02d948b.cap + │ ├── [Dec 31 1979] fwupdx64.efi + │ ├── [May 10 10:47] grub.cfg + │ ├── [Jun 3 12:38] grub.cfg.new.new + │ ├── [May 10 10:41] grub.cfg.old + │ ├── [Jun 27 02:41] grubenv + │ ├── [Dec 31 1979] grubx64.efi + │ ├── [Dec 31 1979] mmx64.efi + │ ├── [Dec 31 1979] shim.efi + │ ├── [Dec 31 1979] shimx64.efi + │ └── [Dec 31 1979] shimx64-fedora.efi + └── [Dec 31 1979] FSCK0000.REC + + 5 directories, 17 files + +This causes grub-probe failure, which in turn causes grub-mkconfig +failure. They are valid filesystems that appear intact, and the Linux +FAT stack is able to mount and manipulate them without complaint. + +The check for mtime of 0 has been present since +20def1a3c3952982395cd7c3ea7e78638527962b ("fat: support file +modification times"). + +Signed-off-by: Robbie Harwood +(cherry picked from commit 0615c4887352e32d7bb7198e9ad0d695f9dc2c31) +--- + grub-core/fs/fat.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c +index dd82e4ee35..ff6200c5be 100644 +--- a/grub-core/fs/fat.c ++++ b/grub-core/fs/fat.c +@@ -1027,9 +1027,6 @@ grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + grub_le_to_cpu16 (ctxt.dir.w_date), + &info.mtime); + #endif +- if (info.mtimeset == 0) +- grub_error (GRUB_ERR_OUT_OF_RANGE, +- "invalid modification timestamp for %s", path); + + if (hook (ctxt.filename, &info, hook_data)) + break; diff --git a/0261-nx-set-attrs-in-our-kernel-loaders.patch b/0261-nx-set-attrs-in-our-kernel-loaders.patch deleted file mode 100644 index 514df1f..0000000 --- a/0261-nx-set-attrs-in-our-kernel-loaders.patch +++ /dev/null @@ -1,565 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 22 Mar 2022 10:57:07 -0400 -Subject: [PATCH] nx: set attrs in our kernel loaders - -For NX, our kernel loaders need to set write and execute page -permissions on allocated pages and the stack. - -This patch adds those calls. - -Signed-off-by: Peter Jones -[rharwood: fix stack_attrs undefined, fix aarch64 callsites] -Signed-off-by: Robbie Harwood ---- - grub-core/kern/efi/mm.c | 77 +++++++++++++++++ - grub-core/loader/arm64/linux.c | 16 +++- - grub-core/loader/arm64/xen_boot.c | 4 +- - grub-core/loader/efi/chainloader.c | 11 +++ - grub-core/loader/efi/linux.c | 164 ++++++++++++++++++++++++++++++++++++- - grub-core/loader/i386/efi/linux.c | 26 +++++- - grub-core/loader/i386/linux.c | 5 ++ - include/grub/efi/efi.h | 6 +- - include/grub/efi/linux.h | 16 +++- - include/grub/efi/pe32.h | 2 + - 10 files changed, 312 insertions(+), 15 deletions(-) - -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index 2c33758ed7..e460b072e6 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -610,6 +610,81 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map, - } - #endif - -+grub_addr_t grub_stack_addr = (grub_addr_t)-1ll; -+grub_size_t grub_stack_size = 0; -+ -+static void -+grub_nx_init (void) -+{ -+ grub_uint64_t attrs, stack_attrs; -+ grub_err_t err; -+ grub_addr_t stack_current, stack_end; -+ const grub_uint64_t page_size = 4096; -+ const grub_uint64_t page_mask = ~(page_size - 1); -+ -+ /* -+ * These are to confirm that the flags are working as expected when -+ * debugging. -+ */ -+ attrs = 0; -+ stack_current = (grub_addr_t)grub_nx_init & page_mask; -+ err = grub_get_mem_attrs (stack_current, page_size, &attrs); -+ if (err) -+ { -+ grub_dprintf ("nx", -+ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", -+ stack_current, err); -+ grub_error_pop (); -+ } -+ else -+ grub_dprintf ("nx", "page attrs for grub_nx_init (%p) are %c%c%c\n", -+ grub_dl_load_core, -+ (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', -+ (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-', -+ (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-'); -+ -+ stack_current = (grub_addr_t)&stack_current & page_mask; -+ err = grub_get_mem_attrs (stack_current, page_size, &stack_attrs); -+ if (err) -+ { -+ grub_dprintf ("nx", -+ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", -+ stack_current, err); -+ grub_error_pop (); -+ } -+ else -+ { -+ attrs = stack_attrs; -+ grub_dprintf ("nx", "page attrs for stack (%p) are %c%c%c\n", -+ &attrs, -+ (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', -+ (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-', -+ (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-'); -+ } -+ for (stack_end = stack_current + page_size ; -+ !(attrs & GRUB_MEM_ATTR_R); -+ stack_end += page_size) -+ { -+ err = grub_get_mem_attrs (stack_current, page_size, &attrs); -+ if (err) -+ { -+ grub_dprintf ("nx", -+ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", -+ stack_current, err); -+ grub_error_pop (); -+ break; -+ } -+ } -+ if (stack_end > stack_current) -+ { -+ grub_stack_addr = stack_current; -+ grub_stack_size = stack_end - stack_current; -+ grub_dprintf ("nx", -+ "detected stack from 0x%"PRIxGRUB_ADDR" to 0x%"PRIxGRUB_ADDR"\n", -+ grub_stack_addr, grub_stack_addr + grub_stack_size - 1); -+ } -+} -+ - void - grub_efi_mm_init (void) - { -@@ -623,6 +698,8 @@ grub_efi_mm_init (void) - grub_efi_uint64_t required_pages; - int mm_status; - -+ grub_nx_init (); -+ - /* Prepare a memory region to store two memory maps. */ - memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); - if (! memory_map) -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index cc67f43906..de85583487 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -172,7 +172,8 @@ free_params (void) - } - - grub_err_t --grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) -+grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args, -+ int nx_supported) - { - grub_err_t retval; - -@@ -182,7 +183,8 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) - - grub_dprintf ("linux", "linux command line: '%s'\n", args); - -- retval = grub_efi_linux_boot ((char *)addr, handover_offset, (void *)addr); -+ retval = grub_efi_linux_boot (addr, size, handover_offset, -+ (void *)addr, nx_supported); - - /* Never reached... */ - free_params(); -@@ -192,7 +194,10 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) - static grub_err_t - grub_linux_boot (void) - { -- return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, linux_args)); -+ return grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, -+ (grub_size_t)kernel_size, -+ linux_args, -+ 0); - } - - static grub_err_t -@@ -340,6 +345,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_off_t filelen; - grub_uint32_t align; - void *kernel = NULL; -+ int nx_supported = 1; - - grub_dl_ref (my_mod); - -@@ -376,6 +382,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); - grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); - -+ err = grub_efi_check_nx_image_support((grub_addr_t)kernel, filelen, &nx_supported); -+ if (err != GRUB_ERR_NONE) -+ goto fail; -+ - grub_loader_unset(); - - kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); -diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c -index d9b7a9ba40..6e7e920416 100644 ---- a/grub-core/loader/arm64/xen_boot.c -+++ b/grub-core/loader/arm64/xen_boot.c -@@ -266,7 +266,9 @@ xen_boot (void) - return err; - - return grub_arch_efi_linux_boot_image (xen_hypervisor->start, -- xen_hypervisor->cmdline); -+ xen_hypervisor->size, -+ xen_hypervisor->cmdline, -+ 0); - } - - static void -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index fb874f1855..dd31ac9bb3 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -1070,6 +1070,17 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -+ /* -+ * The OS kernel is going to set its own permissions when it takes over -+ * paging a few million instructions from now, and load_image() will set up -+ * anything that's needed based on the section headers, so there's no point -+ * in doing anything but clearing the protection bits here. -+ */ -+ grub_dprintf("nx", "setting attributes for %p (%lu bytes) to %llx\n", -+ (void *)(grub_addr_t)address, fsize, 0llu); -+ grub_update_mem_attrs (address, fsize, -+ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X, 0); -+ - #if defined (__i386__) || defined (__x86_64__) - if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header)) - { -diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c -index 9265cf4200..277f352e0c 100644 ---- a/grub-core/loader/efi/linux.c -+++ b/grub-core/loader/efi/linux.c -@@ -26,16 +26,127 @@ - - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" -+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" -+ -+grub_err_t -+grub_efi_check_nx_image_support (grub_addr_t kernel_addr, -+ grub_size_t kernel_size, -+ int *nx_supported) -+{ -+ struct grub_dos_header *doshdr; -+ grub_size_t sz = sizeof (*doshdr); -+ -+ struct grub_pe32_header_32 *pe32; -+ struct grub_pe32_header_64 *pe64; -+ -+ int image_is_compatible = 0; -+ int is_64_bit; -+ -+ if (kernel_size < sz) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); -+ -+ doshdr = (void *)kernel_addr; -+ -+ if ((doshdr->magic & 0xffff) != GRUB_DOS_MAGIC) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel DOS magic is invalid")); -+ -+ sz = doshdr->lfanew + sizeof (*pe32); -+ if (kernel_size < sz) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); -+ -+ pe32 = (struct grub_pe32_header_32 *)(kernel_addr + doshdr->lfanew); -+ pe64 = (struct grub_pe32_header_64 *)pe32; -+ -+ if (grub_memcmp (pe32->signature, GRUB_PE32_SIGNATURE, -+ GRUB_PE32_SIGNATURE_SIZE) != 0) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel PE magic is invalid")); -+ -+ switch (pe32->coff_header.machine) -+ { -+ case GRUB_PE32_MACHINE_ARMTHUMB_MIXED: -+ case GRUB_PE32_MACHINE_I386: -+ case GRUB_PE32_MACHINE_RISCV32: -+ is_64_bit = 0; -+ break; -+ case GRUB_PE32_MACHINE_ARM64: -+ case GRUB_PE32_MACHINE_IA64: -+ case GRUB_PE32_MACHINE_RISCV64: -+ case GRUB_PE32_MACHINE_X86_64: -+ is_64_bit = 1; -+ break; -+ default: -+ return grub_error (GRUB_ERR_BAD_OS, N_("PE machine type 0x%04hx unknown"), -+ pe32->coff_header.machine); -+ } -+ -+ if (is_64_bit) -+ { -+ sz = doshdr->lfanew + sizeof (*pe64); -+ if (kernel_size < sz) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); -+ -+ if (pe64->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT) -+ image_is_compatible = 1; -+ } -+ else -+ { -+ if (pe32->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT) -+ image_is_compatible = 1; -+ } -+ -+ *nx_supported = image_is_compatible; -+ return GRUB_ERR_NONE; -+} -+ -+grub_err_t -+grub_efi_check_nx_required (int *nx_required) -+{ -+ grub_efi_status_t status; -+ grub_efi_guid_t guid = GRUB_EFI_SHIM_LOCK_GUID; -+ grub_size_t mok_policy_sz = 0; -+ char *mok_policy = NULL; -+ grub_uint32_t mok_policy_attrs = 0; -+ -+ status = grub_efi_get_variable_with_attributes ("MokPolicy", &guid, -+ &mok_policy_sz, -+ (void **)&mok_policy, -+ &mok_policy_attrs); -+ if (status == GRUB_EFI_NOT_FOUND || -+ mok_policy_sz == 0 || -+ mok_policy == NULL) -+ { -+ *nx_required = 0; -+ return GRUB_ERR_NONE; -+ } -+ -+ *nx_required = 0; -+ if (mok_policy_sz < 1 || -+ mok_policy_attrs != (GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | -+ GRUB_EFI_VARIABLE_RUNTIME_ACCESS) || -+ (mok_policy[mok_policy_sz-1] & GRUB_MOK_POLICY_NX_REQUIRED)) -+ *nx_required = 1; -+ -+ return GRUB_ERR_NONE; -+} - - typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); - - grub_err_t --grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, -- void *kernel_params) -+grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size, -+ grub_off_t handover_offset, void *kernel_params, -+ int nx_supported) - { - grub_efi_loaded_image_t *loaded_image = NULL; - handover_func hf; - int offset = 0; -+ grub_uint64_t stack_set_attrs = GRUB_MEM_ATTR_R | -+ GRUB_MEM_ATTR_W | -+ GRUB_MEM_ATTR_X; -+ grub_uint64_t stack_clear_attrs = 0; -+ grub_uint64_t kernel_set_attrs = stack_set_attrs; -+ grub_uint64_t kernel_clear_attrs = stack_clear_attrs; -+ grub_uint64_t attrs; -+ int nx_required = 0; - - #ifdef __x86_64__ - offset = 512; -@@ -48,12 +159,57 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, - */ - loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); - if (loaded_image) -- loaded_image->image_base = kernel_addr; -+ loaded_image->image_base = (void *)kernel_addr; - else - grub_dprintf ("linux", "Loaded Image base address could not be set\n"); - - grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n", -- kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params); -+ (void *)kernel_addr, (void *)handover_offset, kernel_params); -+ -+ -+ if (nx_required && !nx_supported) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel does not support NX loading required by policy")); -+ -+ if (nx_supported) -+ { -+ kernel_set_attrs &= ~GRUB_MEM_ATTR_W; -+ kernel_clear_attrs |= GRUB_MEM_ATTR_W; -+ stack_set_attrs &= ~GRUB_MEM_ATTR_X; -+ stack_clear_attrs |= GRUB_MEM_ATTR_X; -+ } -+ -+ grub_dprintf ("nx", "Setting attributes for 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to r%cx\n", -+ kernel_addr, kernel_addr + kernel_size - 1, -+ (kernel_set_attrs & GRUB_MEM_ATTR_W) ? 'w' : '-'); -+ grub_update_mem_attrs (kernel_addr, kernel_size, -+ kernel_set_attrs, kernel_clear_attrs); -+ -+ grub_get_mem_attrs (kernel_addr, 4096, &attrs); -+ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n", -+ (grub_addr_t)kernel_addr, -+ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-", -+ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-", -+ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-"); -+ if (grub_stack_addr != (grub_addr_t)-1ll) -+ { -+ grub_dprintf ("nx", "Setting attributes for stack at 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to rw%c\n", -+ grub_stack_addr, grub_stack_addr + grub_stack_size - 1, -+ (stack_set_attrs & GRUB_MEM_ATTR_X) ? 'x' : '-'); -+ grub_update_mem_attrs (grub_stack_addr, grub_stack_size, -+ stack_set_attrs, stack_clear_attrs); -+ -+ grub_get_mem_attrs (grub_stack_addr, 4096, &attrs); -+ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n", -+ grub_stack_addr, -+ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-", -+ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-", -+ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-"); -+ } -+ -+#if defined(__i386__) || defined(__x86_64__) -+ asm volatile ("cli"); -+#endif -+ - hf = (handover_func)((char *)kernel_addr + handover_offset + offset); - hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 92b2fb5091..91ae274299 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -44,7 +44,7 @@ struct grub_linuxefi_context { - grub_uint32_t handover_offset; - struct linux_kernel_params *params; - char *cmdline; -- -+ int nx_supported; - void *initrd_mem; - }; - -@@ -110,13 +110,19 @@ kernel_alloc(grub_efi_uintn_t size, - pages = BYTES_TO_PAGES(size); - grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n", - (unsigned long)pages, (void *)(unsigned long)max); -+ size = pages * GRUB_EFI_PAGE_SIZE; - - prev_max = max; - addr = grub_efi_allocate_pages_real (max, pages, - max_addresses[i].alloc_type, - memtype); - if (addr) -- grub_dprintf ("linux", "Allocated at %p\n", addr); -+ { -+ grub_dprintf ("linux", "Allocated at %p\n", addr); -+ grub_update_mem_attrs ((grub_addr_t)addr, size, -+ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, -+ GRUB_MEM_ATTR_X); -+ } - } - - while (grub_error_pop ()) -@@ -137,9 +143,11 @@ grub_linuxefi_boot (void *data) - - asm volatile ("cli"); - -- return grub_efi_linux_boot ((char *)context->kernel_mem, -+ return grub_efi_linux_boot ((grub_addr_t)context->kernel_mem, -+ context->kernel_size, - context->handover_offset, -- context->params); -+ context->params, -+ context->nx_supported); - } - - static grub_err_t -@@ -304,7 +312,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_uint32_t handover_offset; - struct linux_kernel_params *params = 0; - char *cmdline = 0; -+ int nx_supported = 1; - struct grub_linuxefi_context *context = 0; -+ grub_err_t err; - - grub_dl_ref (my_mod); - -@@ -334,6 +344,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -+ err = grub_efi_check_nx_image_support ((grub_addr_t)kernel, filelen, -+ &nx_supported); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ grub_dprintf ("linux", "nx is%s supported by this kernel\n", -+ nx_supported ? "" : " not"); -+ - lh = (struct linux_i386_kernel_header *)kernel; - grub_dprintf ("linux", "original lh is at %p\n", kernel); - -@@ -498,6 +515,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - context->handover_offset = handover_offset; - context->params = params; - context->cmdline = cmdline; -+ context->nx_supported = nx_supported; - - grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0); - -diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c -index 4aeb0e4b9a..3c1ff64763 100644 ---- a/grub-core/loader/i386/linux.c -+++ b/grub-core/loader/i386/linux.c -@@ -805,6 +805,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - kernel_offset += len; - } - -+ grub_dprintf("efi", "setting attributes for %p (%zu bytes) to +rw-x\n", -+ &linux_params, sizeof (lh) + len); -+ grub_update_mem_attrs ((grub_addr_t)&linux_params, sizeof (lh) + len, -+ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, GRUB_MEM_ATTR_X); -+ - linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR; - linux_params.kernel_alignment = (1 << align); - linux_params.ps_mouse = linux_params.padding11 = 0; -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index 34825c4adc..449e55269f 100644 ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -140,12 +140,16 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, - char **device, - char **path); - -+extern grub_addr_t EXPORT_VAR(grub_stack_addr); -+extern grub_size_t EXPORT_VAR(grub_stack_size); -+ - #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) - void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); - grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); - #include - grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh); --grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, char *args); -+grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size, -+ char *args, int nx_enabled); - #endif - - grub_addr_t grub_efi_section_addr (const char *section); -diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h -index 887b02fd9f..b82f71006a 100644 ---- a/include/grub/efi/linux.h -+++ b/include/grub/efi/linux.h -@@ -22,8 +22,20 @@ - #include - #include - -+#define GRUB_MOK_POLICY_NX_REQUIRED 0x1 -+ - grub_err_t --EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, -- void *kernel_param); -+EXPORT_FUNC(grub_efi_linux_boot) (grub_addr_t kernel_address, -+ grub_size_t kernel_size, -+ grub_off_t handover_offset, -+ void *kernel_param, int nx_enabled); -+ -+grub_err_t -+EXPORT_FUNC(grub_efi_check_nx_image_support) (grub_addr_t kernel_addr, -+ grub_size_t kernel_size, -+ int *nx_supported); -+ -+grub_err_t -+EXPORT_FUNC(grub_efi_check_nx_required) (int *nx_required); - - #endif /* ! GRUB_EFI_LINUX_HEADER */ -diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h -index 2a5e1ee003..a5e623eb04 100644 ---- a/include/grub/efi/pe32.h -+++ b/include/grub/efi/pe32.h -@@ -181,6 +181,8 @@ struct grub_pe32_optional_header - struct grub_pe32_data_directory reserved_entry; - }; - -+#define GRUB_PE32_NX_COMPAT 0x0100 -+ - struct grub_pe64_optional_header - { - grub_uint16_t magic; diff --git a/0262-Make-debug-file-show-which-file-filters-get-run.patch b/0262-Make-debug-file-show-which-file-filters-get-run.patch new file mode 100644 index 0000000..78bc095 --- /dev/null +++ b/0262-Make-debug-file-show-which-file-filters-get-run.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 29 Jul 2022 15:56:00 -0400 +Subject: [PATCH] Make debug=file show which file filters get run. + +If one of the file filters breaks things, it's hard to figure out where +it has happened. + +This makes grub log which filter is being run, which makes it easier to +figure out where you are in the sequence of events. + +Signed-off-by: Peter Jones +--- + grub-core/kern/file.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c +index db938e099d..868ce3b63e 100644 +--- a/grub-core/kern/file.c ++++ b/grub-core/kern/file.c +@@ -30,6 +30,14 @@ void (*EXPORT_VAR (grub_grubnet_fini)) (void); + + grub_file_filter_t grub_file_filters[GRUB_FILE_FILTER_MAX]; + ++static const char *filter_names[] = { ++ [GRUB_FILE_FILTER_VERIFY] = "GRUB_FILE_FILTER_VERIFY", ++ [GRUB_FILE_FILTER_GZIO] = "GRUB_FILE_FILTER_GZIO", ++ [GRUB_FILE_FILTER_XZIO] = "GRUB_FILE_FILTER_XZIO", ++ [GRUB_FILE_FILTER_LZOPIO] = "GRUB_FILE_FILTER_LZOPIO", ++ [GRUB_FILE_FILTER_MAX] = "GRUB_FILE_FILTER_MAX" ++}; ++ + /* Get the device part of the filename NAME. It is enclosed by parentheses. */ + char * + grub_file_get_device_name (const char *name) +@@ -124,6 +132,9 @@ grub_file_open (const char *name, enum grub_file_type type) + if (grub_file_filters[filter]) + { + last_file = file; ++ if (filter < GRUB_FILE_FILTER_MAX) ++ grub_dprintf ("file", "Running %s file filter\n", ++ filter_names[filter]); + file = grub_file_filters[filter] (file, type); + if (file && file != last_file) + { diff --git a/0262-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch b/0262-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch deleted file mode 100644 index 7da75a8..0000000 --- a/0262-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 22 Mar 2022 10:57:20 -0400 -Subject: [PATCH] nx: set the nx compatible flag in EFI grub images - -For NX, we need the grub binary to announce that it is compatible with -the NX feature. This implies that when loading the executable grub -image, several attributes are true: - -- the binary doesn't need an executable stack -- the binary doesn't need sections to be both executable and writable -- the binary knows how to use the EFI Memory Attributes protocol on code - it is loading. - -This patch adds a definition for the PE DLL Characteristics flag -GRUB_PE32_NX_COMPAT, and changes grub-mkimage to set that flag. - -Signed-off-by: Peter Jones ---- - util/mkimage.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/util/mkimage.c b/util/mkimage.c -index 8319e8dfbd..c3d33aaac8 100644 ---- a/util/mkimage.c -+++ b/util/mkimage.c -@@ -1418,6 +1418,7 @@ grub_install_generate_image (const char *dir, const char *prefix, - section = (struct grub_pe32_section_table *)(o64 + 1); - } - -+ PE_OHDR (o32, o64, dll_characteristics) = grub_host_to_target16 (GRUB_PE32_NX_COMPAT); - PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size); - PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address); - PE_OHDR (o32, o64, image_base) = 0; diff --git a/0263-efi-use-enumerated-array-positions-for-our-allocatio.patch b/0263-efi-use-enumerated-array-positions-for-our-allocatio.patch new file mode 100644 index 0000000..206e3a6 --- /dev/null +++ b/0263-efi-use-enumerated-array-positions-for-our-allocatio.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 1 Aug 2022 14:06:30 -0400 +Subject: [PATCH] efi: use enumerated array positions for our allocation + choices + +In our kernel allocator on EFI systems, we currently have a growing +amount of code that references the various allocation policies by +position in the array, and of course maintenance of this code scales +very poorly. + +This patch changes them to be enumerated, so they're easier to refer to +farther along in the code without confusion. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 91ae274299..8daa070132 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -60,17 +60,26 @@ struct allocation_choice { + grub_efi_allocate_type_t alloc_type; + }; + +-static struct allocation_choice max_addresses[4] = ++enum { ++ KERNEL_PREF_ADDRESS, ++ KERNEL_4G_LIMIT, ++ KERNEL_NO_LIMIT, ++}; ++ ++static struct allocation_choice max_addresses[] = + { + /* the kernel overrides this one with pref_address and + * GRUB_EFI_ALLOCATE_ADDRESS */ +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ [KERNEL_PREF_ADDRESS] = ++ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ /* If the flag in params is set, this one gets changed to be above 4GB. */ ++ [KERNEL_4G_LIMIT] = ++ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + /* this one is always below 4GB, which we still *prefer* even if the flag + * is set. */ +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, +- /* If the flag in params is set, this one gets changed to be above 4GB. */ +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, +- { 0, 0 } ++ [KERNEL_NO_LIMIT] = ++ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { NO_MEM, 0, 0 } + }; + static struct allocation_choice saved_addresses[4]; + +@@ -405,7 +414,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G) + { + grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n"); +- max_addresses[2].addr = GRUB_EFI_MAX_USABLE_ADDRESS; ++ max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_USABLE_ADDRESS; + } + else + { +@@ -478,11 +487,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address); + if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS) + { +- max_addresses[0].addr = lh->pref_address; +- max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; ++ max_addresses[KERNEL_PREF_ADDRESS].addr = lh->pref_address; ++ max_addresses[KERNEL_PREF_ADDRESS].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; + } +- max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; +- max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; ++ max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; ++ max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + kernel_size = lh->init_size; + kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, + N_("can't allocate kernel")); diff --git a/0263-grub-probe-document-the-behavior-of-multiple-v.patch b/0263-grub-probe-document-the-behavior-of-multiple-v.patch deleted file mode 100644 index 4e9d7cc..0000000 --- a/0263-grub-probe-document-the-behavior-of-multiple-v.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Fri, 15 Jul 2022 15:49:25 -0400 -Subject: [PATCH] grub-probe: document the behavior of multiple -v - -Signed-off-by: Robbie Harwood -(cherry picked from commit 51a55233eed08f7f12276afd6b3724b807a0b680) ---- - util/grub-probe.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/util/grub-probe.c b/util/grub-probe.c -index c6fac732b4..ba867319a7 100644 ---- a/util/grub-probe.c -+++ b/util/grub-probe.c -@@ -732,7 +732,8 @@ static struct argp_option options[] = { - {"device-map", 'm', N_("FILE"), 0, - N_("use FILE as the device map [default=%s]"), 0}, - {"target", 't', N_("TARGET"), 0, 0, 0}, -- {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, -+ {"verbose", 'v', 0, 0, -+ N_("print verbose messages (pass twice to enable debug printing)."), 0}, - {0, '0', 0, 0, N_("separate items in output using ASCII NUL characters"), 0}, - { 0, 0, 0, 0, 0, 0 } - }; diff --git a/0264-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch b/0264-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch new file mode 100644 index 0000000..d25cf30 --- /dev/null +++ b/0264-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 1 Aug 2022 14:24:39 -0400 +Subject: [PATCH] efi: split allocation policy for kernel vs initrd memories. + +Currently in our kernel allocator, we use the same set of choices for +all of our various kernel and initramfs allocations, though they do not +have exactly the same constraints. + +This patch adds the concept of an allocation purpose, which currently +can be KERNEL_MEM or INITRD_MEM, and updates kernel_alloc() calls +appropriately, but does not change any current policy decision. It +also adds a few debug prints. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 35 +++++++++++++++++++++++++++-------- + 1 file changed, 27 insertions(+), 8 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 8daa070132..e6b8998e5e 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -55,7 +55,14 @@ struct grub_linuxefi_context { + + #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) + ++typedef enum { ++ NO_MEM, ++ KERNEL_MEM, ++ INITRD_MEM, ++} kernel_alloc_purpose_t; ++ + struct allocation_choice { ++ kernel_alloc_purpose_t purpose; + grub_efi_physical_address_t addr; + grub_efi_allocate_type_t alloc_type; + }; +@@ -64,6 +71,7 @@ enum { + KERNEL_PREF_ADDRESS, + KERNEL_4G_LIMIT, + KERNEL_NO_LIMIT, ++ INITRD_MAX_ADDRESS, + }; + + static struct allocation_choice max_addresses[] = +@@ -71,14 +79,17 @@ static struct allocation_choice max_addresses[] = + /* the kernel overrides this one with pref_address and + * GRUB_EFI_ALLOCATE_ADDRESS */ + [KERNEL_PREF_ADDRESS] = +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + /* If the flag in params is set, this one gets changed to be above 4GB. */ + [KERNEL_4G_LIMIT] = +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + /* this one is always below 4GB, which we still *prefer* even if the flag + * is set. */ + [KERNEL_NO_LIMIT] = +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ /* this is for the initrd */ ++ [INITRD_MAX_ADDRESS] = ++ { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + { NO_MEM, 0, 0 } + }; + static struct allocation_choice saved_addresses[4]; +@@ -95,7 +106,8 @@ kernel_free(void *addr, grub_efi_uintn_t size) + } + + static void * +-kernel_alloc(grub_efi_uintn_t size, ++kernel_alloc(kernel_alloc_purpose_t purpose, ++ grub_efi_uintn_t size, + grub_efi_memory_type_t memtype, + const char * const errmsg) + { +@@ -108,6 +120,9 @@ kernel_alloc(grub_efi_uintn_t size, + grub_uint64_t max = max_addresses[i].addr; + grub_efi_uintn_t pages; + ++ if (purpose != max_addresses[i].purpose) ++ continue; ++ + /* + * When we're *not* loading the kernel, or >4GB allocations aren't + * supported, these entries are basically all the same, so don't re-try +@@ -261,7 +276,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + } + } + +- initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA, ++ grub_dprintf ("linux", "Trying to allocate initrd mem\n"); ++ initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA, + N_("can't allocate initrd")); + if (initrd_mem == NULL) + goto fail; +@@ -422,7 +438,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + #endif + +- params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA, ++ params = kernel_alloc (KERNEL_MEM, sizeof(*params), ++ GRUB_EFI_RUNTIME_SERVICES_DATA, + "cannot allocate kernel parameters"); + if (!params) + goto fail; +@@ -445,7 +462,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "new lh is at %p\n", lh); + + grub_dprintf ("linux", "setting up cmdline\n"); +- cmdline = kernel_alloc (lh->cmdline_size + 1, ++ cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1, + GRUB_EFI_RUNTIME_SERVICES_DATA, + N_("can't allocate cmdline")); + if (!cmdline) +@@ -493,7 +510,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + kernel_size = lh->init_size; +- kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, ++ grub_dprintf ("linux", "Trying to allocate kernel mem\n"); ++ kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size, ++ GRUB_EFI_RUNTIME_SERVICES_CODE, + N_("can't allocate kernel")); + restore_addresses(); + if (!kernel_mem) diff --git a/0264-grub_fs_probe-dprint-errors-from-filesystems.patch b/0264-grub_fs_probe-dprint-errors-from-filesystems.patch deleted file mode 100644 index 1455ae4..0000000 --- a/0264-grub_fs_probe-dprint-errors-from-filesystems.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Fri, 15 Jul 2022 15:39:41 -0400 -Subject: [PATCH] grub_fs_probe(): dprint errors from filesystems - -When filesystem detection fails, all that's currently debug-logged is a -series of messages like: - - grub-core/kern/fs.c:56:fs: Detecting ntfs... - grub-core/kern/fs.c:76:fs: ntfs detection failed. - -repeated for each filesystem. Any messages provided to grub_error() by -the filesystem are lost, and one has to break out gdb to figure out what -went wrong. - -With this change, one instead sees: - - grub-core/kern/fs.c:56:fs: Detecting fat... - grub-core/osdep/hostdisk.c:357:hostdisk: reusing open device - `/path/to/device' - grub-core/kern/fs.c:77:fs: error: invalid modification timestamp for /. - grub-core/kern/fs.c:79:fs: fat detection failed. - -in the debug prints. - -Signed-off-by: Robbie Harwood -(cherry picked from commit 838c79d658797d0662ee7f9e033e38ee88059e02) ---- - grub-core/kern/fs.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c -index c698295bcb..b58e2ae1d2 100644 ---- a/grub-core/kern/fs.c -+++ b/grub-core/kern/fs.c -@@ -74,6 +74,7 @@ grub_fs_probe (grub_device_t device) - if (grub_errno == GRUB_ERR_NONE) - return p; - -+ grub_dprintf ("fs", _("error: %s.\n"), grub_errmsg); - grub_error_push (); - grub_dprintf ("fs", "%s detection failed.\n", p->name); - grub_error_pop (); diff --git a/0265-efi-allocate-the-initrd-within-the-bounds-expressed-.patch b/0265-efi-allocate-the-initrd-within-the-bounds-expressed-.patch new file mode 100644 index 0000000..47e31e2 --- /dev/null +++ b/0265-efi-allocate-the-initrd-within-the-bounds-expressed-.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 1 Aug 2022 14:07:50 -0400 +Subject: [PATCH] efi: allocate the initrd within the bounds expressed by the + kernel + +Currently on x86, only linux kernels built with CONFIG_RELOCATABLE for +x86_64 can be loaded above 4G, but the maximum address for the initramfs +is specified via a HdrS field. This allows us to utilize that value, +and unless loading the kernel above 4G, uses the value present there. +If loading kernel above 4G is allowed, we assume loading the initramfs +above 4G also works; in practice this has been true in the kernel code +for quite some time. + +Resolves: rhbz#2112134 + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index e6b8998e5e..d003b474ee 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -190,6 +190,8 @@ grub_linuxefi_unload (void *data) + cmd_initrdefi->data = 0; + grub_free (context); + ++ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; ++ + return GRUB_ERR_NONE; + } + +@@ -426,11 +428,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + #endif + ++ max_addresses[INITRD_MAX_ADDRESS].addr = lh->initrd_addr_max; + #if defined(__x86_64__) + if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G) + { + grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n"); + max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_USABLE_ADDRESS; ++ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_USABLE_ADDRESS; + } + else + { +@@ -560,6 +564,8 @@ fail: + + grub_dl_unref (my_mod); + ++ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; ++ + if (lh) + kernel_free (cmdline, lh->cmdline_size + 1); + diff --git a/0265-fs-fat-don-t-error-when-mtime-is-0.patch b/0265-fs-fat-don-t-error-when-mtime-is-0.patch deleted file mode 100644 index f014f6c..0000000 --- a/0265-fs-fat-don-t-error-when-mtime-is-0.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Fri, 15 Jul 2022 15:42:41 -0400 -Subject: [PATCH] fs/fat: don't error when mtime is 0 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In the wild, we occasionally see valid ESPs where some file modification times -are 0. For instance: - - ├── [Dec 31 1979] EFI - │ ├── [Dec 31 1979] BOOT - │ │ ├── [Dec 31 1979] BOOTX64.EFI - │ │ └── [Dec 31 1979] fbx64.efi - │ └── [Jun 27 02:41] fedora - │ ├── [Dec 31 1979] BOOTX64.CSV - │ ├── [Dec 31 1979] fonts - │ ├── [Mar 14 03:35] fw - │ │ ├── [Mar 14 03:35] fwupd-359c1169-abd6-4a0d-8bce-e4d4713335c1.cap - │ │ ├── [Mar 14 03:34] fwupd-9d255c4b-2d88-4861-860d-7ee52ade9463.cap - │ │ └── [Mar 14 03:34] fwupd-b36438d8-9128-49d2-b280-487be02d948b.cap - │ ├── [Dec 31 1979] fwupdx64.efi - │ ├── [May 10 10:47] grub.cfg - │ ├── [Jun 3 12:38] grub.cfg.new.new - │ ├── [May 10 10:41] grub.cfg.old - │ ├── [Jun 27 02:41] grubenv - │ ├── [Dec 31 1979] grubx64.efi - │ ├── [Dec 31 1979] mmx64.efi - │ ├── [Dec 31 1979] shim.efi - │ ├── [Dec 31 1979] shimx64.efi - │ └── [Dec 31 1979] shimx64-fedora.efi - └── [Dec 31 1979] FSCK0000.REC - - 5 directories, 17 files - -This causes grub-probe failure, which in turn causes grub-mkconfig -failure. They are valid filesystems that appear intact, and the Linux -FAT stack is able to mount and manipulate them without complaint. - -The check for mtime of 0 has been present since -20def1a3c3952982395cd7c3ea7e78638527962b ("fat: support file -modification times"). - -Signed-off-by: Robbie Harwood -(cherry picked from commit 0615c4887352e32d7bb7198e9ad0d695f9dc2c31) ---- - grub-core/fs/fat.c | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c -index dd82e4ee35..ff6200c5be 100644 ---- a/grub-core/fs/fat.c -+++ b/grub-core/fs/fat.c -@@ -1027,9 +1027,6 @@ grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, - grub_le_to_cpu16 (ctxt.dir.w_date), - &info.mtime); - #endif -- if (info.mtimeset == 0) -- grub_error (GRUB_ERR_OUT_OF_RANGE, -- "invalid modification timestamp for %s", path); - - if (hook (ctxt.filename, &info, hook_data)) - break; diff --git a/0266-Make-debug-file-show-which-file-filters-get-run.patch b/0266-Make-debug-file-show-which-file-filters-get-run.patch deleted file mode 100644 index 78bc095..0000000 --- a/0266-Make-debug-file-show-which-file-filters-get-run.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 29 Jul 2022 15:56:00 -0400 -Subject: [PATCH] Make debug=file show which file filters get run. - -If one of the file filters breaks things, it's hard to figure out where -it has happened. - -This makes grub log which filter is being run, which makes it easier to -figure out where you are in the sequence of events. - -Signed-off-by: Peter Jones ---- - grub-core/kern/file.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c -index db938e099d..868ce3b63e 100644 ---- a/grub-core/kern/file.c -+++ b/grub-core/kern/file.c -@@ -30,6 +30,14 @@ void (*EXPORT_VAR (grub_grubnet_fini)) (void); - - grub_file_filter_t grub_file_filters[GRUB_FILE_FILTER_MAX]; - -+static const char *filter_names[] = { -+ [GRUB_FILE_FILTER_VERIFY] = "GRUB_FILE_FILTER_VERIFY", -+ [GRUB_FILE_FILTER_GZIO] = "GRUB_FILE_FILTER_GZIO", -+ [GRUB_FILE_FILTER_XZIO] = "GRUB_FILE_FILTER_XZIO", -+ [GRUB_FILE_FILTER_LZOPIO] = "GRUB_FILE_FILTER_LZOPIO", -+ [GRUB_FILE_FILTER_MAX] = "GRUB_FILE_FILTER_MAX" -+}; -+ - /* Get the device part of the filename NAME. It is enclosed by parentheses. */ - char * - grub_file_get_device_name (const char *name) -@@ -124,6 +132,9 @@ grub_file_open (const char *name, enum grub_file_type type) - if (grub_file_filters[filter]) - { - last_file = file; -+ if (filter < GRUB_FILE_FILTER_MAX) -+ grub_dprintf ("file", "Running %s file filter\n", -+ filter_names[filter]); - file = grub_file_filters[filter] (file, type); - if (file && file != last_file) - { diff --git a/0266-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch b/0266-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch new file mode 100644 index 0000000..8451dbf --- /dev/null +++ b/0266-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 1 Aug 2022 13:04:43 -0400 +Subject: [PATCH] efi: use EFI_LOADER_(CODE|DATA) for kernel and initrd + allocations + +At some point due to an erroneous kernel warning, we switched kernel and +initramfs to being loaded in EFI_RUNTIME_SERVICES_CODE and +EFI_RUNTIME_SERVICES_DATA memory pools. This doesn't appear to be +correct according to the spec, and that kernel warning has gone away. + +This patch puts them back in EFI_LOADER_CODE and EFI_LOADER_DATA +allocations, respectively. + +Resolves: rhbz#2108456 + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index d003b474ee..ac5ef50bdb 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -279,7 +279,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + } + + grub_dprintf ("linux", "Trying to allocate initrd mem\n"); +- initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA, ++ initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_LOADER_DATA, + N_("can't allocate initrd")); + if (initrd_mem == NULL) + goto fail; +@@ -443,7 +443,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + #endif + + params = kernel_alloc (KERNEL_MEM, sizeof(*params), +- GRUB_EFI_RUNTIME_SERVICES_DATA, ++ GRUB_EFI_LOADER_DATA, + "cannot allocate kernel parameters"); + if (!params) + goto fail; +@@ -467,7 +467,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + grub_dprintf ("linux", "setting up cmdline\n"); + cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1, +- GRUB_EFI_RUNTIME_SERVICES_DATA, ++ GRUB_EFI_LOADER_DATA, + N_("can't allocate cmdline")); + if (!cmdline) + goto fail; +@@ -516,7 +516,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + kernel_size = lh->init_size; + grub_dprintf ("linux", "Trying to allocate kernel mem\n"); + kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size, +- GRUB_EFI_RUNTIME_SERVICES_CODE, ++ GRUB_EFI_LOADER_CODE, + N_("can't allocate kernel")); + restore_addresses(); + if (!kernel_mem) diff --git a/0267-BLS-create-etc-kernel-cmdline-during-mkconfig.patch b/0267-BLS-create-etc-kernel-cmdline-during-mkconfig.patch new file mode 100644 index 0000000..50ba0fb --- /dev/null +++ b/0267-BLS-create-etc-kernel-cmdline-during-mkconfig.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 2 Aug 2022 15:56:28 -0400 +Subject: [PATCH] BLS: create /etc/kernel/cmdline during mkconfig + +Signed-off-by: Robbie Harwood +--- + util/grub.d/10_linux.in | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 865af3d6c4..9ebff661a9 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -161,6 +161,12 @@ update_bls_cmdline() + local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + local -a files=($(get_sorted_bls)) + ++ if [[ ! -f /etc/kernel/cmdline ]]; then ++ # anaconda has the correct information to do this during install; ++ # afterward, grubby will take care of syncing on updates. ++ echo "$cmdline rhgb quiet" > /etc/kernel/cmdline ++ fi ++ + for bls in "${files[@]}"; do + local options="${cmdline}" + if [ -z "${bls##*debug*}" ]; then diff --git a/0267-efi-use-enumerated-array-positions-for-our-allocatio.patch b/0267-efi-use-enumerated-array-positions-for-our-allocatio.patch deleted file mode 100644 index 206e3a6..0000000 --- a/0267-efi-use-enumerated-array-positions-for-our-allocatio.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 1 Aug 2022 14:06:30 -0400 -Subject: [PATCH] efi: use enumerated array positions for our allocation - choices - -In our kernel allocator on EFI systems, we currently have a growing -amount of code that references the various allocation policies by -position in the array, and of course maintenance of this code scales -very poorly. - -This patch changes them to be enumerated, so they're easier to refer to -farther along in the code without confusion. - -Signed-off-by: Peter Jones ---- - grub-core/loader/i386/efi/linux.c | 31 ++++++++++++++++++++----------- - 1 file changed, 20 insertions(+), 11 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 91ae274299..8daa070132 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -60,17 +60,26 @@ struct allocation_choice { - grub_efi_allocate_type_t alloc_type; - }; - --static struct allocation_choice max_addresses[4] = -+enum { -+ KERNEL_PREF_ADDRESS, -+ KERNEL_4G_LIMIT, -+ KERNEL_NO_LIMIT, -+}; -+ -+static struct allocation_choice max_addresses[] = - { - /* the kernel overrides this one with pref_address and - * GRUB_EFI_ALLOCATE_ADDRESS */ -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ [KERNEL_PREF_ADDRESS] = -+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ /* If the flag in params is set, this one gets changed to be above 4GB. */ -+ [KERNEL_4G_LIMIT] = -+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - /* this one is always below 4GB, which we still *prefer* even if the flag - * is set. */ -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -- /* If the flag in params is set, this one gets changed to be above 4GB. */ -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -- { 0, 0 } -+ [KERNEL_NO_LIMIT] = -+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { NO_MEM, 0, 0 } - }; - static struct allocation_choice saved_addresses[4]; - -@@ -405,7 +414,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G) - { - grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n"); -- max_addresses[2].addr = GRUB_EFI_MAX_USABLE_ADDRESS; -+ max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_USABLE_ADDRESS; - } - else - { -@@ -478,11 +487,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address); - if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS) - { -- max_addresses[0].addr = lh->pref_address; -- max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; -+ max_addresses[KERNEL_PREF_ADDRESS].addr = lh->pref_address; -+ max_addresses[KERNEL_PREF_ADDRESS].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; - } -- max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -- max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -+ max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -+ max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - kernel_size = lh->init_size; - kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, - N_("can't allocate kernel")); diff --git a/0268-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch b/0268-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch deleted file mode 100644 index d25cf30..0000000 --- a/0268-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 1 Aug 2022 14:24:39 -0400 -Subject: [PATCH] efi: split allocation policy for kernel vs initrd memories. - -Currently in our kernel allocator, we use the same set of choices for -all of our various kernel and initramfs allocations, though they do not -have exactly the same constraints. - -This patch adds the concept of an allocation purpose, which currently -can be KERNEL_MEM or INITRD_MEM, and updates kernel_alloc() calls -appropriately, but does not change any current policy decision. It -also adds a few debug prints. - -Signed-off-by: Peter Jones ---- - grub-core/loader/i386/efi/linux.c | 35 +++++++++++++++++++++++++++-------- - 1 file changed, 27 insertions(+), 8 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 8daa070132..e6b8998e5e 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -55,7 +55,14 @@ struct grub_linuxefi_context { - - #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) - -+typedef enum { -+ NO_MEM, -+ KERNEL_MEM, -+ INITRD_MEM, -+} kernel_alloc_purpose_t; -+ - struct allocation_choice { -+ kernel_alloc_purpose_t purpose; - grub_efi_physical_address_t addr; - grub_efi_allocate_type_t alloc_type; - }; -@@ -64,6 +71,7 @@ enum { - KERNEL_PREF_ADDRESS, - KERNEL_4G_LIMIT, - KERNEL_NO_LIMIT, -+ INITRD_MAX_ADDRESS, - }; - - static struct allocation_choice max_addresses[] = -@@ -71,14 +79,17 @@ static struct allocation_choice max_addresses[] = - /* the kernel overrides this one with pref_address and - * GRUB_EFI_ALLOCATE_ADDRESS */ - [KERNEL_PREF_ADDRESS] = -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - /* If the flag in params is set, this one gets changed to be above 4GB. */ - [KERNEL_4G_LIMIT] = -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - /* this one is always below 4GB, which we still *prefer* even if the flag - * is set. */ - [KERNEL_NO_LIMIT] = -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ /* this is for the initrd */ -+ [INITRD_MAX_ADDRESS] = -+ { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - { NO_MEM, 0, 0 } - }; - static struct allocation_choice saved_addresses[4]; -@@ -95,7 +106,8 @@ kernel_free(void *addr, grub_efi_uintn_t size) - } - - static void * --kernel_alloc(grub_efi_uintn_t size, -+kernel_alloc(kernel_alloc_purpose_t purpose, -+ grub_efi_uintn_t size, - grub_efi_memory_type_t memtype, - const char * const errmsg) - { -@@ -108,6 +120,9 @@ kernel_alloc(grub_efi_uintn_t size, - grub_uint64_t max = max_addresses[i].addr; - grub_efi_uintn_t pages; - -+ if (purpose != max_addresses[i].purpose) -+ continue; -+ - /* - * When we're *not* loading the kernel, or >4GB allocations aren't - * supported, these entries are basically all the same, so don't re-try -@@ -261,7 +276,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - } - } - -- initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA, -+ grub_dprintf ("linux", "Trying to allocate initrd mem\n"); -+ initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA, - N_("can't allocate initrd")); - if (initrd_mem == NULL) - goto fail; -@@ -422,7 +438,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -- params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA, -+ params = kernel_alloc (KERNEL_MEM, sizeof(*params), -+ GRUB_EFI_RUNTIME_SERVICES_DATA, - "cannot allocate kernel parameters"); - if (!params) - goto fail; -@@ -445,7 +462,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "new lh is at %p\n", lh); - - grub_dprintf ("linux", "setting up cmdline\n"); -- cmdline = kernel_alloc (lh->cmdline_size + 1, -+ cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1, - GRUB_EFI_RUNTIME_SERVICES_DATA, - N_("can't allocate cmdline")); - if (!cmdline) -@@ -493,7 +510,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - kernel_size = lh->init_size; -- kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, -+ grub_dprintf ("linux", "Trying to allocate kernel mem\n"); -+ kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size, -+ GRUB_EFI_RUNTIME_SERVICES_CODE, - N_("can't allocate kernel")); - restore_addresses(); - if (!kernel_mem) diff --git a/0268-squish-don-t-dup-rhgb-quiet-check-mtimes.patch b/0268-squish-don-t-dup-rhgb-quiet-check-mtimes.patch new file mode 100644 index 0000000..67073ec --- /dev/null +++ b/0268-squish-don-t-dup-rhgb-quiet-check-mtimes.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 17 Aug 2022 10:26:07 -0400 +Subject: [PATCH] squish: don't dup rhgb quiet, check mtimes + +Signed-off-by: Robbie Harwood +--- + util/grub.d/10_linux.in | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 9ebff661a9..41c6cb1dc2 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -161,10 +161,16 @@ update_bls_cmdline() + local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + local -a files=($(get_sorted_bls)) + +- if [[ ! -f /etc/kernel/cmdline ]]; then +- # anaconda has the correct information to do this during install; +- # afterward, grubby will take care of syncing on updates. +- echo "$cmdline rhgb quiet" > /etc/kernel/cmdline ++ if [[ ! -f /etc/kernel/cmdline ]] || ++ [[ /etc/kernel/cmdline -ot /etc/default/grub ]]; then ++ # anaconda has the correct information to create this during install; ++ # afterward, grubby will take care of syncing on updates. If the user ++ # has modified /etc/default/grub, try to cope. ++ if [[ ! "$cmdline" =~ "rhgb quiet" ]]; then ++ # ensure these only show up once ++ cmdline="$cmdline rhgb quiet" ++ fi ++ echo "$cmdline" > /etc/kernel/cmdline + fi + + for bls in "${files[@]}"; do diff --git a/0269-efi-allocate-the-initrd-within-the-bounds-expressed-.patch b/0269-efi-allocate-the-initrd-within-the-bounds-expressed-.patch deleted file mode 100644 index 47e31e2..0000000 --- a/0269-efi-allocate-the-initrd-within-the-bounds-expressed-.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 1 Aug 2022 14:07:50 -0400 -Subject: [PATCH] efi: allocate the initrd within the bounds expressed by the - kernel - -Currently on x86, only linux kernels built with CONFIG_RELOCATABLE for -x86_64 can be loaded above 4G, but the maximum address for the initramfs -is specified via a HdrS field. This allows us to utilize that value, -and unless loading the kernel above 4G, uses the value present there. -If loading kernel above 4G is allowed, we assume loading the initramfs -above 4G also works; in practice this has been true in the kernel code -for quite some time. - -Resolves: rhbz#2112134 - -Signed-off-by: Peter Jones ---- - grub-core/loader/i386/efi/linux.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index e6b8998e5e..d003b474ee 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -190,6 +190,8 @@ grub_linuxefi_unload (void *data) - cmd_initrdefi->data = 0; - grub_free (context); - -+ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -+ - return GRUB_ERR_NONE; - } - -@@ -426,11 +428,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -+ max_addresses[INITRD_MAX_ADDRESS].addr = lh->initrd_addr_max; - #if defined(__x86_64__) - if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G) - { - grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n"); - max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_USABLE_ADDRESS; -+ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_USABLE_ADDRESS; - } - else - { -@@ -560,6 +564,8 @@ fail: - - grub_dl_unref (my_mod); - -+ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -+ - if (lh) - kernel_free (cmdline, lh->cmdline_size + 1); - diff --git a/0269-squish-give-up-on-rhgb-quiet.patch b/0269-squish-give-up-on-rhgb-quiet.patch new file mode 100644 index 0000000..5858c91 --- /dev/null +++ b/0269-squish-give-up-on-rhgb-quiet.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 17 Aug 2022 11:30:30 -0400 +Subject: [PATCH] squish: give up on rhgb quiet + +Signed-off-by: Robbie Harwood +--- + util/grub.d/10_linux.in | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 41c6cb1dc2..5d1fa072f2 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -166,10 +166,6 @@ update_bls_cmdline() + # anaconda has the correct information to create this during install; + # afterward, grubby will take care of syncing on updates. If the user + # has modified /etc/default/grub, try to cope. +- if [[ ! "$cmdline" =~ "rhgb quiet" ]]; then +- # ensure these only show up once +- cmdline="$cmdline rhgb quiet" +- fi + echo "$cmdline" > /etc/kernel/cmdline + fi + diff --git a/0270-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch b/0270-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch deleted file mode 100644 index 8451dbf..0000000 --- a/0270-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 1 Aug 2022 13:04:43 -0400 -Subject: [PATCH] efi: use EFI_LOADER_(CODE|DATA) for kernel and initrd - allocations - -At some point due to an erroneous kernel warning, we switched kernel and -initramfs to being loaded in EFI_RUNTIME_SERVICES_CODE and -EFI_RUNTIME_SERVICES_DATA memory pools. This doesn't appear to be -correct according to the spec, and that kernel warning has gone away. - -This patch puts them back in EFI_LOADER_CODE and EFI_LOADER_DATA -allocations, respectively. - -Resolves: rhbz#2108456 - -Signed-off-by: Peter Jones ---- - grub-core/loader/i386/efi/linux.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index d003b474ee..ac5ef50bdb 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -279,7 +279,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - } - - grub_dprintf ("linux", "Trying to allocate initrd mem\n"); -- initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA, -+ initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_LOADER_DATA, - N_("can't allocate initrd")); - if (initrd_mem == NULL) - goto fail; -@@ -443,7 +443,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - #endif - - params = kernel_alloc (KERNEL_MEM, sizeof(*params), -- GRUB_EFI_RUNTIME_SERVICES_DATA, -+ GRUB_EFI_LOADER_DATA, - "cannot allocate kernel parameters"); - if (!params) - goto fail; -@@ -467,7 +467,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - - grub_dprintf ("linux", "setting up cmdline\n"); - cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1, -- GRUB_EFI_RUNTIME_SERVICES_DATA, -+ GRUB_EFI_LOADER_DATA, - N_("can't allocate cmdline")); - if (!cmdline) - goto fail; -@@ -516,7 +516,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - kernel_size = lh->init_size; - grub_dprintf ("linux", "Trying to allocate kernel mem\n"); - kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size, -- GRUB_EFI_RUNTIME_SERVICES_CODE, -+ GRUB_EFI_LOADER_CODE, - N_("can't allocate kernel")); - restore_addresses(); - if (!kernel_mem) diff --git a/0270-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch b/0270-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch new file mode 100644 index 0000000..d5ac923 --- /dev/null +++ b/0270-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jonathan Lebon +Date: Wed, 17 Aug 2022 10:26:03 -0400 +Subject: [PATCH] squish: BLS: only write /etc/kernel/cmdline if writable + +On OSTree systems, `grub2-mkconfig` is run with `/etc` mounted read-only +because as part of the promise of transactional updates, we want to make +sure that we're not modifying the current deployment's state (`/etc` or +`/var`). + +This conflicts with 0837dcdf1 ("BLS: create /etc/kernel/cmdline during +mkconfig") which wants to write to `/etc/kernel/cmdline`. I'm not +exactly sure on the background there, but based on the comment I think +the intent is to fulfill grubby's expectation that the file exists. + +However, in systems like Silverblue, kernel arguments are managed by the +rpm-ostree stack and grubby is not shipped at all. + +Adjust the script slightly so that we only write `/etc/kernel/cmdline` +if the parent directory is writable. + +In the future, we're hoping to simplify things further on rpm-ostree +systems by not running `grub2-mkconfig` at all since libostree already +directly writes BLS entries. Doing that would also have avoided this, +but ratcheting it into existing systems needs more careful thought. + +Signed-off-by: Jonathan Lebon + +Fixes: https://github.com/fedora-silverblue/issue-tracker/issues/322 +--- + util/grub.d/10_linux.in | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 5d1fa072f2..4795a63b4c 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -161,12 +161,13 @@ update_bls_cmdline() + local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + local -a files=($(get_sorted_bls)) + +- if [[ ! -f /etc/kernel/cmdline ]] || +- [[ /etc/kernel/cmdline -ot /etc/default/grub ]]; then +- # anaconda has the correct information to create this during install; +- # afterward, grubby will take care of syncing on updates. If the user +- # has modified /etc/default/grub, try to cope. +- echo "$cmdline" > /etc/kernel/cmdline ++ if [ -w /etc/kernel ] && ++ [[ ! -f /etc/kernel/cmdline || ++ /etc/kernel/cmdline -ot /etc/default/grub ]]; then ++ # anaconda has the correct information to create this during install; ++ # afterward, grubby will take care of syncing on updates. If the user ++ # has modified /etc/default/grub, try to cope. ++ echo "$cmdline" > /etc/kernel/cmdline + fi + + for bls in "${files[@]}"; do diff --git a/0271-BLS-create-etc-kernel-cmdline-during-mkconfig.patch b/0271-BLS-create-etc-kernel-cmdline-during-mkconfig.patch deleted file mode 100644 index 50ba0fb..0000000 --- a/0271-BLS-create-etc-kernel-cmdline-during-mkconfig.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Tue, 2 Aug 2022 15:56:28 -0400 -Subject: [PATCH] BLS: create /etc/kernel/cmdline during mkconfig - -Signed-off-by: Robbie Harwood ---- - util/grub.d/10_linux.in | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index 865af3d6c4..9ebff661a9 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -161,6 +161,12 @@ update_bls_cmdline() - local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" - local -a files=($(get_sorted_bls)) - -+ if [[ ! -f /etc/kernel/cmdline ]]; then -+ # anaconda has the correct information to do this during install; -+ # afterward, grubby will take care of syncing on updates. -+ echo "$cmdline rhgb quiet" > /etc/kernel/cmdline -+ fi -+ - for bls in "${files[@]}"; do - local options="${cmdline}" - if [ -z "${bls##*debug*}" ]; then diff --git a/0271-blscfg-Don-t-root-device-in-emu-builds.patch b/0271-blscfg-Don-t-root-device-in-emu-builds.patch new file mode 100644 index 0000000..3fe8baf --- /dev/null +++ b/0271-blscfg-Don-t-root-device-in-emu-builds.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 25 Aug 2022 17:57:55 -0400 +Subject: [PATCH] blscfg: Don't root device in emu builds + +Otherwise, we end up looking for kernel/initrd in /boot/boot which +doesn't work at all. Non-emu builds need to be looking in +($root)/boot/, which is what this is for. + +Signed-off-by: Robbie Harwood +--- + grub-core/commands/blscfg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c +index e907a6a5d2..dbd0899acf 100644 +--- a/grub-core/commands/blscfg.c ++++ b/grub-core/commands/blscfg.c +@@ -41,7 +41,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + #define GRUB_BLS_CONFIG_PATH "/loader/entries/" + #ifdef GRUB_MACHINE_EMU +-#define GRUB_BOOT_DEVICE "/boot" ++#define GRUB_BOOT_DEVICE "" + #else + #define GRUB_BOOT_DEVICE "($root)" + #endif diff --git a/0272-loader-arm64-linux-Remove-magic-number-header-field-.patch b/0272-loader-arm64-linux-Remove-magic-number-header-field-.patch new file mode 100644 index 0000000..faaa071 --- /dev/null +++ b/0272-loader-arm64-linux-Remove-magic-number-header-field-.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Thu, 11 Aug 2022 16:51:57 +0200 +Subject: [PATCH] loader/arm64/linux: Remove magic number header field check + +The "ARM\x64" magic number in the file header identifies an image as one +that implements the bare metal boot protocol, allowing the loader to +simply move the file to a suitably aligned address in memory, with +sufficient headroom for the trailing .bss segment (the required memory +size is described in the header as well). + +Note of this matters for GRUB, as it only supports EFI boot. EFI does +not care about this magic number, and nor should GRUB: this prevents us +from booting other PE linux images, such as the generic EFI zboot +decompressor, which is a pure PE/COFF image, and does not implement the +bare metal boot protocol. + +So drop the magic number check. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Daniel Kiper +Resolves: rhbz#2125069 +Signed-off-by: Jeremy Linton +(cherry-picked from commit 69edb31205602c29293a8c6e67363bba2a4a1e66) +Signed-off-by: Robbie Harwood +--- + grub-core/loader/arm64/linux.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index de85583487..489d0c7173 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -55,9 +55,6 @@ static grub_addr_t initrd_end; + grub_err_t + grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) + { +- if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE) +- return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); +- + if ((lh->code0 & 0xffff) != GRUB_DOS_MAGIC) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); diff --git a/0272-squish-don-t-dup-rhgb-quiet-check-mtimes.patch b/0272-squish-don-t-dup-rhgb-quiet-check-mtimes.patch deleted file mode 100644 index 67073ec..0000000 --- a/0272-squish-don-t-dup-rhgb-quiet-check-mtimes.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Wed, 17 Aug 2022 10:26:07 -0400 -Subject: [PATCH] squish: don't dup rhgb quiet, check mtimes - -Signed-off-by: Robbie Harwood ---- - util/grub.d/10_linux.in | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index 9ebff661a9..41c6cb1dc2 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -161,10 +161,16 @@ update_bls_cmdline() - local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" - local -a files=($(get_sorted_bls)) - -- if [[ ! -f /etc/kernel/cmdline ]]; then -- # anaconda has the correct information to do this during install; -- # afterward, grubby will take care of syncing on updates. -- echo "$cmdline rhgb quiet" > /etc/kernel/cmdline -+ if [[ ! -f /etc/kernel/cmdline ]] || -+ [[ /etc/kernel/cmdline -ot /etc/default/grub ]]; then -+ # anaconda has the correct information to create this during install; -+ # afterward, grubby will take care of syncing on updates. If the user -+ # has modified /etc/default/grub, try to cope. -+ if [[ ! "$cmdline" =~ "rhgb quiet" ]]; then -+ # ensure these only show up once -+ cmdline="$cmdline rhgb quiet" -+ fi -+ echo "$cmdline" > /etc/kernel/cmdline - fi - - for bls in "${files[@]}"; do diff --git a/0273-Correct-BSS-zeroing-on-aarch64.patch b/0273-Correct-BSS-zeroing-on-aarch64.patch new file mode 100644 index 0000000..4f9a2b7 --- /dev/null +++ b/0273-Correct-BSS-zeroing-on-aarch64.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jeremy Linton +Date: Tue, 6 Sep 2022 15:33:03 -0500 +Subject: [PATCH] Correct BSS zeroing on aarch64 + +The aarch64 loader doesn't use efi bootservices, and +therefor it has a very minimal loader which makes a lot +of assumptions about the kernel layout. With the ZBOOT +changes, the layout has changed a bit and we not should +really be parsing the PE sections to determine how much +data to copy, otherwise the BSS won't be setup properly. + +This code still makes a lot of assumptions about the +the kernel layout, so its far from ideal, but it works. + +Resolves: rhbz#2125069 + +Signed-off-by: Jeremy Linton +--- + grub-core/loader/arm64/linux.c | 27 ++++++++++++++++++++++----- + 1 file changed, 22 insertions(+), 5 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 489d0c7173..419f2201df 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -316,10 +316,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + static grub_err_t + parse_pe_header (void *kernel, grub_uint64_t *total_size, + grub_uint32_t *entry_offset, +- grub_uint32_t *alignment) ++ grub_uint32_t *alignment,grub_uint32_t *code_size) + { + struct linux_arch_kernel_header *lh = kernel; + struct grub_armxx_linux_pe_header *pe; ++ grub_uint16_t i; ++ struct grub_pe32_section_table *sections; + + pe = (void *)((unsigned long)kernel + lh->hdr_offset); + +@@ -329,6 +331,19 @@ parse_pe_header (void *kernel, grub_uint64_t *total_size, + *total_size = pe->opt.image_size; + *entry_offset = pe->opt.entry_addr; + *alignment = pe->opt.section_alignment; ++ *code_size = pe->opt.section_alignment; ++ ++ sections = (struct grub_pe32_section_table *) ((char *)&pe->opt + ++ pe->coff.optional_header_size); ++ grub_dprintf ("linux", "num_sections : %d\n", pe->coff.num_sections ); ++ for (i = 0 ; i < pe->coff.num_sections; i++) ++ { ++ grub_dprintf ("linux", "raw_size : %lld\n", ++ (long long) sections[i].raw_data_size); ++ grub_dprintf ("linux", "virt_size : %lld\n", ++ (long long) sections[i].virtual_size); ++ *code_size += sections[i].raw_data_size; ++ } + + return GRUB_ERR_NONE; + } +@@ -341,6 +356,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_err_t err; + grub_off_t filelen; + grub_uint32_t align; ++ grub_uint32_t code_size; + void *kernel = NULL; + int nx_supported = 1; + +@@ -373,11 +389,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) + goto fail; +- if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) ++ if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align, &code_size) != GRUB_ERR_NONE) + goto fail; + grub_dprintf ("linux", "kernel mem size : %lld\n", (long long) kernel_size); + grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); + grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); ++ grub_dprintf ("linux", "kernel size : 0x%x\n", code_size); + + err = grub_efi_check_nx_image_support((grub_addr_t)kernel, filelen, &nx_supported); + if (err != GRUB_ERR_NONE) +@@ -396,9 +413,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align); + + grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); +- grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size)); +- if (kernel_size > filelen) +- grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen); ++ grub_memcpy (kernel_addr, kernel, grub_min(code_size, kernel_size)); ++ if (kernel_size > code_size) ++ grub_memset ((char *)kernel_addr + code_size, 0, kernel_size - code_size); + grub_free(kernel); + kernel = NULL; + diff --git a/0273-squish-give-up-on-rhgb-quiet.patch b/0273-squish-give-up-on-rhgb-quiet.patch deleted file mode 100644 index 5858c91..0000000 --- a/0273-squish-give-up-on-rhgb-quiet.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Wed, 17 Aug 2022 11:30:30 -0400 -Subject: [PATCH] squish: give up on rhgb quiet - -Signed-off-by: Robbie Harwood ---- - util/grub.d/10_linux.in | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index 41c6cb1dc2..5d1fa072f2 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -166,10 +166,6 @@ update_bls_cmdline() - # anaconda has the correct information to create this during install; - # afterward, grubby will take care of syncing on updates. If the user - # has modified /etc/default/grub, try to cope. -- if [[ ! "$cmdline" =~ "rhgb quiet" ]]; then -- # ensure these only show up once -- cmdline="$cmdline rhgb quiet" -- fi - echo "$cmdline" > /etc/kernel/cmdline - fi - diff --git a/0274-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch b/0274-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch new file mode 100644 index 0000000..eff155d --- /dev/null +++ b/0274-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dann frazier +Date: Thu, 25 Aug 2022 17:08:09 -0600 +Subject: [PATCH] linuxefi: Invalidate i-cache before starting the kernel + +We need to flush the memory range of the code we are about to execute +from the instruction cache before we can safely execute it. Not doing +so appears to be the source of rare synchronous exceptions a user +is seeing on a Cortex-A72-based platform while executing the Linux EFI +stub. Notably they seem to correlate with an instruction on a cache +line boundary. + +Signed-off-by: dann frazier +--- + grub-core/loader/efi/linux.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index 277f352e0c..e413bdcc23 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -16,6 +16,7 @@ + * along with GRUB. If not, see . + */ + ++#include + #include + #include + #include +@@ -210,6 +211,9 @@ grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size, + asm volatile ("cli"); + #endif + ++ /* Invalidate the instruction cache */ ++ grub_arch_sync_caches((void *)kernel_addr, kernel_size); ++ + hf = (handover_func)((char *)kernel_addr + handover_offset + offset); + hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); + diff --git a/0274-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch b/0274-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch deleted file mode 100644 index d5ac923..0000000 --- a/0274-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jonathan Lebon -Date: Wed, 17 Aug 2022 10:26:03 -0400 -Subject: [PATCH] squish: BLS: only write /etc/kernel/cmdline if writable - -On OSTree systems, `grub2-mkconfig` is run with `/etc` mounted read-only -because as part of the promise of transactional updates, we want to make -sure that we're not modifying the current deployment's state (`/etc` or -`/var`). - -This conflicts with 0837dcdf1 ("BLS: create /etc/kernel/cmdline during -mkconfig") which wants to write to `/etc/kernel/cmdline`. I'm not -exactly sure on the background there, but based on the comment I think -the intent is to fulfill grubby's expectation that the file exists. - -However, in systems like Silverblue, kernel arguments are managed by the -rpm-ostree stack and grubby is not shipped at all. - -Adjust the script slightly so that we only write `/etc/kernel/cmdline` -if the parent directory is writable. - -In the future, we're hoping to simplify things further on rpm-ostree -systems by not running `grub2-mkconfig` at all since libostree already -directly writes BLS entries. Doing that would also have avoided this, -but ratcheting it into existing systems needs more careful thought. - -Signed-off-by: Jonathan Lebon - -Fixes: https://github.com/fedora-silverblue/issue-tracker/issues/322 ---- - util/grub.d/10_linux.in | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index 5d1fa072f2..4795a63b4c 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -161,12 +161,13 @@ update_bls_cmdline() - local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" - local -a files=($(get_sorted_bls)) - -- if [[ ! -f /etc/kernel/cmdline ]] || -- [[ /etc/kernel/cmdline -ot /etc/default/grub ]]; then -- # anaconda has the correct information to create this during install; -- # afterward, grubby will take care of syncing on updates. If the user -- # has modified /etc/default/grub, try to cope. -- echo "$cmdline" > /etc/kernel/cmdline -+ if [ -w /etc/kernel ] && -+ [[ ! -f /etc/kernel/cmdline || -+ /etc/kernel/cmdline -ot /etc/default/grub ]]; then -+ # anaconda has the correct information to create this during install; -+ # afterward, grubby will take care of syncing on updates. If the user -+ # has modified /etc/default/grub, try to cope. -+ echo "$cmdline" > /etc/kernel/cmdline - fi - - for bls in "${files[@]}"; do diff --git a/0275-ieee1275-implement-vec5-for-cas-negotiation.patch b/0275-ieee1275-implement-vec5-for-cas-negotiation.patch deleted file mode 100644 index 2749d10..0000000 --- a/0275-ieee1275-implement-vec5-for-cas-negotiation.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Diego Domingos -Date: Thu, 25 Aug 2022 11:37:56 -0400 -Subject: [PATCH] ieee1275: implement vec5 for cas negotiation - -As a legacy support, if the vector 5 is not implemented, Power -Hypervisor will consider the max CPUs as 64 instead 256 currently -supported during client-architecture-support negotiation. - -This patch implements the vector 5 and set the MAX CPUs to 256 while -setting the others values to 0 (default). - -Signed-off-by: Diego Domingos -Signed-off-by: Robbie Harwood ---- - grub-core/kern/ieee1275/init.c | 20 +++++++++++++++++++- - 1 file changed, 19 insertions(+), 1 deletion(-) - -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index ef55107467..6a51c9efab 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -311,6 +311,18 @@ struct option_vector2 { - grub_uint8_t max_pft_size; - } __attribute__((packed)); - -+struct option_vector5 { -+ grub_uint8_t byte1; -+ grub_uint8_t byte2; -+ grub_uint8_t byte3; -+ grub_uint8_t cmo; -+ grub_uint8_t associativity; -+ grub_uint8_t bin_opts; -+ grub_uint8_t micro_checkpoint; -+ grub_uint8_t reserved0; -+ grub_uint32_t max_cpus; -+} __attribute__((packed)); -+ - struct pvr_entry { - grub_uint32_t mask; - grub_uint32_t entry; -@@ -329,6 +341,8 @@ struct cas_vector { - grub_uint16_t vec3; - grub_uint8_t vec4_size; - grub_uint16_t vec4; -+ grub_uint8_t vec5_size; -+ struct option_vector5 vec5; - } __attribute__((packed)); - - /* Call ibm,client-architecture-support to try to get more RMA. -@@ -349,7 +363,7 @@ grub_ieee1275_ibm_cas (void) - } args; - struct cas_vector vector = { - .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ -- .num_vecs = 4 - 1, -+ .num_vecs = 5 - 1, - .vec1_size = 0, - .vec1 = 0x80, /* ignore */ - .vec2_size = 1 + sizeof(struct option_vector2) - 2, -@@ -360,6 +374,10 @@ grub_ieee1275_ibm_cas (void) - .vec3 = 0x00e0, // ask for FP + VMX + DFP but don't halt if unsatisfied - .vec4_size = 2 - 1, - .vec4 = 0x0001, // set required minimum capacity % to the lowest value -+ .vec5_size = 1 + sizeof(struct option_vector5) - 2, -+ .vec5 = { -+ 0, 0, 0, 0, 0, 0, 0, 0, 256 -+ } - }; - - INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); diff --git a/0275-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch b/0275-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch new file mode 100644 index 0000000..0079750 --- /dev/null +++ b/0275-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 11 Oct 2022 17:00:50 -0400 +Subject: [PATCH] x86-efi: Fix an incorrect array size in kernel allocation + +In 81a6ebf62bbe166ddc968463df2e8bd481bf697c ("efi: split allocation +policy for kernel vs initrd memories."), I introduced a split in the +kernel allocator to allow for different dynamic policies for the kernel +and the initrd allocations. + +Unfortunately, that change increased the size of the policy data used to +make decisions, but did not change the size of the temporary storage we +use to back it up and restore. This results in some of .data getting +clobbered at runtime, and hilarity ensues. + +This patch makes the size of the backup storage be based on the size of +the initial policy data. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index ac5ef50bdb..9854b0defa 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -92,7 +92,7 @@ static struct allocation_choice max_addresses[] = + { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + { NO_MEM, 0, 0 } + }; +-static struct allocation_choice saved_addresses[4]; ++static struct allocation_choice saved_addresses[sizeof(max_addresses) / sizeof(max_addresses[0])]; + + #define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses)) + #define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses)) diff --git a/0276-blscfg-Don-t-root-device-in-emu-builds.patch b/0276-blscfg-Don-t-root-device-in-emu-builds.patch deleted file mode 100644 index 3fe8baf..0000000 --- a/0276-blscfg-Don-t-root-device-in-emu-builds.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Thu, 25 Aug 2022 17:57:55 -0400 -Subject: [PATCH] blscfg: Don't root device in emu builds - -Otherwise, we end up looking for kernel/initrd in /boot/boot which -doesn't work at all. Non-emu builds need to be looking in -($root)/boot/, which is what this is for. - -Signed-off-by: Robbie Harwood ---- - grub-core/commands/blscfg.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c -index e907a6a5d2..dbd0899acf 100644 ---- a/grub-core/commands/blscfg.c -+++ b/grub-core/commands/blscfg.c -@@ -41,7 +41,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); - - #define GRUB_BLS_CONFIG_PATH "/loader/entries/" - #ifdef GRUB_MACHINE_EMU --#define GRUB_BOOT_DEVICE "/boot" -+#define GRUB_BOOT_DEVICE "" - #else - #define GRUB_BOOT_DEVICE "($root)" - #endif diff --git a/0276-commands-efi-tpm-Refine-the-status-of-log-event.patch b/0276-commands-efi-tpm-Refine-the-status-of-log-event.patch new file mode 100644 index 0000000..896e49b --- /dev/null +++ b/0276-commands-efi-tpm-Refine-the-status-of-log-event.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lu Ken +Date: Wed, 13 Jul 2022 10:06:10 +0800 +Subject: [PATCH] commands/efi/tpm: Refine the status of log event + +1. Use macro GRUB_ERR_NONE instead of hard code 0. +2. Keep lowercase of the first char for the status string of log event. + +Signed-off-by: Lu Ken +Reviewed-by: Daniel Kiper +(cherry picked from commit 922898573e37135f5dedc16f3e15a1d1d4c53f8a) +--- + grub-core/commands/efi/tpm.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c +index a97d85368a..7acf510499 100644 +--- a/grub-core/commands/efi/tpm.c ++++ b/grub-core/commands/efi/tpm.c +@@ -135,17 +135,17 @@ grub_efi_log_event_status (grub_efi_status_t status) + switch (status) + { + case GRUB_EFI_SUCCESS: +- return 0; ++ return GRUB_ERR_NONE; + case GRUB_EFI_DEVICE_ERROR: +- return grub_error (GRUB_ERR_IO, N_("Command failed")); ++ return grub_error (GRUB_ERR_IO, N_("command failed")); + case GRUB_EFI_INVALID_PARAMETER: +- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter")); ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid parameter")); + case GRUB_EFI_BUFFER_TOO_SMALL: +- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small")); ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("output buffer too small")); + case GRUB_EFI_NOT_FOUND: + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable")); + default: +- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error")); ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("unknown TPM error")); + } + } + diff --git a/0277-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch b/0277-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch new file mode 100644 index 0000000..e04dcbc --- /dev/null +++ b/0277-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lu Ken +Date: Wed, 13 Jul 2022 10:06:11 +0800 +Subject: [PATCH] commands/efi/tpm: Use grub_strcpy() instead of grub_memcpy() + +The event description is a string, so using grub_strcpy() is cleaner than +using grub_memcpy(). + +Signed-off-by: Lu Ken +Reviewed-by: Daniel Kiper +(cherry picked from commit ef8679b645a63eb9eb191bb9539d7d25a9d6ff3b) +--- + grub-core/commands/efi/tpm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c +index 7acf510499..bb59599721 100644 +--- a/grub-core/commands/efi/tpm.c ++++ b/grub-core/commands/efi/tpm.c +@@ -175,7 +175,7 @@ grub_tpm1_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + event->PCRIndex = pcr; + event->EventType = EV_IPL; + event->EventSize = grub_strlen (description) + 1; +- grub_memcpy (event->Event, description, event->EventSize); ++ grub_strcpy ((char *) event->Event, description); + + algorithm = TCG_ALG_SHA; + status = efi_call_7 (tpm->log_extend_event, tpm, (grub_addr_t) buf, (grub_uint64_t) size, +@@ -212,7 +212,7 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + event->Header.EventType = EV_IPL; + event->Size = + sizeof (*event) - sizeof (event->Event) + grub_strlen (description) + 1; +- grub_memcpy (event->Event, description, grub_strlen (description) + 1); ++ grub_strcpy ((char *) event->Event, description); + + status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, (grub_addr_t) buf, + (grub_uint64_t) size, event); diff --git a/0277-loader-arm64-linux-Remove-magic-number-header-field-.patch b/0277-loader-arm64-linux-Remove-magic-number-header-field-.patch deleted file mode 100644 index faaa071..0000000 --- a/0277-loader-arm64-linux-Remove-magic-number-header-field-.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ard Biesheuvel -Date: Thu, 11 Aug 2022 16:51:57 +0200 -Subject: [PATCH] loader/arm64/linux: Remove magic number header field check - -The "ARM\x64" magic number in the file header identifies an image as one -that implements the bare metal boot protocol, allowing the loader to -simply move the file to a suitably aligned address in memory, with -sufficient headroom for the trailing .bss segment (the required memory -size is described in the header as well). - -Note of this matters for GRUB, as it only supports EFI boot. EFI does -not care about this magic number, and nor should GRUB: this prevents us -from booting other PE linux images, such as the generic EFI zboot -decompressor, which is a pure PE/COFF image, and does not implement the -bare metal boot protocol. - -So drop the magic number check. - -Signed-off-by: Ard Biesheuvel -Reviewed-by: Daniel Kiper -Resolves: rhbz#2125069 -Signed-off-by: Jeremy Linton -(cherry-picked from commit 69edb31205602c29293a8c6e67363bba2a4a1e66) -Signed-off-by: Robbie Harwood ---- - grub-core/loader/arm64/linux.c | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index de85583487..489d0c7173 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -55,9 +55,6 @@ static grub_addr_t initrd_end; - grub_err_t - grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) - { -- if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE) -- return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); -- - if ((lh->code0 & 0xffff) != GRUB_DOS_MAGIC) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); diff --git a/0278-Correct-BSS-zeroing-on-aarch64.patch b/0278-Correct-BSS-zeroing-on-aarch64.patch deleted file mode 100644 index 4f9a2b7..0000000 --- a/0278-Correct-BSS-zeroing-on-aarch64.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jeremy Linton -Date: Tue, 6 Sep 2022 15:33:03 -0500 -Subject: [PATCH] Correct BSS zeroing on aarch64 - -The aarch64 loader doesn't use efi bootservices, and -therefor it has a very minimal loader which makes a lot -of assumptions about the kernel layout. With the ZBOOT -changes, the layout has changed a bit and we not should -really be parsing the PE sections to determine how much -data to copy, otherwise the BSS won't be setup properly. - -This code still makes a lot of assumptions about the -the kernel layout, so its far from ideal, but it works. - -Resolves: rhbz#2125069 - -Signed-off-by: Jeremy Linton ---- - grub-core/loader/arm64/linux.c | 27 ++++++++++++++++++++++----- - 1 file changed, 22 insertions(+), 5 deletions(-) - -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index 489d0c7173..419f2201df 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -316,10 +316,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - static grub_err_t - parse_pe_header (void *kernel, grub_uint64_t *total_size, - grub_uint32_t *entry_offset, -- grub_uint32_t *alignment) -+ grub_uint32_t *alignment,grub_uint32_t *code_size) - { - struct linux_arch_kernel_header *lh = kernel; - struct grub_armxx_linux_pe_header *pe; -+ grub_uint16_t i; -+ struct grub_pe32_section_table *sections; - - pe = (void *)((unsigned long)kernel + lh->hdr_offset); - -@@ -329,6 +331,19 @@ parse_pe_header (void *kernel, grub_uint64_t *total_size, - *total_size = pe->opt.image_size; - *entry_offset = pe->opt.entry_addr; - *alignment = pe->opt.section_alignment; -+ *code_size = pe->opt.section_alignment; -+ -+ sections = (struct grub_pe32_section_table *) ((char *)&pe->opt + -+ pe->coff.optional_header_size); -+ grub_dprintf ("linux", "num_sections : %d\n", pe->coff.num_sections ); -+ for (i = 0 ; i < pe->coff.num_sections; i++) -+ { -+ grub_dprintf ("linux", "raw_size : %lld\n", -+ (long long) sections[i].raw_data_size); -+ grub_dprintf ("linux", "virt_size : %lld\n", -+ (long long) sections[i].virtual_size); -+ *code_size += sections[i].raw_data_size; -+ } - - return GRUB_ERR_NONE; - } -@@ -341,6 +356,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_err_t err; - grub_off_t filelen; - grub_uint32_t align; -+ grub_uint32_t code_size; - void *kernel = NULL; - int nx_supported = 1; - -@@ -373,11 +389,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - - if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) - goto fail; -- if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) -+ if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align, &code_size) != GRUB_ERR_NONE) - goto fail; - grub_dprintf ("linux", "kernel mem size : %lld\n", (long long) kernel_size); - grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); - grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); -+ grub_dprintf ("linux", "kernel size : 0x%x\n", code_size); - - err = grub_efi_check_nx_image_support((grub_addr_t)kernel, filelen, &nx_supported); - if (err != GRUB_ERR_NONE) -@@ -396,9 +413,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align); - - grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); -- grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size)); -- if (kernel_size > filelen) -- grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen); -+ grub_memcpy (kernel_addr, kernel, grub_min(code_size, kernel_size)); -+ if (kernel_size > code_size) -+ grub_memset ((char *)kernel_addr + code_size, 0, kernel_size - code_size); - grub_free(kernel); - kernel = NULL; - diff --git a/0278-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch b/0278-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch new file mode 100644 index 0000000..610c81a --- /dev/null +++ b/0278-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch @@ -0,0 +1,258 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lu Ken +Date: Wed, 13 Jul 2022 10:06:12 +0800 +Subject: [PATCH] efi/tpm: Add EFI_CC_MEASUREMENT_PROTOCOL support + +The EFI_CC_MEASUREMENT_PROTOCOL abstracts the measurement for virtual firmware +in confidential computing environment. It is similar to the EFI_TCG2_PROTOCOL. +It was proposed by Intel and ARM and approved by UEFI organization. + +It is defined in Intel GHCI specification: https://cdrdv2.intel.com/v1/dl/getContent/726790 . +The EDKII header file is available at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/CcMeasurement.h . + +Signed-off-by: Lu Ken +Reviewed-by: Daniel Kiper +(cherry picked from commit 4c76565b6cb885b7e144dc27f3612066844e2d19) +--- + grub-core/commands/efi/tpm.c | 48 ++++++++++++++ + include/grub/efi/cc.h | 151 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 199 insertions(+) + create mode 100644 include/grub/efi/cc.h + +diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c +index bb59599721..ae09c1bf8b 100644 +--- a/grub-core/commands/efi/tpm.c ++++ b/grub-core/commands/efi/tpm.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -31,6 +32,7 @@ typedef TCG_PCR_EVENT grub_tpm_event_t; + + static grub_efi_guid_t tpm_guid = EFI_TPM_GUID; + static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID; ++static grub_efi_guid_t cc_measurement_guid = GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID; + + static grub_efi_handle_t *grub_tpm_handle; + static grub_uint8_t grub_tpm_version; +@@ -221,6 +223,50 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + return grub_efi_log_event_status (status); + } + ++static void ++grub_cc_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, ++ const char *description) ++{ ++ grub_efi_cc_event_t *event; ++ grub_efi_status_t status; ++ grub_efi_cc_protocol_t *cc; ++ grub_efi_cc_mr_index_t mr; ++ ++ cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL); ++ if (cc == NULL) ++ return; ++ ++ status = efi_call_3 (cc->map_pcr_to_mr_index, cc, pcr, &mr); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_efi_log_event_status (status); ++ return; ++ } ++ ++ event = grub_zalloc (sizeof (grub_efi_cc_event_t) + ++ grub_strlen (description) + 1); ++ if (event == NULL) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate CC event buffer")); ++ return; ++ } ++ ++ event->Header.HeaderSize = sizeof (grub_efi_cc_event_header_t); ++ event->Header.HeaderVersion = GRUB_EFI_CC_EVENT_HEADER_VERSION; ++ event->Header.MrIndex = mr; ++ event->Header.EventType = EV_IPL; ++ event->Size = sizeof (*event) + grub_strlen (description) + 1; ++ grub_strcpy ((char *) event->Event, description); ++ ++ status = efi_call_5 (cc->hash_log_extend_event, cc, 0, ++ (grub_efi_physical_address_t)(grub_addr_t) buf, ++ (grub_efi_uint64_t) size, event); ++ grub_free (event); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ grub_efi_log_event_status (status); ++} ++ + grub_err_t + grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) +@@ -228,6 +274,8 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + grub_efi_handle_t tpm_handle; + grub_efi_uint8_t protocol_version; + ++ grub_cc_log_event(buf, size, pcr, description); ++ + if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) + return 0; + +diff --git a/include/grub/efi/cc.h b/include/grub/efi/cc.h +new file mode 100644 +index 0000000000..8960306890 +--- /dev/null ++++ b/include/grub/efi/cc.h +@@ -0,0 +1,151 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_EFI_CC_H ++#define GRUB_EFI_CC_H 1 ++ ++#include ++#include ++#include ++ ++#define GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID \ ++ { 0x96751a3d, 0x72f4, 0x41a6, \ ++ { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b } \ ++ }; ++ ++struct grub_efi_cc_version ++{ ++ grub_efi_uint8_t Major; ++ grub_efi_uint8_t Minor; ++}; ++typedef struct grub_efi_cc_version grub_efi_cc_version_t; ++ ++/* EFI_CC Type/SubType definition. */ ++#define GRUB_EFI_CC_TYPE_NONE 0 ++#define GRUB_EFI_CC_TYPE_SEV 1 ++#define GRUB_EFI_CC_TYPE_TDX 2 ++ ++struct grub_efi_cc_type ++{ ++ grub_efi_uint8_t Type; ++ grub_efi_uint8_t SubType; ++}; ++typedef struct grub_efi_cc_type grub_efi_cc_type_t; ++ ++typedef grub_efi_uint32_t grub_efi_cc_event_log_bitmap_t; ++typedef grub_efi_uint32_t grub_efi_cc_event_log_format_t; ++typedef grub_efi_uint32_t grub_efi_cc_event_algorithm_bitmap_t; ++typedef grub_efi_uint32_t grub_efi_cc_mr_index_t; ++ ++/* Intel TDX measure register index. */ ++#define GRUB_TDX_MR_INDEX_MRTD 0 ++#define GRUB_TDX_MR_INDEX_RTMR0 1 ++#define GRUB_TDX_MR_INDEX_RTMR1 2 ++#define GRUB_TDX_MR_INDEX_RTMR2 3 ++#define GRUB_TDX_MR_INDEX_RTMR3 4 ++ ++#define GRUB_EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002 ++#define GRUB_EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004 ++#define GRUB_EFI_CC_EVENT_HEADER_VERSION 1 ++ ++struct grub_efi_cc_event_header ++{ ++ /* Size of the event header itself (sizeof(EFI_TD_EVENT_HEADER)). */ ++ grub_efi_uint32_t HeaderSize; ++ ++ /* ++ * Header version. For this version of this specification, ++ * the value shall be 1. ++ */ ++ grub_efi_uint16_t HeaderVersion; ++ ++ /* Index of the MR that shall be extended. */ ++ grub_efi_cc_mr_index_t MrIndex; ++ ++ /* Type of the event that shall be extended (and optionally logged). */ ++ grub_efi_uint32_t EventType; ++} GRUB_PACKED; ++typedef struct grub_efi_cc_event_header grub_efi_cc_event_header_t; ++ ++struct grub_efi_cc_event ++{ ++ /* Total size of the event including the Size component, the header and the Event data. */ ++ grub_efi_uint32_t Size; ++ grub_efi_cc_event_header_t Header; ++ grub_efi_uint8_t Event[0]; ++} GRUB_PACKED; ++typedef struct grub_efi_cc_event grub_efi_cc_event_t; ++ ++struct grub_efi_cc_boot_service_capability ++{ ++ /* Allocated size of the structure. */ ++ grub_efi_uint8_t Size; ++ ++ /* ++ * Version of the grub_efi_cc_boot_service_capability_t structure itself. ++ * For this version of the protocol, the Major version shall be set to 1 ++ * and the Minor version shall be set to 1. ++ */ ++ grub_efi_cc_version_t StructureVersion; ++ ++ /* ++ * Version of the EFI TD protocol. ++ * For this version of the protocol, the Major version shall be set to 1 ++ * and the Minor version shall be set to 1. ++ */ ++ grub_efi_cc_version_t ProtocolVersion; ++ ++ /* Supported hash algorithms. */ ++ grub_efi_cc_event_algorithm_bitmap_t HashAlgorithmBitmap; ++ ++ /* Bitmap of supported event log formats. */ ++ grub_efi_cc_event_log_bitmap_t SupportedEventLogs; ++ ++ /* Indicates the CC type. */ ++ grub_efi_cc_type_t CcType; ++}; ++typedef struct grub_efi_cc_boot_service_capability grub_efi_cc_boot_service_capability_t; ++ ++struct grub_efi_cc_protocol ++{ ++ grub_efi_status_t ++ (*get_capability) (struct grub_efi_cc_protocol *this, ++ grub_efi_cc_boot_service_capability_t *ProtocolCapability); ++ ++ grub_efi_status_t ++ (*get_event_log) (struct grub_efi_cc_protocol *this, ++ grub_efi_cc_event_log_format_t EventLogFormat, ++ grub_efi_physical_address_t *EventLogLocation, ++ grub_efi_physical_address_t *EventLogLastEntry, ++ grub_efi_boolean_t *EventLogTruncated); ++ ++ grub_efi_status_t ++ (*hash_log_extend_event) (struct grub_efi_cc_protocol *this, ++ grub_efi_uint64_t Flags, ++ grub_efi_physical_address_t DataToHash, ++ grub_efi_uint64_t DataToHashLen, ++ grub_efi_cc_event_t *EfiCcEvent); ++ ++ grub_efi_status_t ++ (*map_pcr_to_mr_index) (struct grub_efi_cc_protocol *this, ++ grub_efi_uint32_t PcrIndex, ++ grub_efi_cc_mr_index_t *MrIndex); ++}; ++typedef struct grub_efi_cc_protocol grub_efi_cc_protocol_t; ++ ++#endif diff --git a/0279-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch b/0279-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch new file mode 100644 index 0000000..e0dd347 --- /dev/null +++ b/0279-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Wed, 3 Aug 2022 19:45:33 +0800 +Subject: [PATCH] font: Reject glyphs exceeds font->max_glyph_width or + font->max_glyph_height + +Check glyph's width and height against limits specified in font's +metadata. Reject the glyph (and font) if such limits are exceeded. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 5760fcfd466cc757540ea0d591bad6a08caeaa16) +--- + grub-core/font/font.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index d09bb38d89..2f09a4a55b 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -760,7 +760,9 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) + || read_be_uint16 (font->file, &height) != 0 + || read_be_int16 (font->file, &xoff) != 0 + || read_be_int16 (font->file, &yoff) != 0 +- || read_be_int16 (font->file, &dwidth) != 0) ++ || read_be_int16 (font->file, &dwidth) != 0 ++ || width > font->max_char_width ++ || height > font->max_char_height) + { + remove_font (font); + return 0; diff --git a/0279-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch b/0279-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch deleted file mode 100644 index eff155d..0000000 --- a/0279-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: dann frazier -Date: Thu, 25 Aug 2022 17:08:09 -0600 -Subject: [PATCH] linuxefi: Invalidate i-cache before starting the kernel - -We need to flush the memory range of the code we are about to execute -from the instruction cache before we can safely execute it. Not doing -so appears to be the source of rare synchronous exceptions a user -is seeing on a Cortex-A72-based platform while executing the Linux EFI -stub. Notably they seem to correlate with an instruction on a cache -line boundary. - -Signed-off-by: dann frazier ---- - grub-core/loader/efi/linux.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c -index 277f352e0c..e413bdcc23 100644 ---- a/grub-core/loader/efi/linux.c -+++ b/grub-core/loader/efi/linux.c -@@ -16,6 +16,7 @@ - * along with GRUB. If not, see . - */ - -+#include - #include - #include - #include -@@ -210,6 +211,9 @@ grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size, - asm volatile ("cli"); - #endif - -+ /* Invalidate the instruction cache */ -+ grub_arch_sync_caches((void *)kernel_addr, kernel_size); -+ - hf = (handover_func)((char *)kernel_addr + handover_offset + offset); - hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); - diff --git a/0280-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch b/0280-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch new file mode 100644 index 0000000..b5f10f6 --- /dev/null +++ b/0280-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 5 Aug 2022 00:51:20 +0800 +Subject: [PATCH] font: Fix size overflow in grub_font_get_glyph_internal() + +The length of memory allocation and file read may overflow. This patch +fixes the problem by using safemath macros. + +There is a lot of code repetition like "(x * y + 7) / 8". It is unsafe +if overflow happens. This patch introduces grub_video_bitmap_calc_1bpp_bufsz(). +It is safe replacement for such code. It has safemath-like prototype. + +This patch also introduces grub_cast(value, pointer), it casts value to +typeof(*pointer) then store the value to *pointer. It returns true when +overflow occurs or false if there is no overflow. The semantics of arguments +and return value are designed to be consistent with other safemath macros. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 941d10ad6f1dcbd12fb613002249e29ba035f985) +--- + grub-core/font/font.c | 17 +++++++++++++---- + include/grub/bitmap.h | 18 ++++++++++++++++++ + include/grub/safemath.h | 2 ++ + 3 files changed, 33 insertions(+), 4 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 2f09a4a55b..6a3fbebbd8 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -739,7 +739,8 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) + grub_int16_t xoff; + grub_int16_t yoff; + grub_int16_t dwidth; +- int len; ++ grub_ssize_t len; ++ grub_size_t sz; + + if (index_entry->glyph) + /* Return cached glyph. */ +@@ -768,9 +769,17 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) + return 0; + } + +- len = (width * height + 7) / 8; +- glyph = grub_malloc (sizeof (struct grub_font_glyph) + len); +- if (!glyph) ++ /* Calculate real struct size of current glyph. */ ++ if (grub_video_bitmap_calc_1bpp_bufsz (width, height, &len) || ++ grub_add (sizeof (struct grub_font_glyph), len, &sz)) ++ { ++ remove_font (font); ++ return 0; ++ } ++ ++ /* Allocate and initialize the glyph struct. */ ++ glyph = grub_malloc (sz); ++ if (glyph == NULL) + { + remove_font (font); + return 0; +diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h +index 5728f8ca3a..0d9603f619 100644 +--- a/include/grub/bitmap.h ++++ b/include/grub/bitmap.h +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + struct grub_video_bitmap + { +@@ -79,6 +80,23 @@ grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap) + return bitmap->mode_info.height; + } + ++/* ++ * Calculate and store the size of data buffer of 1bit bitmap in result. ++ * Equivalent to "*result = (width * height + 7) / 8" if no overflow occurs. ++ * Return true when overflow occurs or false if there is no overflow. ++ * This function is intentionally implemented as a macro instead of ++ * an inline function. Although a bit awkward, it preserves data types for ++ * safemath macros and reduces macro side effects as much as possible. ++ * ++ * XXX: Will report false overflow if width * height > UINT64_MAX. ++ */ ++#define grub_video_bitmap_calc_1bpp_bufsz(width, height, result) \ ++({ \ ++ grub_uint64_t _bitmap_pixels; \ ++ grub_mul ((width), (height), &_bitmap_pixels) ? 1 : \ ++ grub_cast (_bitmap_pixels / GRUB_CHAR_BIT + !!(_bitmap_pixels % GRUB_CHAR_BIT), (result)); \ ++}) ++ + void EXPORT_FUNC (grub_video_bitmap_get_mode_info) (struct grub_video_bitmap *bitmap, + struct grub_video_mode_info *mode_info); + +diff --git a/include/grub/safemath.h b/include/grub/safemath.h +index c17b89bba1..bb0f826de1 100644 +--- a/include/grub/safemath.h ++++ b/include/grub/safemath.h +@@ -30,6 +30,8 @@ + #define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res) + #define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res) + ++#define grub_cast(a, res) grub_add ((a), 0, (res)) ++ + #else + #error gcc 5.1 or newer or clang 3.8 or newer is required + #endif diff --git a/0280-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch b/0280-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch deleted file mode 100644 index 0079750..0000000 --- a/0280-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 11 Oct 2022 17:00:50 -0400 -Subject: [PATCH] x86-efi: Fix an incorrect array size in kernel allocation - -In 81a6ebf62bbe166ddc968463df2e8bd481bf697c ("efi: split allocation -policy for kernel vs initrd memories."), I introduced a split in the -kernel allocator to allow for different dynamic policies for the kernel -and the initrd allocations. - -Unfortunately, that change increased the size of the policy data used to -make decisions, but did not change the size of the temporary storage we -use to back it up and restore. This results in some of .data getting -clobbered at runtime, and hilarity ensues. - -This patch makes the size of the backup storage be based on the size of -the initial policy data. - -Signed-off-by: Peter Jones ---- - grub-core/loader/i386/efi/linux.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index ac5ef50bdb..9854b0defa 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -92,7 +92,7 @@ static struct allocation_choice max_addresses[] = - { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - { NO_MEM, 0, 0 } - }; --static struct allocation_choice saved_addresses[4]; -+static struct allocation_choice saved_addresses[sizeof(max_addresses) / sizeof(max_addresses[0])]; - - #define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses)) - #define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses)) diff --git a/0281-commands-efi-tpm-Refine-the-status-of-log-event.patch b/0281-commands-efi-tpm-Refine-the-status-of-log-event.patch deleted file mode 100644 index 896e49b..0000000 --- a/0281-commands-efi-tpm-Refine-the-status-of-log-event.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lu Ken -Date: Wed, 13 Jul 2022 10:06:10 +0800 -Subject: [PATCH] commands/efi/tpm: Refine the status of log event - -1. Use macro GRUB_ERR_NONE instead of hard code 0. -2. Keep lowercase of the first char for the status string of log event. - -Signed-off-by: Lu Ken -Reviewed-by: Daniel Kiper -(cherry picked from commit 922898573e37135f5dedc16f3e15a1d1d4c53f8a) ---- - grub-core/commands/efi/tpm.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c -index a97d85368a..7acf510499 100644 ---- a/grub-core/commands/efi/tpm.c -+++ b/grub-core/commands/efi/tpm.c -@@ -135,17 +135,17 @@ grub_efi_log_event_status (grub_efi_status_t status) - switch (status) - { - case GRUB_EFI_SUCCESS: -- return 0; -+ return GRUB_ERR_NONE; - case GRUB_EFI_DEVICE_ERROR: -- return grub_error (GRUB_ERR_IO, N_("Command failed")); -+ return grub_error (GRUB_ERR_IO, N_("command failed")); - case GRUB_EFI_INVALID_PARAMETER: -- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter")); -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid parameter")); - case GRUB_EFI_BUFFER_TOO_SMALL: -- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small")); -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("output buffer too small")); - case GRUB_EFI_NOT_FOUND: - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable")); - default: -- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error")); -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("unknown TPM error")); - } - } - diff --git a/0281-font-Fix-several-integer-overflows-in-grub_font_cons.patch b/0281-font-Fix-several-integer-overflows-in-grub_font_cons.patch new file mode 100644 index 0000000..3c76eb4 --- /dev/null +++ b/0281-font-Fix-several-integer-overflows-in-grub_font_cons.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 5 Aug 2022 01:58:27 +0800 +Subject: [PATCH] font: Fix several integer overflows in + grub_font_construct_glyph() + +This patch fixes several integer overflows in grub_font_construct_glyph(). +Glyphs of invalid size, zero or leading to an overflow, are rejected. +The inconsistency between "glyph" and "max_glyph_size" when grub_malloc() +returns NULL is fixed too. + +Fixes: CVE-2022-2601 + +Reported-by: Zhang Boyang +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit b1805f251b31a9d3cfae5c3572ddfa630145dbbf) +--- + grub-core/font/font.c | 29 +++++++++++++++++------------ + 1 file changed, 17 insertions(+), 12 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 6a3fbebbd8..1fa181d4ca 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -1517,6 +1517,7 @@ grub_font_construct_glyph (grub_font_t hinted_font, + struct grub_video_signed_rect bounds; + static struct grub_font_glyph *glyph = 0; + static grub_size_t max_glyph_size = 0; ++ grub_size_t cur_glyph_size; + + ensure_comb_space (glyph_id); + +@@ -1533,29 +1534,33 @@ grub_font_construct_glyph (grub_font_t hinted_font, + if (!glyph_id->ncomb && !glyph_id->attributes) + return main_glyph; + +- if (max_glyph_size < sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) ++ if (grub_video_bitmap_calc_1bpp_bufsz (bounds.width, bounds.height, &cur_glyph_size) || ++ grub_add (sizeof (*glyph), cur_glyph_size, &cur_glyph_size)) ++ return main_glyph; ++ ++ if (max_glyph_size < cur_glyph_size) + { + grub_free (glyph); +- max_glyph_size = (sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) * 2; +- if (max_glyph_size < 8) +- max_glyph_size = 8; +- glyph = grub_malloc (max_glyph_size); ++ if (grub_mul (cur_glyph_size, 2, &max_glyph_size)) ++ max_glyph_size = 0; ++ glyph = max_glyph_size > 0 ? grub_malloc (max_glyph_size) : NULL; + } + if (!glyph) + { ++ max_glyph_size = 0; + grub_errno = GRUB_ERR_NONE; + return main_glyph; + } + +- grub_memset (glyph, 0, sizeof (*glyph) +- + (bounds.width * bounds.height +- + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT); ++ grub_memset (glyph, 0, cur_glyph_size); + + glyph->font = main_glyph->font; +- glyph->width = bounds.width; +- glyph->height = bounds.height; +- glyph->offset_x = bounds.x; +- glyph->offset_y = bounds.y; ++ if (bounds.width == 0 || bounds.height == 0 || ++ grub_cast (bounds.width, &glyph->width) || ++ grub_cast (bounds.height, &glyph->height) || ++ grub_cast (bounds.x, &glyph->offset_x) || ++ grub_cast (bounds.y, &glyph->offset_y)) ++ return main_glyph; + + if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR) + grub_font_blit_glyph_mirror (glyph, main_glyph, diff --git a/0282-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch b/0282-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch deleted file mode 100644 index e04dcbc..0000000 --- a/0282-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lu Ken -Date: Wed, 13 Jul 2022 10:06:11 +0800 -Subject: [PATCH] commands/efi/tpm: Use grub_strcpy() instead of grub_memcpy() - -The event description is a string, so using grub_strcpy() is cleaner than -using grub_memcpy(). - -Signed-off-by: Lu Ken -Reviewed-by: Daniel Kiper -(cherry picked from commit ef8679b645a63eb9eb191bb9539d7d25a9d6ff3b) ---- - grub-core/commands/efi/tpm.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c -index 7acf510499..bb59599721 100644 ---- a/grub-core/commands/efi/tpm.c -+++ b/grub-core/commands/efi/tpm.c -@@ -175,7 +175,7 @@ grub_tpm1_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, - event->PCRIndex = pcr; - event->EventType = EV_IPL; - event->EventSize = grub_strlen (description) + 1; -- grub_memcpy (event->Event, description, event->EventSize); -+ grub_strcpy ((char *) event->Event, description); - - algorithm = TCG_ALG_SHA; - status = efi_call_7 (tpm->log_extend_event, tpm, (grub_addr_t) buf, (grub_uint64_t) size, -@@ -212,7 +212,7 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, - event->Header.EventType = EV_IPL; - event->Size = - sizeof (*event) - sizeof (event->Event) + grub_strlen (description) + 1; -- grub_memcpy (event->Event, description, grub_strlen (description) + 1); -+ grub_strcpy ((char *) event->Event, description); - - status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, (grub_addr_t) buf, - (grub_uint64_t) size, event); diff --git a/0282-font-Remove-grub_font_dup_glyph.patch b/0282-font-Remove-grub_font_dup_glyph.patch new file mode 100644 index 0000000..4c3db92 --- /dev/null +++ b/0282-font-Remove-grub_font_dup_glyph.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 5 Aug 2022 02:13:29 +0800 +Subject: [PATCH] font: Remove grub_font_dup_glyph() + +Remove grub_font_dup_glyph() since nobody is using it since 2013, and +I'm too lazy to fix the integer overflow problem in it. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 25ad31c19c331aaa2dbd9bd2b2e2655de5766a9d) +--- + grub-core/font/font.c | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 1fa181d4ca..a115a63b0c 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -1055,20 +1055,6 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code) + return best_glyph; + } + +-#if 0 +-static struct grub_font_glyph * +-grub_font_dup_glyph (struct grub_font_glyph *glyph) +-{ +- static struct grub_font_glyph *ret; +- ret = grub_malloc (sizeof (*ret) + (glyph->width * glyph->height + 7) / 8); +- if (!ret) +- return NULL; +- grub_memcpy (ret, glyph, sizeof (*ret) +- + (glyph->width * glyph->height + 7) / 8); +- return ret; +-} +-#endif +- + /* FIXME: suboptimal. */ + static void + grub_font_blit_glyph (struct grub_font_glyph *target, diff --git a/0283-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch b/0283-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch deleted file mode 100644 index 610c81a..0000000 --- a/0283-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch +++ /dev/null @@ -1,258 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lu Ken -Date: Wed, 13 Jul 2022 10:06:12 +0800 -Subject: [PATCH] efi/tpm: Add EFI_CC_MEASUREMENT_PROTOCOL support - -The EFI_CC_MEASUREMENT_PROTOCOL abstracts the measurement for virtual firmware -in confidential computing environment. It is similar to the EFI_TCG2_PROTOCOL. -It was proposed by Intel and ARM and approved by UEFI organization. - -It is defined in Intel GHCI specification: https://cdrdv2.intel.com/v1/dl/getContent/726790 . -The EDKII header file is available at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/CcMeasurement.h . - -Signed-off-by: Lu Ken -Reviewed-by: Daniel Kiper -(cherry picked from commit 4c76565b6cb885b7e144dc27f3612066844e2d19) ---- - grub-core/commands/efi/tpm.c | 48 ++++++++++++++ - include/grub/efi/cc.h | 151 +++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 199 insertions(+) - create mode 100644 include/grub/efi/cc.h - -diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c -index bb59599721..ae09c1bf8b 100644 ---- a/grub-core/commands/efi/tpm.c -+++ b/grub-core/commands/efi/tpm.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -31,6 +32,7 @@ typedef TCG_PCR_EVENT grub_tpm_event_t; - - static grub_efi_guid_t tpm_guid = EFI_TPM_GUID; - static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID; -+static grub_efi_guid_t cc_measurement_guid = GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID; - - static grub_efi_handle_t *grub_tpm_handle; - static grub_uint8_t grub_tpm_version; -@@ -221,6 +223,50 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, - return grub_efi_log_event_status (status); - } - -+static void -+grub_cc_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, -+ const char *description) -+{ -+ grub_efi_cc_event_t *event; -+ grub_efi_status_t status; -+ grub_efi_cc_protocol_t *cc; -+ grub_efi_cc_mr_index_t mr; -+ -+ cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL); -+ if (cc == NULL) -+ return; -+ -+ status = efi_call_3 (cc->map_pcr_to_mr_index, cc, pcr, &mr); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_efi_log_event_status (status); -+ return; -+ } -+ -+ event = grub_zalloc (sizeof (grub_efi_cc_event_t) + -+ grub_strlen (description) + 1); -+ if (event == NULL) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate CC event buffer")); -+ return; -+ } -+ -+ event->Header.HeaderSize = sizeof (grub_efi_cc_event_header_t); -+ event->Header.HeaderVersion = GRUB_EFI_CC_EVENT_HEADER_VERSION; -+ event->Header.MrIndex = mr; -+ event->Header.EventType = EV_IPL; -+ event->Size = sizeof (*event) + grub_strlen (description) + 1; -+ grub_strcpy ((char *) event->Event, description); -+ -+ status = efi_call_5 (cc->hash_log_extend_event, cc, 0, -+ (grub_efi_physical_address_t)(grub_addr_t) buf, -+ (grub_efi_uint64_t) size, event); -+ grub_free (event); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ grub_efi_log_event_status (status); -+} -+ - grub_err_t - grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, - const char *description) -@@ -228,6 +274,8 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, - grub_efi_handle_t tpm_handle; - grub_efi_uint8_t protocol_version; - -+ grub_cc_log_event(buf, size, pcr, description); -+ - if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) - return 0; - -diff --git a/include/grub/efi/cc.h b/include/grub/efi/cc.h -new file mode 100644 -index 0000000000..8960306890 ---- /dev/null -+++ b/include/grub/efi/cc.h -@@ -0,0 +1,151 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2022 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_EFI_CC_H -+#define GRUB_EFI_CC_H 1 -+ -+#include -+#include -+#include -+ -+#define GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID \ -+ { 0x96751a3d, 0x72f4, 0x41a6, \ -+ { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b } \ -+ }; -+ -+struct grub_efi_cc_version -+{ -+ grub_efi_uint8_t Major; -+ grub_efi_uint8_t Minor; -+}; -+typedef struct grub_efi_cc_version grub_efi_cc_version_t; -+ -+/* EFI_CC Type/SubType definition. */ -+#define GRUB_EFI_CC_TYPE_NONE 0 -+#define GRUB_EFI_CC_TYPE_SEV 1 -+#define GRUB_EFI_CC_TYPE_TDX 2 -+ -+struct grub_efi_cc_type -+{ -+ grub_efi_uint8_t Type; -+ grub_efi_uint8_t SubType; -+}; -+typedef struct grub_efi_cc_type grub_efi_cc_type_t; -+ -+typedef grub_efi_uint32_t grub_efi_cc_event_log_bitmap_t; -+typedef grub_efi_uint32_t grub_efi_cc_event_log_format_t; -+typedef grub_efi_uint32_t grub_efi_cc_event_algorithm_bitmap_t; -+typedef grub_efi_uint32_t grub_efi_cc_mr_index_t; -+ -+/* Intel TDX measure register index. */ -+#define GRUB_TDX_MR_INDEX_MRTD 0 -+#define GRUB_TDX_MR_INDEX_RTMR0 1 -+#define GRUB_TDX_MR_INDEX_RTMR1 2 -+#define GRUB_TDX_MR_INDEX_RTMR2 3 -+#define GRUB_TDX_MR_INDEX_RTMR3 4 -+ -+#define GRUB_EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002 -+#define GRUB_EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004 -+#define GRUB_EFI_CC_EVENT_HEADER_VERSION 1 -+ -+struct grub_efi_cc_event_header -+{ -+ /* Size of the event header itself (sizeof(EFI_TD_EVENT_HEADER)). */ -+ grub_efi_uint32_t HeaderSize; -+ -+ /* -+ * Header version. For this version of this specification, -+ * the value shall be 1. -+ */ -+ grub_efi_uint16_t HeaderVersion; -+ -+ /* Index of the MR that shall be extended. */ -+ grub_efi_cc_mr_index_t MrIndex; -+ -+ /* Type of the event that shall be extended (and optionally logged). */ -+ grub_efi_uint32_t EventType; -+} GRUB_PACKED; -+typedef struct grub_efi_cc_event_header grub_efi_cc_event_header_t; -+ -+struct grub_efi_cc_event -+{ -+ /* Total size of the event including the Size component, the header and the Event data. */ -+ grub_efi_uint32_t Size; -+ grub_efi_cc_event_header_t Header; -+ grub_efi_uint8_t Event[0]; -+} GRUB_PACKED; -+typedef struct grub_efi_cc_event grub_efi_cc_event_t; -+ -+struct grub_efi_cc_boot_service_capability -+{ -+ /* Allocated size of the structure. */ -+ grub_efi_uint8_t Size; -+ -+ /* -+ * Version of the grub_efi_cc_boot_service_capability_t structure itself. -+ * For this version of the protocol, the Major version shall be set to 1 -+ * and the Minor version shall be set to 1. -+ */ -+ grub_efi_cc_version_t StructureVersion; -+ -+ /* -+ * Version of the EFI TD protocol. -+ * For this version of the protocol, the Major version shall be set to 1 -+ * and the Minor version shall be set to 1. -+ */ -+ grub_efi_cc_version_t ProtocolVersion; -+ -+ /* Supported hash algorithms. */ -+ grub_efi_cc_event_algorithm_bitmap_t HashAlgorithmBitmap; -+ -+ /* Bitmap of supported event log formats. */ -+ grub_efi_cc_event_log_bitmap_t SupportedEventLogs; -+ -+ /* Indicates the CC type. */ -+ grub_efi_cc_type_t CcType; -+}; -+typedef struct grub_efi_cc_boot_service_capability grub_efi_cc_boot_service_capability_t; -+ -+struct grub_efi_cc_protocol -+{ -+ grub_efi_status_t -+ (*get_capability) (struct grub_efi_cc_protocol *this, -+ grub_efi_cc_boot_service_capability_t *ProtocolCapability); -+ -+ grub_efi_status_t -+ (*get_event_log) (struct grub_efi_cc_protocol *this, -+ grub_efi_cc_event_log_format_t EventLogFormat, -+ grub_efi_physical_address_t *EventLogLocation, -+ grub_efi_physical_address_t *EventLogLastEntry, -+ grub_efi_boolean_t *EventLogTruncated); -+ -+ grub_efi_status_t -+ (*hash_log_extend_event) (struct grub_efi_cc_protocol *this, -+ grub_efi_uint64_t Flags, -+ grub_efi_physical_address_t DataToHash, -+ grub_efi_uint64_t DataToHashLen, -+ grub_efi_cc_event_t *EfiCcEvent); -+ -+ grub_efi_status_t -+ (*map_pcr_to_mr_index) (struct grub_efi_cc_protocol *this, -+ grub_efi_uint32_t PcrIndex, -+ grub_efi_cc_mr_index_t *MrIndex); -+}; -+typedef struct grub_efi_cc_protocol grub_efi_cc_protocol_t; -+ -+#endif diff --git a/0283-font-Fix-integer-overflow-in-ensure_comb_space.patch b/0283-font-Fix-integer-overflow-in-ensure_comb_space.patch new file mode 100644 index 0000000..6b73038 --- /dev/null +++ b/0283-font-Fix-integer-overflow-in-ensure_comb_space.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 5 Aug 2022 02:27:05 +0800 +Subject: [PATCH] font: Fix integer overflow in ensure_comb_space() + +In fact it can't overflow at all because glyph_id->ncomb is only 8-bit +wide. But let's keep safe if somebody changes the width of glyph_id->ncomb +in the future. This patch also fixes the inconsistency between +render_max_comb_glyphs and render_combining_glyphs when grub_malloc() +returns NULL. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit b2740b7e4a03bb8331d48b54b119afea76bb9d5f) +--- + grub-core/font/font.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index a115a63b0c..d0e6340404 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -1468,14 +1468,18 @@ ensure_comb_space (const struct grub_unicode_glyph *glyph_id) + if (glyph_id->ncomb <= render_max_comb_glyphs) + return; + +- render_max_comb_glyphs = 2 * glyph_id->ncomb; +- if (render_max_comb_glyphs < 8) ++ if (grub_mul (glyph_id->ncomb, 2, &render_max_comb_glyphs)) ++ render_max_comb_glyphs = 0; ++ if (render_max_comb_glyphs > 0 && render_max_comb_glyphs < 8) + render_max_comb_glyphs = 8; + grub_free (render_combining_glyphs); +- render_combining_glyphs = grub_malloc (render_max_comb_glyphs +- * sizeof (render_combining_glyphs[0])); ++ render_combining_glyphs = (render_max_comb_glyphs > 0) ? ++ grub_calloc (render_max_comb_glyphs, sizeof (render_combining_glyphs[0])) : NULL; + if (!render_combining_glyphs) +- grub_errno = 0; ++ { ++ render_max_comb_glyphs = 0; ++ grub_errno = GRUB_ERR_NONE; ++ } + } + + int diff --git a/0284-font-Fix-integer-overflow-in-BMP-index.patch b/0284-font-Fix-integer-overflow-in-BMP-index.patch new file mode 100644 index 0000000..5e10699 --- /dev/null +++ b/0284-font-Fix-integer-overflow-in-BMP-index.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Mon, 15 Aug 2022 02:04:58 +0800 +Subject: [PATCH] font: Fix integer overflow in BMP index + +The BMP index (font->bmp_idx) is designed as a reverse lookup table of +char entries (font->char_index), in order to speed up lookups for BMP +chars (i.e. code < 0x10000). The values in BMP index are the subscripts +of the corresponding char entries, stored in grub_uint16_t, while 0xffff +means not found. + +This patch fixes the problem of large subscript truncated to grub_uint16_t, +leading BMP index to return wrong char entry or report false miss. The +code now checks for bounds and uses BMP index as a hint, and fallbacks +to binary-search if necessary. + +On the occasion add a comment about BMP index is initialized to 0xffff. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit afda8b60ba0712abe01ae1e64c5f7a067a0e6492) +--- + grub-core/font/font.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index d0e6340404..b208a28717 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -300,6 +300,8 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct + font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t)); + if (!font->bmp_idx) + return 1; ++ ++ /* Init the BMP index array to 0xffff. */ + grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t)); + + +@@ -328,7 +330,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct + return 1; + } + +- if (entry->code < 0x10000) ++ if (entry->code < 0x10000 && i < 0xffff) + font->bmp_idx[entry->code] = i; + + last_code = entry->code; +@@ -696,9 +698,12 @@ find_glyph (const grub_font_t font, grub_uint32_t code) + /* Use BMP index if possible. */ + if (code < 0x10000 && font->bmp_idx) + { +- if (font->bmp_idx[code] == 0xffff) +- return 0; +- return &table[font->bmp_idx[code]]; ++ if (font->bmp_idx[code] < 0xffff) ++ return &table[font->bmp_idx[code]]; ++ /* ++ * When we are here then lookup in BMP index result in miss, ++ * fallthough to binary-search. ++ */ + } + + /* Do a binary search in `char_index', which is ordered by code point. */ diff --git a/0284-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch b/0284-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch deleted file mode 100644 index e0dd347..0000000 --- a/0284-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Wed, 3 Aug 2022 19:45:33 +0800 -Subject: [PATCH] font: Reject glyphs exceeds font->max_glyph_width or - font->max_glyph_height - -Check glyph's width and height against limits specified in font's -metadata. Reject the glyph (and font) if such limits are exceeded. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 5760fcfd466cc757540ea0d591bad6a08caeaa16) ---- - grub-core/font/font.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index d09bb38d89..2f09a4a55b 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -760,7 +760,9 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) - || read_be_uint16 (font->file, &height) != 0 - || read_be_int16 (font->file, &xoff) != 0 - || read_be_int16 (font->file, &yoff) != 0 -- || read_be_int16 (font->file, &dwidth) != 0) -+ || read_be_int16 (font->file, &dwidth) != 0 -+ || width > font->max_char_width -+ || height > font->max_char_height) - { - remove_font (font); - return 0; diff --git a/0285-font-Fix-integer-underflow-in-binary-search-of-char-.patch b/0285-font-Fix-integer-underflow-in-binary-search-of-char-.patch new file mode 100644 index 0000000..e81824b --- /dev/null +++ b/0285-font-Fix-integer-underflow-in-binary-search-of-char-.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Sun, 14 Aug 2022 18:09:38 +0800 +Subject: [PATCH] font: Fix integer underflow in binary search of char index + +If search target is less than all entries in font->index then "hi" +variable is set to -1, which translates to SIZE_MAX and leads to errors. + +This patch fixes the problem by replacing the entire binary search code +with the libstdc++'s std::lower_bound() implementation. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit c140a086838e7c9af87842036f891b8393a8c4bc) +--- + grub-core/font/font.c | 40 ++++++++++++++++++++++------------------ + 1 file changed, 22 insertions(+), 18 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index b208a28717..193dfec045 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -688,12 +688,12 @@ read_be_int16 (grub_file_t file, grub_int16_t * value) + static inline struct char_index_entry * + find_glyph (const grub_font_t font, grub_uint32_t code) + { +- struct char_index_entry *table; +- grub_size_t lo; +- grub_size_t hi; +- grub_size_t mid; ++ struct char_index_entry *table, *first, *end; ++ grub_size_t len; + + table = font->char_index; ++ if (table == NULL) ++ return NULL; + + /* Use BMP index if possible. */ + if (code < 0x10000 && font->bmp_idx) +@@ -706,25 +706,29 @@ find_glyph (const grub_font_t font, grub_uint32_t code) + */ + } + +- /* Do a binary search in `char_index', which is ordered by code point. */ +- lo = 0; +- hi = font->num_chars - 1; ++ /* ++ * Do a binary search in char_index which is ordered by code point. ++ * The code below is the same as libstdc++'s std::lower_bound(). ++ */ ++ first = table; ++ len = font->num_chars; ++ end = first + len; + +- if (!table) +- return 0; +- +- while (lo <= hi) ++ while (len > 0) + { +- mid = lo + (hi - lo) / 2; +- if (code < table[mid].code) +- hi = mid - 1; +- else if (code > table[mid].code) +- lo = mid + 1; ++ grub_size_t half = len >> 1; ++ struct char_index_entry *middle = first + half; ++ ++ if (middle->code < code) ++ { ++ first = middle + 1; ++ len = len - half - 1; ++ } + else +- return &table[mid]; ++ len = half; + } + +- return 0; ++ return (first < end && first->code == code) ? first : NULL; + } + + /* Get a glyph for the Unicode character CODE in FONT. The glyph is loaded diff --git a/0285-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch b/0285-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch deleted file mode 100644 index b5f10f6..0000000 --- a/0285-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 5 Aug 2022 00:51:20 +0800 -Subject: [PATCH] font: Fix size overflow in grub_font_get_glyph_internal() - -The length of memory allocation and file read may overflow. This patch -fixes the problem by using safemath macros. - -There is a lot of code repetition like "(x * y + 7) / 8". It is unsafe -if overflow happens. This patch introduces grub_video_bitmap_calc_1bpp_bufsz(). -It is safe replacement for such code. It has safemath-like prototype. - -This patch also introduces grub_cast(value, pointer), it casts value to -typeof(*pointer) then store the value to *pointer. It returns true when -overflow occurs or false if there is no overflow. The semantics of arguments -and return value are designed to be consistent with other safemath macros. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 941d10ad6f1dcbd12fb613002249e29ba035f985) ---- - grub-core/font/font.c | 17 +++++++++++++---- - include/grub/bitmap.h | 18 ++++++++++++++++++ - include/grub/safemath.h | 2 ++ - 3 files changed, 33 insertions(+), 4 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 2f09a4a55b..6a3fbebbd8 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -739,7 +739,8 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) - grub_int16_t xoff; - grub_int16_t yoff; - grub_int16_t dwidth; -- int len; -+ grub_ssize_t len; -+ grub_size_t sz; - - if (index_entry->glyph) - /* Return cached glyph. */ -@@ -768,9 +769,17 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) - return 0; - } - -- len = (width * height + 7) / 8; -- glyph = grub_malloc (sizeof (struct grub_font_glyph) + len); -- if (!glyph) -+ /* Calculate real struct size of current glyph. */ -+ if (grub_video_bitmap_calc_1bpp_bufsz (width, height, &len) || -+ grub_add (sizeof (struct grub_font_glyph), len, &sz)) -+ { -+ remove_font (font); -+ return 0; -+ } -+ -+ /* Allocate and initialize the glyph struct. */ -+ glyph = grub_malloc (sz); -+ if (glyph == NULL) - { - remove_font (font); - return 0; -diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h -index 5728f8ca3a..0d9603f619 100644 ---- a/include/grub/bitmap.h -+++ b/include/grub/bitmap.h -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - struct grub_video_bitmap - { -@@ -79,6 +80,23 @@ grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap) - return bitmap->mode_info.height; - } - -+/* -+ * Calculate and store the size of data buffer of 1bit bitmap in result. -+ * Equivalent to "*result = (width * height + 7) / 8" if no overflow occurs. -+ * Return true when overflow occurs or false if there is no overflow. -+ * This function is intentionally implemented as a macro instead of -+ * an inline function. Although a bit awkward, it preserves data types for -+ * safemath macros and reduces macro side effects as much as possible. -+ * -+ * XXX: Will report false overflow if width * height > UINT64_MAX. -+ */ -+#define grub_video_bitmap_calc_1bpp_bufsz(width, height, result) \ -+({ \ -+ grub_uint64_t _bitmap_pixels; \ -+ grub_mul ((width), (height), &_bitmap_pixels) ? 1 : \ -+ grub_cast (_bitmap_pixels / GRUB_CHAR_BIT + !!(_bitmap_pixels % GRUB_CHAR_BIT), (result)); \ -+}) -+ - void EXPORT_FUNC (grub_video_bitmap_get_mode_info) (struct grub_video_bitmap *bitmap, - struct grub_video_mode_info *mode_info); - -diff --git a/include/grub/safemath.h b/include/grub/safemath.h -index c17b89bba1..bb0f826de1 100644 ---- a/include/grub/safemath.h -+++ b/include/grub/safemath.h -@@ -30,6 +30,8 @@ - #define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res) - #define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res) - -+#define grub_cast(a, res) grub_add ((a), 0, (res)) -+ - #else - #error gcc 5.1 or newer or clang 3.8 or newer is required - #endif diff --git a/0286-font-Fix-several-integer-overflows-in-grub_font_cons.patch b/0286-font-Fix-several-integer-overflows-in-grub_font_cons.patch deleted file mode 100644 index 3c76eb4..0000000 --- a/0286-font-Fix-several-integer-overflows-in-grub_font_cons.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 5 Aug 2022 01:58:27 +0800 -Subject: [PATCH] font: Fix several integer overflows in - grub_font_construct_glyph() - -This patch fixes several integer overflows in grub_font_construct_glyph(). -Glyphs of invalid size, zero or leading to an overflow, are rejected. -The inconsistency between "glyph" and "max_glyph_size" when grub_malloc() -returns NULL is fixed too. - -Fixes: CVE-2022-2601 - -Reported-by: Zhang Boyang -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit b1805f251b31a9d3cfae5c3572ddfa630145dbbf) ---- - grub-core/font/font.c | 29 +++++++++++++++++------------ - 1 file changed, 17 insertions(+), 12 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 6a3fbebbd8..1fa181d4ca 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -1517,6 +1517,7 @@ grub_font_construct_glyph (grub_font_t hinted_font, - struct grub_video_signed_rect bounds; - static struct grub_font_glyph *glyph = 0; - static grub_size_t max_glyph_size = 0; -+ grub_size_t cur_glyph_size; - - ensure_comb_space (glyph_id); - -@@ -1533,29 +1534,33 @@ grub_font_construct_glyph (grub_font_t hinted_font, - if (!glyph_id->ncomb && !glyph_id->attributes) - return main_glyph; - -- if (max_glyph_size < sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) -+ if (grub_video_bitmap_calc_1bpp_bufsz (bounds.width, bounds.height, &cur_glyph_size) || -+ grub_add (sizeof (*glyph), cur_glyph_size, &cur_glyph_size)) -+ return main_glyph; -+ -+ if (max_glyph_size < cur_glyph_size) - { - grub_free (glyph); -- max_glyph_size = (sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) * 2; -- if (max_glyph_size < 8) -- max_glyph_size = 8; -- glyph = grub_malloc (max_glyph_size); -+ if (grub_mul (cur_glyph_size, 2, &max_glyph_size)) -+ max_glyph_size = 0; -+ glyph = max_glyph_size > 0 ? grub_malloc (max_glyph_size) : NULL; - } - if (!glyph) - { -+ max_glyph_size = 0; - grub_errno = GRUB_ERR_NONE; - return main_glyph; - } - -- grub_memset (glyph, 0, sizeof (*glyph) -- + (bounds.width * bounds.height -- + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT); -+ grub_memset (glyph, 0, cur_glyph_size); - - glyph->font = main_glyph->font; -- glyph->width = bounds.width; -- glyph->height = bounds.height; -- glyph->offset_x = bounds.x; -- glyph->offset_y = bounds.y; -+ if (bounds.width == 0 || bounds.height == 0 || -+ grub_cast (bounds.width, &glyph->width) || -+ grub_cast (bounds.height, &glyph->height) || -+ grub_cast (bounds.x, &glyph->offset_x) || -+ grub_cast (bounds.y, &glyph->offset_y)) -+ return main_glyph; - - if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR) - grub_font_blit_glyph_mirror (glyph, main_glyph, diff --git a/0286-kern-efi-sb-Enforce-verification-of-font-files.patch b/0286-kern-efi-sb-Enforce-verification-of-font-files.patch new file mode 100644 index 0000000..1a381b0 --- /dev/null +++ b/0286-kern-efi-sb-Enforce-verification-of-font-files.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Sun, 14 Aug 2022 15:51:54 +0800 +Subject: [PATCH] kern/efi/sb: Enforce verification of font files + +As a mitigation and hardening measure enforce verification of font +files. Then only trusted font files can be load. This will reduce the +attack surface at cost of losing the ability of end-users to customize +fonts if e.g. UEFI Secure Boot is enabled. Vendors can always customize +fonts because they have ability to pack fonts into their GRUB bundles. + +This goal is achieved by: + + * Removing GRUB_FILE_TYPE_FONT from shim lock verifier's + skip-verification list. + + * Adding GRUB_FILE_TYPE_FONT to lockdown verifier's defer-auth list, + so font files must be verified by a verifier before they can be loaded. + +Suggested-by: Daniel Kiper +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 630deb8c0d8b02b670ced4b7030414bcf17aa080) +--- + grub-core/kern/efi/sb.c | 1 - + grub-core/kern/lockdown.c | 1 + + 2 files changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c +index 89c4bb3fd1..db42c2539f 100644 +--- a/grub-core/kern/efi/sb.c ++++ b/grub-core/kern/efi/sb.c +@@ -145,7 +145,6 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), + case GRUB_FILE_TYPE_PRINT_BLOCKLIST: + case GRUB_FILE_TYPE_TESTLOAD: + case GRUB_FILE_TYPE_GET_SIZE: +- case GRUB_FILE_TYPE_FONT: + case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY: + case GRUB_FILE_TYPE_CAT: + case GRUB_FILE_TYPE_HEXCAT: +diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c +index 0bc70fd42d..af6d493cd3 100644 +--- a/grub-core/kern/lockdown.c ++++ b/grub-core/kern/lockdown.c +@@ -51,6 +51,7 @@ lockdown_verifier_init (grub_file_t io __attribute__ ((unused)), + case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: + case GRUB_FILE_TYPE_ACPI_TABLE: + case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: ++ case GRUB_FILE_TYPE_FONT: + *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; + + /* Fall through. */ diff --git a/0287-fbutil-Fix-integer-overflow.patch b/0287-fbutil-Fix-integer-overflow.patch new file mode 100644 index 0000000..4d32dbd --- /dev/null +++ b/0287-fbutil-Fix-integer-overflow.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Tue, 6 Sep 2022 03:03:21 +0800 +Subject: [PATCH] fbutil: Fix integer overflow + +Expressions like u64 = u32 * u32 are unsafe because their products are +truncated to u32 even if left hand side is u64. This patch fixes all +problems like that one in fbutil. + +To get right result not only left hand side have to be u64 but it's also +necessary to cast at least one of the operands of all leaf operators of +right hand side to u64, e.g. u64 = u32 * u32 + u32 * u32 should be +u64 = (u64)u32 * u32 + (u64)u32 * u32. + +For 1-bit bitmaps grub_uint64_t have to be used. It's safe because any +combination of values in (grub_uint64_t)u32 * u32 + u32 expression will +not overflow grub_uint64_t. + +Other expressions like ptr + u32 * u32 + u32 * u32 are also vulnerable. +They should be ptr + (grub_addr_t)u32 * u32 + (grub_addr_t)u32 * u32. + +This patch also adds a comment to grub_video_fb_get_video_ptr() which +says it's arguments must be valid and no sanity check is performed +(like its siblings in grub-core/video/fb/fbutil.c). + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 50a11a81bc842c58962244a2dc86bbd31a426e12) +--- + grub-core/video/fb/fbutil.c | 4 ++-- + include/grub/fbutil.h | 13 +++++++++---- + 2 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/grub-core/video/fb/fbutil.c b/grub-core/video/fb/fbutil.c +index b98bb51fe8..25ef39f47d 100644 +--- a/grub-core/video/fb/fbutil.c ++++ b/grub-core/video/fb/fbutil.c +@@ -67,7 +67,7 @@ get_pixel (struct grub_video_fbblit_info *source, + case 1: + if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) + { +- int bit_index = y * source->mode_info->width + x; ++ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x; + grub_uint8_t *ptr = source->data + bit_index / 8; + int bit_pos = 7 - bit_index % 8; + color = (*ptr >> bit_pos) & 0x01; +@@ -138,7 +138,7 @@ set_pixel (struct grub_video_fbblit_info *source, + case 1: + if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) + { +- int bit_index = y * source->mode_info->width + x; ++ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x; + grub_uint8_t *ptr = source->data + bit_index / 8; + int bit_pos = 7 - bit_index % 8; + *ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos); +diff --git a/include/grub/fbutil.h b/include/grub/fbutil.h +index 4205eb917f..78a1ab3b45 100644 +--- a/include/grub/fbutil.h ++++ b/include/grub/fbutil.h +@@ -31,14 +31,19 @@ struct grub_video_fbblit_info + grub_uint8_t *data; + }; + +-/* Don't use for 1-bit bitmaps, addressing needs to be done at the bit level +- and it doesn't make sense, in general, to ask for a pointer +- to a particular pixel's data. */ ++/* ++ * Don't use for 1-bit bitmaps, addressing needs to be done at the bit level ++ * and it doesn't make sense, in general, to ask for a pointer ++ * to a particular pixel's data. ++ * ++ * This function assumes that bounds checking has been done in previous phase ++ * and they are opted out in here. ++ */ + static inline void * + grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, + unsigned int x, unsigned int y) + { +- return source->data + y * source->mode_info->pitch + x * source->mode_info->bytes_per_pixel; ++ return source->data + (grub_addr_t) y * source->mode_info->pitch + (grub_addr_t) x * source->mode_info->bytes_per_pixel; + } + + /* Advance pointer by VAL bytes. If there is no unaligned access available, diff --git a/0287-font-Remove-grub_font_dup_glyph.patch b/0287-font-Remove-grub_font_dup_glyph.patch deleted file mode 100644 index 4c3db92..0000000 --- a/0287-font-Remove-grub_font_dup_glyph.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 5 Aug 2022 02:13:29 +0800 -Subject: [PATCH] font: Remove grub_font_dup_glyph() - -Remove grub_font_dup_glyph() since nobody is using it since 2013, and -I'm too lazy to fix the integer overflow problem in it. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 25ad31c19c331aaa2dbd9bd2b2e2655de5766a9d) ---- - grub-core/font/font.c | 14 -------------- - 1 file changed, 14 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 1fa181d4ca..a115a63b0c 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -1055,20 +1055,6 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code) - return best_glyph; - } - --#if 0 --static struct grub_font_glyph * --grub_font_dup_glyph (struct grub_font_glyph *glyph) --{ -- static struct grub_font_glyph *ret; -- ret = grub_malloc (sizeof (*ret) + (glyph->width * glyph->height + 7) / 8); -- if (!ret) -- return NULL; -- grub_memcpy (ret, glyph, sizeof (*ret) -- + (glyph->width * glyph->height + 7) / 8); -- return ret; --} --#endif -- - /* FIXME: suboptimal. */ - static void - grub_font_blit_glyph (struct grub_font_glyph *target, diff --git a/0288-font-Fix-an-integer-underflow-in-blit_comb.patch b/0288-font-Fix-an-integer-underflow-in-blit_comb.patch new file mode 100644 index 0000000..72f4308 --- /dev/null +++ b/0288-font-Fix-an-integer-underflow-in-blit_comb.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Mon, 24 Oct 2022 08:05:35 +0800 +Subject: [PATCH] font: Fix an integer underflow in blit_comb() + +The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may +evaluate to a very big invalid value even if both ctx.bounds.height and +combining_glyphs[i]->height are small integers. For example, if +ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this +expression evaluates to 2147483647 (expected -1). This is because +coordinates are allowed to be negative but ctx.bounds.height is an +unsigned int. So, the subtraction operates on unsigned ints and +underflows to a very big value. The division makes things even worse. +The quotient is still an invalid value even if converted back to int. + +This patch fixes the problem by casting ctx.bounds.height to int. As +a result the subtraction will operate on int and grub_uint16_t which +will be promoted to an int. So, the underflow will no longer happen. Other +uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int, +to ensure coordinates are always calculated on signed integers. + +Fixes: CVE-2022-3775 + +Reported-by: Daniel Axtens +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 6d2668dea3774ed74c4cd1eadd146f1b846bc3d4) +--- + grub-core/font/font.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 193dfec045..12a5f0d08c 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -1203,12 +1203,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + ctx.bounds.height = main_glyph->height; + + above_rightx = main_glyph->offset_x + main_glyph->width; +- above_righty = ctx.bounds.y + ctx.bounds.height; ++ above_righty = ctx.bounds.y + (int) ctx.bounds.height; + + above_leftx = main_glyph->offset_x; +- above_lefty = ctx.bounds.y + ctx.bounds.height; ++ above_lefty = ctx.bounds.y + (int) ctx.bounds.height; + +- below_rightx = ctx.bounds.x + ctx.bounds.width; ++ below_rightx = ctx.bounds.x + (int) ctx.bounds.width; + below_righty = ctx.bounds.y; + + comb = grub_unicode_get_comb (glyph_id); +@@ -1221,7 +1221,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + + if (!combining_glyphs[i]) + continue; +- targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; ++ targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; + /* CGJ is to avoid diacritics reordering. */ + if (comb[i].code + == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) +@@ -1231,8 +1231,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + case GRUB_UNICODE_COMB_OVERLAY: + do_blit (combining_glyphs[i], + targetx, +- (ctx.bounds.height - combining_glyphs[i]->height) / 2 +- - (ctx.bounds.height + ctx.bounds.y), &ctx); ++ ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2 ++ - ((int) ctx.bounds.height + ctx.bounds.y), &ctx); + if (min_devwidth < combining_glyphs[i]->width) + min_devwidth = combining_glyphs[i]->width; + break; +@@ -1305,7 +1305,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + /* Fallthrough. */ + case GRUB_UNICODE_STACK_ATTACHED_ABOVE: + do_blit (combining_glyphs[i], targetx, +- -(ctx.bounds.height + ctx.bounds.y + space ++ -((int) ctx.bounds.height + ctx.bounds.y + space + + combining_glyphs[i]->height), &ctx); + if (min_devwidth < combining_glyphs[i]->width) + min_devwidth = combining_glyphs[i]->width; +@@ -1313,7 +1313,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + + case GRUB_UNICODE_COMB_HEBREW_DAGESH: + do_blit (combining_glyphs[i], targetx, +- -(ctx.bounds.height / 2 + ctx.bounds.y ++ -((int) ctx.bounds.height / 2 + ctx.bounds.y + + combining_glyphs[i]->height / 2), &ctx); + if (min_devwidth < combining_glyphs[i]->width) + min_devwidth = combining_glyphs[i]->width; diff --git a/0288-font-Fix-integer-overflow-in-ensure_comb_space.patch b/0288-font-Fix-integer-overflow-in-ensure_comb_space.patch deleted file mode 100644 index 6b73038..0000000 --- a/0288-font-Fix-integer-overflow-in-ensure_comb_space.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 5 Aug 2022 02:27:05 +0800 -Subject: [PATCH] font: Fix integer overflow in ensure_comb_space() - -In fact it can't overflow at all because glyph_id->ncomb is only 8-bit -wide. But let's keep safe if somebody changes the width of glyph_id->ncomb -in the future. This patch also fixes the inconsistency between -render_max_comb_glyphs and render_combining_glyphs when grub_malloc() -returns NULL. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit b2740b7e4a03bb8331d48b54b119afea76bb9d5f) ---- - grub-core/font/font.c | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index a115a63b0c..d0e6340404 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -1468,14 +1468,18 @@ ensure_comb_space (const struct grub_unicode_glyph *glyph_id) - if (glyph_id->ncomb <= render_max_comb_glyphs) - return; - -- render_max_comb_glyphs = 2 * glyph_id->ncomb; -- if (render_max_comb_glyphs < 8) -+ if (grub_mul (glyph_id->ncomb, 2, &render_max_comb_glyphs)) -+ render_max_comb_glyphs = 0; -+ if (render_max_comb_glyphs > 0 && render_max_comb_glyphs < 8) - render_max_comb_glyphs = 8; - grub_free (render_combining_glyphs); -- render_combining_glyphs = grub_malloc (render_max_comb_glyphs -- * sizeof (render_combining_glyphs[0])); -+ render_combining_glyphs = (render_max_comb_glyphs > 0) ? -+ grub_calloc (render_max_comb_glyphs, sizeof (render_combining_glyphs[0])) : NULL; - if (!render_combining_glyphs) -- grub_errno = 0; -+ { -+ render_max_comb_glyphs = 0; -+ grub_errno = GRUB_ERR_NONE; -+ } - } - - int diff --git a/0289-font-Fix-integer-overflow-in-BMP-index.patch b/0289-font-Fix-integer-overflow-in-BMP-index.patch deleted file mode 100644 index 5e10699..0000000 --- a/0289-font-Fix-integer-overflow-in-BMP-index.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Mon, 15 Aug 2022 02:04:58 +0800 -Subject: [PATCH] font: Fix integer overflow in BMP index - -The BMP index (font->bmp_idx) is designed as a reverse lookup table of -char entries (font->char_index), in order to speed up lookups for BMP -chars (i.e. code < 0x10000). The values in BMP index are the subscripts -of the corresponding char entries, stored in grub_uint16_t, while 0xffff -means not found. - -This patch fixes the problem of large subscript truncated to grub_uint16_t, -leading BMP index to return wrong char entry or report false miss. The -code now checks for bounds and uses BMP index as a hint, and fallbacks -to binary-search if necessary. - -On the occasion add a comment about BMP index is initialized to 0xffff. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit afda8b60ba0712abe01ae1e64c5f7a067a0e6492) ---- - grub-core/font/font.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index d0e6340404..b208a28717 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -300,6 +300,8 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct - font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t)); - if (!font->bmp_idx) - return 1; -+ -+ /* Init the BMP index array to 0xffff. */ - grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t)); - - -@@ -328,7 +330,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct - return 1; - } - -- if (entry->code < 0x10000) -+ if (entry->code < 0x10000 && i < 0xffff) - font->bmp_idx[entry->code] = i; - - last_code = entry->code; -@@ -696,9 +698,12 @@ find_glyph (const grub_font_t font, grub_uint32_t code) - /* Use BMP index if possible. */ - if (code < 0x10000 && font->bmp_idx) - { -- if (font->bmp_idx[code] == 0xffff) -- return 0; -- return &table[font->bmp_idx[code]]; -+ if (font->bmp_idx[code] < 0xffff) -+ return &table[font->bmp_idx[code]]; -+ /* -+ * When we are here then lookup in BMP index result in miss, -+ * fallthough to binary-search. -+ */ - } - - /* Do a binary search in `char_index', which is ordered by code point. */ diff --git a/0289-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch b/0289-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch new file mode 100644 index 0000000..5207c12 --- /dev/null +++ b/0289-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Mon, 24 Oct 2022 07:15:41 +0800 +Subject: [PATCH] font: Harden grub_font_blit_glyph() and + grub_font_blit_glyph_mirror() + +As a mitigation and hardening measure add sanity checks to +grub_font_blit_glyph() and grub_font_blit_glyph_mirror(). This patch +makes these two functions do nothing if target blitting area isn't fully +contained in target bitmap. Therefore, if complex calculations in caller +overflows and malicious coordinates are given, we are still safe because +any coordinates which result in out-of-bound-write are rejected. However, +this patch only checks for invalid coordinates, and doesn't provide any +protection against invalid source glyph or destination glyph, e.g. +mismatch between glyph size and buffer size. + +This hardening measure is designed to mitigate possible overflows in +blit_comb(). If overflow occurs, it may return invalid bounding box +during dry run and call grub_font_blit_glyph() with malicious +coordinates during actual blitting. However, we are still safe because +the scratch glyph itself is valid, although its size makes no sense, and +any invalid coordinates are rejected. + +It would be better to call grub_fatal() if illegal parameter is detected. +However, doing this may end up in a dangerous recursion because grub_fatal() +would print messages to the screen and we are in the progress of drawing +characters on the screen. + +Reported-by: Daniel Axtens +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit fcd7aa0c278f7cf3fb9f93f1a3966e1792339eb6) +--- + grub-core/font/font.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 12a5f0d08c..29fbb94294 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -1069,8 +1069,15 @@ static void + grub_font_blit_glyph (struct grub_font_glyph *target, + struct grub_font_glyph *src, unsigned dx, unsigned dy) + { ++ grub_uint16_t max_x, max_y; + unsigned src_bit, tgt_bit, src_byte, tgt_byte; + unsigned i, j; ++ ++ /* Harden against out-of-bound writes. */ ++ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) || ++ (grub_add (dy, src->height, &max_y) || max_y > target->height)) ++ return; ++ + for (i = 0; i < src->height; i++) + { + src_bit = (src->width * i) % 8; +@@ -1102,9 +1109,16 @@ grub_font_blit_glyph_mirror (struct grub_font_glyph *target, + struct grub_font_glyph *src, + unsigned dx, unsigned dy) + { ++ grub_uint16_t max_x, max_y; + unsigned tgt_bit, src_byte, tgt_byte; + signed src_bit; + unsigned i, j; ++ ++ /* Harden against out-of-bound writes. */ ++ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) || ++ (grub_add (dy, src->height, &max_y) || max_y > target->height)) ++ return; ++ + for (i = 0; i < src->height; i++) + { + src_bit = (src->width * i + src->width - 1) % 8; diff --git a/0290-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch b/0290-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch new file mode 100644 index 0000000..c2bcc18 --- /dev/null +++ b/0290-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 28 Oct 2022 17:29:16 +0800 +Subject: [PATCH] font: Assign null_font to glyphs in ascii_font_glyph[] + +The calculations in blit_comb() need information from glyph's font, e.g. +grub_font_get_xheight(main_glyph->font). However, main_glyph->font is +NULL if main_glyph comes from ascii_font_glyph[]. Therefore +grub_font_get_*() crashes because of NULL pointer. + +There is already a solution, the null_font. So, assign it to those glyphs +in ascii_font_glyph[]. + +Reported-by: Daniel Axtens +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit dd539d695482069d28b40f2d3821f710cdcf6ee6) +--- + grub-core/font/font.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 29fbb94294..e6616e610c 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -137,7 +137,7 @@ ascii_glyph_lookup (grub_uint32_t code) + ascii_font_glyph[current]->offset_x = 0; + ascii_font_glyph[current]->offset_y = -2; + ascii_font_glyph[current]->device_width = 8; +- ascii_font_glyph[current]->font = NULL; ++ ascii_font_glyph[current]->font = &null_font; + + grub_memcpy (ascii_font_glyph[current]->bitmap, + &ascii_bitmaps[current * ASCII_BITMAP_SIZE], diff --git a/0290-font-Fix-integer-underflow-in-binary-search-of-char-.patch b/0290-font-Fix-integer-underflow-in-binary-search-of-char-.patch deleted file mode 100644 index e81824b..0000000 --- a/0290-font-Fix-integer-underflow-in-binary-search-of-char-.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Sun, 14 Aug 2022 18:09:38 +0800 -Subject: [PATCH] font: Fix integer underflow in binary search of char index - -If search target is less than all entries in font->index then "hi" -variable is set to -1, which translates to SIZE_MAX and leads to errors. - -This patch fixes the problem by replacing the entire binary search code -with the libstdc++'s std::lower_bound() implementation. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit c140a086838e7c9af87842036f891b8393a8c4bc) ---- - grub-core/font/font.c | 40 ++++++++++++++++++++++------------------ - 1 file changed, 22 insertions(+), 18 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index b208a28717..193dfec045 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -688,12 +688,12 @@ read_be_int16 (grub_file_t file, grub_int16_t * value) - static inline struct char_index_entry * - find_glyph (const grub_font_t font, grub_uint32_t code) - { -- struct char_index_entry *table; -- grub_size_t lo; -- grub_size_t hi; -- grub_size_t mid; -+ struct char_index_entry *table, *first, *end; -+ grub_size_t len; - - table = font->char_index; -+ if (table == NULL) -+ return NULL; - - /* Use BMP index if possible. */ - if (code < 0x10000 && font->bmp_idx) -@@ -706,25 +706,29 @@ find_glyph (const grub_font_t font, grub_uint32_t code) - */ - } - -- /* Do a binary search in `char_index', which is ordered by code point. */ -- lo = 0; -- hi = font->num_chars - 1; -+ /* -+ * Do a binary search in char_index which is ordered by code point. -+ * The code below is the same as libstdc++'s std::lower_bound(). -+ */ -+ first = table; -+ len = font->num_chars; -+ end = first + len; - -- if (!table) -- return 0; -- -- while (lo <= hi) -+ while (len > 0) - { -- mid = lo + (hi - lo) / 2; -- if (code < table[mid].code) -- hi = mid - 1; -- else if (code > table[mid].code) -- lo = mid + 1; -+ grub_size_t half = len >> 1; -+ struct char_index_entry *middle = first + half; -+ -+ if (middle->code < code) -+ { -+ first = middle + 1; -+ len = len - half - 1; -+ } - else -- return &table[mid]; -+ len = half; - } - -- return 0; -+ return (first < end && first->code == code) ? first : NULL; - } - - /* Get a glyph for the Unicode character CODE in FONT. The glyph is loaded diff --git a/0291-kern-efi-sb-Enforce-verification-of-font-files.patch b/0291-kern-efi-sb-Enforce-verification-of-font-files.patch deleted file mode 100644 index 1a381b0..0000000 --- a/0291-kern-efi-sb-Enforce-verification-of-font-files.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Sun, 14 Aug 2022 15:51:54 +0800 -Subject: [PATCH] kern/efi/sb: Enforce verification of font files - -As a mitigation and hardening measure enforce verification of font -files. Then only trusted font files can be load. This will reduce the -attack surface at cost of losing the ability of end-users to customize -fonts if e.g. UEFI Secure Boot is enabled. Vendors can always customize -fonts because they have ability to pack fonts into their GRUB bundles. - -This goal is achieved by: - - * Removing GRUB_FILE_TYPE_FONT from shim lock verifier's - skip-verification list. - - * Adding GRUB_FILE_TYPE_FONT to lockdown verifier's defer-auth list, - so font files must be verified by a verifier before they can be loaded. - -Suggested-by: Daniel Kiper -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 630deb8c0d8b02b670ced4b7030414bcf17aa080) ---- - grub-core/kern/efi/sb.c | 1 - - grub-core/kern/lockdown.c | 1 + - 2 files changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c -index 89c4bb3fd1..db42c2539f 100644 ---- a/grub-core/kern/efi/sb.c -+++ b/grub-core/kern/efi/sb.c -@@ -145,7 +145,6 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), - case GRUB_FILE_TYPE_PRINT_BLOCKLIST: - case GRUB_FILE_TYPE_TESTLOAD: - case GRUB_FILE_TYPE_GET_SIZE: -- case GRUB_FILE_TYPE_FONT: - case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY: - case GRUB_FILE_TYPE_CAT: - case GRUB_FILE_TYPE_HEXCAT: -diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c -index 0bc70fd42d..af6d493cd3 100644 ---- a/grub-core/kern/lockdown.c -+++ b/grub-core/kern/lockdown.c -@@ -51,6 +51,7 @@ lockdown_verifier_init (grub_file_t io __attribute__ ((unused)), - case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: - case GRUB_FILE_TYPE_ACPI_TABLE: - case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: -+ case GRUB_FILE_TYPE_FONT: - *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; - - /* Fall through. */ diff --git a/0291-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch b/0291-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch new file mode 100644 index 0000000..ec2184f --- /dev/null +++ b/0291-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 28 Oct 2022 21:31:39 +0800 +Subject: [PATCH] normal/charset: Fix an integer overflow in + grub_unicode_aglomerate_comb() + +The out->ncomb is a bit-field of 8 bits. So, the max possible value is 255. +However, code in grub_unicode_aglomerate_comb() doesn't check for an +overflow when incrementing out->ncomb. If out->ncomb is already 255, +after incrementing it will get 0 instead of 256, and cause illegal +memory access in subsequent processing. + +This patch introduces GRUB_UNICODE_NCOMB_MAX to represent the max +acceptable value of ncomb. The code now checks for this limit and +ignores additional combining characters when limit is reached. + +Reported-by: Daniel Axtens +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit da90d62316a3b105d2fbd7334d6521936bd6dcf6) +--- + grub-core/normal/charset.c | 3 +++ + include/grub/unicode.h | 2 ++ + 2 files changed, 5 insertions(+) + +diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c +index 7a5a7c153c..c243ca6dae 100644 +--- a/grub-core/normal/charset.c ++++ b/grub-core/normal/charset.c +@@ -472,6 +472,9 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, + if (!haveout) + continue; + ++ if (out->ncomb == GRUB_UNICODE_NCOMB_MAX) ++ continue; ++ + if (comb_type == GRUB_UNICODE_COMB_MC + || comb_type == GRUB_UNICODE_COMB_ME + || comb_type == GRUB_UNICODE_COMB_MN) +diff --git a/include/grub/unicode.h b/include/grub/unicode.h +index 4de986a857..c4f6fca043 100644 +--- a/include/grub/unicode.h ++++ b/include/grub/unicode.h +@@ -147,7 +147,9 @@ struct grub_unicode_glyph + grub_uint8_t bidi_level:6; /* minimum: 6 */ + enum grub_bidi_type bidi_type:5; /* minimum: :5 */ + ++#define GRUB_UNICODE_NCOMB_MAX ((1 << 8) - 1) + unsigned ncomb:8; ++ + /* Hint by unicode subsystem how wide this character usually is. + Real width is determined by font. Set only in UTF-8 stream. */ + int estimated_width:8; diff --git a/0292-fbutil-Fix-integer-overflow.patch b/0292-fbutil-Fix-integer-overflow.patch deleted file mode 100644 index 4d32dbd..0000000 --- a/0292-fbutil-Fix-integer-overflow.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Tue, 6 Sep 2022 03:03:21 +0800 -Subject: [PATCH] fbutil: Fix integer overflow - -Expressions like u64 = u32 * u32 are unsafe because their products are -truncated to u32 even if left hand side is u64. This patch fixes all -problems like that one in fbutil. - -To get right result not only left hand side have to be u64 but it's also -necessary to cast at least one of the operands of all leaf operators of -right hand side to u64, e.g. u64 = u32 * u32 + u32 * u32 should be -u64 = (u64)u32 * u32 + (u64)u32 * u32. - -For 1-bit bitmaps grub_uint64_t have to be used. It's safe because any -combination of values in (grub_uint64_t)u32 * u32 + u32 expression will -not overflow grub_uint64_t. - -Other expressions like ptr + u32 * u32 + u32 * u32 are also vulnerable. -They should be ptr + (grub_addr_t)u32 * u32 + (grub_addr_t)u32 * u32. - -This patch also adds a comment to grub_video_fb_get_video_ptr() which -says it's arguments must be valid and no sanity check is performed -(like its siblings in grub-core/video/fb/fbutil.c). - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 50a11a81bc842c58962244a2dc86bbd31a426e12) ---- - grub-core/video/fb/fbutil.c | 4 ++-- - include/grub/fbutil.h | 13 +++++++++---- - 2 files changed, 11 insertions(+), 6 deletions(-) - -diff --git a/grub-core/video/fb/fbutil.c b/grub-core/video/fb/fbutil.c -index b98bb51fe8..25ef39f47d 100644 ---- a/grub-core/video/fb/fbutil.c -+++ b/grub-core/video/fb/fbutil.c -@@ -67,7 +67,7 @@ get_pixel (struct grub_video_fbblit_info *source, - case 1: - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) - { -- int bit_index = y * source->mode_info->width + x; -+ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x; - grub_uint8_t *ptr = source->data + bit_index / 8; - int bit_pos = 7 - bit_index % 8; - color = (*ptr >> bit_pos) & 0x01; -@@ -138,7 +138,7 @@ set_pixel (struct grub_video_fbblit_info *source, - case 1: - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) - { -- int bit_index = y * source->mode_info->width + x; -+ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x; - grub_uint8_t *ptr = source->data + bit_index / 8; - int bit_pos = 7 - bit_index % 8; - *ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos); -diff --git a/include/grub/fbutil.h b/include/grub/fbutil.h -index 4205eb917f..78a1ab3b45 100644 ---- a/include/grub/fbutil.h -+++ b/include/grub/fbutil.h -@@ -31,14 +31,19 @@ struct grub_video_fbblit_info - grub_uint8_t *data; - }; - --/* Don't use for 1-bit bitmaps, addressing needs to be done at the bit level -- and it doesn't make sense, in general, to ask for a pointer -- to a particular pixel's data. */ -+/* -+ * Don't use for 1-bit bitmaps, addressing needs to be done at the bit level -+ * and it doesn't make sense, in general, to ask for a pointer -+ * to a particular pixel's data. -+ * -+ * This function assumes that bounds checking has been done in previous phase -+ * and they are opted out in here. -+ */ - static inline void * - grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, - unsigned int x, unsigned int y) - { -- return source->data + y * source->mode_info->pitch + x * source->mode_info->bytes_per_pixel; -+ return source->data + (grub_addr_t) y * source->mode_info->pitch + (grub_addr_t) x * source->mode_info->bytes_per_pixel; - } - - /* Advance pointer by VAL bytes. If there is no unaligned access available, diff --git a/0292-font-Try-opening-fonts-from-the-bundled-memdisk.patch b/0292-font-Try-opening-fonts-from-the-bundled-memdisk.patch new file mode 100644 index 0000000..bad9d90 --- /dev/null +++ b/0292-font-Try-opening-fonts-from-the-bundled-memdisk.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Wed, 16 Nov 2022 14:40:04 +0000 +Subject: [PATCH] font: Try opening fonts from the bundled memdisk + +Signed-off-by: Robbie Harwood +--- + grub-core/font/font.c | 48 +++++++++++++++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 17 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index e6616e610c..e421d1ae6f 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -409,6 +409,27 @@ read_section_as_short (struct font_file_section *section, + return 0; + } + ++static grub_file_t ++try_open_from_prefix (const char *prefix, const char *filename) ++{ ++ grub_file_t file; ++ char *fullname, *ptr; ++ ++ fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1 ++ + sizeof ("/fonts/") + sizeof (".pf2")); ++ if (!fullname) ++ return 0; ++ ptr = grub_stpcpy (fullname, prefix); ++ ptr = grub_stpcpy (ptr, "/fonts/"); ++ ptr = grub_stpcpy (ptr, filename); ++ ptr = grub_stpcpy (ptr, ".pf2"); ++ *ptr = 0; ++ ++ file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024); ++ grub_free (fullname); ++ return file; ++} ++ + /* Load a font and add it to the beginning of the global font list. + Returns 0 upon success, nonzero upon failure. */ + grub_font_t +@@ -427,25 +448,18 @@ grub_font_load (const char *filename) + file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024); + else + { +- const char *prefix = grub_env_get ("prefix"); +- char *fullname, *ptr; +- if (!prefix) ++ file = try_open_from_prefix ("(memdisk)", filename); ++ if (!file) + { +- grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), +- "prefix"); +- goto fail; ++ const char *prefix = grub_env_get ("prefix"); ++ if (!prefix) ++ { ++ grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), ++ "prefix"); ++ goto fail; ++ } ++ file = try_open_from_prefix (prefix, filename); + } +- fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1 +- + sizeof ("/fonts/") + sizeof (".pf2")); +- if (!fullname) +- goto fail; +- ptr = grub_stpcpy (fullname, prefix); +- ptr = grub_stpcpy (ptr, "/fonts/"); +- ptr = grub_stpcpy (ptr, filename); +- ptr = grub_stpcpy (ptr, ".pf2"); +- *ptr = 0; +- file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024); +- grub_free (fullname); + } + if (!file) + goto fail; diff --git a/0293-font-Fix-an-integer-underflow-in-blit_comb.patch b/0293-font-Fix-an-integer-underflow-in-blit_comb.patch deleted file mode 100644 index 72f4308..0000000 --- a/0293-font-Fix-an-integer-underflow-in-blit_comb.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Mon, 24 Oct 2022 08:05:35 +0800 -Subject: [PATCH] font: Fix an integer underflow in blit_comb() - -The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may -evaluate to a very big invalid value even if both ctx.bounds.height and -combining_glyphs[i]->height are small integers. For example, if -ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this -expression evaluates to 2147483647 (expected -1). This is because -coordinates are allowed to be negative but ctx.bounds.height is an -unsigned int. So, the subtraction operates on unsigned ints and -underflows to a very big value. The division makes things even worse. -The quotient is still an invalid value even if converted back to int. - -This patch fixes the problem by casting ctx.bounds.height to int. As -a result the subtraction will operate on int and grub_uint16_t which -will be promoted to an int. So, the underflow will no longer happen. Other -uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int, -to ensure coordinates are always calculated on signed integers. - -Fixes: CVE-2022-3775 - -Reported-by: Daniel Axtens -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 6d2668dea3774ed74c4cd1eadd146f1b846bc3d4) ---- - grub-core/font/font.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 193dfec045..12a5f0d08c 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -1203,12 +1203,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - ctx.bounds.height = main_glyph->height; - - above_rightx = main_glyph->offset_x + main_glyph->width; -- above_righty = ctx.bounds.y + ctx.bounds.height; -+ above_righty = ctx.bounds.y + (int) ctx.bounds.height; - - above_leftx = main_glyph->offset_x; -- above_lefty = ctx.bounds.y + ctx.bounds.height; -+ above_lefty = ctx.bounds.y + (int) ctx.bounds.height; - -- below_rightx = ctx.bounds.x + ctx.bounds.width; -+ below_rightx = ctx.bounds.x + (int) ctx.bounds.width; - below_righty = ctx.bounds.y; - - comb = grub_unicode_get_comb (glyph_id); -@@ -1221,7 +1221,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - - if (!combining_glyphs[i]) - continue; -- targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; -+ targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; - /* CGJ is to avoid diacritics reordering. */ - if (comb[i].code - == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) -@@ -1231,8 +1231,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - case GRUB_UNICODE_COMB_OVERLAY: - do_blit (combining_glyphs[i], - targetx, -- (ctx.bounds.height - combining_glyphs[i]->height) / 2 -- - (ctx.bounds.height + ctx.bounds.y), &ctx); -+ ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2 -+ - ((int) ctx.bounds.height + ctx.bounds.y), &ctx); - if (min_devwidth < combining_glyphs[i]->width) - min_devwidth = combining_glyphs[i]->width; - break; -@@ -1305,7 +1305,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - /* Fallthrough. */ - case GRUB_UNICODE_STACK_ATTACHED_ABOVE: - do_blit (combining_glyphs[i], targetx, -- -(ctx.bounds.height + ctx.bounds.y + space -+ -((int) ctx.bounds.height + ctx.bounds.y + space - + combining_glyphs[i]->height), &ctx); - if (min_devwidth < combining_glyphs[i]->width) - min_devwidth = combining_glyphs[i]->width; -@@ -1313,7 +1313,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - - case GRUB_UNICODE_COMB_HEBREW_DAGESH: - do_blit (combining_glyphs[i], targetx, -- -(ctx.bounds.height / 2 + ctx.bounds.y -+ -((int) ctx.bounds.height / 2 + ctx.bounds.y - + combining_glyphs[i]->height / 2), &ctx); - if (min_devwidth < combining_glyphs[i]->width) - min_devwidth = combining_glyphs[i]->width; diff --git a/0293-mm-Clarify-grub_real_malloc.patch b/0293-mm-Clarify-grub_real_malloc.patch new file mode 100644 index 0000000..0a99c08 --- /dev/null +++ b/0293-mm-Clarify-grub_real_malloc.patch @@ -0,0 +1,183 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 25 Nov 2021 02:22:46 +1100 +Subject: [PATCH] mm: Clarify grub_real_malloc() + +When iterating through the singly linked list of free blocks, +grub_real_malloc() uses p and q for the current and previous blocks +respectively. This isn't super clear, so swap to using prev and cur. + +This makes another quirk more obvious. The comment at the top of +grub_real_malloc() might lead you to believe that the function will +allocate from *first if there is space in that block. + +It actually doesn't do that, and it can't do that with the current +data structures. If we used up all of *first, we would need to change +the ->next of the previous block to point to *first->next, but we +can't do that because it's a singly linked list and we don't have +access to *first's previous block. + +What grub_real_malloc() actually does is set *first to the initial +previous block, and *first->next is the block we try to allocate +from. That allows us to keep all the data structures consistent. + +Document that. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 246ad6a44c281bb13486ddea0a26bb661db73106) +--- + grub-core/kern/mm.c | 76 +++++++++++++++++++++++++++++------------------------ + 1 file changed, 41 insertions(+), 35 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index d8c8377578..fb20e93acf 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -178,13 +178,20 @@ grub_mm_init_region (void *addr, grub_size_t size) + } + + /* Allocate the number of units N with the alignment ALIGN from the ring +- buffer starting from *FIRST. ALIGN must be a power of two. Both N and +- ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful, +- otherwise return NULL. */ ++ * buffer given in *FIRST. ALIGN must be a power of two. Both N and ++ * ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful, ++ * otherwise return NULL. ++ * ++ * Note: because in certain circumstances we need to adjust the ->next ++ * pointer of the previous block, we iterate over the singly linked ++ * list with the pair (prev, cur). *FIRST is our initial previous, and ++ * *FIRST->next is our initial current pointer. So we will actually ++ * allocate from *FIRST->next first and *FIRST itself last. ++ */ + static void * + grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + { +- grub_mm_header_t p, q; ++ grub_mm_header_t cur, prev; + + /* When everything is allocated side effect is that *first will have alloc + magic marked, meaning that there is no room in this region. */ +@@ -192,24 +199,24 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + return 0; + + /* Try to search free slot for allocation in this memory region. */ +- for (q = *first, p = q->next; ; q = p, p = p->next) ++ for (prev = *first, cur = prev->next; ; prev = cur, cur = cur->next) + { + grub_off_t extra; + +- extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1); ++ extra = ((grub_addr_t) (cur + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1); + if (extra) + extra = align - extra; + +- if (! p) ++ if (! cur) + grub_fatal ("null in the ring"); + +- if (p->magic != GRUB_MM_FREE_MAGIC) +- grub_fatal ("free magic is broken at %p: 0x%x", p, p->magic); ++ if (cur->magic != GRUB_MM_FREE_MAGIC) ++ grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic); + +- if (p->size >= n + extra) ++ if (cur->size >= n + extra) + { +- extra += (p->size - extra - n) & (~(align - 1)); +- if (extra == 0 && p->size == n) ++ extra += (cur->size - extra - n) & (~(align - 1)); ++ if (extra == 0 && cur->size == n) + { + /* There is no special alignment requirement and memory block + is complete match. +@@ -222,9 +229,9 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + | alloc, size=n | | + +---------------+ v + */ +- q->next = p->next; ++ prev->next = cur->next; + } +- else if (align == 1 || p->size == n + extra) ++ else if (align == 1 || cur->size == n + extra) + { + /* There might be alignment requirement, when taking it into + account memory block fits in. +@@ -241,23 +248,22 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + | alloc, size=n | | + +---------------+ v + */ +- +- p->size -= n; +- p += p->size; ++ cur->size -= n; ++ cur += cur->size; + } + else if (extra == 0) + { + grub_mm_header_t r; + +- r = p + extra + n; ++ r = cur + extra + n; + r->magic = GRUB_MM_FREE_MAGIC; +- r->size = p->size - extra - n; +- r->next = p->next; +- q->next = r; ++ r->size = cur->size - extra - n; ++ r->next = cur->next; ++ prev->next = r; + +- if (q == p) ++ if (prev == cur) + { +- q = r; ++ prev = r; + r->next = r; + } + } +@@ -284,32 +290,32 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + */ + grub_mm_header_t r; + +- r = p + extra + n; ++ r = cur + extra + n; + r->magic = GRUB_MM_FREE_MAGIC; +- r->size = p->size - extra - n; +- r->next = p; ++ r->size = cur->size - extra - n; ++ r->next = cur; + +- p->size = extra; +- q->next = r; +- p += extra; ++ cur->size = extra; ++ prev->next = r; ++ cur += extra; + } + +- p->magic = GRUB_MM_ALLOC_MAGIC; +- p->size = n; ++ cur->magic = GRUB_MM_ALLOC_MAGIC; ++ cur->size = n; + + /* Mark find as a start marker for next allocation to fasten it. + This will have side effect of fragmenting memory as small + pieces before this will be un-used. */ + /* So do it only for chunks under 64K. */ + if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2) +- || *first == p) +- *first = q; ++ || *first == cur) ++ *first = prev; + +- return p + 1; ++ return cur + 1; + } + + /* Search was completed without result. */ +- if (p == *first) ++ if (cur == *first) + break; + } + diff --git a/0294-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch b/0294-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch deleted file mode 100644 index 5207c12..0000000 --- a/0294-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Mon, 24 Oct 2022 07:15:41 +0800 -Subject: [PATCH] font: Harden grub_font_blit_glyph() and - grub_font_blit_glyph_mirror() - -As a mitigation and hardening measure add sanity checks to -grub_font_blit_glyph() and grub_font_blit_glyph_mirror(). This patch -makes these two functions do nothing if target blitting area isn't fully -contained in target bitmap. Therefore, if complex calculations in caller -overflows and malicious coordinates are given, we are still safe because -any coordinates which result in out-of-bound-write are rejected. However, -this patch only checks for invalid coordinates, and doesn't provide any -protection against invalid source glyph or destination glyph, e.g. -mismatch between glyph size and buffer size. - -This hardening measure is designed to mitigate possible overflows in -blit_comb(). If overflow occurs, it may return invalid bounding box -during dry run and call grub_font_blit_glyph() with malicious -coordinates during actual blitting. However, we are still safe because -the scratch glyph itself is valid, although its size makes no sense, and -any invalid coordinates are rejected. - -It would be better to call grub_fatal() if illegal parameter is detected. -However, doing this may end up in a dangerous recursion because grub_fatal() -would print messages to the screen and we are in the progress of drawing -characters on the screen. - -Reported-by: Daniel Axtens -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit fcd7aa0c278f7cf3fb9f93f1a3966e1792339eb6) ---- - grub-core/font/font.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 12a5f0d08c..29fbb94294 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -1069,8 +1069,15 @@ static void - grub_font_blit_glyph (struct grub_font_glyph *target, - struct grub_font_glyph *src, unsigned dx, unsigned dy) - { -+ grub_uint16_t max_x, max_y; - unsigned src_bit, tgt_bit, src_byte, tgt_byte; - unsigned i, j; -+ -+ /* Harden against out-of-bound writes. */ -+ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) || -+ (grub_add (dy, src->height, &max_y) || max_y > target->height)) -+ return; -+ - for (i = 0; i < src->height; i++) - { - src_bit = (src->width * i) % 8; -@@ -1102,9 +1109,16 @@ grub_font_blit_glyph_mirror (struct grub_font_glyph *target, - struct grub_font_glyph *src, - unsigned dx, unsigned dy) - { -+ grub_uint16_t max_x, max_y; - unsigned tgt_bit, src_byte, tgt_byte; - signed src_bit; - unsigned i, j; -+ -+ /* Harden against out-of-bound writes. */ -+ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) || -+ (grub_add (dy, src->height, &max_y) || max_y > target->height)) -+ return; -+ - for (i = 0; i < src->height; i++) - { - src_bit = (src->width * i + src->width - 1) % 8; diff --git a/0294-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch b/0294-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch new file mode 100644 index 0000000..a5601c9 --- /dev/null +++ b/0294-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 25 Nov 2021 02:22:47 +1100 +Subject: [PATCH] mm: grub_real_malloc(): Make small allocs comment match code + +Small allocations move the region's *first pointer. The comment +says that this happens for allocations under 64K. The code says +it's for allocations under 32K. Commit 45bf8b3a7549 changed the +code intentionally: make the comment match. + +Fixes: 45bf8b3a7549 (* grub-core/kern/mm.c (grub_real_malloc): Decrease cut-off of moving the) + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit a847895a8d000bdf27ad4d4326f883a0eed769ca) +--- + grub-core/kern/mm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index fb20e93acf..db7e0b2a5b 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -306,7 +306,7 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + /* Mark find as a start marker for next allocation to fasten it. + This will have side effect of fragmenting memory as small + pieces before this will be un-used. */ +- /* So do it only for chunks under 64K. */ ++ /* So do it only for chunks under 32K. */ + if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2) + || *first == cur) + *first = prev; diff --git a/0295-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch b/0295-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch deleted file mode 100644 index c2bcc18..0000000 --- a/0295-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 28 Oct 2022 17:29:16 +0800 -Subject: [PATCH] font: Assign null_font to glyphs in ascii_font_glyph[] - -The calculations in blit_comb() need information from glyph's font, e.g. -grub_font_get_xheight(main_glyph->font). However, main_glyph->font is -NULL if main_glyph comes from ascii_font_glyph[]. Therefore -grub_font_get_*() crashes because of NULL pointer. - -There is already a solution, the null_font. So, assign it to those glyphs -in ascii_font_glyph[]. - -Reported-by: Daniel Axtens -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit dd539d695482069d28b40f2d3821f710cdcf6ee6) ---- - grub-core/font/font.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 29fbb94294..e6616e610c 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -137,7 +137,7 @@ ascii_glyph_lookup (grub_uint32_t code) - ascii_font_glyph[current]->offset_x = 0; - ascii_font_glyph[current]->offset_y = -2; - ascii_font_glyph[current]->device_width = 8; -- ascii_font_glyph[current]->font = NULL; -+ ascii_font_glyph[current]->font = &null_font; - - grub_memcpy (ascii_font_glyph[current]->bitmap, - &ascii_bitmaps[current * ASCII_BITMAP_SIZE], diff --git a/0295-mm-Document-grub_free.patch b/0295-mm-Document-grub_free.patch new file mode 100644 index 0000000..6c9b7cc --- /dev/null +++ b/0295-mm-Document-grub_free.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 25 Nov 2021 02:22:48 +1100 +Subject: [PATCH] mm: Document grub_free() + +The grub_free() possesses a surprising number of quirks, and also +uses single-letter variable names confusingly to iterate through +the free list. + +Document what's going on. + +Use prev and cur to iterate over the free list. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 1f8d0b01738e49767d662d6426af3570a64565f0) +--- + grub-core/kern/mm.c | 63 ++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 41 insertions(+), 22 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index db7e0b2a5b..0351171cf9 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -446,54 +446,73 @@ grub_free (void *ptr) + } + else + { +- grub_mm_header_t q, s; ++ grub_mm_header_t cur, prev; + + #if 0 +- q = r->first; ++ cur = r->first; + do + { + grub_printf ("%s:%d: q=%p, q->size=0x%x, q->magic=0x%x\n", +- GRUB_FILE, __LINE__, q, q->size, q->magic); +- q = q->next; ++ GRUB_FILE, __LINE__, cur, cur->size, cur->magic); ++ cur = cur->next; + } +- while (q != r->first); ++ while (cur != r->first); + #endif +- +- for (s = r->first, q = s->next; q <= p || q->next >= p; s = q, q = s->next) ++ /* Iterate over all blocks in the free ring. ++ * ++ * The free ring is arranged from high addresses to low ++ * addresses, modulo wraparound. ++ * ++ * We are looking for a block with a higher address than p or ++ * whose next address is lower than p. ++ */ ++ for (prev = r->first, cur = prev->next; cur <= p || cur->next >= p; ++ prev = cur, cur = prev->next) + { +- if (q->magic != GRUB_MM_FREE_MAGIC) +- grub_fatal ("free magic is broken at %p: 0x%x", q, q->magic); ++ if (cur->magic != GRUB_MM_FREE_MAGIC) ++ grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic); + +- if (q <= q->next && (q > p || q->next < p)) ++ /* Deal with wrap-around */ ++ if (cur <= cur->next && (cur > p || cur->next < p)) + break; + } + ++ /* mark p as free and insert it between cur and cur->next */ + p->magic = GRUB_MM_FREE_MAGIC; +- p->next = q->next; +- q->next = p; ++ p->next = cur->next; ++ cur->next = p; + ++ /* ++ * If the block we are freeing can be merged with the next ++ * free block, do that. ++ */ + if (p->next + p->next->size == p) + { + p->magic = 0; + + p->next->size += p->size; +- q->next = p->next; ++ cur->next = p->next; + p = p->next; + } + +- r->first = q; ++ r->first = cur; + +- if (q == p + p->size) ++ /* Likewise if can be merged with the preceeding free block */ ++ if (cur == p + p->size) + { +- q->magic = 0; +- p->size += q->size; +- if (q == s) +- s = p; +- s->next = p; +- q = s; ++ cur->magic = 0; ++ p->size += cur->size; ++ if (cur == prev) ++ prev = p; ++ prev->next = p; ++ cur = prev; + } + +- r->first = q; ++ /* ++ * Set r->first such that the just free()d block is tried first. ++ * (An allocation is tried from *first->next, and cur->next == p.) ++ */ ++ r->first = cur; + } + } + diff --git a/0296-mm-Document-grub_mm_init_region.patch b/0296-mm-Document-grub_mm_init_region.patch new file mode 100644 index 0000000..0173f04 --- /dev/null +++ b/0296-mm-Document-grub_mm_init_region.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 25 Nov 2021 02:22:49 +1100 +Subject: [PATCH] mm: Document grub_mm_init_region() + +The grub_mm_init_region() does some things that seem magical, especially +around region merging. Make it a bit clearer. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 246d69b7ea619fc1e77dcc5960e37aea45a9808c) +--- + grub-core/kern/mm.c | 31 ++++++++++++++++++++++++++++++- + 1 file changed, 30 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 0351171cf9..1cbf98c7ab 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -128,23 +128,52 @@ grub_mm_init_region (void *addr, grub_size_t size) + if (((grub_addr_t) addr + 0x1000) > ~(grub_addr_t) size) + size = ((grub_addr_t) -0x1000) - (grub_addr_t) addr; + ++ /* Attempt to merge this region with every existing region */ + for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) ++ /* ++ * Is the new region immediately below an existing region? That ++ * is, is the address of the memory we're adding now (addr) + size ++ * of the memory we're adding (size) + the bytes we couldn't use ++ * at the start of the region we're considering (q->pre_size) ++ * equal to the address of q? In other words, does the memory ++ * looks like this? ++ * ++ * addr q ++ * |----size-----|-q->pre_size-|| ++ */ + if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) + { ++ /* ++ * Yes, we can merge the memory starting at addr into the ++ * existing region from below. Align up addr to GRUB_MM_ALIGN ++ * so that our new region has proper alignment. ++ */ + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); ++ /* Copy the region data across */ + *r = *q; ++ /* Consider all the new size as pre-size */ + r->pre_size += size; +- ++ ++ /* ++ * If we have enough pre-size to create a block, create a ++ * block with it. Mark it as allocated and pass it to ++ * grub_free (), which will sort out getting it into the free ++ * list. ++ */ + if (r->pre_size >> GRUB_MM_ALIGN_LOG2) + { + h = (grub_mm_header_t) (r + 1); ++ /* block size is pre-size converted to cells */ + h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); + h->magic = GRUB_MM_ALLOC_MAGIC; ++ /* region size grows by block size converted back to bytes */ + r->size += h->size << GRUB_MM_ALIGN_LOG2; ++ /* adjust pre_size to be accurate */ + r->pre_size &= (GRUB_MM_ALIGN - 1); + *p = r; + grub_free (h + 1); + } ++ /* Replace the old region with the new region */ + *p = r; + return; + } diff --git a/0296-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch b/0296-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch deleted file mode 100644 index ec2184f..0000000 --- a/0296-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 28 Oct 2022 21:31:39 +0800 -Subject: [PATCH] normal/charset: Fix an integer overflow in - grub_unicode_aglomerate_comb() - -The out->ncomb is a bit-field of 8 bits. So, the max possible value is 255. -However, code in grub_unicode_aglomerate_comb() doesn't check for an -overflow when incrementing out->ncomb. If out->ncomb is already 255, -after incrementing it will get 0 instead of 256, and cause illegal -memory access in subsequent processing. - -This patch introduces GRUB_UNICODE_NCOMB_MAX to represent the max -acceptable value of ncomb. The code now checks for this limit and -ignores additional combining characters when limit is reached. - -Reported-by: Daniel Axtens -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit da90d62316a3b105d2fbd7334d6521936bd6dcf6) ---- - grub-core/normal/charset.c | 3 +++ - include/grub/unicode.h | 2 ++ - 2 files changed, 5 insertions(+) - -diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c -index 7a5a7c153c..c243ca6dae 100644 ---- a/grub-core/normal/charset.c -+++ b/grub-core/normal/charset.c -@@ -472,6 +472,9 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, - if (!haveout) - continue; - -+ if (out->ncomb == GRUB_UNICODE_NCOMB_MAX) -+ continue; -+ - if (comb_type == GRUB_UNICODE_COMB_MC - || comb_type == GRUB_UNICODE_COMB_ME - || comb_type == GRUB_UNICODE_COMB_MN) -diff --git a/include/grub/unicode.h b/include/grub/unicode.h -index 4de986a857..c4f6fca043 100644 ---- a/include/grub/unicode.h -+++ b/include/grub/unicode.h -@@ -147,7 +147,9 @@ struct grub_unicode_glyph - grub_uint8_t bidi_level:6; /* minimum: 6 */ - enum grub_bidi_type bidi_type:5; /* minimum: :5 */ - -+#define GRUB_UNICODE_NCOMB_MAX ((1 << 8) - 1) - unsigned ncomb:8; -+ - /* Hint by unicode subsystem how wide this character usually is. - Real width is determined by font. Set only in UTF-8 stream. */ - int estimated_width:8; diff --git a/0297-font-Try-opening-fonts-from-the-bundled-memdisk.patch b/0297-font-Try-opening-fonts-from-the-bundled-memdisk.patch deleted file mode 100644 index bad9d90..0000000 --- a/0297-font-Try-opening-fonts-from-the-bundled-memdisk.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Wed, 16 Nov 2022 14:40:04 +0000 -Subject: [PATCH] font: Try opening fonts from the bundled memdisk - -Signed-off-by: Robbie Harwood ---- - grub-core/font/font.c | 48 +++++++++++++++++++++++++++++++----------------- - 1 file changed, 31 insertions(+), 17 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index e6616e610c..e421d1ae6f 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -409,6 +409,27 @@ read_section_as_short (struct font_file_section *section, - return 0; - } - -+static grub_file_t -+try_open_from_prefix (const char *prefix, const char *filename) -+{ -+ grub_file_t file; -+ char *fullname, *ptr; -+ -+ fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1 -+ + sizeof ("/fonts/") + sizeof (".pf2")); -+ if (!fullname) -+ return 0; -+ ptr = grub_stpcpy (fullname, prefix); -+ ptr = grub_stpcpy (ptr, "/fonts/"); -+ ptr = grub_stpcpy (ptr, filename); -+ ptr = grub_stpcpy (ptr, ".pf2"); -+ *ptr = 0; -+ -+ file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024); -+ grub_free (fullname); -+ return file; -+} -+ - /* Load a font and add it to the beginning of the global font list. - Returns 0 upon success, nonzero upon failure. */ - grub_font_t -@@ -427,25 +448,18 @@ grub_font_load (const char *filename) - file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024); - else - { -- const char *prefix = grub_env_get ("prefix"); -- char *fullname, *ptr; -- if (!prefix) -+ file = try_open_from_prefix ("(memdisk)", filename); -+ if (!file) - { -- grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), -- "prefix"); -- goto fail; -+ const char *prefix = grub_env_get ("prefix"); -+ if (!prefix) -+ { -+ grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), -+ "prefix"); -+ goto fail; -+ } -+ file = try_open_from_prefix (prefix, filename); - } -- fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1 -- + sizeof ("/fonts/") + sizeof (".pf2")); -- if (!fullname) -- goto fail; -- ptr = grub_stpcpy (fullname, prefix); -- ptr = grub_stpcpy (ptr, "/fonts/"); -- ptr = grub_stpcpy (ptr, filename); -- ptr = grub_stpcpy (ptr, ".pf2"); -- *ptr = 0; -- file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024); -- grub_free (fullname); - } - if (!file) - goto fail; diff --git a/0297-mm-Document-GRUB-internal-memory-management-structur.patch b/0297-mm-Document-GRUB-internal-memory-management-structur.patch new file mode 100644 index 0000000..c793926 --- /dev/null +++ b/0297-mm-Document-GRUB-internal-memory-management-structur.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 25 Nov 2021 02:22:45 +1100 +Subject: [PATCH] mm: Document GRUB internal memory management structures + +I spent more than a trivial quantity of time figuring out pre_size and +whether a memory region's size contains the header cell or not. + +Document the meanings of all the properties. Hopefully now no-one else +has to figure it out! + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit a6c5c52ccffd2674d43db25fb4baa9c528526aa0) +--- + include/grub/mm_private.h | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h +index c2c4cb1511..203533cc3d 100644 +--- a/include/grub/mm_private.h ++++ b/include/grub/mm_private.h +@@ -21,15 +21,27 @@ + + #include + ++/* For context, see kern/mm.c */ ++ + /* Magic words. */ + #define GRUB_MM_FREE_MAGIC 0x2d3c2808 + #define GRUB_MM_ALLOC_MAGIC 0x6db08fa4 + ++/* A header describing a block of memory - either allocated or free */ + typedef struct grub_mm_header + { ++ /* ++ * The 'next' free block in this region's circular free list. ++ * Only meaningful if the block is free. ++ */ + struct grub_mm_header *next; ++ /* The block size, not in bytes but the number of cells of ++ * GRUB_MM_ALIGN bytes. Includes the header cell. ++ */ + grub_size_t size; ++ /* either free or alloc magic, depending on the block type. */ + grub_size_t magic; ++ /* pad to cell size: see the top of kern/mm.c. */ + #if GRUB_CPU_SIZEOF_VOID_P == 4 + char padding[4]; + #elif GRUB_CPU_SIZEOF_VOID_P == 8 +@@ -48,11 +60,27 @@ typedef struct grub_mm_header + + #define GRUB_MM_ALIGN (1 << GRUB_MM_ALIGN_LOG2) + ++/* A region from which we can make allocations. */ + typedef struct grub_mm_region + { ++ /* The first free block in this region. */ + struct grub_mm_header *first; ++ ++ /* ++ * The next region in the linked list of regions. Regions are initially ++ * sorted in order of increasing size, but can grow, in which case the ++ * ordering may not be preserved. ++ */ + struct grub_mm_region *next; ++ ++ /* ++ * A grub_mm_region will always be aligned to cell size. The pre-size is ++ * the number of bytes we were given but had to skip in order to get that ++ * alignment. ++ */ + grub_size_t pre_size; ++ ++ /* How many bytes are in this region? (free and allocated) */ + grub_size_t size; + } + *grub_mm_region_t; diff --git a/0298-Correction-in-vector-5-values.patch b/0298-Correction-in-vector-5-values.patch deleted file mode 100644 index 9be1f4a..0000000 --- a/0298-Correction-in-vector-5-values.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Avnish Chouhan -Date: Tue, 22 Nov 2022 08:01:47 -0500 -Subject: [PATCH] Correction in vector 5 values - -This patch is to update the vector 5 values which is troubling some -machines to bootup properly. Max out the values of all the properties of -Vector 5 (similar to vector 2) except max cpu property, which were set -as 0 earlier. - -Signed-off-by: Avnish Chouhan -[rharwood: rewrap comit message] -Signed-off-by: Robbie Harwood ---- - grub-core/kern/ieee1275/init.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index 6a51c9efab..28a3bd4621 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -376,7 +376,7 @@ grub_ieee1275_ibm_cas (void) - .vec4 = 0x0001, // set required minimum capacity % to the lowest value - .vec5_size = 1 + sizeof(struct option_vector5) - 2, - .vec5 = { -- 0, 0, 0, 0, 0, 0, 0, 0, 256 -+ -1, -1, -1, -1, -1, -1, -1, -1, 256 - } - }; - diff --git a/0298-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch b/0298-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch new file mode 100644 index 0000000..2893784 --- /dev/null +++ b/0298-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 21 Apr 2022 15:24:14 +1000 +Subject: [PATCH] mm: Assert that we preserve header vs region alignment + +grub_mm_region_init() does: + + h = (grub_mm_header_t) (r + 1); + +where h is a grub_mm_header_t and r is a grub_mm_region_t. + +Cells are supposed to be GRUB_MM_ALIGN aligned, but while grub_mm_dump +ensures this vs the region header, grub_mm_region_init() does not. + +It's better to be explicit than implicit here: rather than changing +grub_mm_region_init() to ALIGN_UP(), require that the struct is +explicitly a multiple of the header size. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 1df8fe66c57087eb33bd6dc69f786ed124615aa7) +--- + include/grub/mm_private.h | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h +index 203533cc3d..a688b92a83 100644 +--- a/include/grub/mm_private.h ++++ b/include/grub/mm_private.h +@@ -20,6 +20,7 @@ + #define GRUB_MM_PRIVATE_H 1 + + #include ++#include + + /* For context, see kern/mm.c */ + +@@ -89,4 +90,17 @@ typedef struct grub_mm_region + extern grub_mm_region_t EXPORT_VAR (grub_mm_base); + #endif + ++static inline void ++grub_mm_size_sanity_check (void) { ++ /* Ensure we preserve alignment when doing h = (grub_mm_header_t) (r + 1). */ ++ COMPILE_TIME_ASSERT ((sizeof (struct grub_mm_region) % ++ sizeof (struct grub_mm_header)) == 0); ++ ++ /* ++ * GRUB_MM_ALIGN is supposed to represent cell size, and a mm_header is ++ * supposed to be 1 cell. ++ */ ++ COMPILE_TIME_ASSERT (sizeof (struct grub_mm_header) == GRUB_MM_ALIGN); ++} ++ + #endif diff --git a/0299-mm-Clarify-grub_real_malloc.patch b/0299-mm-Clarify-grub_real_malloc.patch deleted file mode 100644 index 0a99c08..0000000 --- a/0299-mm-Clarify-grub_real_malloc.patch +++ /dev/null @@ -1,183 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 25 Nov 2021 02:22:46 +1100 -Subject: [PATCH] mm: Clarify grub_real_malloc() - -When iterating through the singly linked list of free blocks, -grub_real_malloc() uses p and q for the current and previous blocks -respectively. This isn't super clear, so swap to using prev and cur. - -This makes another quirk more obvious. The comment at the top of -grub_real_malloc() might lead you to believe that the function will -allocate from *first if there is space in that block. - -It actually doesn't do that, and it can't do that with the current -data structures. If we used up all of *first, we would need to change -the ->next of the previous block to point to *first->next, but we -can't do that because it's a singly linked list and we don't have -access to *first's previous block. - -What grub_real_malloc() actually does is set *first to the initial -previous block, and *first->next is the block we try to allocate -from. That allows us to keep all the data structures consistent. - -Document that. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 246ad6a44c281bb13486ddea0a26bb661db73106) ---- - grub-core/kern/mm.c | 76 +++++++++++++++++++++++++++++------------------------ - 1 file changed, 41 insertions(+), 35 deletions(-) - -diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c -index d8c8377578..fb20e93acf 100644 ---- a/grub-core/kern/mm.c -+++ b/grub-core/kern/mm.c -@@ -178,13 +178,20 @@ grub_mm_init_region (void *addr, grub_size_t size) - } - - /* Allocate the number of units N with the alignment ALIGN from the ring -- buffer starting from *FIRST. ALIGN must be a power of two. Both N and -- ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful, -- otherwise return NULL. */ -+ * buffer given in *FIRST. ALIGN must be a power of two. Both N and -+ * ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful, -+ * otherwise return NULL. -+ * -+ * Note: because in certain circumstances we need to adjust the ->next -+ * pointer of the previous block, we iterate over the singly linked -+ * list with the pair (prev, cur). *FIRST is our initial previous, and -+ * *FIRST->next is our initial current pointer. So we will actually -+ * allocate from *FIRST->next first and *FIRST itself last. -+ */ - static void * - grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) - { -- grub_mm_header_t p, q; -+ grub_mm_header_t cur, prev; - - /* When everything is allocated side effect is that *first will have alloc - magic marked, meaning that there is no room in this region. */ -@@ -192,24 +199,24 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) - return 0; - - /* Try to search free slot for allocation in this memory region. */ -- for (q = *first, p = q->next; ; q = p, p = p->next) -+ for (prev = *first, cur = prev->next; ; prev = cur, cur = cur->next) - { - grub_off_t extra; - -- extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1); -+ extra = ((grub_addr_t) (cur + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1); - if (extra) - extra = align - extra; - -- if (! p) -+ if (! cur) - grub_fatal ("null in the ring"); - -- if (p->magic != GRUB_MM_FREE_MAGIC) -- grub_fatal ("free magic is broken at %p: 0x%x", p, p->magic); -+ if (cur->magic != GRUB_MM_FREE_MAGIC) -+ grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic); - -- if (p->size >= n + extra) -+ if (cur->size >= n + extra) - { -- extra += (p->size - extra - n) & (~(align - 1)); -- if (extra == 0 && p->size == n) -+ extra += (cur->size - extra - n) & (~(align - 1)); -+ if (extra == 0 && cur->size == n) - { - /* There is no special alignment requirement and memory block - is complete match. -@@ -222,9 +229,9 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) - | alloc, size=n | | - +---------------+ v - */ -- q->next = p->next; -+ prev->next = cur->next; - } -- else if (align == 1 || p->size == n + extra) -+ else if (align == 1 || cur->size == n + extra) - { - /* There might be alignment requirement, when taking it into - account memory block fits in. -@@ -241,23 +248,22 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) - | alloc, size=n | | - +---------------+ v - */ -- -- p->size -= n; -- p += p->size; -+ cur->size -= n; -+ cur += cur->size; - } - else if (extra == 0) - { - grub_mm_header_t r; - -- r = p + extra + n; -+ r = cur + extra + n; - r->magic = GRUB_MM_FREE_MAGIC; -- r->size = p->size - extra - n; -- r->next = p->next; -- q->next = r; -+ r->size = cur->size - extra - n; -+ r->next = cur->next; -+ prev->next = r; - -- if (q == p) -+ if (prev == cur) - { -- q = r; -+ prev = r; - r->next = r; - } - } -@@ -284,32 +290,32 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) - */ - grub_mm_header_t r; - -- r = p + extra + n; -+ r = cur + extra + n; - r->magic = GRUB_MM_FREE_MAGIC; -- r->size = p->size - extra - n; -- r->next = p; -+ r->size = cur->size - extra - n; -+ r->next = cur; - -- p->size = extra; -- q->next = r; -- p += extra; -+ cur->size = extra; -+ prev->next = r; -+ cur += extra; - } - -- p->magic = GRUB_MM_ALLOC_MAGIC; -- p->size = n; -+ cur->magic = GRUB_MM_ALLOC_MAGIC; -+ cur->size = n; - - /* Mark find as a start marker for next allocation to fasten it. - This will have side effect of fragmenting memory as small - pieces before this will be un-used. */ - /* So do it only for chunks under 64K. */ - if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2) -- || *first == p) -- *first = q; -+ || *first == cur) -+ *first = prev; - -- return p + 1; -+ return cur + 1; - } - - /* Search was completed without result. */ -- if (p == *first) -+ if (cur == *first) - break; - } - diff --git a/0299-mm-When-adding-a-region-merge-with-region-after-as-w.patch b/0299-mm-When-adding-a-region-merge-with-region-after-as-w.patch new file mode 100644 index 0000000..52cfeee --- /dev/null +++ b/0299-mm-When-adding-a-region-merge-with-region-after-as-w.patch @@ -0,0 +1,203 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 21 Apr 2022 15:24:15 +1000 +Subject: [PATCH] mm: When adding a region, merge with region after as well as + before + +On x86_64-efi (at least) regions seem to be added from top down. The mm +code will merge a new region with an existing region that comes +immediately before the new region. This allows larger allocations to be +satisfied that would otherwise be the case. + +On powerpc-ieee1275, however, regions are added from bottom up. So if +we add 3x 32MB regions, we can still only satisfy a 32MB allocation, +rather than the 96MB allocation we might otherwise be able to satisfy. + + * Define 'post_size' as being bytes lost to the end of an allocation + due to being given weird sizes from firmware that are not multiples + of GRUB_MM_ALIGN. + + * Allow merging of regions immediately _after_ existing regions, not + just before. As with the other approach, we create an allocated + block to represent the new space and the pass it to grub_free() to + get the metadata right. + +Signed-off-by: Daniel Axtens +Tested-by: Stefan Berger +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 052e6068be622ff53f1238b449c300dbd0a8abcd) +--- + grub-core/kern/mm.c | 128 +++++++++++++++++++++++++++++----------------- + include/grub/mm_private.h | 9 ++++ + 2 files changed, 91 insertions(+), 46 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 1cbf98c7ab..7be33e23bf 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -130,53 +130,88 @@ grub_mm_init_region (void *addr, grub_size_t size) + + /* Attempt to merge this region with every existing region */ + for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) +- /* +- * Is the new region immediately below an existing region? That +- * is, is the address of the memory we're adding now (addr) + size +- * of the memory we're adding (size) + the bytes we couldn't use +- * at the start of the region we're considering (q->pre_size) +- * equal to the address of q? In other words, does the memory +- * looks like this? +- * +- * addr q +- * |----size-----|-q->pre_size-|| +- */ +- if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) +- { +- /* +- * Yes, we can merge the memory starting at addr into the +- * existing region from below. Align up addr to GRUB_MM_ALIGN +- * so that our new region has proper alignment. +- */ +- r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); +- /* Copy the region data across */ +- *r = *q; +- /* Consider all the new size as pre-size */ +- r->pre_size += size; ++ { ++ /* ++ * Is the new region immediately below an existing region? That ++ * is, is the address of the memory we're adding now (addr) + size ++ * of the memory we're adding (size) + the bytes we couldn't use ++ * at the start of the region we're considering (q->pre_size) ++ * equal to the address of q? In other words, does the memory ++ * looks like this? ++ * ++ * addr q ++ * |----size-----|-q->pre_size-|| ++ */ ++ if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) ++ { ++ /* ++ * Yes, we can merge the memory starting at addr into the ++ * existing region from below. Align up addr to GRUB_MM_ALIGN ++ * so that our new region has proper alignment. ++ */ ++ r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); ++ /* Copy the region data across */ ++ *r = *q; ++ /* Consider all the new size as pre-size */ ++ r->pre_size += size; + +- /* +- * If we have enough pre-size to create a block, create a +- * block with it. Mark it as allocated and pass it to +- * grub_free (), which will sort out getting it into the free +- * list. +- */ +- if (r->pre_size >> GRUB_MM_ALIGN_LOG2) +- { +- h = (grub_mm_header_t) (r + 1); +- /* block size is pre-size converted to cells */ +- h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); +- h->magic = GRUB_MM_ALLOC_MAGIC; +- /* region size grows by block size converted back to bytes */ +- r->size += h->size << GRUB_MM_ALIGN_LOG2; +- /* adjust pre_size to be accurate */ +- r->pre_size &= (GRUB_MM_ALIGN - 1); +- *p = r; +- grub_free (h + 1); +- } +- /* Replace the old region with the new region */ +- *p = r; +- return; +- } ++ /* ++ * If we have enough pre-size to create a block, create a ++ * block with it. Mark it as allocated and pass it to ++ * grub_free (), which will sort out getting it into the free ++ * list. ++ */ ++ if (r->pre_size >> GRUB_MM_ALIGN_LOG2) ++ { ++ h = (grub_mm_header_t) (r + 1); ++ /* block size is pre-size converted to cells */ ++ h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); ++ h->magic = GRUB_MM_ALLOC_MAGIC; ++ /* region size grows by block size converted back to bytes */ ++ r->size += h->size << GRUB_MM_ALIGN_LOG2; ++ /* adjust pre_size to be accurate */ ++ r->pre_size &= (GRUB_MM_ALIGN - 1); ++ *p = r; ++ grub_free (h + 1); ++ } ++ /* Replace the old region with the new region */ ++ *p = r; ++ return; ++ } ++ ++ /* ++ * Is the new region immediately above an existing region? That ++ * is: ++ * q addr ++ * ||-q->post_size-|----size-----| ++ */ ++ if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size == ++ (grub_uint8_t *) addr) ++ { ++ /* ++ * Yes! Follow a similar pattern to above, but simpler. ++ * Our header starts at address - post_size, which should align us ++ * to a cell boundary. ++ * ++ * Cast to (void *) first to avoid the following build error: ++ * kern/mm.c: In function ‘grub_mm_init_region’: ++ * kern/mm.c:211:15: error: cast increases required alignment of target type [-Werror=cast-align] ++ * 211 | h = (grub_mm_header_t) ((grub_uint8_t *) addr - q->post_size); ++ * | ^ ++ * It is safe to do that because proper alignment is enforced in grub_mm_size_sanity_check(). ++ */ ++ h = (grub_mm_header_t)(void *) ((grub_uint8_t *) addr - q->post_size); ++ /* our size is the allocated size plus post_size, in cells */ ++ h->size = (size + q->post_size) >> GRUB_MM_ALIGN_LOG2; ++ h->magic = GRUB_MM_ALLOC_MAGIC; ++ /* region size grows by block size converted back to bytes */ ++ q->size += h->size << GRUB_MM_ALIGN_LOG2; ++ /* adjust new post_size to be accurate */ ++ q->post_size = (q->post_size + size) & (GRUB_MM_ALIGN - 1); ++ grub_free (h + 1); ++ return; ++ } ++ } + + /* Allocate a region from the head. */ + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); +@@ -195,6 +230,7 @@ grub_mm_init_region (void *addr, grub_size_t size) + r->first = h; + r->pre_size = (grub_addr_t) r - (grub_addr_t) addr; + r->size = (h->size << GRUB_MM_ALIGN_LOG2); ++ r->post_size = size - r->size; + + /* Find where to insert this region. Put a smaller one before bigger ones, + to prevent fragmentation. */ +diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h +index a688b92a83..96c2d816be 100644 +--- a/include/grub/mm_private.h ++++ b/include/grub/mm_private.h +@@ -81,8 +81,17 @@ typedef struct grub_mm_region + */ + grub_size_t pre_size; + ++ /* ++ * Likewise, the post-size is the number of bytes we wasted at the end ++ * of the allocation because it wasn't a multiple of GRUB_MM_ALIGN ++ */ ++ grub_size_t post_size; ++ + /* How many bytes are in this region? (free and allocated) */ + grub_size_t size; ++ ++ /* pad to a multiple of cell size */ ++ char padding[3 * GRUB_CPU_SIZEOF_VOID_P]; + } + *grub_mm_region_t; + diff --git a/0300-mm-Debug-support-for-region-operations.patch b/0300-mm-Debug-support-for-region-operations.patch new file mode 100644 index 0000000..f434260 --- /dev/null +++ b/0300-mm-Debug-support-for-region-operations.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 21 Apr 2022 15:24:16 +1000 +Subject: [PATCH] mm: Debug support for region operations + +This is handy for debugging. Enable with "set debug=regions". + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 8afa5ef45b797ba5d8147ceee85ac2c59dcc7f09) +--- + grub-core/kern/mm.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 7be33e23bf..38bfb01df9 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -115,9 +115,8 @@ grub_mm_init_region (void *addr, grub_size_t size) + grub_mm_header_t h; + grub_mm_region_t r, *p, q; + +-#if 0 +- grub_printf ("Using memory for heap: start=%p, end=%p\n", addr, addr + (unsigned int) size); +-#endif ++ grub_dprintf ("regions", "Using memory for heap: start=%p, end=%p\n", ++ addr, (char *) addr + (unsigned int) size); + + /* Exclude last 4K to avoid overflows. */ + /* If addr + 0x1000 overflows then whole region is in excluded zone. */ +@@ -142,8 +141,14 @@ grub_mm_init_region (void *addr, grub_size_t size) + * addr q + * |----size-----|-q->pre_size-|| + */ ++ grub_dprintf ("regions", "Can we extend into region above?" ++ " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n", ++ (grub_uint8_t *) addr, size, q->pre_size, (grub_uint8_t *) q); + if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) + { ++ grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n", ++ q, (grub_uint8_t *) q + sizeof (*q) + q->size, ++ addr, (grub_uint8_t *) q + sizeof (*q) + q->size); + /* + * Yes, we can merge the memory starting at addr into the + * existing region from below. Align up addr to GRUB_MM_ALIGN +@@ -185,9 +190,15 @@ grub_mm_init_region (void *addr, grub_size_t size) + * q addr + * ||-q->post_size-|----size-----| + */ ++ grub_dprintf ("regions", "Can we extend into region below?" ++ " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n", ++ (grub_uint8_t *) q, sizeof(*q), q->size, q->post_size, (grub_uint8_t *) addr); + if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size == + (grub_uint8_t *) addr) + { ++ grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n", ++ q, (grub_uint8_t *) q + sizeof (*q) + q->size, ++ q, (grub_uint8_t *) addr + size); + /* + * Yes! Follow a similar pattern to above, but simpler. + * Our header starts at address - post_size, which should align us +@@ -213,6 +224,8 @@ grub_mm_init_region (void *addr, grub_size_t size) + } + } + ++ grub_dprintf ("regions", "No: considering a new region at %p of size %" PRIxGRUB_SIZE "\n", ++ addr, size); + /* Allocate a region from the head. */ + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); + diff --git a/0300-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch b/0300-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch deleted file mode 100644 index a5601c9..0000000 --- a/0300-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 25 Nov 2021 02:22:47 +1100 -Subject: [PATCH] mm: grub_real_malloc(): Make small allocs comment match code - -Small allocations move the region's *first pointer. The comment -says that this happens for allocations under 64K. The code says -it's for allocations under 32K. Commit 45bf8b3a7549 changed the -code intentionally: make the comment match. - -Fixes: 45bf8b3a7549 (* grub-core/kern/mm.c (grub_real_malloc): Decrease cut-off of moving the) - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit a847895a8d000bdf27ad4d4326f883a0eed769ca) ---- - grub-core/kern/mm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c -index fb20e93acf..db7e0b2a5b 100644 ---- a/grub-core/kern/mm.c -+++ b/grub-core/kern/mm.c -@@ -306,7 +306,7 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) - /* Mark find as a start marker for next allocation to fasten it. - This will have side effect of fragmenting memory as small - pieces before this will be un-used. */ -- /* So do it only for chunks under 64K. */ -+ /* So do it only for chunks under 32K. */ - if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2) - || *first == cur) - *first = prev; diff --git a/0301-mm-Document-grub_free.patch b/0301-mm-Document-grub_free.patch deleted file mode 100644 index 6c9b7cc..0000000 --- a/0301-mm-Document-grub_free.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 25 Nov 2021 02:22:48 +1100 -Subject: [PATCH] mm: Document grub_free() - -The grub_free() possesses a surprising number of quirks, and also -uses single-letter variable names confusingly to iterate through -the free list. - -Document what's going on. - -Use prev and cur to iterate over the free list. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 1f8d0b01738e49767d662d6426af3570a64565f0) ---- - grub-core/kern/mm.c | 63 ++++++++++++++++++++++++++++++++++------------------- - 1 file changed, 41 insertions(+), 22 deletions(-) - -diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c -index db7e0b2a5b..0351171cf9 100644 ---- a/grub-core/kern/mm.c -+++ b/grub-core/kern/mm.c -@@ -446,54 +446,73 @@ grub_free (void *ptr) - } - else - { -- grub_mm_header_t q, s; -+ grub_mm_header_t cur, prev; - - #if 0 -- q = r->first; -+ cur = r->first; - do - { - grub_printf ("%s:%d: q=%p, q->size=0x%x, q->magic=0x%x\n", -- GRUB_FILE, __LINE__, q, q->size, q->magic); -- q = q->next; -+ GRUB_FILE, __LINE__, cur, cur->size, cur->magic); -+ cur = cur->next; - } -- while (q != r->first); -+ while (cur != r->first); - #endif -- -- for (s = r->first, q = s->next; q <= p || q->next >= p; s = q, q = s->next) -+ /* Iterate over all blocks in the free ring. -+ * -+ * The free ring is arranged from high addresses to low -+ * addresses, modulo wraparound. -+ * -+ * We are looking for a block with a higher address than p or -+ * whose next address is lower than p. -+ */ -+ for (prev = r->first, cur = prev->next; cur <= p || cur->next >= p; -+ prev = cur, cur = prev->next) - { -- if (q->magic != GRUB_MM_FREE_MAGIC) -- grub_fatal ("free magic is broken at %p: 0x%x", q, q->magic); -+ if (cur->magic != GRUB_MM_FREE_MAGIC) -+ grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic); - -- if (q <= q->next && (q > p || q->next < p)) -+ /* Deal with wrap-around */ -+ if (cur <= cur->next && (cur > p || cur->next < p)) - break; - } - -+ /* mark p as free and insert it between cur and cur->next */ - p->magic = GRUB_MM_FREE_MAGIC; -- p->next = q->next; -- q->next = p; -+ p->next = cur->next; -+ cur->next = p; - -+ /* -+ * If the block we are freeing can be merged with the next -+ * free block, do that. -+ */ - if (p->next + p->next->size == p) - { - p->magic = 0; - - p->next->size += p->size; -- q->next = p->next; -+ cur->next = p->next; - p = p->next; - } - -- r->first = q; -+ r->first = cur; - -- if (q == p + p->size) -+ /* Likewise if can be merged with the preceeding free block */ -+ if (cur == p + p->size) - { -- q->magic = 0; -- p->size += q->size; -- if (q == s) -- s = p; -- s->next = p; -- q = s; -+ cur->magic = 0; -+ p->size += cur->size; -+ if (cur == prev) -+ prev = p; -+ prev->next = p; -+ cur = prev; - } - -- r->first = q; -+ /* -+ * Set r->first such that the just free()d block is tried first. -+ * (An allocation is tried from *first->next, and cur->next == p.) -+ */ -+ r->first = cur; - } - } - diff --git a/0301-mm-Drop-unused-unloading-of-modules-on-OOM.patch b/0301-mm-Drop-unused-unloading-of-modules-on-OOM.patch new file mode 100644 index 0000000..a18d912 --- /dev/null +++ b/0301-mm-Drop-unused-unloading-of-modules-on-OOM.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:17 +1000 +Subject: [PATCH] mm: Drop unused unloading of modules on OOM + +In grub_memalign(), there's a commented section which would allow for +unloading of unneeded modules in case where there is not enough free +memory available to satisfy a request. Given that this code is never +compiled in, let's remove it together with grub_dl_unload_unneeded(). + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 139fd9b134a01e0b5fe0ebefafa7f48d1ffb6d60) +--- + grub-core/kern/dl.c | 20 -------------------- + grub-core/kern/mm.c | 8 -------- + include/grub/dl.h | 1 - + 3 files changed, 29 deletions(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index d5de80186f..ab9101a5ad 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -998,23 +998,3 @@ grub_dl_unload (grub_dl_t mod) + grub_free (mod); + return 1; + } +- +-/* Unload unneeded modules. */ +-void +-grub_dl_unload_unneeded (void) +-{ +- /* Because grub_dl_remove modifies the list of modules, this +- implementation is tricky. */ +- grub_dl_t p = grub_dl_head; +- +- while (p) +- { +- if (grub_dl_unload (p)) +- { +- p = grub_dl_head; +- continue; +- } +- +- p = p->next; +- } +-} +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 38bfb01df9..1825dc8289 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -444,14 +444,6 @@ grub_memalign (grub_size_t align, grub_size_t size) + count++; + goto again; + +-#if 0 +- case 1: +- /* Unload unneeded modules. */ +- grub_dl_unload_unneeded (); +- count++; +- goto again; +-#endif +- + default: + break; + } +diff --git a/include/grub/dl.h b/include/grub/dl.h +index 45ac8e339f..6bc2560bf0 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -206,7 +206,6 @@ grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name); + grub_dl_t grub_dl_load_core (void *addr, grub_size_t size); + grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size); + int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod); +-extern void grub_dl_unload_unneeded (void); + extern int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod); + extern int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod); + extern int EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod); diff --git a/0302-mm-Allow-dynamically-requesting-additional-memory-re.patch b/0302-mm-Allow-dynamically-requesting-additional-memory-re.patch new file mode 100644 index 0000000..d225c10 --- /dev/null +++ b/0302-mm-Allow-dynamically-requesting-additional-memory-re.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:18 +1000 +Subject: [PATCH] mm: Allow dynamically requesting additional memory regions + +Currently, all platforms will set up their heap on initialization of the +platform code. While this works mostly fine, it poses some limitations +on memory management on us. Most notably, allocating big chunks of +memory in the gigabyte range would require us to pre-request this many +bytes from the firmware and add it to the heap from the beginning on +some platforms like EFI. As this isn't needed for most configurations, +it is inefficient and may even negatively impact some usecases when, +e.g., chainloading. Nonetheless, allocating big chunks of memory is +required sometimes, where one example is the upcoming support for the +Argon2 key derival function in LUKS2. + +In order to avoid pre-allocating big chunks of memory, this commit +implements a runtime mechanism to add more pages to the system. When +a given allocation cannot be currently satisfied, we'll call a given +callback set up by the platform's own memory management subsystem, +asking it to add a memory area with at least "n" bytes. If this +succeeds, we retry searching for a valid memory region, which should +now succeed. + +If this fails, we try asking for "n" bytes, possibly spread across +multiple regions, in hopes that region merging means that we end up +with enough memory for things to work out. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Tested-by: Stefan Berger +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 887f98f0db43e33fba4ec1f85e42fae1185700bc) +--- + grub-core/kern/mm.c | 30 ++++++++++++++++++++++++++++++ + include/grub/mm.h | 18 ++++++++++++++++++ + 2 files changed, 48 insertions(+) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 1825dc8289..f2e27f263b 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -28,6 +28,9 @@ + - multiple regions may be used as free space. They may not be + contiguous. + ++ - if existing regions are insufficient to satisfy an allocation, a new ++ region can be requested from firmware. ++ + Regions are managed by a singly linked list, and the meta information is + stored in the beginning of each region. Space after the meta information + is used to allocate memory. +@@ -81,6 +84,7 @@ + + + grub_mm_region_t grub_mm_base; ++grub_mm_add_region_func_t grub_mm_add_region_fn; + + /* Get a header from the pointer PTR, and set *P and *R to a pointer + to the header and a pointer to its region, respectively. PTR must +@@ -444,6 +448,32 @@ grub_memalign (grub_size_t align, grub_size_t size) + count++; + goto again; + ++ case 1: ++ /* Request additional pages, contiguous */ ++ count++; ++ ++ if (grub_mm_add_region_fn != NULL && ++ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) ++ goto again; ++ ++ /* fallthrough */ ++ ++ case 2: ++ /* Request additional pages, anything at all */ ++ count++; ++ ++ if (grub_mm_add_region_fn != NULL) ++ { ++ /* ++ * Try again even if this fails, in case it was able to partially ++ * satisfy the request ++ */ ++ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE); ++ goto again; ++ } ++ ++ /* fallthrough */ ++ + default: + break; + } +diff --git a/include/grub/mm.h b/include/grub/mm.h +index d81623d226..7c6f925ffd 100644 +--- a/include/grub/mm.h ++++ b/include/grub/mm.h +@@ -20,6 +20,7 @@ + #ifndef GRUB_MM_H + #define GRUB_MM_H 1 + ++#include + #include + #include + #include +@@ -29,6 +30,23 @@ + # define NULL ((void *) 0) + #endif + ++#define GRUB_MM_ADD_REGION_NONE 0 ++#define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0) ++ ++/* ++ * Function used to request memory regions of `grub_size_t` bytes. The second ++ * parameter is a bitfield of `GRUB_MM_ADD_REGION` flags. ++ */ ++typedef grub_err_t (*grub_mm_add_region_func_t) (grub_size_t, unsigned int); ++ ++/* ++ * Set this function pointer to enable adding memory-regions at runtime in case ++ * a memory allocation cannot be satisfied with existing regions. ++ */ ++#ifndef GRUB_MACHINE_EMU ++extern grub_mm_add_region_func_t EXPORT_VAR(grub_mm_add_region_fn); ++#endif ++ + void grub_mm_init_region (void *addr, grub_size_t size); + void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size); + void *EXPORT_FUNC(grub_malloc) (grub_size_t size); diff --git a/0302-mm-Document-grub_mm_init_region.patch b/0302-mm-Document-grub_mm_init_region.patch deleted file mode 100644 index 0173f04..0000000 --- a/0302-mm-Document-grub_mm_init_region.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 25 Nov 2021 02:22:49 +1100 -Subject: [PATCH] mm: Document grub_mm_init_region() - -The grub_mm_init_region() does some things that seem magical, especially -around region merging. Make it a bit clearer. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 246d69b7ea619fc1e77dcc5960e37aea45a9808c) ---- - grub-core/kern/mm.c | 31 ++++++++++++++++++++++++++++++- - 1 file changed, 30 insertions(+), 1 deletion(-) - -diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c -index 0351171cf9..1cbf98c7ab 100644 ---- a/grub-core/kern/mm.c -+++ b/grub-core/kern/mm.c -@@ -128,23 +128,52 @@ grub_mm_init_region (void *addr, grub_size_t size) - if (((grub_addr_t) addr + 0x1000) > ~(grub_addr_t) size) - size = ((grub_addr_t) -0x1000) - (grub_addr_t) addr; - -+ /* Attempt to merge this region with every existing region */ - for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) -+ /* -+ * Is the new region immediately below an existing region? That -+ * is, is the address of the memory we're adding now (addr) + size -+ * of the memory we're adding (size) + the bytes we couldn't use -+ * at the start of the region we're considering (q->pre_size) -+ * equal to the address of q? In other words, does the memory -+ * looks like this? -+ * -+ * addr q -+ * |----size-----|-q->pre_size-|| -+ */ - if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) - { -+ /* -+ * Yes, we can merge the memory starting at addr into the -+ * existing region from below. Align up addr to GRUB_MM_ALIGN -+ * so that our new region has proper alignment. -+ */ - r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); -+ /* Copy the region data across */ - *r = *q; -+ /* Consider all the new size as pre-size */ - r->pre_size += size; -- -+ -+ /* -+ * If we have enough pre-size to create a block, create a -+ * block with it. Mark it as allocated and pass it to -+ * grub_free (), which will sort out getting it into the free -+ * list. -+ */ - if (r->pre_size >> GRUB_MM_ALIGN_LOG2) - { - h = (grub_mm_header_t) (r + 1); -+ /* block size is pre-size converted to cells */ - h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); - h->magic = GRUB_MM_ALLOC_MAGIC; -+ /* region size grows by block size converted back to bytes */ - r->size += h->size << GRUB_MM_ALIGN_LOG2; -+ /* adjust pre_size to be accurate */ - r->pre_size &= (GRUB_MM_ALIGN - 1); - *p = r; - grub_free (h + 1); - } -+ /* Replace the old region with the new region */ - *p = r; - return; - } diff --git a/0303-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch b/0303-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch new file mode 100644 index 0000000..6fa378c --- /dev/null +++ b/0303-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:19 +1000 +Subject: [PATCH] kern/efi/mm: Always request a fixed number of pages on init + +When initializing the EFI memory subsystem, we will by default request +a quarter of the available memory, bounded by a minimum/maximum value. +Given that we're about to extend the EFI memory system to dynamically +request additional pages from the firmware as required, this scaling of +requested memory based on available memory will not make a lot of sense +anymore. + +Remove this logic as a preparatory patch such that we'll instead defer +to the runtime memory allocator. Note that ideally, we'd want to change +this after dynamic requesting of pages has been implemented for the EFI +platform. But because we'll need to split up initialization of the +memory subsystem and the request of pages from the firmware, we'd have +to duplicate quite some logic at first only to remove it afterwards +again. This seems quite pointless, so we instead have patches slightly +out of order. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 938c3760b8c0fca759140be48307179b50107ff6) +--- + grub-core/kern/efi/mm.c | 35 +++-------------------------------- + 1 file changed, 3 insertions(+), 32 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index e460b072e6..782a1365a1 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -38,9 +38,8 @@ + a multiplier of 4KB. */ + #define MEMORY_MAP_SIZE 0x3000 + +-/* The minimum and maximum heap size for GRUB itself. */ +-#define MIN_HEAP_SIZE 0x100000 +-#define MAX_HEAP_SIZE (1600 * 0x100000) ++/* The default heap size for GRUB itself in bytes. */ ++#define DEFAULT_HEAP_SIZE 0x100000 + + static void *finish_mmap_buf = 0; + static grub_efi_uintn_t finish_mmap_size = 0; +@@ -514,23 +513,6 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + return filtered_desc; + } + +-/* Return the total number of pages. */ +-static grub_efi_uint64_t +-get_total_pages (grub_efi_memory_descriptor_t *memory_map, +- grub_efi_uintn_t desc_size, +- grub_efi_memory_descriptor_t *memory_map_end) +-{ +- grub_efi_memory_descriptor_t *desc; +- grub_efi_uint64_t total = 0; +- +- for (desc = memory_map; +- desc < memory_map_end; +- desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) +- total += desc->num_pages; +- +- return total; +-} +- + /* Add memory regions. */ + static void + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, +@@ -694,8 +676,6 @@ grub_efi_mm_init (void) + grub_efi_memory_descriptor_t *filtered_memory_map_end; + grub_efi_uintn_t map_size; + grub_efi_uintn_t desc_size; +- grub_efi_uint64_t total_pages; +- grub_efi_uint64_t required_pages; + int mm_status; + + grub_nx_init (); +@@ -737,22 +717,13 @@ grub_efi_mm_init (void) + filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, + desc_size, memory_map_end); + +- /* By default, request a quarter of the available memory. */ +- total_pages = get_total_pages (filtered_memory_map, desc_size, +- filtered_memory_map_end); +- required_pages = (total_pages >> 2); +- if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE)) +- required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE); +- else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE)) +- required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE); +- + /* Sort the filtered descriptors, so that GRUB can allocate pages + from smaller regions. */ + sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); + + /* Allocate memory regions for GRUB's memory management. */ + add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, required_pages); ++ filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE)); + + #if 0 + /* For debug. */ diff --git a/0303-mm-Document-GRUB-internal-memory-management-structur.patch b/0303-mm-Document-GRUB-internal-memory-management-structur.patch deleted file mode 100644 index c793926..0000000 --- a/0303-mm-Document-GRUB-internal-memory-management-structur.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 25 Nov 2021 02:22:45 +1100 -Subject: [PATCH] mm: Document GRUB internal memory management structures - -I spent more than a trivial quantity of time figuring out pre_size and -whether a memory region's size contains the header cell or not. - -Document the meanings of all the properties. Hopefully now no-one else -has to figure it out! - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit a6c5c52ccffd2674d43db25fb4baa9c528526aa0) ---- - include/grub/mm_private.h | 28 ++++++++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - -diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h -index c2c4cb1511..203533cc3d 100644 ---- a/include/grub/mm_private.h -+++ b/include/grub/mm_private.h -@@ -21,15 +21,27 @@ - - #include - -+/* For context, see kern/mm.c */ -+ - /* Magic words. */ - #define GRUB_MM_FREE_MAGIC 0x2d3c2808 - #define GRUB_MM_ALLOC_MAGIC 0x6db08fa4 - -+/* A header describing a block of memory - either allocated or free */ - typedef struct grub_mm_header - { -+ /* -+ * The 'next' free block in this region's circular free list. -+ * Only meaningful if the block is free. -+ */ - struct grub_mm_header *next; -+ /* The block size, not in bytes but the number of cells of -+ * GRUB_MM_ALIGN bytes. Includes the header cell. -+ */ - grub_size_t size; -+ /* either free or alloc magic, depending on the block type. */ - grub_size_t magic; -+ /* pad to cell size: see the top of kern/mm.c. */ - #if GRUB_CPU_SIZEOF_VOID_P == 4 - char padding[4]; - #elif GRUB_CPU_SIZEOF_VOID_P == 8 -@@ -48,11 +60,27 @@ typedef struct grub_mm_header - - #define GRUB_MM_ALIGN (1 << GRUB_MM_ALIGN_LOG2) - -+/* A region from which we can make allocations. */ - typedef struct grub_mm_region - { -+ /* The first free block in this region. */ - struct grub_mm_header *first; -+ -+ /* -+ * The next region in the linked list of regions. Regions are initially -+ * sorted in order of increasing size, but can grow, in which case the -+ * ordering may not be preserved. -+ */ - struct grub_mm_region *next; -+ -+ /* -+ * A grub_mm_region will always be aligned to cell size. The pre-size is -+ * the number of bytes we were given but had to skip in order to get that -+ * alignment. -+ */ - grub_size_t pre_size; -+ -+ /* How many bytes are in this region? (free and allocated) */ - grub_size_t size; - } - *grub_mm_region_t; diff --git a/0304-kern-efi-mm-Extract-function-to-add-memory-regions.patch b/0304-kern-efi-mm-Extract-function-to-add-memory-regions.patch new file mode 100644 index 0000000..28cf2e7 --- /dev/null +++ b/0304-kern-efi-mm-Extract-function-to-add-memory-regions.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:20 +1000 +Subject: [PATCH] kern/efi/mm: Extract function to add memory regions + +In preparation of support for runtime-allocating additional memory +region, this patch extracts the function to retrieve the EFI memory +map and add a subset of it to GRUB's own memory regions. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 96a7ea29e3cb61b6c2302e260e8e6a6117e17fa3) +[rharwood: backport around our nx] +--- + grub-core/kern/efi/mm.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 782a1365a1..a1d3b51fe6 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -667,8 +667,8 @@ grub_nx_init (void) + } + } + +-void +-grub_efi_mm_init (void) ++static grub_err_t ++grub_efi_mm_add_regions (grub_size_t required_bytes) + { + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; +@@ -683,7 +683,7 @@ grub_efi_mm_init (void) + /* Prepare a memory region to store two memory maps. */ + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + if (! memory_map) +- grub_fatal ("cannot allocate memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map"); + + /* Obtain descriptors for available memory. */ + map_size = MEMORY_MAP_SIZE; +@@ -701,14 +701,14 @@ grub_efi_mm_init (void) + + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size)); + if (! memory_map) +- grub_fatal ("cannot allocate memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map"); + + mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, + &desc_size, 0); + } + + if (mm_status < 0) +- grub_fatal ("cannot get memory map"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "error fetching memory map from EFI"); + + memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); + +@@ -723,7 +723,7 @@ grub_efi_mm_init (void) + + /* Allocate memory regions for GRUB's memory management. */ + add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE)); ++ filtered_memory_map_end, BYTES_TO_PAGES (required_bytes)); + + #if 0 + /* For debug. */ +@@ -741,6 +741,15 @@ grub_efi_mm_init (void) + /* Release the memory maps. */ + grub_efi_free_pages ((grub_addr_t) memory_map, + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); ++ ++ return GRUB_ERR_NONE; ++} ++ ++void ++grub_efi_mm_init (void) ++{ ++ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE) ++ grub_fatal ("%s", grub_errmsg); + } + + #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) diff --git a/0304-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch b/0304-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch deleted file mode 100644 index 2893784..0000000 --- a/0304-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 21 Apr 2022 15:24:14 +1000 -Subject: [PATCH] mm: Assert that we preserve header vs region alignment - -grub_mm_region_init() does: - - h = (grub_mm_header_t) (r + 1); - -where h is a grub_mm_header_t and r is a grub_mm_region_t. - -Cells are supposed to be GRUB_MM_ALIGN aligned, but while grub_mm_dump -ensures this vs the region header, grub_mm_region_init() does not. - -It's better to be explicit than implicit here: rather than changing -grub_mm_region_init() to ALIGN_UP(), require that the struct is -explicitly a multiple of the header size. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -Tested-by: Patrick Steinhardt -(cherry picked from commit 1df8fe66c57087eb33bd6dc69f786ed124615aa7) ---- - include/grub/mm_private.h | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h -index 203533cc3d..a688b92a83 100644 ---- a/include/grub/mm_private.h -+++ b/include/grub/mm_private.h -@@ -20,6 +20,7 @@ - #define GRUB_MM_PRIVATE_H 1 - - #include -+#include - - /* For context, see kern/mm.c */ - -@@ -89,4 +90,17 @@ typedef struct grub_mm_region - extern grub_mm_region_t EXPORT_VAR (grub_mm_base); - #endif - -+static inline void -+grub_mm_size_sanity_check (void) { -+ /* Ensure we preserve alignment when doing h = (grub_mm_header_t) (r + 1). */ -+ COMPILE_TIME_ASSERT ((sizeof (struct grub_mm_region) % -+ sizeof (struct grub_mm_header)) == 0); -+ -+ /* -+ * GRUB_MM_ALIGN is supposed to represent cell size, and a mm_header is -+ * supposed to be 1 cell. -+ */ -+ COMPILE_TIME_ASSERT (sizeof (struct grub_mm_header) == GRUB_MM_ALIGN); -+} -+ - #endif diff --git a/0305-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch b/0305-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch new file mode 100644 index 0000000..b4b7891 --- /dev/null +++ b/0305-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:21 +1000 +Subject: [PATCH] kern/efi/mm: Pass up errors from add_memory_regions() + +The function add_memory_regions() is currently only called on system +initialization to allocate a fixed amount of pages. As such, it didn't +need to return any errors: in case it failed, we cannot proceed anyway. +This will change with the upcoming support for requesting more memory +from the firmware at runtime, where it doesn't make sense anymore to +fail hard. + +Refactor the function to return an error to prepare for this. Note that +this does not change the behaviour when initializing the memory system +because grub_efi_mm_init() knows to call grub_fatal() in case +grub_efi_mm_add_regions() returns an error. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 15a015698921240adc1ac266a3b5bc5fcbd81521) +--- + grub-core/kern/efi/mm.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index a1d3b51fe6..e0ebc65dba 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -514,7 +514,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + } + + /* Add memory regions. */ +-static void ++static grub_err_t + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end, +@@ -542,9 +542,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + GRUB_EFI_ALLOCATE_ADDRESS, + GRUB_EFI_LOADER_CODE); + if (! addr) +- grub_fatal ("cannot allocate conventional memory %p with %u pages", +- (void *) ((grub_addr_t) start), +- (unsigned) pages); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Memory starting at %p (%u pages) marked as free, but EFI would not allocate", ++ (void *) ((grub_addr_t) start), (unsigned) pages); + + grub_mm_init_region (addr, PAGES_TO_BYTES (pages)); + +@@ -554,7 +554,11 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + } + + if (required_pages > 0) +- grub_fatal ("too little memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "could not allocate all requested memory: %" PRIuGRUB_UINT64_T " pages still required after iterating EFI memory map", ++ required_pages); ++ ++ return GRUB_ERR_NONE; + } + + void +@@ -676,6 +680,7 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + grub_efi_memory_descriptor_t *filtered_memory_map_end; + grub_efi_uintn_t map_size; + grub_efi_uintn_t desc_size; ++ grub_err_t err; + int mm_status; + + grub_nx_init (); +@@ -722,8 +727,11 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); + + /* Allocate memory regions for GRUB's memory management. */ +- add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, BYTES_TO_PAGES (required_bytes)); ++ err = add_memory_regions (filtered_memory_map, desc_size, ++ filtered_memory_map_end, ++ BYTES_TO_PAGES (required_bytes)); ++ if (err != GRUB_ERR_NONE) ++ return err; + + #if 0 + /* For debug. */ diff --git a/0305-mm-When-adding-a-region-merge-with-region-after-as-w.patch b/0305-mm-When-adding-a-region-merge-with-region-after-as-w.patch deleted file mode 100644 index 52cfeee..0000000 --- a/0305-mm-When-adding-a-region-merge-with-region-after-as-w.patch +++ /dev/null @@ -1,203 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 21 Apr 2022 15:24:15 +1000 -Subject: [PATCH] mm: When adding a region, merge with region after as well as - before - -On x86_64-efi (at least) regions seem to be added from top down. The mm -code will merge a new region with an existing region that comes -immediately before the new region. This allows larger allocations to be -satisfied that would otherwise be the case. - -On powerpc-ieee1275, however, regions are added from bottom up. So if -we add 3x 32MB regions, we can still only satisfy a 32MB allocation, -rather than the 96MB allocation we might otherwise be able to satisfy. - - * Define 'post_size' as being bytes lost to the end of an allocation - due to being given weird sizes from firmware that are not multiples - of GRUB_MM_ALIGN. - - * Allow merging of regions immediately _after_ existing regions, not - just before. As with the other approach, we create an allocated - block to represent the new space and the pass it to grub_free() to - get the metadata right. - -Signed-off-by: Daniel Axtens -Tested-by: Stefan Berger -Reviewed-by: Daniel Kiper -Tested-by: Patrick Steinhardt -(cherry picked from commit 052e6068be622ff53f1238b449c300dbd0a8abcd) ---- - grub-core/kern/mm.c | 128 +++++++++++++++++++++++++++++----------------- - include/grub/mm_private.h | 9 ++++ - 2 files changed, 91 insertions(+), 46 deletions(-) - -diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c -index 1cbf98c7ab..7be33e23bf 100644 ---- a/grub-core/kern/mm.c -+++ b/grub-core/kern/mm.c -@@ -130,53 +130,88 @@ grub_mm_init_region (void *addr, grub_size_t size) - - /* Attempt to merge this region with every existing region */ - for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) -- /* -- * Is the new region immediately below an existing region? That -- * is, is the address of the memory we're adding now (addr) + size -- * of the memory we're adding (size) + the bytes we couldn't use -- * at the start of the region we're considering (q->pre_size) -- * equal to the address of q? In other words, does the memory -- * looks like this? -- * -- * addr q -- * |----size-----|-q->pre_size-|| -- */ -- if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) -- { -- /* -- * Yes, we can merge the memory starting at addr into the -- * existing region from below. Align up addr to GRUB_MM_ALIGN -- * so that our new region has proper alignment. -- */ -- r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); -- /* Copy the region data across */ -- *r = *q; -- /* Consider all the new size as pre-size */ -- r->pre_size += size; -+ { -+ /* -+ * Is the new region immediately below an existing region? That -+ * is, is the address of the memory we're adding now (addr) + size -+ * of the memory we're adding (size) + the bytes we couldn't use -+ * at the start of the region we're considering (q->pre_size) -+ * equal to the address of q? In other words, does the memory -+ * looks like this? -+ * -+ * addr q -+ * |----size-----|-q->pre_size-|| -+ */ -+ if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) -+ { -+ /* -+ * Yes, we can merge the memory starting at addr into the -+ * existing region from below. Align up addr to GRUB_MM_ALIGN -+ * so that our new region has proper alignment. -+ */ -+ r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); -+ /* Copy the region data across */ -+ *r = *q; -+ /* Consider all the new size as pre-size */ -+ r->pre_size += size; - -- /* -- * If we have enough pre-size to create a block, create a -- * block with it. Mark it as allocated and pass it to -- * grub_free (), which will sort out getting it into the free -- * list. -- */ -- if (r->pre_size >> GRUB_MM_ALIGN_LOG2) -- { -- h = (grub_mm_header_t) (r + 1); -- /* block size is pre-size converted to cells */ -- h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); -- h->magic = GRUB_MM_ALLOC_MAGIC; -- /* region size grows by block size converted back to bytes */ -- r->size += h->size << GRUB_MM_ALIGN_LOG2; -- /* adjust pre_size to be accurate */ -- r->pre_size &= (GRUB_MM_ALIGN - 1); -- *p = r; -- grub_free (h + 1); -- } -- /* Replace the old region with the new region */ -- *p = r; -- return; -- } -+ /* -+ * If we have enough pre-size to create a block, create a -+ * block with it. Mark it as allocated and pass it to -+ * grub_free (), which will sort out getting it into the free -+ * list. -+ */ -+ if (r->pre_size >> GRUB_MM_ALIGN_LOG2) -+ { -+ h = (grub_mm_header_t) (r + 1); -+ /* block size is pre-size converted to cells */ -+ h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); -+ h->magic = GRUB_MM_ALLOC_MAGIC; -+ /* region size grows by block size converted back to bytes */ -+ r->size += h->size << GRUB_MM_ALIGN_LOG2; -+ /* adjust pre_size to be accurate */ -+ r->pre_size &= (GRUB_MM_ALIGN - 1); -+ *p = r; -+ grub_free (h + 1); -+ } -+ /* Replace the old region with the new region */ -+ *p = r; -+ return; -+ } -+ -+ /* -+ * Is the new region immediately above an existing region? That -+ * is: -+ * q addr -+ * ||-q->post_size-|----size-----| -+ */ -+ if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size == -+ (grub_uint8_t *) addr) -+ { -+ /* -+ * Yes! Follow a similar pattern to above, but simpler. -+ * Our header starts at address - post_size, which should align us -+ * to a cell boundary. -+ * -+ * Cast to (void *) first to avoid the following build error: -+ * kern/mm.c: In function ‘grub_mm_init_region’: -+ * kern/mm.c:211:15: error: cast increases required alignment of target type [-Werror=cast-align] -+ * 211 | h = (grub_mm_header_t) ((grub_uint8_t *) addr - q->post_size); -+ * | ^ -+ * It is safe to do that because proper alignment is enforced in grub_mm_size_sanity_check(). -+ */ -+ h = (grub_mm_header_t)(void *) ((grub_uint8_t *) addr - q->post_size); -+ /* our size is the allocated size plus post_size, in cells */ -+ h->size = (size + q->post_size) >> GRUB_MM_ALIGN_LOG2; -+ h->magic = GRUB_MM_ALLOC_MAGIC; -+ /* region size grows by block size converted back to bytes */ -+ q->size += h->size << GRUB_MM_ALIGN_LOG2; -+ /* adjust new post_size to be accurate */ -+ q->post_size = (q->post_size + size) & (GRUB_MM_ALIGN - 1); -+ grub_free (h + 1); -+ return; -+ } -+ } - - /* Allocate a region from the head. */ - r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); -@@ -195,6 +230,7 @@ grub_mm_init_region (void *addr, grub_size_t size) - r->first = h; - r->pre_size = (grub_addr_t) r - (grub_addr_t) addr; - r->size = (h->size << GRUB_MM_ALIGN_LOG2); -+ r->post_size = size - r->size; - - /* Find where to insert this region. Put a smaller one before bigger ones, - to prevent fragmentation. */ -diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h -index a688b92a83..96c2d816be 100644 ---- a/include/grub/mm_private.h -+++ b/include/grub/mm_private.h -@@ -81,8 +81,17 @@ typedef struct grub_mm_region - */ - grub_size_t pre_size; - -+ /* -+ * Likewise, the post-size is the number of bytes we wasted at the end -+ * of the allocation because it wasn't a multiple of GRUB_MM_ALIGN -+ */ -+ grub_size_t post_size; -+ - /* How many bytes are in this region? (free and allocated) */ - grub_size_t size; -+ -+ /* pad to a multiple of cell size */ -+ char padding[3 * GRUB_CPU_SIZEOF_VOID_P]; - } - *grub_mm_region_t; - diff --git a/0306-kern-efi-mm-Implement-runtime-addition-of-pages.patch b/0306-kern-efi-mm-Implement-runtime-addition-of-pages.patch new file mode 100644 index 0000000..1f52581 --- /dev/null +++ b/0306-kern-efi-mm-Implement-runtime-addition-of-pages.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:22 +1000 +Subject: [PATCH] kern/efi/mm: Implement runtime addition of pages + +Adjust the interface of grub_efi_mm_add_regions() to take a set of +GRUB_MM_ADD_REGION_* flags, which most notably is currently only the +GRUB_MM_ADD_REGION_CONSECUTIVE flag. This allows us to set the function +up as callback for the memory subsystem and have it call out to us in +case there's not enough pages available in the current heap. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 1df2934822df4c1170dde069d97cfbf7a9572bba) +--- + grub-core/kern/efi/mm.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index e0ebc65dba..016ba6cf2f 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -518,7 +518,8 @@ static grub_err_t + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end, +- grub_efi_uint64_t required_pages) ++ grub_efi_uint64_t required_pages, ++ unsigned int flags) + { + grub_efi_memory_descriptor_t *desc; + +@@ -532,6 +533,10 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + + start = desc->physical_start; + pages = desc->num_pages; ++ ++ if (pages < required_pages && (flags & GRUB_MM_ADD_REGION_CONSECUTIVE)) ++ continue; ++ + if (pages > required_pages) + { + start += PAGES_TO_BYTES (pages - required_pages); +@@ -672,7 +677,7 @@ grub_nx_init (void) + } + + static grub_err_t +-grub_efi_mm_add_regions (grub_size_t required_bytes) ++grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags) + { + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; +@@ -729,7 +734,8 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + /* Allocate memory regions for GRUB's memory management. */ + err = add_memory_regions (filtered_memory_map, desc_size, + filtered_memory_map_end, +- BYTES_TO_PAGES (required_bytes)); ++ BYTES_TO_PAGES (required_bytes), ++ flags); + if (err != GRUB_ERR_NONE) + return err; + +@@ -756,8 +762,9 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + void + grub_efi_mm_init (void) + { +- if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE) ++ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE, GRUB_MM_ADD_REGION_NONE) != GRUB_ERR_NONE) + grub_fatal ("%s", grub_errmsg); ++ grub_mm_add_region_fn = grub_efi_mm_add_regions; + } + + #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) diff --git a/0306-mm-Debug-support-for-region-operations.patch b/0306-mm-Debug-support-for-region-operations.patch deleted file mode 100644 index f434260..0000000 --- a/0306-mm-Debug-support-for-region-operations.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 21 Apr 2022 15:24:16 +1000 -Subject: [PATCH] mm: Debug support for region operations - -This is handy for debugging. Enable with "set debug=regions". - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -Tested-by: Patrick Steinhardt -(cherry picked from commit 8afa5ef45b797ba5d8147ceee85ac2c59dcc7f09) ---- - grub-core/kern/mm.c | 19 ++++++++++++++++--- - 1 file changed, 16 insertions(+), 3 deletions(-) - -diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c -index 7be33e23bf..38bfb01df9 100644 ---- a/grub-core/kern/mm.c -+++ b/grub-core/kern/mm.c -@@ -115,9 +115,8 @@ grub_mm_init_region (void *addr, grub_size_t size) - grub_mm_header_t h; - grub_mm_region_t r, *p, q; - --#if 0 -- grub_printf ("Using memory for heap: start=%p, end=%p\n", addr, addr + (unsigned int) size); --#endif -+ grub_dprintf ("regions", "Using memory for heap: start=%p, end=%p\n", -+ addr, (char *) addr + (unsigned int) size); - - /* Exclude last 4K to avoid overflows. */ - /* If addr + 0x1000 overflows then whole region is in excluded zone. */ -@@ -142,8 +141,14 @@ grub_mm_init_region (void *addr, grub_size_t size) - * addr q - * |----size-----|-q->pre_size-|| - */ -+ grub_dprintf ("regions", "Can we extend into region above?" -+ " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n", -+ (grub_uint8_t *) addr, size, q->pre_size, (grub_uint8_t *) q); - if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) - { -+ grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n", -+ q, (grub_uint8_t *) q + sizeof (*q) + q->size, -+ addr, (grub_uint8_t *) q + sizeof (*q) + q->size); - /* - * Yes, we can merge the memory starting at addr into the - * existing region from below. Align up addr to GRUB_MM_ALIGN -@@ -185,9 +190,15 @@ grub_mm_init_region (void *addr, grub_size_t size) - * q addr - * ||-q->post_size-|----size-----| - */ -+ grub_dprintf ("regions", "Can we extend into region below?" -+ " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n", -+ (grub_uint8_t *) q, sizeof(*q), q->size, q->post_size, (grub_uint8_t *) addr); - if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size == - (grub_uint8_t *) addr) - { -+ grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n", -+ q, (grub_uint8_t *) q + sizeof (*q) + q->size, -+ q, (grub_uint8_t *) addr + size); - /* - * Yes! Follow a similar pattern to above, but simpler. - * Our header starts at address - post_size, which should align us -@@ -213,6 +224,8 @@ grub_mm_init_region (void *addr, grub_size_t size) - } - } - -+ grub_dprintf ("regions", "No: considering a new region at %p of size %" PRIxGRUB_SIZE "\n", -+ addr, size); - /* Allocate a region from the head. */ - r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); - diff --git a/0307-efi-Increase-default-memory-allocation-to-32-MiB.patch b/0307-efi-Increase-default-memory-allocation-to-32-MiB.patch new file mode 100644 index 0000000..b70c3cc --- /dev/null +++ b/0307-efi-Increase-default-memory-allocation-to-32-MiB.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 20 Sep 2022 00:30:30 +1000 +Subject: [PATCH] efi: Increase default memory allocation to 32 MiB + +We have multiple reports of things being slower with a 1 MiB initial static +allocation, and a report (more difficult to nail down) of a boot failure +as a result of the smaller initial allocation. + +Make the initial memory allocation 32 MiB. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 75e38e86e7d9202f050b093f20500d9ad4c6dad9) +--- + grub-core/kern/efi/mm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 016ba6cf2f..b27e966e1f 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -39,7 +39,7 @@ + #define MEMORY_MAP_SIZE 0x3000 + + /* The default heap size for GRUB itself in bytes. */ +-#define DEFAULT_HEAP_SIZE 0x100000 ++#define DEFAULT_HEAP_SIZE 0x2000000 + + static void *finish_mmap_buf = 0; + static grub_efi_uintn_t finish_mmap_size = 0; diff --git a/0307-mm-Drop-unused-unloading-of-modules-on-OOM.patch b/0307-mm-Drop-unused-unloading-of-modules-on-OOM.patch deleted file mode 100644 index a18d912..0000000 --- a/0307-mm-Drop-unused-unloading-of-modules-on-OOM.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Patrick Steinhardt -Date: Thu, 21 Apr 2022 15:24:17 +1000 -Subject: [PATCH] mm: Drop unused unloading of modules on OOM - -In grub_memalign(), there's a commented section which would allow for -unloading of unneeded modules in case where there is not enough free -memory available to satisfy a request. Given that this code is never -compiled in, let's remove it together with grub_dl_unload_unneeded(). - -Signed-off-by: Patrick Steinhardt -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -Tested-by: Patrick Steinhardt -(cherry picked from commit 139fd9b134a01e0b5fe0ebefafa7f48d1ffb6d60) ---- - grub-core/kern/dl.c | 20 -------------------- - grub-core/kern/mm.c | 8 -------- - include/grub/dl.h | 1 - - 3 files changed, 29 deletions(-) - -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index d5de80186f..ab9101a5ad 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -998,23 +998,3 @@ grub_dl_unload (grub_dl_t mod) - grub_free (mod); - return 1; - } -- --/* Unload unneeded modules. */ --void --grub_dl_unload_unneeded (void) --{ -- /* Because grub_dl_remove modifies the list of modules, this -- implementation is tricky. */ -- grub_dl_t p = grub_dl_head; -- -- while (p) -- { -- if (grub_dl_unload (p)) -- { -- p = grub_dl_head; -- continue; -- } -- -- p = p->next; -- } --} -diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c -index 38bfb01df9..1825dc8289 100644 ---- a/grub-core/kern/mm.c -+++ b/grub-core/kern/mm.c -@@ -444,14 +444,6 @@ grub_memalign (grub_size_t align, grub_size_t size) - count++; - goto again; - --#if 0 -- case 1: -- /* Unload unneeded modules. */ -- grub_dl_unload_unneeded (); -- count++; -- goto again; --#endif -- - default: - break; - } -diff --git a/include/grub/dl.h b/include/grub/dl.h -index 45ac8e339f..6bc2560bf0 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -206,7 +206,6 @@ grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name); - grub_dl_t grub_dl_load_core (void *addr, grub_size_t size); - grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size); - int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod); --extern void grub_dl_unload_unneeded (void); - extern int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod); - extern int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod); - extern int EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod); diff --git a/0308-mm-Allow-dynamically-requesting-additional-memory-re.patch b/0308-mm-Allow-dynamically-requesting-additional-memory-re.patch deleted file mode 100644 index d225c10..0000000 --- a/0308-mm-Allow-dynamically-requesting-additional-memory-re.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Patrick Steinhardt -Date: Thu, 21 Apr 2022 15:24:18 +1000 -Subject: [PATCH] mm: Allow dynamically requesting additional memory regions - -Currently, all platforms will set up their heap on initialization of the -platform code. While this works mostly fine, it poses some limitations -on memory management on us. Most notably, allocating big chunks of -memory in the gigabyte range would require us to pre-request this many -bytes from the firmware and add it to the heap from the beginning on -some platforms like EFI. As this isn't needed for most configurations, -it is inefficient and may even negatively impact some usecases when, -e.g., chainloading. Nonetheless, allocating big chunks of memory is -required sometimes, where one example is the upcoming support for the -Argon2 key derival function in LUKS2. - -In order to avoid pre-allocating big chunks of memory, this commit -implements a runtime mechanism to add more pages to the system. When -a given allocation cannot be currently satisfied, we'll call a given -callback set up by the platform's own memory management subsystem, -asking it to add a memory area with at least "n" bytes. If this -succeeds, we retry searching for a valid memory region, which should -now succeed. - -If this fails, we try asking for "n" bytes, possibly spread across -multiple regions, in hopes that region merging means that we end up -with enough memory for things to work out. - -Signed-off-by: Patrick Steinhardt -Signed-off-by: Daniel Axtens -Tested-by: Stefan Berger -Reviewed-by: Daniel Kiper -Tested-by: Patrick Steinhardt -(cherry picked from commit 887f98f0db43e33fba4ec1f85e42fae1185700bc) ---- - grub-core/kern/mm.c | 30 ++++++++++++++++++++++++++++++ - include/grub/mm.h | 18 ++++++++++++++++++ - 2 files changed, 48 insertions(+) - -diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c -index 1825dc8289..f2e27f263b 100644 ---- a/grub-core/kern/mm.c -+++ b/grub-core/kern/mm.c -@@ -28,6 +28,9 @@ - - multiple regions may be used as free space. They may not be - contiguous. - -+ - if existing regions are insufficient to satisfy an allocation, a new -+ region can be requested from firmware. -+ - Regions are managed by a singly linked list, and the meta information is - stored in the beginning of each region. Space after the meta information - is used to allocate memory. -@@ -81,6 +84,7 @@ - - - grub_mm_region_t grub_mm_base; -+grub_mm_add_region_func_t grub_mm_add_region_fn; - - /* Get a header from the pointer PTR, and set *P and *R to a pointer - to the header and a pointer to its region, respectively. PTR must -@@ -444,6 +448,32 @@ grub_memalign (grub_size_t align, grub_size_t size) - count++; - goto again; - -+ case 1: -+ /* Request additional pages, contiguous */ -+ count++; -+ -+ if (grub_mm_add_region_fn != NULL && -+ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) -+ goto again; -+ -+ /* fallthrough */ -+ -+ case 2: -+ /* Request additional pages, anything at all */ -+ count++; -+ -+ if (grub_mm_add_region_fn != NULL) -+ { -+ /* -+ * Try again even if this fails, in case it was able to partially -+ * satisfy the request -+ */ -+ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE); -+ goto again; -+ } -+ -+ /* fallthrough */ -+ - default: - break; - } -diff --git a/include/grub/mm.h b/include/grub/mm.h -index d81623d226..7c6f925ffd 100644 ---- a/include/grub/mm.h -+++ b/include/grub/mm.h -@@ -20,6 +20,7 @@ - #ifndef GRUB_MM_H - #define GRUB_MM_H 1 - -+#include - #include - #include - #include -@@ -29,6 +30,23 @@ - # define NULL ((void *) 0) - #endif - -+#define GRUB_MM_ADD_REGION_NONE 0 -+#define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0) -+ -+/* -+ * Function used to request memory regions of `grub_size_t` bytes. The second -+ * parameter is a bitfield of `GRUB_MM_ADD_REGION` flags. -+ */ -+typedef grub_err_t (*grub_mm_add_region_func_t) (grub_size_t, unsigned int); -+ -+/* -+ * Set this function pointer to enable adding memory-regions at runtime in case -+ * a memory allocation cannot be satisfied with existing regions. -+ */ -+#ifndef GRUB_MACHINE_EMU -+extern grub_mm_add_region_func_t EXPORT_VAR(grub_mm_add_region_fn); -+#endif -+ - void grub_mm_init_region (void *addr, grub_size_t size); - void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size); - void *EXPORT_FUNC(grub_malloc) (grub_size_t size); diff --git a/0308-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch b/0308-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch new file mode 100644 index 0000000..c919891 --- /dev/null +++ b/0308-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Sat, 15 Oct 2022 22:15:11 +0800 +Subject: [PATCH] mm: Try invalidate disk caches last when out of memory + +Every heap grow will cause all disk caches invalidated which decreases +performance severely. This patch moves disk cache invalidation code to +the last of memory squeezing measures. So, disk caches are released only +when there are no other ways to get free memory. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +Reviewed-by: Patrick Steinhardt +(cherry picked from commit 17975d10a80e2457e5237f87fa58a7943031983e) +--- + grub-core/kern/mm.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index f2e27f263b..da1ac9427c 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -443,12 +443,6 @@ grub_memalign (grub_size_t align, grub_size_t size) + switch (count) + { + case 0: +- /* Invalidate disk caches. */ +- grub_disk_cache_invalidate_all (); +- count++; +- goto again; +- +- case 1: + /* Request additional pages, contiguous */ + count++; + +@@ -458,7 +452,7 @@ grub_memalign (grub_size_t align, grub_size_t size) + + /* fallthrough */ + +- case 2: ++ case 1: + /* Request additional pages, anything at all */ + count++; + +@@ -474,6 +468,12 @@ grub_memalign (grub_size_t align, grub_size_t size) + + /* fallthrough */ + ++ case 2: ++ /* Invalidate disk caches. */ ++ grub_disk_cache_invalidate_all (); ++ count++; ++ goto again; ++ + default: + break; + } diff --git a/0309-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch b/0309-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch deleted file mode 100644 index 6fa378c..0000000 --- a/0309-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Patrick Steinhardt -Date: Thu, 21 Apr 2022 15:24:19 +1000 -Subject: [PATCH] kern/efi/mm: Always request a fixed number of pages on init - -When initializing the EFI memory subsystem, we will by default request -a quarter of the available memory, bounded by a minimum/maximum value. -Given that we're about to extend the EFI memory system to dynamically -request additional pages from the firmware as required, this scaling of -requested memory based on available memory will not make a lot of sense -anymore. - -Remove this logic as a preparatory patch such that we'll instead defer -to the runtime memory allocator. Note that ideally, we'd want to change -this after dynamic requesting of pages has been implemented for the EFI -platform. But because we'll need to split up initialization of the -memory subsystem and the request of pages from the firmware, we'd have -to duplicate quite some logic at first only to remove it afterwards -again. This seems quite pointless, so we instead have patches slightly -out of order. - -Signed-off-by: Patrick Steinhardt -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -Tested-by: Patrick Steinhardt -(cherry picked from commit 938c3760b8c0fca759140be48307179b50107ff6) ---- - grub-core/kern/efi/mm.c | 35 +++-------------------------------- - 1 file changed, 3 insertions(+), 32 deletions(-) - -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index e460b072e6..782a1365a1 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -38,9 +38,8 @@ - a multiplier of 4KB. */ - #define MEMORY_MAP_SIZE 0x3000 - --/* The minimum and maximum heap size for GRUB itself. */ --#define MIN_HEAP_SIZE 0x100000 --#define MAX_HEAP_SIZE (1600 * 0x100000) -+/* The default heap size for GRUB itself in bytes. */ -+#define DEFAULT_HEAP_SIZE 0x100000 - - static void *finish_mmap_buf = 0; - static grub_efi_uintn_t finish_mmap_size = 0; -@@ -514,23 +513,6 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, - return filtered_desc; - } - --/* Return the total number of pages. */ --static grub_efi_uint64_t --get_total_pages (grub_efi_memory_descriptor_t *memory_map, -- grub_efi_uintn_t desc_size, -- grub_efi_memory_descriptor_t *memory_map_end) --{ -- grub_efi_memory_descriptor_t *desc; -- grub_efi_uint64_t total = 0; -- -- for (desc = memory_map; -- desc < memory_map_end; -- desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) -- total += desc->num_pages; -- -- return total; --} -- - /* Add memory regions. */ - static void - add_memory_regions (grub_efi_memory_descriptor_t *memory_map, -@@ -694,8 +676,6 @@ grub_efi_mm_init (void) - grub_efi_memory_descriptor_t *filtered_memory_map_end; - grub_efi_uintn_t map_size; - grub_efi_uintn_t desc_size; -- grub_efi_uint64_t total_pages; -- grub_efi_uint64_t required_pages; - int mm_status; - - grub_nx_init (); -@@ -737,22 +717,13 @@ grub_efi_mm_init (void) - filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, - desc_size, memory_map_end); - -- /* By default, request a quarter of the available memory. */ -- total_pages = get_total_pages (filtered_memory_map, desc_size, -- filtered_memory_map_end); -- required_pages = (total_pages >> 2); -- if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE)) -- required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE); -- else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE)) -- required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE); -- - /* Sort the filtered descriptors, so that GRUB can allocate pages - from smaller regions. */ - sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); - - /* Allocate memory regions for GRUB's memory management. */ - add_memory_regions (filtered_memory_map, desc_size, -- filtered_memory_map_end, required_pages); -+ filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE)); - - #if 0 - /* For debug. */ diff --git a/0309-ppc64le-signed-boot-media-changes.patch b/0309-ppc64le-signed-boot-media-changes.patch new file mode 100644 index 0000000..bd71437 --- /dev/null +++ b/0309-ppc64le-signed-boot-media-changes.patch @@ -0,0 +1,125 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 25 Jan 2023 16:10:58 -0500 +Subject: [PATCH] ppc64le: signed boot media changes + +Skip mdraid < 1.1 on isos since mdraid* can't even + +Prior to this change, on ppc64le with part_msdos and the mdraid* modules +enabled, we see: + + disk/diskfilter.c:191: scanning ieee1275/cdrom + kern/disk.c:196: Opening `ieee1275/cdrom'... + disk/ieee1275/ofdisk.c:477: Opening `cdrom'. + disk/ieee1275/ofdisk.c:502: MAX_RETRIES set to 20 + kern/disk.c:288: Opening `ieee1275/cdrom' succeeded. + disk/diskfilter.c:136: Scanning for DISKFILTER devices on disk ieee1275/cdrom + partmap/msdos.c:184: partition 0: flag 0x80, type 0x96, start 0x0, len + 0x6a5d70 + disk/diskfilter.c:136: Scanning for DISKFILTER devices on disk ieee1275/cdrom + SCSI-DISK: Access beyond end of device ! + SCSI-DISK: Access beyond end of device ! + SCSI-DISK: Access beyond end of device ! + SCSI-DISK: Access beyond end of device ! + SCSI-DISK: Access beyond end of device ! + disk/ieee1275/ofdisk.c:578: MAX_RETRIES set to 20 + +These latter two lines repeat many times, eventually ending in: + + kern/disk.c:388: ieee1275/cdrom read failed + error: ../../grub-core/disk/ieee1275/ofdisk.c:608:failure reading sector + 0x1a9720 from `ieee1275/cdrom'. + +and the system drops to a "grub>" prompt. + +Prior to 1.1, mdraid stored the superblock offset from the end of the +disk, and the firmware really doesn't like reads there. Best guess was +that the firmware and the iso image appear to diagree on the blocksize +(512 vs. 2048), and the diskfilter RAID probing is too much for it. +It's tempting to just skip probing for cdroms, but unfortunately isos +can be virtualized elsewhere - such as regular disks. + +Also fix detection of root, and try the chrp path as a fallback if the +built prefix doesn't work. + +Signed-off-by: Robbie Harwood + +wip +--- + grub-core/disk/mdraid1x_linux.c | 8 +++++++- + grub-core/disk/mdraid_linux.c | 5 +++++ + grub-core/kern/ieee1275/openfw.c | 2 +- + grub-core/normal/main.c | 5 +++++ + 4 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c +index 38444b02c7..08c57ae16e 100644 +--- a/grub-core/disk/mdraid1x_linux.c ++++ b/grub-core/disk/mdraid1x_linux.c +@@ -129,7 +129,13 @@ grub_mdraid_detect (grub_disk_t disk, + grub_uint32_t level; + struct grub_diskfilter_vg *array; + char *uuid; +- ++ ++#ifdef __powerpc__ ++ /* Firmware will yell at us for reading too far. */ ++ if (minor_version == 0) ++ continue; ++#endif ++ + if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0) + continue; + +diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c +index e40216f511..98fcfb1be6 100644 +--- a/grub-core/disk/mdraid_linux.c ++++ b/grub-core/disk/mdraid_linux.c +@@ -189,6 +189,11 @@ grub_mdraid_detect (grub_disk_t disk, + grub_uint32_t level; + struct grub_diskfilter_vg *ret; + ++#ifdef __powerpc__ ++ /* Firmware will yell at us for reading too far. */ ++ return NULL; ++#endif ++ + /* The sector where the mdraid 0.90 superblock is stored, if available. */ + size = grub_disk_native_sectors (disk); + if (size == GRUB_DISK_SIZE_UNKNOWN) +diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c +index 3a6689abb1..0278054c61 100644 +--- a/grub-core/kern/ieee1275/openfw.c ++++ b/grub-core/kern/ieee1275/openfw.c +@@ -499,7 +499,7 @@ grub_ieee1275_encode_devname (const char *path) + *optr++ ='\\'; + *optr++ = *iptr++; + } +- if (partition && partition[0]) ++ if (partition && partition[0] >= '0' && partition[0] <= '9') + { + unsigned int partno = grub_strtoul (partition, 0, 0); + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 8f5fd81003..d59145f861 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -372,6 +372,7 @@ grub_try_normal_prefix (const char *prefix) + file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); + if (file) + { ++ grub_env_set ("prefix", prefix); + grub_file_close (file); + err = GRUB_ERR_NONE; + } +@@ -447,6 +448,10 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + err = grub_try_normal ("fw_path"); + if (err == GRUB_ERR_FILE_NOT_FOUND) + err = grub_try_normal ("prefix"); ++#ifdef __powerpc__ ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ err = grub_try_normal_prefix ("/boot/grub"); ++#endif + if (err == GRUB_ERR_FILE_NOT_FOUND) + err = grub_try_normal_discover (); + if (err == GRUB_ERR_FILE_NOT_FOUND) diff --git a/0310-core-Fix-several-implicit-function-declarations.patch b/0310-core-Fix-several-implicit-function-declarations.patch new file mode 100644 index 0000000..48c5bb0 --- /dev/null +++ b/0310-core-Fix-several-implicit-function-declarations.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Arjun Shankar +Date: Sun, 5 Feb 2023 11:13:55 +0100 +Subject: [PATCH] core: Fix several implicit function declarations + +These #include lines ensure that grub2 continues to build with C99 +where implicit function declarations are removed. + +Related to: + + + +--- + grub-core/commands/efi/connectefi.c | 1 + + grub-core/net/http.c | 1 + + grub-core/term/at_keyboard.c | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/grub-core/commands/efi/connectefi.c b/grub-core/commands/efi/connectefi.c +index 8ab75bd51b..3752ae17ed 100644 +--- a/grub-core/commands/efi/connectefi.c ++++ b/grub-core/commands/efi/connectefi.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 57d2721719..5f956b743e 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c +index dac0f946fe..de3e4abe44 100644 +--- a/grub-core/term/at_keyboard.c ++++ b/grub-core/term/at_keyboard.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + diff --git a/0310-kern-efi-mm-Extract-function-to-add-memory-regions.patch b/0310-kern-efi-mm-Extract-function-to-add-memory-regions.patch deleted file mode 100644 index 28cf2e7..0000000 --- a/0310-kern-efi-mm-Extract-function-to-add-memory-regions.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Patrick Steinhardt -Date: Thu, 21 Apr 2022 15:24:20 +1000 -Subject: [PATCH] kern/efi/mm: Extract function to add memory regions - -In preparation of support for runtime-allocating additional memory -region, this patch extracts the function to retrieve the EFI memory -map and add a subset of it to GRUB's own memory regions. - -Signed-off-by: Patrick Steinhardt -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -Tested-by: Patrick Steinhardt -(cherry picked from commit 96a7ea29e3cb61b6c2302e260e8e6a6117e17fa3) -[rharwood: backport around our nx] ---- - grub-core/kern/efi/mm.c | 21 +++++++++++++++------ - 1 file changed, 15 insertions(+), 6 deletions(-) - -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index 782a1365a1..a1d3b51fe6 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -667,8 +667,8 @@ grub_nx_init (void) - } - } - --void --grub_efi_mm_init (void) -+static grub_err_t -+grub_efi_mm_add_regions (grub_size_t required_bytes) - { - grub_efi_memory_descriptor_t *memory_map; - grub_efi_memory_descriptor_t *memory_map_end; -@@ -683,7 +683,7 @@ grub_efi_mm_init (void) - /* Prepare a memory region to store two memory maps. */ - memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); - if (! memory_map) -- grub_fatal ("cannot allocate memory"); -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map"); - - /* Obtain descriptors for available memory. */ - map_size = MEMORY_MAP_SIZE; -@@ -701,14 +701,14 @@ grub_efi_mm_init (void) - - memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size)); - if (! memory_map) -- grub_fatal ("cannot allocate memory"); -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map"); - - mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, - &desc_size, 0); - } - - if (mm_status < 0) -- grub_fatal ("cannot get memory map"); -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "error fetching memory map from EFI"); - - memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); - -@@ -723,7 +723,7 @@ grub_efi_mm_init (void) - - /* Allocate memory regions for GRUB's memory management. */ - add_memory_regions (filtered_memory_map, desc_size, -- filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE)); -+ filtered_memory_map_end, BYTES_TO_PAGES (required_bytes)); - - #if 0 - /* For debug. */ -@@ -741,6 +741,15 @@ grub_efi_mm_init (void) - /* Release the memory maps. */ - grub_efi_free_pages ((grub_addr_t) memory_map, - 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); -+ -+ return GRUB_ERR_NONE; -+} -+ -+void -+grub_efi_mm_init (void) -+{ -+ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE) -+ grub_fatal ("%s", grub_errmsg); - } - - #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) diff --git a/0311-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch b/0311-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch deleted file mode 100644 index b4b7891..0000000 --- a/0311-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Patrick Steinhardt -Date: Thu, 21 Apr 2022 15:24:21 +1000 -Subject: [PATCH] kern/efi/mm: Pass up errors from add_memory_regions() - -The function add_memory_regions() is currently only called on system -initialization to allocate a fixed amount of pages. As such, it didn't -need to return any errors: in case it failed, we cannot proceed anyway. -This will change with the upcoming support for requesting more memory -from the firmware at runtime, where it doesn't make sense anymore to -fail hard. - -Refactor the function to return an error to prepare for this. Note that -this does not change the behaviour when initializing the memory system -because grub_efi_mm_init() knows to call grub_fatal() in case -grub_efi_mm_add_regions() returns an error. - -Signed-off-by: Patrick Steinhardt -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -Tested-by: Patrick Steinhardt -(cherry picked from commit 15a015698921240adc1ac266a3b5bc5fcbd81521) ---- - grub-core/kern/efi/mm.c | 22 +++++++++++++++------- - 1 file changed, 15 insertions(+), 7 deletions(-) - -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index a1d3b51fe6..e0ebc65dba 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -514,7 +514,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, - } - - /* Add memory regions. */ --static void -+static grub_err_t - add_memory_regions (grub_efi_memory_descriptor_t *memory_map, - grub_efi_uintn_t desc_size, - grub_efi_memory_descriptor_t *memory_map_end, -@@ -542,9 +542,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, - GRUB_EFI_ALLOCATE_ADDRESS, - GRUB_EFI_LOADER_CODE); - if (! addr) -- grub_fatal ("cannot allocate conventional memory %p with %u pages", -- (void *) ((grub_addr_t) start), -- (unsigned) pages); -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Memory starting at %p (%u pages) marked as free, but EFI would not allocate", -+ (void *) ((grub_addr_t) start), (unsigned) pages); - - grub_mm_init_region (addr, PAGES_TO_BYTES (pages)); - -@@ -554,7 +554,11 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, - } - - if (required_pages > 0) -- grub_fatal ("too little memory"); -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "could not allocate all requested memory: %" PRIuGRUB_UINT64_T " pages still required after iterating EFI memory map", -+ required_pages); -+ -+ return GRUB_ERR_NONE; - } - - void -@@ -676,6 +680,7 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) - grub_efi_memory_descriptor_t *filtered_memory_map_end; - grub_efi_uintn_t map_size; - grub_efi_uintn_t desc_size; -+ grub_err_t err; - int mm_status; - - grub_nx_init (); -@@ -722,8 +727,11 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) - sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); - - /* Allocate memory regions for GRUB's memory management. */ -- add_memory_regions (filtered_memory_map, desc_size, -- filtered_memory_map_end, BYTES_TO_PAGES (required_bytes)); -+ err = add_memory_regions (filtered_memory_map, desc_size, -+ filtered_memory_map_end, -+ BYTES_TO_PAGES (required_bytes)); -+ if (err != GRUB_ERR_NONE) -+ return err; - - #if 0 - /* For debug. */ diff --git a/0311-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch b/0311-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch new file mode 100644 index 0000000..65834d8 --- /dev/null +++ b/0311-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch @@ -0,0 +1,431 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Raymund Will +Date: Mon, 24 Oct 2022 14:33:50 -0400 +Subject: [PATCH] loader: Add support for grub-emu to kexec Linux menu entries + +The GRUB emulator is used as a debugging utility but it could also be +used as a user-space bootloader if there is support to boot an operating +system. + +The Linux kernel is already able to (re)boot another kernel via the +kexec boot mechanism. So the grub-emu tool could rely on this feature +and have linux and initrd commands that are used to pass a kernel, +initramfs image and command line parameters to kexec for booting +a selected menu entry. + +By default the systemctl kexec option is used so systemd can shutdown +all of the running services before doing a reboot using kexec. But if +this is not present, it can fall back to executing the kexec user-space +tool directly. The ability to force a kexec-reboot when systemctl kexec +fails must only be used in controlled environments to avoid possible +filesystem corruption and data loss. + +Signed-off-by: Raymund Will +Signed-off-by: John Jolly +Signed-off-by: Javier Martinez Canillas +Signed-off-by: Robbie Harwood +Reviewed-by: Daniel Kiper +(cherry picked from commit e364307f6acc2f631b4c1fefda0791b9ce1f205f) +[rharwood: conflicts around makefile and grub_exit return code] +--- + grub-core/Makefile.core.def | 3 - + grub-core/kern/emu/main.c | 4 + + grub-core/kern/emu/misc.c | 18 ++++- + grub-core/loader/emu/linux.c | 178 +++++++++++++++++++++++++++++++++++++++++++ + include/grub/emu/exec.h | 4 +- + include/grub/emu/hostfile.h | 3 +- + include/grub/emu/misc.h | 3 + + docs/grub.texi | 30 ++++++-- + grub-core/Makefile.am | 1 + + 9 files changed, 230 insertions(+), 14 deletions(-) + create mode 100644 grub-core/loader/emu/linux.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 741a033978..f21da23213 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1864,11 +1864,8 @@ module = { + riscv32 = loader/riscv/linux.c; + riscv64 = loader/riscv/linux.c; + emu = loader/emu/linux.c; +- + common = loader/linux.c; + common = lib/cmdline.c; +- enable = noemu; +- + efi = loader/efi/linux.c; + }; + +diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c +index 12277c34d2..68e2b283bb 100644 +--- a/grub-core/kern/emu/main.c ++++ b/grub-core/kern/emu/main.c +@@ -107,6 +107,7 @@ static struct argp_option options[] = { + N_("use GRUB files in the directory DIR [default=%s]"), 0}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, + {"hold", 'H', N_("SECS"), OPTION_ARG_OPTIONAL, N_("wait until a debugger will attach"), 0}, ++ {"kexec", 'X', 0, 0, N_("use kexec to boot Linux kernels via systemctl (pass twice to enable dangerous fallback to non-systemctl)."), 0}, + { 0, 0, 0, 0, 0, 0 } + }; + +@@ -164,6 +165,9 @@ argp_parser (int key, char *arg, struct argp_state *state) + case 'v': + verbosity++; + break; ++ case 'X': ++ grub_util_set_kexecute (); ++ break; + + case ARGP_KEY_ARG: + { +diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c +index d278c2921f..02d27c3440 100644 +--- a/grub-core/kern/emu/misc.c ++++ b/grub-core/kern/emu/misc.c +@@ -39,6 +39,7 @@ + #include + + int verbosity; ++int kexecute; + + void + grub_util_warn (const char *fmt, ...) +@@ -82,7 +83,7 @@ grub_util_error (const char *fmt, ...) + vfprintf (stderr, fmt, ap); + va_end (ap); + fprintf (stderr, ".\n"); +- exit (1); ++ grub_exit (1); + } + + void * +@@ -154,6 +155,9 @@ void + __attribute__ ((noreturn)) + grub_exit (int rc) + { ++#if defined (GRUB_KERNEL) ++ grub_reboot (); ++#endif + exit (rc < 0 ? 1 : rc); + } + #endif +@@ -215,3 +219,15 @@ grub_util_load_image (const char *path, char *buf) + + fclose (fp); + } ++ ++void ++grub_util_set_kexecute (void) ++{ ++ kexecute++; ++} ++ ++int ++grub_util_get_kexecute (void) ++{ ++ return kexecute; ++} +diff --git a/grub-core/loader/emu/linux.c b/grub-core/loader/emu/linux.c +new file mode 100644 +index 0000000000..0cf378a376 +--- /dev/null ++++ b/grub-core/loader/emu/linux.c +@@ -0,0 +1,178 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static grub_dl_t my_mod; ++ ++static char *kernel_path; ++static char *initrd_path; ++static char *boot_cmdline; ++ ++static grub_err_t ++grub_linux_boot (void) ++{ ++ grub_err_t rc = GRUB_ERR_NONE; ++ char *initrd_param; ++ const char *kexec[] = {"kexec", "-la", kernel_path, boot_cmdline, NULL, NULL}; ++ const char *systemctl[] = {"systemctl", "kexec", NULL}; ++ int kexecute = grub_util_get_kexecute (); ++ ++ if (initrd_path) ++ { ++ initrd_param = grub_xasprintf ("--initrd=%s", initrd_path); ++ kexec[3] = initrd_param; ++ kexec[4] = boot_cmdline; ++ } ++ else ++ initrd_param = grub_xasprintf ("%s", ""); ++ ++ grub_dprintf ("linux", "%serforming 'kexec -la %s %s %s'\n", ++ (kexecute) ? "P" : "Not p", ++ kernel_path, initrd_param, boot_cmdline); ++ ++ if (kexecute) ++ rc = grub_util_exec (kexec); ++ ++ grub_free (initrd_param); ++ ++ if (rc != GRUB_ERR_NONE) ++ { ++ grub_error (rc, N_("error trying to perform kexec load operation")); ++ grub_sleep (3); ++ return rc; ++ } ++ ++ if (kexecute < 1) ++ grub_fatal (N_("use '"PACKAGE"-emu --kexec' to force a system restart")); ++ ++ grub_dprintf ("linux", "Performing 'systemctl kexec' (%s) ", ++ (kexecute==1) ? "do-or-die" : "just-in-case"); ++ rc = grub_util_exec (systemctl); ++ ++ if (kexecute == 1) ++ grub_fatal (N_("error trying to perform 'systemctl kexec': %d"), rc); ++ ++ /* ++ * WARNING: forcible reset should only be used in read-only environments. ++ * grub-emu cannot check for these - users beware. ++ */ ++ grub_dprintf ("linux", "Performing 'kexec -ex'"); ++ kexec[1] = "-ex"; ++ kexec[2] = NULL; ++ rc = grub_util_exec (kexec); ++ if (rc != GRUB_ERR_NONE) ++ grub_fatal (N_("error trying to directly perform 'kexec -ex': %d"), rc); ++ ++ return rc; ++} ++ ++static grub_err_t ++grub_linux_unload (void) ++{ ++ /* Unloading: we're no longer in use. */ ++ grub_dl_unref (my_mod); ++ grub_free (boot_cmdline); ++ boot_cmdline = NULL; ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, ++ char *argv[]) ++{ ++ int i; ++ char *tempstr; ++ ++ /* Mark ourselves as in-use. */ ++ grub_dl_ref (my_mod); ++ ++ if (argc == 0) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ ++ if (!grub_util_is_regular (argv[0])) ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, ++ N_("cannot find kernel file %s"), argv[0]); ++ ++ grub_free (kernel_path); ++ kernel_path = grub_xasprintf ("%s", argv[0]); ++ ++ grub_free (boot_cmdline); ++ boot_cmdline = NULL; ++ ++ if (argc > 1) ++ { ++ boot_cmdline = grub_xasprintf ("--command-line=%s", argv[1]); ++ for (i = 2; i < argc; i++) ++ { ++ tempstr = grub_xasprintf ("%s %s", boot_cmdline, argv[i]); ++ grub_free (boot_cmdline); ++ boot_cmdline = tempstr; ++ } ++ } ++ ++ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, ++ char *argv[]) ++{ ++ if (argc == 0) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ ++ if (!grub_util_is_regular (argv[0])) ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, ++ N_("Cannot find initrd file %s"), argv[0]); ++ ++ grub_free (initrd_path); ++ initrd_path = grub_xasprintf ("%s", argv[0]); ++ ++ /* We are done - mark ourselves as on longer in use. */ ++ grub_dl_unref (my_mod); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_command_t cmd_linux, cmd_initrd; ++ ++GRUB_MOD_INIT (linux) ++{ ++ cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0, ++ N_("Load Linux.")); ++ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0, ++ N_("Load initrd.")); ++ my_mod = mod; ++} ++ ++GRUB_MOD_FINI (linux) ++{ ++ grub_unregister_command (cmd_linux); ++ grub_unregister_command (cmd_initrd); ++} +diff --git a/include/grub/emu/exec.h b/include/grub/emu/exec.h +index d1073ef86a..1b61b4a2e5 100644 +--- a/include/grub/emu/exec.h ++++ b/include/grub/emu/exec.h +@@ -23,6 +23,8 @@ + #include + + #include ++#include ++ + pid_t + grub_util_exec_pipe (const char *const *argv, int *fd); + pid_t +@@ -32,7 +34,7 @@ int + grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file, + const char *stdout_file, const char *stderr_file); + int +-grub_util_exec (const char *const *argv); ++EXPORT_FUNC(grub_util_exec) (const char *const *argv); + int + grub_util_exec_redirect (const char *const *argv, const char *stdin_file, + const char *stdout_file); +diff --git a/include/grub/emu/hostfile.h b/include/grub/emu/hostfile.h +index cfb1e2b566..a61568e36e 100644 +--- a/include/grub/emu/hostfile.h ++++ b/include/grub/emu/hostfile.h +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + + int +@@ -29,7 +30,7 @@ grub_util_is_directory (const char *path); + int + grub_util_is_special_file (const char *path); + int +-grub_util_is_regular (const char *path); ++EXPORT_FUNC(grub_util_is_regular) (const char *path); + + char * + grub_util_path_concat (size_t n, ...); +diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h +index ff9c48a649..01056954b9 100644 +--- a/include/grub/emu/misc.h ++++ b/include/grub/emu/misc.h +@@ -57,6 +57,9 @@ void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...) __attribute__ ((format ( + void EXPORT_FUNC(grub_util_info) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2))); + void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2), noreturn)); + ++void EXPORT_FUNC(grub_util_set_kexecute) (void); ++int EXPORT_FUNC(grub_util_get_kexecute) (void) WARN_UNUSED_RESULT; ++ + grub_uint64_t EXPORT_FUNC (grub_util_get_cpu_time_ms) (void); + + #ifdef HAVE_DEVICE_MAPPER +diff --git a/docs/grub.texi b/docs/grub.texi +index a4da9c2a1b..1750b72ee9 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -923,17 +923,17 @@ magic. + @node General boot methods + @section How to boot operating systems + +-GRUB has two distinct boot methods. One of the two is to load an +-operating system directly, and the other is to chain-load another boot +-loader which then will load an operating system actually. Generally +-speaking, the former is more desirable, because you don't need to +-install or maintain other boot loaders and GRUB is flexible enough to +-load an operating system from an arbitrary disk/partition. However, +-the latter is sometimes required, since GRUB doesn't support all the +-existing operating systems natively. ++GRUB has three distinct boot methods: loading an operating system ++directly, using kexec from userspace, and chainloading another ++bootloader. Generally speaking, the first two are more desirable ++because you don't need to install or maintain other boot loaders and ++GRUB is flexible enough to load an operating system from an arbitrary ++disk/partition. However, chainloading is sometimes required, as GRUB ++doesn't support all existing operating systems natively. + + @menu + * Loading an operating system directly:: ++* Kexec:: + * Chain-loading:: + @end menu + +@@ -959,6 +959,20 @@ use more complicated instructions. @xref{DOS/Windows}, for more + information. + + ++@node Kexec ++@subsection Kexec with grub2-emu ++ ++GRUB can be run in userspace by invoking the grub2-emu tool. It will ++read all configuration scripts as if booting directly (see @xref{Loading ++an operating system directly}). With the @code{--kexec} flag, and ++kexec(8) support from the operating system, the @command{linux} command ++will directly boot the target image. For systems that lack working ++systemctl(1) support for kexec, passing the @code{--kexec} flag twice ++will fallback to invoking kexec(8) directly; note however that this ++fallback may be unsafe outside read-only environments, as it does not ++invoke shutdown machinery. ++ ++ + @node Chain-loading + @subsection Chain-loading an OS + +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index c2e8a82bce..dd49939aaa 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -309,6 +309,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/net.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostdisk.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostfile.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/exec.h + if COND_GRUB_EMU_SDL + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h + endif diff --git a/0312-kern-efi-mm-Implement-runtime-addition-of-pages.patch b/0312-kern-efi-mm-Implement-runtime-addition-of-pages.patch deleted file mode 100644 index 1f52581..0000000 --- a/0312-kern-efi-mm-Implement-runtime-addition-of-pages.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Patrick Steinhardt -Date: Thu, 21 Apr 2022 15:24:22 +1000 -Subject: [PATCH] kern/efi/mm: Implement runtime addition of pages - -Adjust the interface of grub_efi_mm_add_regions() to take a set of -GRUB_MM_ADD_REGION_* flags, which most notably is currently only the -GRUB_MM_ADD_REGION_CONSECUTIVE flag. This allows us to set the function -up as callback for the memory subsystem and have it call out to us in -case there's not enough pages available in the current heap. - -Signed-off-by: Patrick Steinhardt -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -Tested-by: Patrick Steinhardt -(cherry picked from commit 1df2934822df4c1170dde069d97cfbf7a9572bba) ---- - grub-core/kern/efi/mm.c | 15 +++++++++++---- - 1 file changed, 11 insertions(+), 4 deletions(-) - -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index e0ebc65dba..016ba6cf2f 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -518,7 +518,8 @@ static grub_err_t - add_memory_regions (grub_efi_memory_descriptor_t *memory_map, - grub_efi_uintn_t desc_size, - grub_efi_memory_descriptor_t *memory_map_end, -- grub_efi_uint64_t required_pages) -+ grub_efi_uint64_t required_pages, -+ unsigned int flags) - { - grub_efi_memory_descriptor_t *desc; - -@@ -532,6 +533,10 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, - - start = desc->physical_start; - pages = desc->num_pages; -+ -+ if (pages < required_pages && (flags & GRUB_MM_ADD_REGION_CONSECUTIVE)) -+ continue; -+ - if (pages > required_pages) - { - start += PAGES_TO_BYTES (pages - required_pages); -@@ -672,7 +677,7 @@ grub_nx_init (void) - } - - static grub_err_t --grub_efi_mm_add_regions (grub_size_t required_bytes) -+grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags) - { - grub_efi_memory_descriptor_t *memory_map; - grub_efi_memory_descriptor_t *memory_map_end; -@@ -729,7 +734,8 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) - /* Allocate memory regions for GRUB's memory management. */ - err = add_memory_regions (filtered_memory_map, desc_size, - filtered_memory_map_end, -- BYTES_TO_PAGES (required_bytes)); -+ BYTES_TO_PAGES (required_bytes), -+ flags); - if (err != GRUB_ERR_NONE) - return err; - -@@ -756,8 +762,9 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) - void - grub_efi_mm_init (void) - { -- if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE) -+ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE, GRUB_MM_ADD_REGION_NONE) != GRUB_ERR_NONE) - grub_fatal ("%s", grub_errmsg); -+ grub_mm_add_region_fn = grub_efi_mm_add_regions; - } - - #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) diff --git a/0312-powerpc-Drop-Open-Hack-Ware-remove-GRUB_IEEE1275_FLA.patch b/0312-powerpc-Drop-Open-Hack-Ware-remove-GRUB_IEEE1275_FLA.patch new file mode 100644 index 0000000..735075a --- /dev/null +++ b/0312-powerpc-Drop-Open-Hack-Ware-remove-GRUB_IEEE1275_FLA.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 6 Sep 2021 15:46:12 +1000 +Subject: [PATCH] powerpc: Drop Open Hack'Ware - remove + GRUB_IEEE1275_FLAG_FORCE_CLAIM + +Open Hack'Ware was the only user. It added a lot of complexity. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 333e63b356f1ce833cda1937ed8351618cbdf9d3) +--- + grub-core/kern/ieee1275/init.c | 6 +----- + grub-core/lib/ieee1275/relocator.c | 4 ---- + grub-core/loader/powerpc/ieee1275/linux.c | 14 -------------- + include/grub/ieee1275/ieee1275.h | 11 ----------- + 4 files changed, 1 insertion(+), 34 deletions(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 0dcd114ce5..6581c2c996 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -207,11 +207,7 @@ grub_claim_heap (void) + { + unsigned long total = 0; + +- if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) +- heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN, +- 1, &total); +- else +- grub_machine_mmap_iterate (heap_init, &total); ++ grub_machine_mmap_iterate (heap_init, &total); + } + #endif + +diff --git a/grub-core/lib/ieee1275/relocator.c b/grub-core/lib/ieee1275/relocator.c +index c6dd8facb0..d1bb45c75e 100644 +--- a/grub-core/lib/ieee1275/relocator.c ++++ b/grub-core/lib/ieee1275/relocator.c +@@ -38,8 +38,6 @@ grub_relocator_firmware_get_max_events (void) + { + int counter = 0; + +- if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) +- return 0; + grub_machine_mmap_iterate (count, &counter); + return 2 * counter; + } +@@ -92,8 +90,6 @@ grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) + .counter = 0 + }; + +- if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) +- return 0; + grub_machine_mmap_iterate (grub_relocator_firmware_fill_events_iter, &ctx); + return ctx.counter; + } +diff --git a/grub-core/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c +index 818b2a86d1..6fdd863130 100644 +--- a/grub-core/loader/powerpc/ieee1275/linux.c ++++ b/grub-core/loader/powerpc/ieee1275/linux.c +@@ -111,20 +111,6 @@ grub_linux_claimmap_iterate (grub_addr_t target, grub_size_t size, + .found_addr = (grub_addr_t) -1 + }; + +- if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) +- { +- grub_uint64_t addr = target; +- if (addr < GRUB_IEEE1275_STATIC_HEAP_START +- + GRUB_IEEE1275_STATIC_HEAP_LEN) +- addr = GRUB_IEEE1275_STATIC_HEAP_START +- + GRUB_IEEE1275_STATIC_HEAP_LEN; +- addr = ALIGN_UP (addr, align); +- if (grub_claimmap (addr, size) == GRUB_ERR_NONE) +- return addr; +- return (grub_addr_t) -1; +- } +- +- + grub_machine_mmap_iterate (alloc_mem, &ctx); + + return ctx.found_addr; +diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h +index b5a1d49bbc..6a1d3e5d70 100644 +--- a/include/grub/ieee1275/ieee1275.h ++++ b/include/grub/ieee1275/ieee1275.h +@@ -85,14 +85,6 @@ extern grub_ieee1275_ihandle_t EXPORT_VAR(grub_ieee1275_mmu); + + extern int (* EXPORT_VAR(grub_ieee1275_entry_fn)) (void *) GRUB_IEEE1275_ENTRY_FN_ATTRIBUTE; + +-/* Static heap, used only if FORCE_CLAIM is set, +- happens on Open Hack'Ware. Should be in platform-specific +- header but is used only on PPC anyway. +-*/ +-#define GRUB_IEEE1275_STATIC_HEAP_START 0x1000000 +-#define GRUB_IEEE1275_STATIC_HEAP_LEN 0x1000000 +- +- + enum grub_ieee1275_flag + { + /* Old World Macintosh firmware fails seek when "dev:0" is opened. */ +@@ -119,9 +111,6 @@ enum grub_ieee1275_flag + /* Open Hack'Ware stops when grub_ieee1275_interpret is used. */ + GRUB_IEEE1275_FLAG_CANNOT_INTERPRET, + +- /* Open Hack'Ware has no memory map, just claim what we need. */ +- GRUB_IEEE1275_FLAG_FORCE_CLAIM, +- + /* Open Hack'Ware don't support the ANSI sequence. */ + GRUB_IEEE1275_FLAG_NO_ANSI, + diff --git a/0313-efi-Increase-default-memory-allocation-to-32-MiB.patch b/0313-efi-Increase-default-memory-allocation-to-32-MiB.patch deleted file mode 100644 index b70c3cc..0000000 --- a/0313-efi-Increase-default-memory-allocation-to-32-MiB.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 20 Sep 2022 00:30:30 +1000 -Subject: [PATCH] efi: Increase default memory allocation to 32 MiB - -We have multiple reports of things being slower with a 1 MiB initial static -allocation, and a report (more difficult to nail down) of a boot failure -as a result of the smaller initial allocation. - -Make the initial memory allocation 32 MiB. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 75e38e86e7d9202f050b093f20500d9ad4c6dad9) ---- - grub-core/kern/efi/mm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index 016ba6cf2f..b27e966e1f 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -39,7 +39,7 @@ - #define MEMORY_MAP_SIZE 0x3000 - - /* The default heap size for GRUB itself in bytes. */ --#define DEFAULT_HEAP_SIZE 0x100000 -+#define DEFAULT_HEAP_SIZE 0x2000000 - - static void *finish_mmap_buf = 0; - static grub_efi_uintn_t finish_mmap_size = 0; diff --git a/0313-ieee1275-request-memory-with-ibm-client-architecture.patch b/0313-ieee1275-request-memory-with-ibm-client-architecture.patch new file mode 100644 index 0000000..4e95630 --- /dev/null +++ b/0313-ieee1275-request-memory-with-ibm-client-architecture.patch @@ -0,0 +1,308 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 6 Feb 2023 10:03:20 -0500 +Subject: [PATCH] ieee1275: request memory with ibm, + client-architecture-support + +On PowerVM, the first time we boot a Linux partition, we may only get +256MB of real memory area, even if the partition has more memory. + +This isn't enough to reliably verify a kernel. Fortunately, the Power +Architecture Platform Reference (PAPR) defines a method we can call to ask +for more memory: the broad and powerful ibm,client-architecture-support +(CAS) method. + +CAS can do an enormous amount of things on a PAPR platform: as well as +asking for memory, you can set the supported processor level, the interrupt +controller, hash vs radix mmu, and so on. + +If: + + - we are running under what we think is PowerVM (compatible property of / + begins with "IBM"), and + + - the full amount of RMA is less than 512MB (as determined by the reg + property of /memory) + +then call CAS as follows: (refer to the Linux on Power Architecture +Reference, LoPAR, which is public, at B.5.2.3): + + - Use the "any" PVR value and supply 2 option vectors. + + - Set option vector 1 (PowerPC Server Processor Architecture Level) + to "ignore". + + - Set option vector 2 with default or Linux-like options, including a + min-rma-size of 512MB. + + - Set option vector 3 to request Floating Point, VMX and Decimal Floating + point, but don't abort the boot if we can't get them. + + - Set option vector 4 to request a minimum VP percentage to 1%, which is + what Linux requests, and is below the default of 10%. Without this, + some systems with very large or very small configurations fail to boot. + +This will cause a CAS reboot and the partition will restart with 512MB +of RMA. Importantly, grub will notice the 512MB and not call CAS again. + +Notes about the choices of parameters: + + - A partition can be configured with only 256MB of memory, which would + mean this request couldn't be satisfied, but PFW refuses to load with + only 256MB of memory, so it's a bit moot. SLOF will run fine with 256MB, + but we will never call CAS under qemu/SLOF because /compatible won't + begin with "IBM".) + + - unspecified CAS vectors take on default values. Some of these values + might restrict the ability of certain hardware configurations to boot. + This is why we need to specify the VP percentage in vector 4, which is + in turn why we need to specify vector 3. + +Finally, we should have enough memory to verify a kernel, and we will +reach Linux. One of the first things Linux does while still running under +OpenFirmware is to call CAS with a much fuller set of options (including +asking for 512MB of memory). Linux includes a much more restrictive set of +PVR values and processor support levels, and this CAS invocation will likely +induce another reboot. On this reboot grub will again notice the higher RMA, +and not call CAS. We will get to Linux again, Linux will call CAS again, but +because the values are now set for Linux this will not induce another CAS +reboot and we will finally boot all the way to userspace. + +On all subsequent boots, everything will be configured with 512MB of RMA, +so there will be no further CAS reboots from grub. (phyp is super sticky +with the RMA size - it persists even on cold boots. So if you've ever booted +Linux in a partition, you'll probably never have grub call CAS. It'll only +ever fire the first time a partition loads grub, or if you deliberately lower +the amount of memory your partition has below 512MB.) + +Signed-off-by: Daniel Axtens +Signed-off-by: Stefan Berger +Reviewed-by: Daniel Kiper +(cherry picked from commit d5571590b7de61887efac1c298901455697ba307) +--- + grub-core/kern/ieee1275/cmain.c | 5 ++ + grub-core/kern/ieee1275/init.c | 167 ++++++++++++++++++++++++++++++++++++++- + include/grub/ieee1275/ieee1275.h | 12 ++- + 3 files changed, 182 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c +index 04df9d2c66..dce7b84922 100644 +--- a/grub-core/kern/ieee1275/cmain.c ++++ b/grub-core/kern/ieee1275/cmain.c +@@ -127,6 +127,11 @@ grub_ieee1275_find_options (void) + break; + } + } ++ ++#if defined(__powerpc__) ++ if (grub_strncmp (tmp, "IBM,", 4) == 0) ++ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY); ++#endif + } + + if (is_smartfirmware) +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 6581c2c996..8ae405bc79 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -202,11 +202,176 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + return 0; + } + +-static void ++/* ++ * How much memory does OF believe it has? (regardless of whether ++ * it's accessible or not) ++ */ ++static grub_err_t ++grub_ieee1275_total_mem (grub_uint64_t *total) ++{ ++ grub_ieee1275_phandle_t root; ++ grub_ieee1275_phandle_t memory; ++ grub_uint32_t reg[4]; ++ grub_ssize_t reg_size; ++ grub_uint32_t address_cells = 1; ++ grub_uint32_t size_cells = 1; ++ grub_uint64_t size; ++ ++ /* If we fail to get to the end, report 0. */ ++ *total = 0; ++ ++ /* Determine the format of each entry in `reg'. */ ++ if (grub_ieee1275_finddevice ("/", &root)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find / node"); ++ if (grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells, ++ sizeof (address_cells), 0)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine #address-cells"); ++ if (grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells, ++ sizeof (size_cells), 0)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine #size-cells"); ++ ++ if (size_cells > address_cells) ++ address_cells = size_cells; ++ ++ /* Load `/memory/reg'. */ ++ if (grub_ieee1275_finddevice ("/memory", &memory)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find /memory node"); ++ if (grub_ieee1275_get_integer_property (memory, "reg", reg, ++ sizeof (reg), ®_size)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine /memory/reg property"); ++ if (reg_size < 0 || (grub_size_t) reg_size > sizeof (reg)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "/memory response buffer exceeded"); ++ ++ if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS)) ++ { ++ address_cells = 1; ++ size_cells = 1; ++ } ++ ++ /* Decode only the size */ ++ size = reg[address_cells]; ++ if (size_cells == 2) ++ size = (size << 32) | reg[address_cells + 1]; ++ ++ *total = size; ++ ++ return grub_errno; ++} ++ ++#if defined(__powerpc__) ++ ++/* See PAPR or arch/powerpc/kernel/prom_init.c */ ++struct option_vector2 ++{ ++ grub_uint8_t byte1; ++ grub_uint16_t reserved; ++ grub_uint32_t real_base; ++ grub_uint32_t real_size; ++ grub_uint32_t virt_base; ++ grub_uint32_t virt_size; ++ grub_uint32_t load_base; ++ grub_uint32_t min_rma; ++ grub_uint32_t min_load; ++ grub_uint8_t min_rma_percent; ++ grub_uint8_t max_pft_size; ++} GRUB_PACKED; ++ ++struct pvr_entry ++{ ++ grub_uint32_t mask; ++ grub_uint32_t entry; ++}; ++ ++struct cas_vector ++{ ++ struct ++ { ++ struct pvr_entry terminal; ++ } pvr_list; ++ grub_uint8_t num_vecs; ++ grub_uint8_t vec1_size; ++ grub_uint8_t vec1; ++ grub_uint8_t vec2_size; ++ struct option_vector2 vec2; ++ grub_uint8_t vec3_size; ++ grub_uint16_t vec3; ++ grub_uint8_t vec4_size; ++ grub_uint16_t vec4; ++} GRUB_PACKED; ++ ++/* ++ * Call ibm,client-architecture-support to try to get more RMA. ++ * We ask for 512MB which should be enough to verify a distro kernel. ++ * We ignore most errors: if we don't succeed we'll proceed with whatever ++ * memory we have. ++ */ ++static void ++grub_ieee1275_ibm_cas (void) ++{ ++ int rc; ++ grub_ieee1275_ihandle_t root; ++ struct cas_args ++ { ++ struct grub_ieee1275_common_hdr common; ++ grub_ieee1275_cell_t method; ++ grub_ieee1275_ihandle_t ihandle; ++ grub_ieee1275_cell_t cas_addr; ++ grub_ieee1275_cell_t result; ++ } args; ++ struct cas_vector vector = ++ { ++ .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ ++ .num_vecs = 4 - 1, ++ .vec1_size = 0, ++ .vec1 = 0x80, /* ignore */ ++ .vec2_size = 1 + sizeof (struct option_vector2) - 2, ++ .vec2 = { ++ 0, 0, -1, -1, -1, -1, -1, 512, -1, 0, 48 ++ }, ++ .vec3_size = 2 - 1, ++ .vec3 = 0x00e0, /* ask for FP + VMX + DFP but don't halt if unsatisfied */ ++ .vec4_size = 2 - 1, ++ .vec4 = 0x0001, /* set required minimum capacity % to the lowest value */ ++ }; ++ ++ INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); ++ args.method = (grub_ieee1275_cell_t) "ibm,client-architecture-support"; ++ rc = grub_ieee1275_open ("/", &root); ++ if (rc) ++ { ++ grub_error (GRUB_ERR_IO, "could not open root when trying to call CAS"); ++ return; ++ } ++ args.ihandle = root; ++ args.cas_addr = (grub_ieee1275_cell_t) &vector; ++ ++ grub_printf ("Calling ibm,client-architecture-support from grub..."); ++ IEEE1275_CALL_ENTRY_FN (&args); ++ grub_printf ("done\n"); ++ ++ grub_ieee1275_close (root); ++} ++ ++#endif /* __powerpc__ */ ++ ++static void + grub_claim_heap (void) + { + unsigned long total = 0; + ++#if defined(__powerpc__) ++ if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY)) ++ { ++ grub_uint64_t rma_size; ++ grub_err_t err; ++ ++ err = grub_ieee1275_total_mem (&rma_size); ++ /* if we have an error, don't call CAS, just hope for the best */ ++ if (err == GRUB_ERR_NONE && rma_size < (512 * 1024 * 1024)) ++ grub_ieee1275_ibm_cas (); ++ } ++#endif ++ + grub_machine_mmap_iterate (heap_init, &total); + } + #endif +diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h +index 6a1d3e5d70..560c968460 100644 +--- a/include/grub/ieee1275/ieee1275.h ++++ b/include/grub/ieee1275/ieee1275.h +@@ -138,7 +138,17 @@ enum grub_ieee1275_flag + + GRUB_IEEE1275_FLAG_RAW_DEVNAMES, + +- GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT ++ GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT, ++ ++#if defined(__powerpc__) ++ /* ++ * On PFW, the first time we boot a Linux partition, we may only get 256MB of ++ * real memory area, even if the partition has more memory. Set this flag if ++ * we think we're running under PFW. Then, if this flag is set, and the RMA is ++ * only 256MB in size, try asking for more with CAS. ++ */ ++ GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY, ++#endif + }; + + extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag); diff --git a/0314-ieee1275-drop-len-1-quirk-in-heap_init.patch b/0314-ieee1275-drop-len-1-quirk-in-heap_init.patch new file mode 100644 index 0000000..4ce064b --- /dev/null +++ b/0314-ieee1275-drop-len-1-quirk-in-heap_init.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 6 Feb 2023 10:03:21 -0500 +Subject: [PATCH] ieee1275: drop len -= 1 quirk in heap_init + +This was apparently 'required by some firmware': commit dc9468500919 +("2007-02-12 Hollis Blanchard "). + +It's not clear what firmware that was, and what platform from 14 years ago +which exhibited the bug then is still both in use and buggy now. + +It doesn't cause issues on qemu (mac99 or pseries) or under PFW for Power8. + +I don't have access to old Mac hardware, but if anyone feels especially +strongly we can put it under some feature flag. I really want to disable +it under pseries because it will mess with region merging. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit fc639d430297321ee4f77c5d2d698f698cec0dc7) +--- + grub-core/kern/ieee1275/init.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 8ae405bc79..c8d551759d 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -168,7 +168,6 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + addr = 0x180000; + } + } +- len -= 1; /* Required for some firmware. */ + + /* Never exceed HEAP_MAX_SIZE */ + if (*total + len > HEAP_MAX_SIZE) diff --git a/0314-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch b/0314-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch deleted file mode 100644 index c919891..0000000 --- a/0314-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Sat, 15 Oct 2022 22:15:11 +0800 -Subject: [PATCH] mm: Try invalidate disk caches last when out of memory - -Every heap grow will cause all disk caches invalidated which decreases -performance severely. This patch moves disk cache invalidation code to -the last of memory squeezing measures. So, disk caches are released only -when there are no other ways to get free memory. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -Reviewed-by: Patrick Steinhardt -(cherry picked from commit 17975d10a80e2457e5237f87fa58a7943031983e) ---- - grub-core/kern/mm.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c -index f2e27f263b..da1ac9427c 100644 ---- a/grub-core/kern/mm.c -+++ b/grub-core/kern/mm.c -@@ -443,12 +443,6 @@ grub_memalign (grub_size_t align, grub_size_t size) - switch (count) - { - case 0: -- /* Invalidate disk caches. */ -- grub_disk_cache_invalidate_all (); -- count++; -- goto again; -- -- case 1: - /* Request additional pages, contiguous */ - count++; - -@@ -458,7 +452,7 @@ grub_memalign (grub_size_t align, grub_size_t size) - - /* fallthrough */ - -- case 2: -+ case 1: - /* Request additional pages, anything at all */ - count++; - -@@ -474,6 +468,12 @@ grub_memalign (grub_size_t align, grub_size_t size) - - /* fallthrough */ - -+ case 2: -+ /* Invalidate disk caches. */ -+ grub_disk_cache_invalidate_all (); -+ count++; -+ goto again; -+ - default: - break; - } diff --git a/0315-ieee1275-support-runtime-memory-claiming.patch b/0315-ieee1275-support-runtime-memory-claiming.patch new file mode 100644 index 0000000..17ad61d --- /dev/null +++ b/0315-ieee1275-support-runtime-memory-claiming.patch @@ -0,0 +1,435 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 6 Feb 2023 10:03:22 -0500 +Subject: [PATCH] ieee1275: support runtime memory claiming + +On powerpc-ieee1275, we are running out of memory trying to verify +anything. This is because: + + - we have to load an entire file into memory to verify it. This is + difficult to change with appended signatures. + - We only have 32MB of heap. + - Distro kernels are now often around 30MB. + +So we want to be able to claim more memory from OpenFirmware for our heap +at runtime. + +There are some complications: + + - The grub mm code isn't the only thing that will make claims on + memory from OpenFirmware: + + * PFW/SLOF will have claimed some for their own use. + + * The ieee1275 loader will try to find other bits of memory that we + haven't claimed to place the kernel and initrd when we go to boot. + + * Once we load Linux, it will also try to claim memory. It claims + memory without any reference to /memory/available, it just starts + at min(top of RMO, 768MB) and works down. So we need to avoid this + area. See arch/powerpc/kernel/prom_init.c as of v5.11. + + - The smallest amount of memory a ppc64 KVM guest can have is 256MB. + It doesn't work with distro kernels but can work with custom kernels. + We should maintain support for that. (ppc32 can boot with even less, + and we shouldn't break that either.) + + - Even if a VM has more memory, the memory OpenFirmware makes available + as Real Memory Area can be restricted. Even with our CAS work, an LPAR + on a PowerVM box is likely to have only 512MB available to OpenFirmware + even if it has many gigabytes of memory allocated. + +What should we do? + +We don't know in advance how big the kernel and initrd are going to be, +which makes figuring out how much memory we can take a bit tricky. + +To figure out how much memory we should leave unused, I looked at: + + - an Ubuntu 20.04.1 ppc64le pseries KVM guest: + vmlinux: ~30MB + initrd: ~50MB + + - a RHEL8.2 ppc64le pseries KVM guest: + vmlinux: ~30MB + initrd: ~30MB + +So to give us a little wriggle room, I think we want to leave at least +128MB for the loader to put vmlinux and initrd in memory and leave Linux +with space to satisfy its early allocations. + +Allow other space to be allocated at runtime. + +Tested-by: Stefan Berger +Signed-off-by: Daniel Axtens +(cherry picked from commit a5c710789ccdd27a84ae4a34c7d453bd585e2b66) +[rharwood: _start?] +--- + grub-core/kern/ieee1275/init.c | 270 ++++++++++++++++++++++++++++++++++++++--- + docs/grub-dev.texi | 7 +- + 2 files changed, 257 insertions(+), 20 deletions(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index c8d551759d..85af8fa97b 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -46,13 +46,26 @@ + #endif + #include + +-/* The maximum heap size we're going to claim */ ++/* The maximum heap size we're going to claim at boot. Not used by sparc. */ + #ifdef __i386__ + #define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024) +-#else ++#else /* __powerpc__ */ + #define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024) + #endif + ++/* RMO max. address at 768 MB */ ++#define RMO_ADDR_MAX (grub_uint64_t) (768 * 1024 * 1024) ++ ++/* ++ * The amount of OF space we will not claim here so as to leave space for ++ * the loader and linux to service early allocations. ++ * ++ * In 2021, Daniel Axtens claims that we should leave at least 128MB to ++ * ensure we can load a stock kernel and initrd on a pseries guest with ++ * a 512MB real memory area under PowerVM. ++ */ ++#define RUNTIME_MIN_SPACE (128UL * 1024 * 1024) ++ + extern char _end[]; + + #ifdef __sparc__ +@@ -147,16 +160,52 @@ grub_claim_heap (void) + + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); + } + #else +-/* Helper for grub_claim_heap. */ ++/* Helpers for mm on powerpc. */ ++ ++/* ++ * How much memory does OF believe exists in total? ++ * ++ * This isn't necessarily the true total. It can be the total memory ++ * accessible in real mode for a pseries guest, for example. ++ */ ++static grub_uint64_t rmo_top; ++ + static int +-heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, +- void *data) ++count_free (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, ++ void *data) + { +- unsigned long *total = data; ++ if (type != GRUB_MEMORY_AVAILABLE) ++ return 0; ++ ++ /* Do not consider memory beyond 4GB */ ++ if (addr > 0xffffffffULL) ++ return 0; ++ ++ if (addr + len > 0xffffffffULL) ++ len = 0xffffffffULL - addr; ++ ++ *(grub_uint32_t *) data += len; ++ ++ return 0; ++} ++ ++static int ++regions_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, ++ unsigned int flags, void *data) ++{ ++ grub_uint32_t total = *(grub_uint32_t *) data; ++ grub_uint64_t linux_rmo_save; + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + ++ /* Do not consider memory beyond 4GB */ ++ if (addr > 0xffffffffULL) ++ return 0; ++ ++ if (addr + len > 0xffffffffULL) ++ len = 0xffffffffULL - addr; ++ + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) + { + if (addr + len <= 0x180000) +@@ -169,10 +218,6 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + } + } + +- /* Never exceed HEAP_MAX_SIZE */ +- if (*total + len > HEAP_MAX_SIZE) +- len = HEAP_MAX_SIZE - *total; +- + /* In theory, firmware should already prevent this from happening by not + listing our own image in /memory/available. The check below is intended + as a safeguard in case that doesn't happen. However, it doesn't protect +@@ -184,6 +229,108 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + len = 0; + } + ++ /* ++ * Linux likes to claim memory at min(RMO top, 768MB) and works down ++ * without reference to /memory/available. (See prom_init.c::alloc_down) ++ * ++ * If this block contains min(RMO top, 768MB), do not claim below that for ++ * at least a few MB (this is where RTAS, SML and potentially TCEs live). ++ * ++ * We also need to leave enough space for the DT in the RMA. (See ++ * prom_init.c::alloc_up) ++ * ++ * Finally, we also want to make sure that when grub loads the kernel, ++ * it isn't going to use up all the memory we're trying to reserve! So ++ * enforce our entire RUNTIME_MIN_SPACE here: ++ * ++ * |---------- Top of memory ----------| ++ * | | ++ * | available | ++ * | | ++ * |---------- 768 MB ----------| ++ * | | ++ * | reserved | ++ * | | ++ * |--- 768 MB - runtime min space ---| ++ * | | ++ * | available | ++ * | | ++ * |---------- 0 MB ----------| ++ * ++ * Edge cases: ++ * ++ * - Total memory less than RUNTIME_MIN_SPACE: only claim up to HEAP_MAX_SIZE. ++ * (enforced elsewhere) ++ * ++ * - Total memory between RUNTIME_MIN_SPACE and 768MB: ++ * ++ * |---------- Top of memory ----------| ++ * | | ++ * | reserved | ++ * | | ++ * |---- top - runtime min space ----| ++ * | | ++ * | available | ++ * | | ++ * |---------- 0 MB ----------| ++ * ++ * This by itself would not leave us with RUNTIME_MIN_SPACE of free bytes: if ++ * rmo_top < 768MB, we will almost certainly have FW claims in the reserved ++ * region. We try to address that elsewhere: grub_ieee1275_mm_add_region will ++ * not call us if the resulting free space would be less than RUNTIME_MIN_SPACE. ++ */ ++ linux_rmo_save = grub_min (RMO_ADDR_MAX, rmo_top) - RUNTIME_MIN_SPACE; ++ if (rmo_top > RUNTIME_MIN_SPACE) ++ { ++ if (rmo_top <= RMO_ADDR_MAX) ++ { ++ if (addr > linux_rmo_save) ++ { ++ grub_dprintf ("ieee1275", "rejecting region in RUNTIME_MIN_SPACE reservation (%llx)\n", ++ addr); ++ return 0; ++ } ++ else if (addr + len > linux_rmo_save) ++ { ++ grub_dprintf ("ieee1275", "capping region: (%llx -> %llx) -> (%llx -> %llx)\n", ++ addr, addr + len, addr, rmo_top - RUNTIME_MIN_SPACE); ++ len = linux_rmo_save - addr; ++ } ++ } ++ else ++ { ++ /* ++ * we order these cases to prefer higher addresses and avoid some ++ * splitting issues ++ */ ++ if (addr < RMO_ADDR_MAX && (addr + len) > RMO_ADDR_MAX) ++ { ++ grub_dprintf ("ieee1275", ++ "adjusting region for RUNTIME_MIN_SPACE: (%llx -> %llx) -> (%llx -> %llx)\n", ++ addr, addr + len, RMO_ADDR_MAX, addr + len); ++ len = (addr + len) - RMO_ADDR_MAX; ++ addr = RMO_ADDR_MAX; ++ } ++ else if ((addr < linux_rmo_save) && ((addr + len) > linux_rmo_save)) ++ { ++ grub_dprintf ("ieee1275", "capping region: (%llx -> %llx) -> (%llx -> %llx)\n", ++ addr, addr + len, addr, linux_rmo_save); ++ len = linux_rmo_save - addr; ++ } ++ else if (addr >= linux_rmo_save && (addr + len) <= RMO_ADDR_MAX) ++ { ++ grub_dprintf ("ieee1275", "rejecting region in RUNTIME_MIN_SPACE reservation (%llx)\n", ++ addr); ++ return 0; ++ } ++ } ++ } ++ if (flags & GRUB_MM_ADD_REGION_CONSECUTIVE && len < total) ++ return 0; ++ ++ if (len > total) ++ len = total; ++ + if (len) + { + grub_err_t err; +@@ -192,15 +339,95 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + if (err) + return err; + grub_mm_init_region ((void *) (grub_addr_t) addr, len); ++ total -= len; + } + +- *total += len; +- if (*total >= HEAP_MAX_SIZE) ++ *(grub_uint32_t *) data = total; ++ ++ if (total == 0) + return 1; + + return 0; + } + ++static int ++heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, ++ void *data) ++{ ++ return regions_claim (addr, len, type, GRUB_MM_ADD_REGION_NONE, data); ++} ++ ++static int ++region_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, ++ void *data) ++{ ++ return regions_claim (addr, len, type, GRUB_MM_ADD_REGION_CONSECUTIVE, data); ++} ++ ++static grub_err_t ++grub_ieee1275_mm_add_region (grub_size_t size, unsigned int flags) ++{ ++ grub_uint32_t free_memory = 0; ++ grub_uint32_t avail = 0; ++ grub_uint32_t total; ++ ++ grub_dprintf ("ieee1275", "mm requested region of size %x, flags %x\n", ++ size, flags); ++ ++ /* ++ * Update free memory each time, which is a bit inefficient but guards us ++ * against a situation where some OF driver goes out to firmware for ++ * memory and we don't realise. ++ */ ++ grub_machine_mmap_iterate (count_free, &free_memory); ++ ++ /* Ensure we leave enough space to boot. */ ++ if (free_memory <= RUNTIME_MIN_SPACE + size) ++ { ++ grub_dprintf ("ieee1275", "Cannot satisfy allocation and retain minimum runtime space\n"); ++ return GRUB_ERR_OUT_OF_MEMORY; ++ } ++ ++ if (free_memory > RUNTIME_MIN_SPACE) ++ avail = free_memory - RUNTIME_MIN_SPACE; ++ ++ grub_dprintf ("ieee1275", "free = 0x%x available = 0x%x\n", free_memory, avail); ++ ++ if (flags & GRUB_MM_ADD_REGION_CONSECUTIVE) ++ { ++ /* first try rounding up hard for the sake of speed */ ++ total = grub_max (ALIGN_UP (size, 1024 * 1024) + 1024 * 1024, 32 * 1024 * 1024); ++ total = grub_min (avail, total); ++ ++ grub_dprintf ("ieee1275", "looking for %x bytes of memory (%x requested)\n", total, size); ++ ++ grub_machine_mmap_iterate (region_claim, &total); ++ grub_dprintf ("ieee1275", "get memory from fw %s\n", total == 0 ? "succeeded" : "failed"); ++ ++ if (total != 0) ++ { ++ total = grub_min (avail, size); ++ ++ grub_dprintf ("ieee1275", "fallback for %x bytes of memory (%x requested)\n", total, size); ++ ++ grub_machine_mmap_iterate (region_claim, &total); ++ grub_dprintf ("ieee1275", "fallback from fw %s\n", total == 0 ? "succeeded" : "failed"); ++ } ++ } ++ else ++ { ++ /* provide padding for a grub_mm_header_t and region */ ++ total = grub_min (avail, size); ++ grub_machine_mmap_iterate (heap_init, &total); ++ grub_dprintf ("ieee1275", "get noncontig memory from fw %s\n", total == 0 ? "succeeded" : "failed"); ++ } ++ ++ if (total == 0) ++ return GRUB_ERR_NONE; ++ else ++ return GRUB_ERR_OUT_OF_MEMORY; ++} ++ + /* + * How much memory does OF believe it has? (regardless of whether + * it's accessible or not) +@@ -356,17 +583,24 @@ grub_ieee1275_ibm_cas (void) + static void + grub_claim_heap (void) + { +- unsigned long total = 0; ++ grub_err_t err; ++ grub_uint32_t total = HEAP_MAX_SIZE; ++ ++ err = grub_ieee1275_total_mem (&rmo_top); ++ ++ /* ++ * If we cannot size the available memory, we can't be sure we're leaving ++ * space for the kernel, initrd and things Linux loads early in boot. So only ++ * allow further allocations from firmware on success ++ */ ++ if (err == GRUB_ERR_NONE) ++ grub_mm_add_region_fn = grub_ieee1275_mm_add_region; + + #if defined(__powerpc__) + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY)) + { +- grub_uint64_t rma_size; +- grub_err_t err; +- +- err = grub_ieee1275_total_mem (&rma_size); + /* if we have an error, don't call CAS, just hope for the best */ +- if (err == GRUB_ERR_NONE && rma_size < (512 * 1024 * 1024)) ++ if (err == GRUB_ERR_NONE && rmo_top < (512 * 1024 * 1024)) + grub_ieee1275_ibm_cas (); + } + #endif +diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi +index 7b2455a8fe..7edc5b7e2b 100644 +--- a/docs/grub-dev.texi ++++ b/docs/grub-dev.texi +@@ -1047,7 +1047,10 @@ space is limited to 4GiB. GRUB allocates pages from EFI for its heap, at most + 1.6 GiB. + + On i386-ieee1275 and powerpc-ieee1275 GRUB uses same stack as IEEE1275. +-It allocates at most 32MiB for its heap. ++ ++On i386-ieee1275 and powerpc-ieee1275, GRUB will allocate 32MiB for its heap on ++startup. It may allocate more at runtime, as long as at least 128MiB remain free ++in OpenFirmware. + + On sparc64-ieee1275 stack is 256KiB and heap is 2MiB. + +@@ -1075,7 +1078,7 @@ In short: + @item i386-qemu @tab 60 KiB @tab < 4 GiB + @item *-efi @tab ? @tab < 1.6 GiB + @item i386-ieee1275 @tab ? @tab < 32 MiB +-@item powerpc-ieee1275 @tab ? @tab < 32 MiB ++@item powerpc-ieee1275 @tab ? @tab available memory - 128MiB + @item sparc64-ieee1275 @tab 256KiB @tab 2 MiB + @item arm-uboot @tab 256KiB @tab 2 MiB + @item mips(el)-qemu_mips @tab 2MiB @tab 253 MiB diff --git a/0315-ppc64le-signed-boot-media-changes.patch b/0315-ppc64le-signed-boot-media-changes.patch deleted file mode 100644 index bd71437..0000000 --- a/0315-ppc64le-signed-boot-media-changes.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Wed, 25 Jan 2023 16:10:58 -0500 -Subject: [PATCH] ppc64le: signed boot media changes - -Skip mdraid < 1.1 on isos since mdraid* can't even - -Prior to this change, on ppc64le with part_msdos and the mdraid* modules -enabled, we see: - - disk/diskfilter.c:191: scanning ieee1275/cdrom - kern/disk.c:196: Opening `ieee1275/cdrom'... - disk/ieee1275/ofdisk.c:477: Opening `cdrom'. - disk/ieee1275/ofdisk.c:502: MAX_RETRIES set to 20 - kern/disk.c:288: Opening `ieee1275/cdrom' succeeded. - disk/diskfilter.c:136: Scanning for DISKFILTER devices on disk ieee1275/cdrom - partmap/msdos.c:184: partition 0: flag 0x80, type 0x96, start 0x0, len - 0x6a5d70 - disk/diskfilter.c:136: Scanning for DISKFILTER devices on disk ieee1275/cdrom - SCSI-DISK: Access beyond end of device ! - SCSI-DISK: Access beyond end of device ! - SCSI-DISK: Access beyond end of device ! - SCSI-DISK: Access beyond end of device ! - SCSI-DISK: Access beyond end of device ! - disk/ieee1275/ofdisk.c:578: MAX_RETRIES set to 20 - -These latter two lines repeat many times, eventually ending in: - - kern/disk.c:388: ieee1275/cdrom read failed - error: ../../grub-core/disk/ieee1275/ofdisk.c:608:failure reading sector - 0x1a9720 from `ieee1275/cdrom'. - -and the system drops to a "grub>" prompt. - -Prior to 1.1, mdraid stored the superblock offset from the end of the -disk, and the firmware really doesn't like reads there. Best guess was -that the firmware and the iso image appear to diagree on the blocksize -(512 vs. 2048), and the diskfilter RAID probing is too much for it. -It's tempting to just skip probing for cdroms, but unfortunately isos -can be virtualized elsewhere - such as regular disks. - -Also fix detection of root, and try the chrp path as a fallback if the -built prefix doesn't work. - -Signed-off-by: Robbie Harwood - -wip ---- - grub-core/disk/mdraid1x_linux.c | 8 +++++++- - grub-core/disk/mdraid_linux.c | 5 +++++ - grub-core/kern/ieee1275/openfw.c | 2 +- - grub-core/normal/main.c | 5 +++++ - 4 files changed, 18 insertions(+), 2 deletions(-) - -diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c -index 38444b02c7..08c57ae16e 100644 ---- a/grub-core/disk/mdraid1x_linux.c -+++ b/grub-core/disk/mdraid1x_linux.c -@@ -129,7 +129,13 @@ grub_mdraid_detect (grub_disk_t disk, - grub_uint32_t level; - struct grub_diskfilter_vg *array; - char *uuid; -- -+ -+#ifdef __powerpc__ -+ /* Firmware will yell at us for reading too far. */ -+ if (minor_version == 0) -+ continue; -+#endif -+ - if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0) - continue; - -diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c -index e40216f511..98fcfb1be6 100644 ---- a/grub-core/disk/mdraid_linux.c -+++ b/grub-core/disk/mdraid_linux.c -@@ -189,6 +189,11 @@ grub_mdraid_detect (grub_disk_t disk, - grub_uint32_t level; - struct grub_diskfilter_vg *ret; - -+#ifdef __powerpc__ -+ /* Firmware will yell at us for reading too far. */ -+ return NULL; -+#endif -+ - /* The sector where the mdraid 0.90 superblock is stored, if available. */ - size = grub_disk_native_sectors (disk); - if (size == GRUB_DISK_SIZE_UNKNOWN) -diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c -index 3a6689abb1..0278054c61 100644 ---- a/grub-core/kern/ieee1275/openfw.c -+++ b/grub-core/kern/ieee1275/openfw.c -@@ -499,7 +499,7 @@ grub_ieee1275_encode_devname (const char *path) - *optr++ ='\\'; - *optr++ = *iptr++; - } -- if (partition && partition[0]) -+ if (partition && partition[0] >= '0' && partition[0] <= '9') - { - unsigned int partno = grub_strtoul (partition, 0, 0); - -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index 8f5fd81003..d59145f861 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -372,6 +372,7 @@ grub_try_normal_prefix (const char *prefix) - file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); - if (file) - { -+ grub_env_set ("prefix", prefix); - grub_file_close (file); - err = GRUB_ERR_NONE; - } -@@ -447,6 +448,10 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), - err = grub_try_normal ("fw_path"); - if (err == GRUB_ERR_FILE_NOT_FOUND) - err = grub_try_normal ("prefix"); -+#ifdef __powerpc__ -+ if (err == GRUB_ERR_FILE_NOT_FOUND) -+ err = grub_try_normal_prefix ("/boot/grub"); -+#endif - if (err == GRUB_ERR_FILE_NOT_FOUND) - err = grub_try_normal_discover (); - if (err == GRUB_ERR_FILE_NOT_FOUND) diff --git a/0316-core-Fix-several-implicit-function-declarations.patch b/0316-core-Fix-several-implicit-function-declarations.patch deleted file mode 100644 index 48c5bb0..0000000 --- a/0316-core-Fix-several-implicit-function-declarations.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Arjun Shankar -Date: Sun, 5 Feb 2023 11:13:55 +0100 -Subject: [PATCH] core: Fix several implicit function declarations - -These #include lines ensure that grub2 continues to build with C99 -where implicit function declarations are removed. - -Related to: - - - ---- - grub-core/commands/efi/connectefi.c | 1 + - grub-core/net/http.c | 1 + - grub-core/term/at_keyboard.c | 1 + - 3 files changed, 3 insertions(+) - -diff --git a/grub-core/commands/efi/connectefi.c b/grub-core/commands/efi/connectefi.c -index 8ab75bd51b..3752ae17ed 100644 ---- a/grub-core/commands/efi/connectefi.c -+++ b/grub-core/commands/efi/connectefi.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/grub-core/net/http.c b/grub-core/net/http.c -index 57d2721719..5f956b743e 100644 ---- a/grub-core/net/http.c -+++ b/grub-core/net/http.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c -index dac0f946fe..de3e4abe44 100644 ---- a/grub-core/term/at_keyboard.c -+++ b/grub-core/term/at_keyboard.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - GRUB_MOD_LICENSE ("GPLv3+"); - diff --git a/0316-ieee1275-implement-vec5-for-cas-negotiation.patch b/0316-ieee1275-implement-vec5-for-cas-negotiation.patch new file mode 100644 index 0000000..fad39db --- /dev/null +++ b/0316-ieee1275-implement-vec5-for-cas-negotiation.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Diego Domingos +Date: Mon, 6 Feb 2023 10:03:23 -0500 +Subject: [PATCH] ieee1275: implement vec5 for cas negotiation + +As a legacy support, if the vector 5 is not implemented, Power Hypervisor will +consider the max CPUs as 64 instead 256 currently supported during +client-architecture-support negotiation. + +This patch implements the vector 5 and set the MAX CPUs to 256 while setting the +others values to 0 (default). + +Signed-off-by: Diego Domingos +Acked-by: Daniel Axtens +Signed-off-by: Stefan Berger +Signed-off-by: Avnish Chouhan +(cherry picked from commit 942f19959fe7465fb52a1da39ff271a7ab704892) +--- + grub-core/kern/ieee1275/init.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 85af8fa97b..72d4fed312 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -502,6 +502,19 @@ struct option_vector2 + grub_uint8_t max_pft_size; + } GRUB_PACKED; + ++struct option_vector5 ++{ ++ grub_uint8_t byte1; ++ grub_uint8_t byte2; ++ grub_uint8_t byte3; ++ grub_uint8_t cmo; ++ grub_uint8_t associativity; ++ grub_uint8_t bin_opts; ++ grub_uint8_t micro_checkpoint; ++ grub_uint8_t reserved0; ++ grub_uint32_t max_cpus; ++} GRUB_PACKED; ++ + struct pvr_entry + { + grub_uint32_t mask; +@@ -523,6 +536,8 @@ struct cas_vector + grub_uint16_t vec3; + grub_uint8_t vec4_size; + grub_uint16_t vec4; ++ grub_uint8_t vec5_size; ++ struct option_vector5 vec5; + } GRUB_PACKED; + + /* +@@ -547,7 +562,7 @@ grub_ieee1275_ibm_cas (void) + struct cas_vector vector = + { + .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ +- .num_vecs = 4 - 1, ++ .num_vecs = 5 - 1, + .vec1_size = 0, + .vec1 = 0x80, /* ignore */ + .vec2_size = 1 + sizeof (struct option_vector2) - 2, +@@ -558,6 +573,10 @@ grub_ieee1275_ibm_cas (void) + .vec3 = 0x00e0, /* ask for FP + VMX + DFP but don't halt if unsatisfied */ + .vec4_size = 2 - 1, + .vec4 = 0x0001, /* set required minimum capacity % to the lowest value */ ++ .vec5_size = 1 + sizeof (struct option_vector5) - 2, ++ .vec5 = { ++ 0, 192, 0, 128, 0, 0, 0, 0, 256 ++ } + }; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); diff --git a/0317-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch b/0317-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch new file mode 100644 index 0000000..02c0282 --- /dev/null +++ b/0317-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch @@ -0,0 +1,246 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Mon, 6 Feb 2023 10:03:25 -0500 +Subject: [PATCH] ibmvtpm: Add support for trusted boot using a vTPM 2.0 + +Add support for trusted boot using a vTPM 2.0 on the IBM IEEE1275 +PowerPC platform. With this patch grub now measures text and binary data +into the TPM's PCRs 8 and 9 in the same way as the x86_64 platform +does. + +This patch requires Daniel Axtens's patches for claiming more memory. + +Note: The tpm_init() function cannot be called from GRUB_MOD_INIT() since +it does not find the device nodes upon module initialization and +therefore the call to tpm_init() must be deferred to grub_tpm_measure(). + +For vTPM support to work on PowerVM, system driver levels 1010.30 +or 1020.00 are required. + +Note: Previous versions of firmware levels with the 2hash-ext-log +API call have a bug that, once this API call is invoked, has the +effect of disabling the vTPM driver under Linux causing an error +message to be displayed in the Linux kernel log. Those users will +have to update their machines to the firmware levels mentioned +above. + +Cc: Eric Snowberg +Signed-off-by: Stefan Berger +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 2aa5ef83743dfea79377309ff4f5e9c9a55de355) +--- + grub-core/Makefile.core.def | 7 ++ + grub-core/commands/ieee1275/ibmvtpm.c | 155 ++++++++++++++++++++++++++++++++++ + include/grub/ieee1275/ieee1275.h | 3 + + docs/grub.texi | 3 +- + 4 files changed, 167 insertions(+), 1 deletion(-) + create mode 100644 grub-core/commands/ieee1275/ibmvtpm.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index f21da23213..02ea718652 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1175,6 +1175,13 @@ module = { + enable = powerpc_ieee1275; + }; + ++module = { ++ name = tpm; ++ common = commands/tpm.c; ++ ieee1275 = commands/ieee1275/ibmvtpm.c; ++ enable = powerpc_ieee1275; ++}; ++ + module = { + name = terminal; + common = commands/terminal.c; +diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c +new file mode 100644 +index 0000000000..239942d27e +--- /dev/null ++++ b/grub-core/commands/ieee1275/ibmvtpm.c +@@ -0,0 +1,155 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Free Software Foundation, Inc. ++ * Copyright (C) 2022 IBM Corporation ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ * ++ * IBM vTPM support code. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static grub_ieee1275_ihandle_t tpm_ihandle; ++static grub_uint8_t tpm_version; ++ ++#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t) 0) ++ ++static void ++tpm_get_tpm_version (void) ++{ ++ grub_ieee1275_phandle_t vtpm; ++ char buffer[20]; ++ ++ if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) && ++ !grub_ieee1275_get_property (vtpm, "compatible", buffer, ++ sizeof (buffer), NULL) && ++ !grub_strcmp (buffer, "IBM,vtpm20")) ++ tpm_version = 2; ++} ++ ++static grub_err_t ++tpm_init (void) ++{ ++ static int init_success = 0; ++ ++ if (!init_success) ++ { ++ if (grub_ieee1275_open ("/vdevice/vtpm", &tpm_ihandle) < 0) ++ { ++ tpm_ihandle = IEEE1275_IHANDLE_INVALID; ++ return GRUB_ERR_UNKNOWN_DEVICE; ++ } ++ ++ init_success = 1; ++ ++ tpm_get_tpm_version (); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static int ++ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex, ++ grub_uint32_t eventtype, ++ const char *description, ++ grub_size_t description_size, ++ void *buf, grub_size_t size) ++{ ++ struct tpm_2hash_ext_log ++ { ++ struct grub_ieee1275_common_hdr common; ++ grub_ieee1275_cell_t method; ++ grub_ieee1275_cell_t ihandle; ++ grub_ieee1275_cell_t size; ++ grub_ieee1275_cell_t buf; ++ grub_ieee1275_cell_t description_size; ++ grub_ieee1275_cell_t description; ++ grub_ieee1275_cell_t eventtype; ++ grub_ieee1275_cell_t pcrindex; ++ grub_ieee1275_cell_t catch_result; ++ grub_ieee1275_cell_t rc; ++ }; ++ struct tpm_2hash_ext_log args; ++ ++ INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2); ++ args.method = (grub_ieee1275_cell_t) "2hash-ext-log"; ++ args.ihandle = tpm_ihandle; ++ args.pcrindex = pcrindex; ++ args.eventtype = eventtype; ++ args.description = (grub_ieee1275_cell_t) description; ++ args.description_size = description_size; ++ args.buf = (grub_ieee1275_cell_t) buf; ++ args.size = (grub_ieee1275_cell_t) size; ++ ++ if (IEEE1275_CALL_ENTRY_FN (&args) == -1) ++ return -1; ++ ++ /* ++ * catch_result is set if firmware does not support 2hash-ext-log ++ * rc is GRUB_IEEE1275_CELL_FALSE (0) on failure ++ */ ++ if ((args.catch_result) || args.rc == GRUB_IEEE1275_CELL_FALSE) ++ return -1; ++ ++ return 0; ++} ++ ++static grub_err_t ++tpm2_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, ++ const char *description) ++{ ++ static int error_displayed = 0; ++ int rc; ++ ++ rc = ibmvtpm_2hash_ext_log (pcr, EV_IPL, ++ description, grub_strlen(description) + 1, ++ buf, size); ++ if (rc && !error_displayed) ++ { ++ error_displayed++; ++ return grub_error (GRUB_ERR_BAD_DEVICE, ++ "2HASH-EXT-LOG failed: Firmware is likely too old.\n"); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++grub_err_t ++grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, ++ const char *description) ++{ ++ /* ++ * Call tpm_init() 'late' rather than from GRUB_MOD_INIT() so that device nodes ++ * can be found. ++ */ ++ grub_err_t err = tpm_init (); ++ ++ /* Absence of a TPM isn't a failure. */ ++ if (err != GRUB_ERR_NONE) ++ return GRUB_ERR_NONE; ++ ++ grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n", ++ pcr, size, description); ++ ++ if (tpm_version == 2) ++ return tpm2_log_event (buf, size, pcr, description); ++ ++ return GRUB_ERR_NONE; ++} +diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h +index 560c968460..27b9cf259b 100644 +--- a/include/grub/ieee1275/ieee1275.h ++++ b/include/grub/ieee1275/ieee1275.h +@@ -24,6 +24,9 @@ + #include + #include + ++#define GRUB_IEEE1275_CELL_FALSE ((grub_ieee1275_cell_t) 0) ++#define GRUB_IEEE1275_CELL_TRUE ((grub_ieee1275_cell_t) -1) ++ + struct grub_ieee1275_mem_region + { + unsigned int start; +diff --git a/docs/grub.texi b/docs/grub.texi +index 1750b72ee9..825278a7f3 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -6235,7 +6235,8 @@ tpm module is loaded. As such it is recommended that the tpm module be built + into @file{core.img} in order to avoid a potential gap in measurement between + @file{core.img} being loaded and the tpm module being loaded. + +-Measured boot is currently only supported on EFI platforms. ++Measured boot is currently only supported on EFI and IBM IEEE1275 PowerPC ++platforms. + + @node Lockdown + @section Lockdown when booting on a secure setup diff --git a/0317-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch b/0317-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch deleted file mode 100644 index 61fe876..0000000 --- a/0317-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch +++ /dev/null @@ -1,431 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Raymund Will -Date: Mon, 24 Oct 2022 14:33:50 -0400 -Subject: [PATCH] loader: Add support for grub-emu to kexec Linux menu entries - -The GRUB emulator is used as a debugging utility but it could also be -used as a user-space bootloader if there is support to boot an operating -system. - -The Linux kernel is already able to (re)boot another kernel via the -kexec boot mechanism. So the grub-emu tool could rely on this feature -and have linux and initrd commands that are used to pass a kernel, -initramfs image and command line parameters to kexec for booting -a selected menu entry. - -By default the systemctl kexec option is used so systemd can shutdown -all of the running services before doing a reboot using kexec. But if -this is not present, it can fall back to executing the kexec user-space -tool directly. The ability to force a kexec-reboot when systemctl kexec -fails must only be used in controlled environments to avoid possible -filesystem corruption and data loss. - -Signed-off-by: Raymund Will -Signed-off-by: John Jolly -Signed-off-by: Javier Martinez Canillas -Signed-off-by: Robbie Harwood -Reviewed-by: Daniel Kiper -(cherry picked from commit e364307f6acc2f631b4c1fefda0791b9ce1f205f) -[rharwood: conflicts around makefile and grub_exit return code] ---- - grub-core/Makefile.core.def | 3 - - grub-core/kern/emu/main.c | 4 + - grub-core/kern/emu/misc.c | 18 ++++- - grub-core/loader/emu/linux.c | 178 +++++++++++++++++++++++++++++++++++++++++++ - include/grub/emu/exec.h | 4 +- - include/grub/emu/hostfile.h | 3 +- - include/grub/emu/misc.h | 3 + - docs/grub.texi | 30 ++++++-- - grub-core/Makefile.am | 1 + - 9 files changed, 230 insertions(+), 14 deletions(-) - create mode 100644 grub-core/loader/emu/linux.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index e038c5e6fd..02ea718652 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -1871,11 +1871,8 @@ module = { - riscv32 = loader/riscv/linux.c; - riscv64 = loader/riscv/linux.c; - emu = loader/emu/linux.c; -- - common = loader/linux.c; - common = lib/cmdline.c; -- enable = noemu; -- - efi = loader/efi/linux.c; - }; - -diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c -index 12277c34d2..68e2b283bb 100644 ---- a/grub-core/kern/emu/main.c -+++ b/grub-core/kern/emu/main.c -@@ -107,6 +107,7 @@ static struct argp_option options[] = { - N_("use GRUB files in the directory DIR [default=%s]"), 0}, - {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, - {"hold", 'H', N_("SECS"), OPTION_ARG_OPTIONAL, N_("wait until a debugger will attach"), 0}, -+ {"kexec", 'X', 0, 0, N_("use kexec to boot Linux kernels via systemctl (pass twice to enable dangerous fallback to non-systemctl)."), 0}, - { 0, 0, 0, 0, 0, 0 } - }; - -@@ -164,6 +165,9 @@ argp_parser (int key, char *arg, struct argp_state *state) - case 'v': - verbosity++; - break; -+ case 'X': -+ grub_util_set_kexecute (); -+ break; - - case ARGP_KEY_ARG: - { -diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c -index d278c2921f..02d27c3440 100644 ---- a/grub-core/kern/emu/misc.c -+++ b/grub-core/kern/emu/misc.c -@@ -39,6 +39,7 @@ - #include - - int verbosity; -+int kexecute; - - void - grub_util_warn (const char *fmt, ...) -@@ -82,7 +83,7 @@ grub_util_error (const char *fmt, ...) - vfprintf (stderr, fmt, ap); - va_end (ap); - fprintf (stderr, ".\n"); -- exit (1); -+ grub_exit (1); - } - - void * -@@ -154,6 +155,9 @@ void - __attribute__ ((noreturn)) - grub_exit (int rc) - { -+#if defined (GRUB_KERNEL) -+ grub_reboot (); -+#endif - exit (rc < 0 ? 1 : rc); - } - #endif -@@ -215,3 +219,15 @@ grub_util_load_image (const char *path, char *buf) - - fclose (fp); - } -+ -+void -+grub_util_set_kexecute (void) -+{ -+ kexecute++; -+} -+ -+int -+grub_util_get_kexecute (void) -+{ -+ return kexecute; -+} -diff --git a/grub-core/loader/emu/linux.c b/grub-core/loader/emu/linux.c -new file mode 100644 -index 0000000000..0cf378a376 ---- /dev/null -+++ b/grub-core/loader/emu/linux.c -@@ -0,0 +1,178 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2022 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+static grub_dl_t my_mod; -+ -+static char *kernel_path; -+static char *initrd_path; -+static char *boot_cmdline; -+ -+static grub_err_t -+grub_linux_boot (void) -+{ -+ grub_err_t rc = GRUB_ERR_NONE; -+ char *initrd_param; -+ const char *kexec[] = {"kexec", "-la", kernel_path, boot_cmdline, NULL, NULL}; -+ const char *systemctl[] = {"systemctl", "kexec", NULL}; -+ int kexecute = grub_util_get_kexecute (); -+ -+ if (initrd_path) -+ { -+ initrd_param = grub_xasprintf ("--initrd=%s", initrd_path); -+ kexec[3] = initrd_param; -+ kexec[4] = boot_cmdline; -+ } -+ else -+ initrd_param = grub_xasprintf ("%s", ""); -+ -+ grub_dprintf ("linux", "%serforming 'kexec -la %s %s %s'\n", -+ (kexecute) ? "P" : "Not p", -+ kernel_path, initrd_param, boot_cmdline); -+ -+ if (kexecute) -+ rc = grub_util_exec (kexec); -+ -+ grub_free (initrd_param); -+ -+ if (rc != GRUB_ERR_NONE) -+ { -+ grub_error (rc, N_("error trying to perform kexec load operation")); -+ grub_sleep (3); -+ return rc; -+ } -+ -+ if (kexecute < 1) -+ grub_fatal (N_("use '"PACKAGE"-emu --kexec' to force a system restart")); -+ -+ grub_dprintf ("linux", "Performing 'systemctl kexec' (%s) ", -+ (kexecute==1) ? "do-or-die" : "just-in-case"); -+ rc = grub_util_exec (systemctl); -+ -+ if (kexecute == 1) -+ grub_fatal (N_("error trying to perform 'systemctl kexec': %d"), rc); -+ -+ /* -+ * WARNING: forcible reset should only be used in read-only environments. -+ * grub-emu cannot check for these - users beware. -+ */ -+ grub_dprintf ("linux", "Performing 'kexec -ex'"); -+ kexec[1] = "-ex"; -+ kexec[2] = NULL; -+ rc = grub_util_exec (kexec); -+ if (rc != GRUB_ERR_NONE) -+ grub_fatal (N_("error trying to directly perform 'kexec -ex': %d"), rc); -+ -+ return rc; -+} -+ -+static grub_err_t -+grub_linux_unload (void) -+{ -+ /* Unloading: we're no longer in use. */ -+ grub_dl_unref (my_mod); -+ grub_free (boot_cmdline); -+ boot_cmdline = NULL; -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, -+ char *argv[]) -+{ -+ int i; -+ char *tempstr; -+ -+ /* Mark ourselves as in-use. */ -+ grub_dl_ref (my_mod); -+ -+ if (argc == 0) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -+ -+ if (!grub_util_is_regular (argv[0])) -+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, -+ N_("cannot find kernel file %s"), argv[0]); -+ -+ grub_free (kernel_path); -+ kernel_path = grub_xasprintf ("%s", argv[0]); -+ -+ grub_free (boot_cmdline); -+ boot_cmdline = NULL; -+ -+ if (argc > 1) -+ { -+ boot_cmdline = grub_xasprintf ("--command-line=%s", argv[1]); -+ for (i = 2; i < argc; i++) -+ { -+ tempstr = grub_xasprintf ("%s %s", boot_cmdline, argv[i]); -+ grub_free (boot_cmdline); -+ boot_cmdline = tempstr; -+ } -+ } -+ -+ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, -+ char *argv[]) -+{ -+ if (argc == 0) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -+ -+ if (!grub_util_is_regular (argv[0])) -+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, -+ N_("Cannot find initrd file %s"), argv[0]); -+ -+ grub_free (initrd_path); -+ initrd_path = grub_xasprintf ("%s", argv[0]); -+ -+ /* We are done - mark ourselves as on longer in use. */ -+ grub_dl_unref (my_mod); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_command_t cmd_linux, cmd_initrd; -+ -+GRUB_MOD_INIT (linux) -+{ -+ cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0, -+ N_("Load Linux.")); -+ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0, -+ N_("Load initrd.")); -+ my_mod = mod; -+} -+ -+GRUB_MOD_FINI (linux) -+{ -+ grub_unregister_command (cmd_linux); -+ grub_unregister_command (cmd_initrd); -+} -diff --git a/include/grub/emu/exec.h b/include/grub/emu/exec.h -index d1073ef86a..1b61b4a2e5 100644 ---- a/include/grub/emu/exec.h -+++ b/include/grub/emu/exec.h -@@ -23,6 +23,8 @@ - #include - - #include -+#include -+ - pid_t - grub_util_exec_pipe (const char *const *argv, int *fd); - pid_t -@@ -32,7 +34,7 @@ int - grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file, - const char *stdout_file, const char *stderr_file); - int --grub_util_exec (const char *const *argv); -+EXPORT_FUNC(grub_util_exec) (const char *const *argv); - int - grub_util_exec_redirect (const char *const *argv, const char *stdin_file, - const char *stdout_file); -diff --git a/include/grub/emu/hostfile.h b/include/grub/emu/hostfile.h -index cfb1e2b566..a61568e36e 100644 ---- a/include/grub/emu/hostfile.h -+++ b/include/grub/emu/hostfile.h -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - - int -@@ -29,7 +30,7 @@ grub_util_is_directory (const char *path); - int - grub_util_is_special_file (const char *path); - int --grub_util_is_regular (const char *path); -+EXPORT_FUNC(grub_util_is_regular) (const char *path); - - char * - grub_util_path_concat (size_t n, ...); -diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h -index ff9c48a649..01056954b9 100644 ---- a/include/grub/emu/misc.h -+++ b/include/grub/emu/misc.h -@@ -57,6 +57,9 @@ void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...) __attribute__ ((format ( - void EXPORT_FUNC(grub_util_info) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2))); - void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2), noreturn)); - -+void EXPORT_FUNC(grub_util_set_kexecute) (void); -+int EXPORT_FUNC(grub_util_get_kexecute) (void) WARN_UNUSED_RESULT; -+ - grub_uint64_t EXPORT_FUNC (grub_util_get_cpu_time_ms) (void); - - #ifdef HAVE_DEVICE_MAPPER -diff --git a/docs/grub.texi b/docs/grub.texi -index c433240f34..825278a7f3 100644 ---- a/docs/grub.texi -+++ b/docs/grub.texi -@@ -923,17 +923,17 @@ magic. - @node General boot methods - @section How to boot operating systems - --GRUB has two distinct boot methods. One of the two is to load an --operating system directly, and the other is to chain-load another boot --loader which then will load an operating system actually. Generally --speaking, the former is more desirable, because you don't need to --install or maintain other boot loaders and GRUB is flexible enough to --load an operating system from an arbitrary disk/partition. However, --the latter is sometimes required, since GRUB doesn't support all the --existing operating systems natively. -+GRUB has three distinct boot methods: loading an operating system -+directly, using kexec from userspace, and chainloading another -+bootloader. Generally speaking, the first two are more desirable -+because you don't need to install or maintain other boot loaders and -+GRUB is flexible enough to load an operating system from an arbitrary -+disk/partition. However, chainloading is sometimes required, as GRUB -+doesn't support all existing operating systems natively. - - @menu - * Loading an operating system directly:: -+* Kexec:: - * Chain-loading:: - @end menu - -@@ -959,6 +959,20 @@ use more complicated instructions. @xref{DOS/Windows}, for more - information. - - -+@node Kexec -+@subsection Kexec with grub2-emu -+ -+GRUB can be run in userspace by invoking the grub2-emu tool. It will -+read all configuration scripts as if booting directly (see @xref{Loading -+an operating system directly}). With the @code{--kexec} flag, and -+kexec(8) support from the operating system, the @command{linux} command -+will directly boot the target image. For systems that lack working -+systemctl(1) support for kexec, passing the @code{--kexec} flag twice -+will fallback to invoking kexec(8) directly; note however that this -+fallback may be unsafe outside read-only environments, as it does not -+invoke shutdown machinery. -+ -+ - @node Chain-loading - @subsection Chain-loading an OS - -diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am -index c2e8a82bce..dd49939aaa 100644 ---- a/grub-core/Makefile.am -+++ b/grub-core/Makefile.am -@@ -309,6 +309,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/net.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostdisk.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostfile.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h -+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/exec.h - if COND_GRUB_EMU_SDL - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h - endif diff --git a/0318-powerpc-Drop-Open-Hack-Ware.patch b/0318-powerpc-Drop-Open-Hack-Ware.patch new file mode 100644 index 0000000..1d201d3 --- /dev/null +++ b/0318-powerpc-Drop-Open-Hack-Ware.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 6 Sep 2021 15:46:11 +1000 +Subject: [PATCH] powerpc: Drop Open Hack'Ware + +Open Hack'Ware was an alternative firmware of powerpc under QEMU. + +The last commit to any Open Hack'Ware repo I can find is from 2014 [1]. + +Open Hack'Ware was used for the QEMU "prep" machine type, which was +deprecated in QEMU in commit 54c86f5a4844 (hw/ppc: deprecate the +machine type 'prep', replaced by '40p') in QEMU v3.1, and had reportedly +been broken for years before without anyone noticing. Support was removed +in February 2020 by commit b2ce76a0730e (hw/ppc/prep: Remove the +deprecated "prep" machine and the OpenHackware BIOS). + +Open Hack'Ware's limitations require some messy code in GRUB. This +complexity is not worth carrying any more. + +Remove detection of Open Hack'Ware. We will clean up the feature flags +in following commits. + +[1]: https://github.com/qemu/openhackware and + https://repo.or.cz/w/openhackware.git are QEMU submodules. They have + only small changes on top of OHW v0.4.1, which was imported into + QEMU SCM in 2010. I can't find anything resembling an official repo + any more. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit f9ce538eec88c5cffbfde021c4e8a95a5e9d0e8f) +--- + grub-core/kern/ieee1275/cmain.c | 16 ---------------- + 1 file changed, 16 deletions(-) + +diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c +index dce7b84922..cb42f60ebe 100644 +--- a/grub-core/kern/ieee1275/cmain.c ++++ b/grub-core/kern/ieee1275/cmain.c +@@ -49,7 +49,6 @@ grub_ieee1275_find_options (void) + grub_ieee1275_phandle_t root; + grub_ieee1275_phandle_t options; + grub_ieee1275_phandle_t openprom; +- grub_ieee1275_phandle_t bootrom; + int rc; + grub_uint32_t realmode = 0; + char tmp[256]; +@@ -198,21 +197,6 @@ grub_ieee1275_find_options (void) + + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); + } +- +- if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom) +- || ! grub_ieee1275_finddevice ("/boot-rom", &bootrom)) +- { +- rc = grub_ieee1275_get_property (bootrom, "model", tmp, sizeof (tmp), 0); +- if (rc >= 0 && !grub_strncmp (tmp, "PPC Open Hack'Ware", +- sizeof ("PPC Open Hack'Ware") - 1)) +- { +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT); +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS); +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET); +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM); +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_ANSI); +- } +- } + } + + void diff --git a/grub.patches b/grub.patches index ae57994..45eb553 100644 --- a/grub.patches +++ b/grub.patches @@ -172,146 +172,147 @@ Patch0171: 0171-appended-signatures-verification-tests.patch Patch0172: 0172-appended-signatures-documentation.patch Patch0173: 0173-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch Patch0174: 0174-ieee1275-drop-HEAP_MAX_ADDR-HEAP_MIN_SIZE.patch -Patch0175: 0175-ieee1275-claim-more-memory.patch -Patch0176: 0176-ieee1275-request-memory-with-ibm-client-architecture.patch -Patch0177: 0177-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch -Patch0178: 0178-ieee1275-ofdisk-retry-on-open-failure.patch -Patch0179: 0179-Allow-chainloading-EFI-apps-from-loop-mounts.patch -Patch0180: 0180-efinet-Add-DHCP-proxy-support.patch -Patch0181: 0181-fs-ext2-Ignore-checksum-seed-incompat-feature.patch -Patch0182: 0182-Don-t-update-the-cmdline-when-generating-legacy-menu.patch -Patch0183: 0183-Suppress-gettext-error-message.patch -Patch0184: 0184-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch -Patch0185: 0185-templates-Check-for-EFI-at-runtime-instead-of-config.patch -Patch0186: 0186-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch -Patch0187: 0187-arm64-Fix-EFI-loader-kernel-image-allocation.patch -Patch0188: 0188-normal-main-Discover-the-device-to-read-the-config-f.patch -Patch0189: 0189-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch -Patch0190: 0190-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch -Patch0191: 0191-Print-module-name-on-license-check-failure.patch -Patch0192: 0192-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch -Patch0193: 0193-grub-mkconfig-restore-umask-for-grub.cfg.patch -Patch0194: 0194-fs-btrfs-Use-full-btrfs-bootloader-area.patch -Patch0195: 0195-Add-Fedora-location-of-DejaVu-SANS-font.patch -Patch0196: 0196-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch -Patch0197: 0197-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch -Patch0198: 0198-EFI-console-Do-not-set-colorstate-until-the-first-te.patch -Patch0199: 0199-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch -Patch0200: 0200-Use-visual-indentation-in-config.h.in.patch -Patch0201: 0201-Where-present-ensure-config-util.h-precedes-config.h.patch -Patch0202: 0202-Drop-gnulib-fix-base64.patch.patch -Patch0203: 0203-Drop-gnulib-no-abort.patch.patch -Patch0204: 0204-Update-gnulib-version-and-drop-most-gnulib-patches.patch -Patch0205: 0205-commands-search-Fix-bug-stopping-iteration-when-no-f.patch -Patch0206: 0206-search-new-efidisk-only-option-on-EFI-systems.patch -Patch0207: 0207-efi-new-connectefi-command.patch -Patch0208: 0208-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch -Patch0209: 0209-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch -Patch0210: 0210-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch -Patch0211: 0211-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch -Patch0212: 0212-powerpc-do-CAS-in-a-more-compatible-way.patch -Patch0213: 0213-powerpc-prefix-detection-support-device-names-with-c.patch -Patch0214: 0214-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch -Patch0215: 0215-make-ofdisk_retries-optional.patch -Patch0216: 0216-loader-efi-chainloader-grub_load_and_start_image-doe.patch -Patch0217: 0217-loader-efi-chainloader-simplify-the-loader-state.patch -Patch0218: 0218-commands-boot-Add-API-to-pass-context-to-loader.patch -Patch0219: 0219-loader-efi-chainloader-Use-grub_loader_set_ex.patch -Patch0220: 0220-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch -Patch0221: 0221-loader-i386-efi-linux-Use-grub_loader_set_ex.patch -Patch0222: 0222-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch -Patch0223: 0223-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch -Patch0224: 0224-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch -Patch0225: 0225-video-readers-png-Abort-sooner-if-a-read-operation-f.patch -Patch0226: 0226-video-readers-png-Refuse-to-handle-multiple-image-he.patch -Patch0227: 0227-video-readers-png-Drop-greyscale-support-to-fix-heap.patch -Patch0228: 0228-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch -Patch0229: 0229-video-readers-png-Sanity-check-some-huffman-codes.patch -Patch0230: 0230-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch -Patch0231: 0231-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch -Patch0232: 0232-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch -Patch0233: 0233-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch -Patch0234: 0234-normal-charset-Fix-array-out-of-bounds-formatting-un.patch -Patch0235: 0235-net-netbuff-Block-overly-large-netbuff-allocs.patch -Patch0236: 0236-net-ip-Do-IP-fragment-maths-safely.patch -Patch0237: 0237-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch -Patch0238: 0238-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch -Patch0239: 0239-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch -Patch0240: 0240-net-tftp-Avoid-a-trivial-UAF.patch -Patch0241: 0241-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch -Patch0242: 0242-net-http-Fix-OOB-write-for-split-http-headers.patch -Patch0243: 0243-net-http-Error-out-on-headers-with-LF-without-CR.patch -Patch0244: 0244-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch -Patch0245: 0245-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch -Patch0246: 0246-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch -Patch0247: 0247-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch -Patch0248: 0248-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch -Patch0249: 0249-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch -Patch0250: 0250-misc-Make-grub_min-and-grub_max-more-resilient.patch -Patch0251: 0251-ReiserFS-switch-to-using-grub_min-grub_max.patch -Patch0252: 0252-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch -Patch0253: 0253-modules-make-.module_license-read-only.patch -Patch0254: 0254-modules-strip-.llvm_addrsig-sections-and-similar.patch -Patch0255: 0255-modules-Don-t-allocate-space-for-non-allocable-secti.patch -Patch0256: 0256-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch -Patch0257: 0257-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch -Patch0258: 0258-modules-load-module-sections-at-page-aligned-address.patch -Patch0259: 0259-nx-add-memory-attribute-get-set-API.patch -Patch0260: 0260-nx-set-page-permissions-for-loaded-modules.patch -Patch0261: 0261-nx-set-attrs-in-our-kernel-loaders.patch -Patch0262: 0262-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch -Patch0263: 0263-grub-probe-document-the-behavior-of-multiple-v.patch -Patch0264: 0264-grub_fs_probe-dprint-errors-from-filesystems.patch -Patch0265: 0265-fs-fat-don-t-error-when-mtime-is-0.patch -Patch0266: 0266-Make-debug-file-show-which-file-filters-get-run.patch -Patch0267: 0267-efi-use-enumerated-array-positions-for-our-allocatio.patch -Patch0268: 0268-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch -Patch0269: 0269-efi-allocate-the-initrd-within-the-bounds-expressed-.patch -Patch0270: 0270-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch -Patch0271: 0271-BLS-create-etc-kernel-cmdline-during-mkconfig.patch -Patch0272: 0272-squish-don-t-dup-rhgb-quiet-check-mtimes.patch -Patch0273: 0273-squish-give-up-on-rhgb-quiet.patch -Patch0274: 0274-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch -Patch0275: 0275-ieee1275-implement-vec5-for-cas-negotiation.patch -Patch0276: 0276-blscfg-Don-t-root-device-in-emu-builds.patch -Patch0277: 0277-loader-arm64-linux-Remove-magic-number-header-field-.patch -Patch0278: 0278-Correct-BSS-zeroing-on-aarch64.patch -Patch0279: 0279-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch -Patch0280: 0280-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch -Patch0281: 0281-commands-efi-tpm-Refine-the-status-of-log-event.patch -Patch0282: 0282-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch -Patch0283: 0283-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch -Patch0284: 0284-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch -Patch0285: 0285-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch -Patch0286: 0286-font-Fix-several-integer-overflows-in-grub_font_cons.patch -Patch0287: 0287-font-Remove-grub_font_dup_glyph.patch -Patch0288: 0288-font-Fix-integer-overflow-in-ensure_comb_space.patch -Patch0289: 0289-font-Fix-integer-overflow-in-BMP-index.patch -Patch0290: 0290-font-Fix-integer-underflow-in-binary-search-of-char-.patch -Patch0291: 0291-kern-efi-sb-Enforce-verification-of-font-files.patch -Patch0292: 0292-fbutil-Fix-integer-overflow.patch -Patch0293: 0293-font-Fix-an-integer-underflow-in-blit_comb.patch -Patch0294: 0294-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch -Patch0295: 0295-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch -Patch0296: 0296-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch -Patch0297: 0297-font-Try-opening-fonts-from-the-bundled-memdisk.patch -Patch0298: 0298-Correction-in-vector-5-values.patch -Patch0299: 0299-mm-Clarify-grub_real_malloc.patch -Patch0300: 0300-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch -Patch0301: 0301-mm-Document-grub_free.patch -Patch0302: 0302-mm-Document-grub_mm_init_region.patch -Patch0303: 0303-mm-Document-GRUB-internal-memory-management-structur.patch -Patch0304: 0304-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch -Patch0305: 0305-mm-When-adding-a-region-merge-with-region-after-as-w.patch -Patch0306: 0306-mm-Debug-support-for-region-operations.patch -Patch0307: 0307-mm-Drop-unused-unloading-of-modules-on-OOM.patch -Patch0308: 0308-mm-Allow-dynamically-requesting-additional-memory-re.patch -Patch0309: 0309-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch -Patch0310: 0310-kern-efi-mm-Extract-function-to-add-memory-regions.patch -Patch0311: 0311-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch -Patch0312: 0312-kern-efi-mm-Implement-runtime-addition-of-pages.patch -Patch0313: 0313-efi-Increase-default-memory-allocation-to-32-MiB.patch -Patch0314: 0314-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch -Patch0315: 0315-ppc64le-signed-boot-media-changes.patch -Patch0316: 0316-core-Fix-several-implicit-function-declarations.patch -Patch0317: 0317-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch +Patch0175: 0175-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch +Patch0176: 0176-ieee1275-ofdisk-retry-on-open-failure.patch +Patch0177: 0177-Allow-chainloading-EFI-apps-from-loop-mounts.patch +Patch0178: 0178-efinet-Add-DHCP-proxy-support.patch +Patch0179: 0179-fs-ext2-Ignore-checksum-seed-incompat-feature.patch +Patch0180: 0180-Don-t-update-the-cmdline-when-generating-legacy-menu.patch +Patch0181: 0181-Suppress-gettext-error-message.patch +Patch0182: 0182-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch +Patch0183: 0183-templates-Check-for-EFI-at-runtime-instead-of-config.patch +Patch0184: 0184-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch +Patch0185: 0185-arm64-Fix-EFI-loader-kernel-image-allocation.patch +Patch0186: 0186-normal-main-Discover-the-device-to-read-the-config-f.patch +Patch0187: 0187-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch +Patch0188: 0188-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch +Patch0189: 0189-Print-module-name-on-license-check-failure.patch +Patch0190: 0190-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch +Patch0191: 0191-grub-mkconfig-restore-umask-for-grub.cfg.patch +Patch0192: 0192-fs-btrfs-Use-full-btrfs-bootloader-area.patch +Patch0193: 0193-Add-Fedora-location-of-DejaVu-SANS-font.patch +Patch0194: 0194-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch +Patch0195: 0195-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch +Patch0196: 0196-EFI-console-Do-not-set-colorstate-until-the-first-te.patch +Patch0197: 0197-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch +Patch0198: 0198-Use-visual-indentation-in-config.h.in.patch +Patch0199: 0199-Where-present-ensure-config-util.h-precedes-config.h.patch +Patch0200: 0200-Drop-gnulib-fix-base64.patch.patch +Patch0201: 0201-Drop-gnulib-no-abort.patch.patch +Patch0202: 0202-Update-gnulib-version-and-drop-most-gnulib-patches.patch +Patch0203: 0203-commands-search-Fix-bug-stopping-iteration-when-no-f.patch +Patch0204: 0204-search-new-efidisk-only-option-on-EFI-systems.patch +Patch0205: 0205-efi-new-connectefi-command.patch +Patch0206: 0206-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch +Patch0207: 0207-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch +Patch0208: 0208-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch +Patch0209: 0209-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch +Patch0210: 0210-powerpc-prefix-detection-support-device-names-with-c.patch +Patch0211: 0211-make-ofdisk_retries-optional.patch +Patch0212: 0212-loader-efi-chainloader-grub_load_and_start_image-doe.patch +Patch0213: 0213-loader-efi-chainloader-simplify-the-loader-state.patch +Patch0214: 0214-commands-boot-Add-API-to-pass-context-to-loader.patch +Patch0215: 0215-loader-efi-chainloader-Use-grub_loader_set_ex.patch +Patch0216: 0216-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch +Patch0217: 0217-loader-i386-efi-linux-Use-grub_loader_set_ex.patch +Patch0218: 0218-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch +Patch0219: 0219-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch +Patch0220: 0220-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch +Patch0221: 0221-video-readers-png-Abort-sooner-if-a-read-operation-f.patch +Patch0222: 0222-video-readers-png-Refuse-to-handle-multiple-image-he.patch +Patch0223: 0223-video-readers-png-Drop-greyscale-support-to-fix-heap.patch +Patch0224: 0224-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch +Patch0225: 0225-video-readers-png-Sanity-check-some-huffman-codes.patch +Patch0226: 0226-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch +Patch0227: 0227-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch +Patch0228: 0228-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch +Patch0229: 0229-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch +Patch0230: 0230-normal-charset-Fix-array-out-of-bounds-formatting-un.patch +Patch0231: 0231-net-netbuff-Block-overly-large-netbuff-allocs.patch +Patch0232: 0232-net-ip-Do-IP-fragment-maths-safely.patch +Patch0233: 0233-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch +Patch0234: 0234-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch +Patch0235: 0235-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch +Patch0236: 0236-net-tftp-Avoid-a-trivial-UAF.patch +Patch0237: 0237-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch +Patch0238: 0238-net-http-Fix-OOB-write-for-split-http-headers.patch +Patch0239: 0239-net-http-Error-out-on-headers-with-LF-without-CR.patch +Patch0240: 0240-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch +Patch0241: 0241-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch +Patch0242: 0242-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch +Patch0243: 0243-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch +Patch0244: 0244-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch +Patch0245: 0245-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch +Patch0246: 0246-misc-Make-grub_min-and-grub_max-more-resilient.patch +Patch0247: 0247-ReiserFS-switch-to-using-grub_min-grub_max.patch +Patch0248: 0248-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch +Patch0249: 0249-modules-make-.module_license-read-only.patch +Patch0250: 0250-modules-strip-.llvm_addrsig-sections-and-similar.patch +Patch0251: 0251-modules-Don-t-allocate-space-for-non-allocable-secti.patch +Patch0252: 0252-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch +Patch0253: 0253-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch +Patch0254: 0254-modules-load-module-sections-at-page-aligned-address.patch +Patch0255: 0255-nx-add-memory-attribute-get-set-API.patch +Patch0256: 0256-nx-set-page-permissions-for-loaded-modules.patch +Patch0257: 0257-nx-set-attrs-in-our-kernel-loaders.patch +Patch0258: 0258-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch +Patch0259: 0259-grub-probe-document-the-behavior-of-multiple-v.patch +Patch0260: 0260-grub_fs_probe-dprint-errors-from-filesystems.patch +Patch0261: 0261-fs-fat-don-t-error-when-mtime-is-0.patch +Patch0262: 0262-Make-debug-file-show-which-file-filters-get-run.patch +Patch0263: 0263-efi-use-enumerated-array-positions-for-our-allocatio.patch +Patch0264: 0264-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch +Patch0265: 0265-efi-allocate-the-initrd-within-the-bounds-expressed-.patch +Patch0266: 0266-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch +Patch0267: 0267-BLS-create-etc-kernel-cmdline-during-mkconfig.patch +Patch0268: 0268-squish-don-t-dup-rhgb-quiet-check-mtimes.patch +Patch0269: 0269-squish-give-up-on-rhgb-quiet.patch +Patch0270: 0270-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch +Patch0271: 0271-blscfg-Don-t-root-device-in-emu-builds.patch +Patch0272: 0272-loader-arm64-linux-Remove-magic-number-header-field-.patch +Patch0273: 0273-Correct-BSS-zeroing-on-aarch64.patch +Patch0274: 0274-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch +Patch0275: 0275-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch +Patch0276: 0276-commands-efi-tpm-Refine-the-status-of-log-event.patch +Patch0277: 0277-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch +Patch0278: 0278-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch +Patch0279: 0279-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch +Patch0280: 0280-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch +Patch0281: 0281-font-Fix-several-integer-overflows-in-grub_font_cons.patch +Patch0282: 0282-font-Remove-grub_font_dup_glyph.patch +Patch0283: 0283-font-Fix-integer-overflow-in-ensure_comb_space.patch +Patch0284: 0284-font-Fix-integer-overflow-in-BMP-index.patch +Patch0285: 0285-font-Fix-integer-underflow-in-binary-search-of-char-.patch +Patch0286: 0286-kern-efi-sb-Enforce-verification-of-font-files.patch +Patch0287: 0287-fbutil-Fix-integer-overflow.patch +Patch0288: 0288-font-Fix-an-integer-underflow-in-blit_comb.patch +Patch0289: 0289-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch +Patch0290: 0290-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch +Patch0291: 0291-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch +Patch0292: 0292-font-Try-opening-fonts-from-the-bundled-memdisk.patch +Patch0293: 0293-mm-Clarify-grub_real_malloc.patch +Patch0294: 0294-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch +Patch0295: 0295-mm-Document-grub_free.patch +Patch0296: 0296-mm-Document-grub_mm_init_region.patch +Patch0297: 0297-mm-Document-GRUB-internal-memory-management-structur.patch +Patch0298: 0298-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch +Patch0299: 0299-mm-When-adding-a-region-merge-with-region-after-as-w.patch +Patch0300: 0300-mm-Debug-support-for-region-operations.patch +Patch0301: 0301-mm-Drop-unused-unloading-of-modules-on-OOM.patch +Patch0302: 0302-mm-Allow-dynamically-requesting-additional-memory-re.patch +Patch0303: 0303-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch +Patch0304: 0304-kern-efi-mm-Extract-function-to-add-memory-regions.patch +Patch0305: 0305-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch +Patch0306: 0306-kern-efi-mm-Implement-runtime-addition-of-pages.patch +Patch0307: 0307-efi-Increase-default-memory-allocation-to-32-MiB.patch +Patch0308: 0308-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch +Patch0309: 0309-ppc64le-signed-boot-media-changes.patch +Patch0310: 0310-core-Fix-several-implicit-function-declarations.patch +Patch0311: 0311-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch +Patch0312: 0312-powerpc-Drop-Open-Hack-Ware-remove-GRUB_IEEE1275_FLA.patch +Patch0313: 0313-ieee1275-request-memory-with-ibm-client-architecture.patch +Patch0314: 0314-ieee1275-drop-len-1-quirk-in-heap_init.patch +Patch0315: 0315-ieee1275-support-runtime-memory-claiming.patch +Patch0316: 0316-ieee1275-implement-vec5-for-cas-negotiation.patch +Patch0317: 0317-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch +Patch0318: 0318-powerpc-Drop-Open-Hack-Ware.patch diff --git a/grub2.spec b/grub2.spec index d4fa238..1367fe6 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 84%{?dist} +Release: 85%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -544,6 +544,9 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Wed Feb 08 2023 Robbie Harwood - 2.06-85 +- ppc64le: sync cas/tpm patchset with upstream + * Mon Feb 06 2023 Robbie Harwood - 2.06-84 - emu: support newer kexec syscall