From owner-svn-src-head@freebsd.org Tue Mar 20 13:35:20 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id C75DAF4E1A3; Tue, 20 Mar 2018 13:35:20 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 77C4973055; Tue, 20 Mar 2018 13:35:20 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 729511D823; Tue, 20 Mar 2018 13:35:20 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w2KDZKii029316; Tue, 20 Mar 2018 13:35:20 GMT (envelope-from andrew@FreeBSD.org) Received: (from andrew@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w2KDZKs1029315; Tue, 20 Mar 2018 13:35:20 GMT (envelope-from andrew@FreeBSD.org) Message-Id: <201803201335.w2KDZKs1029315@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: andrew set sender to andrew@FreeBSD.org using -f From: Andrew Turner Date: Tue, 20 Mar 2018 13:35:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r331241 - head/sys/dev/efidev X-SVN-Group: head X-SVN-Commit-Author: andrew X-SVN-Commit-Paths: head/sys/dev/efidev X-SVN-Commit-Revision: 331241 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Mar 2018 13:35:21 -0000 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); }