From owner-svn-src-all@FreeBSD.ORG Thu Apr 9 19:03:12 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id CB904EB1; Thu, 9 Apr 2015 19:03:12 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id B5C9784D; Thu, 9 Apr 2015 19:03:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t39J3CuY070746; Thu, 9 Apr 2015 19:03:12 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t39J3CcS070744; Thu, 9 Apr 2015 19:03:12 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201504091903.t39J3CcS070744@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Thu, 9 Apr 2015 19:03:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r281319 - stable/10/sys/boot/amd64/efi X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Apr 2015 19:03:13 -0000 Author: jhb Date: Thu Apr 9 19:03:11 2015 New Revision: 281319 URL: https://svnweb.freebsd.org/changeset/base/281319 Log: MFC 279929: Allow the EFI loader to work with large kernels and/or modules (for example, a large mfsroot). Note that for EFI the kernel and modules (as well as other metadata files such as splash screens or memory disk images) are loaded into a statically-sized staging area. When the EFI loader exits it copies this staging area down to the location the kernel expects to run at. - Add bounds checking to the copy routines to fail attempts to access memory outside of the staging area. Previously loading a combined kernel + modules larger than the staging size (32MB) would overflow the staging area trashing whatever memory was afterwards. Under Intel's OVMF firmware for qemu this resulted in fatal faults in the firmware itself. Now the attempt will fail with ENOMEM. - Allow the staging area size to be configured at compile time via an EFI_STAGING_SIZE variable in src.conf or on the command line. It accepts the size of the staging area in MB. The default size remains 32MB. Modified: stable/10/sys/boot/amd64/efi/Makefile stable/10/sys/boot/amd64/efi/copy.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/boot/amd64/efi/Makefile ============================================================================== --- stable/10/sys/boot/amd64/efi/Makefile Thu Apr 9 18:50:41 2015 (r281318) +++ stable/10/sys/boot/amd64/efi/Makefile Thu Apr 9 19:03:11 2015 (r281319) @@ -44,6 +44,10 @@ LIBFICL= ${.OBJDIR}/../../ficl/libficl.a # Include bcache code. HAVE_BCACHE= yes +.if defined(EFI_STAGING_SIZE) +CFLAGS+= -DEFI_STAGING_SIZE=${EFI_STAGING_SIZE} +.endif + # Always add MI sources .PATH: ${.CURDIR}/../../common .include "${.CURDIR}/../../common/Makefile.inc" Modified: stable/10/sys/boot/amd64/efi/copy.c ============================================================================== --- stable/10/sys/boot/amd64/efi/copy.c Thu Apr 9 18:50:41 2015 (r281318) +++ stable/10/sys/boot/amd64/efi/copy.c Thu Apr 9 19:03:11 2015 (r281319) @@ -37,9 +37,13 @@ __FBSDID("$FreeBSD$"); #include #include -#define STAGE_PAGES 8192 /* 32MB */ +#ifndef EFI_STAGING_SIZE +#define EFI_STAGING_SIZE 32 +#endif -EFI_PHYSICAL_ADDRESS staging; +#define STAGE_PAGES ((EFI_STAGING_SIZE) * 1024 * 1024 / 4096) + +EFI_PHYSICAL_ADDRESS staging, staging_end; int stage_offset_set = 0; ssize_t stage_offset; @@ -55,6 +59,7 @@ x86_efi_copy_init(void) (unsigned long)(status & EFI_ERROR_MASK)); return (status); } + staging_end = staging + STAGE_PAGES * 4096; return (0); } @@ -68,6 +73,11 @@ x86_efi_copyin(const void *src, vm_offse stage_offset_set = 1; } + /* XXX: Callers do not check for failure. */ + if (dest + stage_offset + len > staging_end) { + errno = ENOMEM; + return (-1); + } bcopy(src, (void *)(dest + stage_offset), len); return (len); } @@ -76,6 +86,11 @@ ssize_t x86_efi_copyout(const vm_offset_t src, void *dest, const size_t len) { + /* XXX: Callers do not check for failure. */ + if (src + stage_offset + len > staging_end) { + errno = ENOMEM; + return (-1); + } bcopy((void *)(src + stage_offset), dest, len); return (len); } @@ -85,6 +100,10 @@ ssize_t x86_efi_readin(const int fd, vm_offset_t dest, const size_t len) { + if (dest + stage_offset + len > staging_end) { + errno = ENOMEM; + return (-1); + } return (read(fd, (void *)(dest + stage_offset), len)); }