From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1ncT35-0001Ra-GQ for mharc-grub-devel@gnu.org; Thu, 07 Apr 2022 10:23:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38752) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ncIto-0005cw-8g for grub-devel@gnu.org; Wed, 06 Apr 2022 23:33:32 -0400 Received: from mail.ispras.ru ([83.149.199.84]:38862) by eggs.gnu.org with esmtps (TLS1.2:DHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ncItk-0007RB-Nx for grub-devel@gnu.org; Wed, 06 Apr 2022 23:33:31 -0400 Received: from localhost.localdomain (unknown [80.240.223.29]) by mail.ispras.ru (Postfix) with ESMTPSA id 6EF584076B39; Thu, 7 Apr 2022 03:33:00 +0000 (UTC) From: Baskov Evgeniy To: grub-devel@gnu.org Cc: Baskov Evgeniy Subject: [PATCH RFC 3/3] efi: explicitly set memory attributes for memory Date: Thu, 7 Apr 2022 06:32:28 +0300 Message-Id: <20220407033228.30242-4-baskov@ispras.ru> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220407033228.30242-1-baskov@ispras.ru> References: <20220407033228.30242-1-baskov@ispras.ru> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Received-SPF: pass client-ip=83.149.199.84; envelope-from=baskov@ispras.ru; helo=mail.ispras.ru X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 07 Apr 2022 10:23:45 -0400 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Apr 2022 03:33:32 -0000 UEFI specification does not guarantee that memory used for trampoline by GRUB would be executable. Some stricter implementations set NX flag for most regions. Explicitly mark memory range where trampoline would be allocated as writable and executable using DXE services on x86-efi variations. Avoid modification if not necessary and only modify system memory to reduce the possibility to encounter firmware bugs. Signed-off-by: Baskov Evgeniy diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c index d8e411454..f6d1170d1 100644 --- a/grub-core/kern/efi/mm.c +++ b/grub-core/kern/efi/mm.c @@ -230,6 +230,71 @@ stop_broadcom (void) #endif +static void +unprotect_memory_range (grub_efi_physical_address_t start, + grub_efi_physical_address_t end) +{ + static grub_efi_guid_t dxe_guid = GRUB_EFI_DXE_SERVICES_TABLE_GUID; + grub_efi_physical_address_t rounded_start, rounded_end, next; + grub_efi_physical_address_t unprotect_start, unprotect_end; + grub_efi_dxe_services_t *dxe; + grub_efi_gcd_memory_space_descriptor_t desc; + grub_efi_status_t status; + + dxe = grub_efi_get_config_table (&dxe_guid); + if (dxe == NULL || dxe->hdr.signature != GRUB_EFI_DXE_SERVICES_SIGNATURE) + return; + + rounded_start = start & ~GRUB_EFI_PAGE_SIZE; + rounded_end = (end + GRUB_EFI_PAGE_SIZE - 1) & ~GRUB_EFI_PAGE_SIZE; + + /* + * Don't modify memory region attributes, they are + * already suitable, to lower the possibility to + * encounter firmware bugs. + */ + + for (; start < end; start = next) + { + status = efi_call_2 (dxe->get_memory_space_descriptor, start, &desc); + + if (status != GRUB_EFI_SUCCESS) + return; + + next = desc.base_address + desc.length; + + /* + * Only system memory is suitable for trampoline/kernel image placement, + * so only this type of memory needs its attributes to be modified. + */ + + if (desc.gcd_memory_type != GRUB_EFI_GCD_MEMORY_TYPE_SYSTEM_MEMORY || + (desc.attributes & (GRUB_EFI_MEMORY_RO | GRUB_EFI_MEMORY_XP)) == 0) + continue; + + unprotect_start = rounded_start; + if (unprotect_start < desc.base_address) + unprotect_start = desc.base_address; + + unprotect_end = rounded_end; + if (unprotect_end > next) + unprotect_end = next; + + status = efi_call_3 (dxe->set_memory_space_attributes, + unprotect_start, + unprotect_end - unprotect_start, + GRUB_EFI_MEMORY_WB); + + if (status != GRUB_EFI_SUCCESS) + { + grub_printf ("Cannot change memory attributes in range [0x%lX, 0x%lX): 0x%lX\n", + (long)unprotect_start, + (long)unprotect_end, + (long)status); + } + } +} + grub_err_t grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, grub_efi_uintn_t *map_key, @@ -239,6 +304,8 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, grub_efi_boot_services_t *b; grub_efi_status_t status; + unprotect_memory_range(0x1000, 0xa0000); + #if defined (__i386__) || defined (__x86_64__) const grub_uint16_t apple[] = { 'A', 'p', 'p', 'l', 'e' }; int is_apple; -- 2.35.1