Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752165AbbBWNcV (ORCPT ); Mon, 23 Feb 2015 08:32:21 -0500 Received: from mail-wi0-f176.google.com ([209.85.212.176]:53004 "EHLO mail-wi0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751071AbbBWNcT (ORCPT ); Mon, 23 Feb 2015 08:32:19 -0500 Date: Mon, 23 Feb 2015 13:32:15 +0000 From: Matt Fleming To: Yinghai Lu Cc: "H. Peter Anvin" , Ard Biesheuvel , Leif Lindholm , Roy Franz , Mark Rutland , linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH] efi: fix boundary checking in efi_high_alloc() Message-ID: <20150223133215.GA19367@codeblueprint.co.uk> References: <1424405883-19842-1-git-send-email-yinghai@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1424405883-19842-1-git-send-email-yinghai@kernel.org> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3872 Lines: 108 On Thu, 19 Feb, at 08:18:03PM, Yinghai Lu wrote: > While adding support loading kernel and initrd above 4G to grub2 in legacy > mode, I was referring to efi_high_alloc(). > That will allocate buffer for kernel and then initrd, and initrd will > use kernel buffer start as limit. > > During testing found two buffers will be overlapped when initrd size is > very big like 400M. > > It turns out efi_high_alloc() boundary checking is not right. > end - size will be the new start, and should not compare new > start with max, we need to make sure end is smaller than max. > > Signed-off-by: Yinghai Lu > > --- > drivers/firmware/efi/libstub/efi-stub-helper.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) The patch looks fine but this changelog could do with some finessing because I spent 30 minutes trying to understand what the bug was, and more specifically, what values to feed into the allocation algorithm to trigger it. Basically, with the current efi_high_alloc() code it's possible to allocate memory above 'max', because efi_high_alloc() doesn't check that the tail of the allocation is below 'max'. If you have an EFI memory map with a single entry that looks like so, [0xc0000000-0xc0004000] And want to allocate 0x3000 bytes below 0xc0003000 the current code will allocate [0xc0001000-0xc0004000], not [0xc0000000-0xc0003000] like you would expect. I've queued up the below patch. If the Linaro/ARM gang could test it out I'd really appreciate it. --- >From 1e7295b5d4c5226a160a9167e61b581e388f7f9a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 19 Feb 2015 20:18:03 -0800 Subject: [PATCH] efi/libstub: Fix boundary checking in efi_high_alloc() While adding support loading kernel and initrd above 4G to grub2 in legacy mode, I was referring to efi_high_alloc(). That will allocate buffer for kernel and then initrd, and initrd will use kernel buffer start as limit. During testing found two buffers will be overlapped when initrd size is very big like 400M. It turns out efi_high_alloc() boundary checking is not right. end - size will be the new start, and should not compare new start with max, we need to make sure end is smaller than max. [ Basically, with the current efi_high_alloc() code it's possible to allocate memory above 'max', because efi_high_alloc() doesn't check that the tail of the allocation is below 'max'. If you have an EFI memory map with a single entry that looks like so, [0xc0000000-0xc0004000] And want to allocate 0x3000 bytes below 0xc0003000 the current code will allocate [0xc0001000-0xc0004000], not [0xc0000000-0xc0003000] like you would expect. - Matt ] Signed-off-by: Yinghai Lu Cc: Signed-off-by: Matt Fleming --- drivers/firmware/efi/libstub/efi-stub-helper.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 9bd9fbb5bea8..c927bccd92bd 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -170,12 +170,12 @@ again: start = desc->phys_addr; end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); - if ((start + size) > end || (start + size) > max) - continue; - - if (end - size > max) + if (end > max) end = max; + if ((start + size) > end) + continue; + if (round_down(end - size, align) < start) continue; -- 1.9.3 -- Matt Fleming, Intel Open Source Technology Center -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/