diff mbox series

[1/1] efi/x86/Add missing error handling to old_memmap 1:1 mapping code

Message ID 20200608153531.72628-2-benjamin.romer@canonical.com
State New
Headers show
Series CVE-2019-12380 | expand

Commit Message

Benjamin M Romer June 8, 2020, 3:35 p.m. UTC
From: Gen Zhang <blackgod016574@gmail.com>

The old_memmap flow in efi_call_phys_prolog() performs numerous memory
allocations, and either does not check for failure at all, or it does
but fails to propagate it back to the caller, which may end up calling
into the firmware with an incomplete 1:1 mapping.

So let's fix this by returning NULL from efi_call_phys_prolog() on
memory allocation failures only, and by handling this condition in the
caller. Also, clean up any half baked sets of page tables that we may
have created before returning with a NULL return value.

Note that any failure at this level will trigger a panic() two levels
up, so none of this makes a huge difference, but it is a nice cleanup
nonetheless.

[ardb: update commit log, add efi_call_phys_epilog() call on error path]

Signed-off-by: Gen Zhang <blackgod016574@gmail.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rob Bradford <robert.bradford@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-efi@vger.kernel.org
Link: http://lkml.kernel.org/r/20190525112559.7917-2-ard.biesheuvel@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>

CVE-2019-12380
(cherry picked from commit 4e78921ba4dd0aca1cc89168f45039add4183f8e)
[ ben_r: backport drops nearly entire patch. The 4.4 kernel skips
  restore of save_pgd if EFI_OLD_MEMMAP isn't set and returns NULL. We
  should not fail out in this case, so we check both conditions instead,
  and return an error code that exists in this tree. ]
Signed-off-by: Benjamin M Romer <benjamin.romer@canonical.com>
---
 arch/x86/platform/efi/efi.c    | 2 ++
 arch/x86/platform/efi/efi_64.c | 2 ++
 2 files changed, 4 insertions(+)

Comments

Stefan Bader June 9, 2020, 7:54 a.m. UTC | #1
On 08.06.20 17:35, Benjamin M Romer wrote:
> From: Gen Zhang <blackgod016574@gmail.com>
> 
> The old_memmap flow in efi_call_phys_prolog() performs numerous memory
> allocations, and either does not check for failure at all, or it does
> but fails to propagate it back to the caller, which may end up calling
> into the firmware with an incomplete 1:1 mapping.
> 
> So let's fix this by returning NULL from efi_call_phys_prolog() on
> memory allocation failures only, and by handling this condition in the
> caller. Also, clean up any half baked sets of page tables that we may
> have created before returning with a NULL return value.
> 
> Note that any failure at this level will trigger a panic() two levels
> up, so none of this makes a huge difference, but it is a nice cleanup
> nonetheless.
> 
> [ardb: update commit log, add efi_call_phys_epilog() call on error path]
> 
> Signed-off-by: Gen Zhang <blackgod016574@gmail.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Rob Bradford <robert.bradford@intel.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: linux-efi@vger.kernel.org
> Link: http://lkml.kernel.org/r/20190525112559.7917-2-ard.biesheuvel@linaro.org
> Signed-off-by: Ingo Molnar <mingo@kernel.org>
> 
> CVE-2019-12380
> (cherry picked from commit 4e78921ba4dd0aca1cc89168f45039add4183f8e)
> [ ben_r: backport drops nearly entire patch. The 4.4 kernel skips
>   restore of save_pgd if EFI_OLD_MEMMAP isn't set and returns NULL. We
>   should not fail out in this case, so we check both conditions instead,
>   and return an error code that exists in this tree. ]
> Signed-off-by: Benjamin M Romer <benjamin.romer@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
> ---

Same (or even worse) that for the bionic backport. Should be changed into a
backported from when applying.

-Stefan

>  arch/x86/platform/efi/efi.c    | 2 ++
>  arch/x86/platform/efi/efi_64.c | 2 ++
>  2 files changed, 4 insertions(+)
> 
> diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
> index 105872617be0..ee95e64320d8 100644
> --- a/arch/x86/platform/efi/efi.c
> +++ b/arch/x86/platform/efi/efi.c
> @@ -89,6 +89,8 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
>  	pgd_t *save_pgd;
>  
>  	save_pgd = efi_call_phys_prolog();
> +	if (!save_pgd && efi_enabled(EFI_OLD_MEMMAP))
> +		return EFI_BAD_BUFFER_SIZE;
>  
>  	/* Disable interrupts around EFI calls: */
>  	local_irq_save(flags);
> diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
> index 8067840818e9..8f9f9ba5ad5b 100644
> --- a/arch/x86/platform/efi/efi_64.c
> +++ b/arch/x86/platform/efi/efi_64.c
> @@ -92,6 +92,8 @@ pgd_t * __init efi_call_phys_prolog(void)
>  
>  	n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
>  	save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL);
> +	if (!save_pgd)
> +		return NULL;
>  
>  	for (pgd = 0; pgd < n_pgds; pgd++) {
>  		save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE);
>
Thadeu Lima de Souza Cascardo June 22, 2020, 9:07 p.m. UTC | #2
Acked-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Thadeu Lima de Souza Cascardo June 22, 2020, 9:09 p.m. UTC | #3
Applied to xenial/master-next branch.

Thanks.
Cascardo.
diff mbox series

Patch

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 105872617be0..ee95e64320d8 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -89,6 +89,8 @@  static efi_status_t __init phys_efi_set_virtual_address_map(
 	pgd_t *save_pgd;
 
 	save_pgd = efi_call_phys_prolog();
+	if (!save_pgd && efi_enabled(EFI_OLD_MEMMAP))
+		return EFI_BAD_BUFFER_SIZE;
 
 	/* Disable interrupts around EFI calls: */
 	local_irq_save(flags);
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 8067840818e9..8f9f9ba5ad5b 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -92,6 +92,8 @@  pgd_t * __init efi_call_phys_prolog(void)
 
 	n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
 	save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL);
+	if (!save_pgd)
+		return NULL;
 
 	for (pgd = 0; pgd < n_pgds; pgd++) {
 		save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE);