svn commit: r331241 - head/sys/dev/efidev
Andrew Turner
andrew at FreeBSD.org
Tue Mar 20 13:35:21 UTC 2018
Author: andrew
Date: Tue Mar 20 13:35:20 2018
New Revision: 331241
URL: https://svnweb.freebsd.org/changeset/base/331241
Log:
Check if the gettime runtime service is valid.
The U-Boot efi runtime service expects us to set the address map before
calling any runtime services. It will then remap a few functions to their
runtime version. One of these is the gettime function. If we call into
this without having set a runtime map we get a page fault.
Add a check to see if this is valid in efi_init() so we don't try to use
the possibly invalid pointer.
Reviewed by: imp, kevans (both previous version)
X-MFC-With: r330868
Sponsored by: DARPA, AFRL
Differential Revision: https://reviews.freebsd.org/D14759
Modified:
head/sys/dev/efidev/efirt.c
Modified: head/sys/dev/efidev/efirt.c
==============================================================================
--- head/sys/dev/efidev/efirt.c Tue Mar 20 13:14:10 2018 (r331240)
+++ head/sys/dev/efidev/efirt.c Tue Mar 20 13:35:20 2018 (r331241)
@@ -99,6 +99,25 @@ efi_status_to_errno(efi_status status)
static struct mtx efi_lock;
+static bool
+efi_is_in_map(struct efi_md *map, int ndesc, int descsz, vm_offset_t addr)
+{
+ struct efi_md *p;
+ int i;
+
+ for (i = 0, p = map; i < ndesc; i++, p = efi_next_descriptor(p,
+ descsz)) {
+ if ((p->md_attr & EFI_MD_ATTR_RT) == 0)
+ continue;
+
+ if (addr >= (uintptr_t)p->md_virt &&
+ addr < (uintptr_t)p->md_virt + p->md_pages * PAGE_SIZE)
+ return (true);
+ }
+
+ return (false);
+}
+
static int
efi_init(void)
{
@@ -160,6 +179,24 @@ efi_init(void)
if (efi_runtime == NULL) {
if (bootverbose)
printf("EFI runtime services table is not present\n");
+ efi_destroy_1t1_map();
+ return (ENXIO);
+ }
+
+ /*
+ * Some UEFI implementations have multiple implementations of the
+ * RS->GetTime function. They switch from one we can only use early
+ * in the boot process to one valid as a RunTime service only when we
+ * call RS->SetVirtualAddressMap. As this is not always the case, e.g.
+ * with an old loader.efi, check if the RS->GetTime function is within
+ * the EFI map, and fail to attach if not.
+ */
+ if (!efi_is_in_map(map, efihdr->memory_size / efihdr->descriptor_size,
+ efihdr->descriptor_size, (vm_offset_t)efi_runtime->rt_gettime)) {
+ if (bootverbose)
+ printf(
+ "EFI runtime services table has an invalid pointer\n");
+ efi_runtime = NULL;
efi_destroy_1t1_map();
return (ENXIO);
}
More information about the svn-src-all
mailing list