From 2f1e21089de838d53c33d8721dd03008395b1ab7 Mon Sep 17 00:00:00 2001
From: Michael Ellerman <mpe@ellerman.id.au>
Date: Wed, 10 Jan 2018 23:39:55 +0530
Subject: [PATCH 14/26] UBUNTU: SAUCE: rfi-flush: Fix fallback on distros using
 bootmem

CVE-2017-5754

Older kernels use bootmem as well as memblock. Because of the order of
initialisation we can't use memblock in the RFI flush setup code. We
could use bootmem, but its APIs for allocating with a limit are crap
and also appear to be buggy at least on some revisions. So for now
just put the fallback area in BSS.

This is needed in any kernel where this grep returns no matches:
  $ grep NO_BOOTMEM arch/powerpc/Kconfig

Patch by Nick.
[mauricfo: update patch]
Signed-off-by: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
---
 arch/powerpc/kernel/setup_64.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 51a17a7..2f064bc 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -729,7 +729,8 @@ EXPORT_SYMBOL(ppc_pci_io);
 
 #ifdef CONFIG_PPC_BOOK3S_64
 static enum l1d_flush_type enabled_flush_types;
-static void *l1d_flush_fallback_area;
+#define MAX_L1D_SIZE (64 * 1024)
+static char l1d_flush_fallback_area[2 * MAX_L1D_SIZE] __page_aligned_bss;
 static bool no_rfi_flush;
 bool rfi_flush;
 
@@ -792,12 +793,16 @@ static bool init_fallback_flush(void)
 	limit = min(safe_stack_limit(), ppc64_rma_size);
 
 	/*
-	 * Align to L1d size, and size it at 2x L1d size, to catch possible
-	 * hardware prefetch runoff. We don't have a recipe for load patterns to
-	 * reliably avoid the prefetcher.
+	 * We allocate 2x L1d size for the dummy area, to
+	 * catch possible hardware prefetch runoff.
+	 *
+	 * We can't use memblock_alloc here because bootmem has
+	 * been initialized, and the bootmem APIs don't work well
+	 * with an upper limit we need, so we allocate it statically
+	 * from BSS. The biggest L1d supported by this kernel is
+	 * 64kB (POWER8), so 128kB is reserved above.
 	 */
-	l1d_flush_fallback_area = __va(memblock_alloc_base(l1d_size * 2, l1d_size, limit));
-	memset(l1d_flush_fallback_area, 0, l1d_size * 2);
+	WARN_ON(l1d_size > MAX_L1D_SIZE);
 
 	for_each_possible_cpu(cpu) {
 		/*
-- 
2.7.4

