4fe85b
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
4fe85b
From: Andrei Borzenkov <arvidjaar@gmail.com>
4fe85b
Date: Wed, 16 May 2018 13:06:04 -0400
4fe85b
Subject: [PATCH] efi/uga: use 64 bit for fb_base
4fe85b
4fe85b
We get 64 bit from PCI BAR but then truncate by assigning to 32 bit.
4fe85b
Make sure to check that pointer does not overflow on 32 bit platform.
4fe85b
4fe85b
Closes: 50931
4fe85b
---
4fe85b
 grub-core/video/efi_uga.c | 31 ++++++++++++++++---------------
4fe85b
 1 file changed, 16 insertions(+), 15 deletions(-)
4fe85b
4fe85b
diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c
4fe85b
index 464ede874da..1d4091c5631 100644
4fe85b
--- a/grub-core/video/efi_uga.c
4fe85b
+++ b/grub-core/video/efi_uga.c
4fe85b
@@ -34,7 +34,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
4fe85b
 
4fe85b
 static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
4fe85b
 static struct grub_efi_uga_draw_protocol *uga;
4fe85b
-static grub_uint32_t uga_fb;
4fe85b
+static grub_uint64_t uga_fb;
4fe85b
 static grub_uint32_t uga_pitch;
4fe85b
 
4fe85b
 static struct
4fe85b
@@ -52,7 +52,7 @@ static struct
4fe85b
 #define FBTEST_COUNT	8
4fe85b
 
4fe85b
 static int
4fe85b
-find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
4fe85b
+find_line_len (grub_uint64_t *fb_base, grub_uint32_t *line_len)
4fe85b
 {
4fe85b
   grub_uint32_t *base = (grub_uint32_t *) (grub_addr_t) *fb_base;
4fe85b
   int i;
4fe85b
@@ -67,7 +67,7 @@ find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
4fe85b
 	    {
4fe85b
 	      if ((base[j] & RGB_MASK) == RGB_MAGIC)
4fe85b
 		{
4fe85b
-		  *fb_base = (grub_uint32_t) (grub_addr_t) base;
4fe85b
+		  *fb_base = (grub_uint64_t) (grub_addr_t) base;
4fe85b
 		  *line_len = j << 2;
4fe85b
 
4fe85b
 		  return 1;
4fe85b
@@ -84,7 +84,7 @@ find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
4fe85b
 /* Context for find_framebuf.  */
4fe85b
 struct find_framebuf_ctx
4fe85b
 {
4fe85b
-  grub_uint32_t *fb_base;
4fe85b
+  grub_uint64_t *fb_base;
4fe85b
   grub_uint32_t *line_len;
4fe85b
   int found;
4fe85b
 };
4fe85b
@@ -120,7 +120,9 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
4fe85b
 	      if (i == 5)
4fe85b
 		break;
4fe85b
 
4fe85b
-	      old_bar2 = grub_pci_read (addr + 4);
4fe85b
+	      i++;
4fe85b
+	      addr += 4;
4fe85b
+	      old_bar2 = grub_pci_read (addr);
4fe85b
 	    }
4fe85b
 	  else
4fe85b
 	    old_bar2 = 0;
4fe85b
@@ -129,10 +131,15 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
4fe85b
 	  base64 <<= 32;
4fe85b
 	  base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK);
4fe85b
 
4fe85b
-	  grub_dprintf ("fb", "%s(%d): 0x%llx\n",
4fe85b
+	  grub_dprintf ("fb", "%s(%d): 0x%" PRIxGRUB_UINT64_T "\n",
4fe85b
 			((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ?
4fe85b
-			"VMEM" : "MMIO"), i,
4fe85b
-		       (unsigned long long) base64);
4fe85b
+			"VMEM" : "MMIO"), type == GRUB_PCI_ADDR_MEM_TYPE_64 ? i - 1 : i,
4fe85b
+			base64);
4fe85b
+
4fe85b
+#if GRUB_CPU_SIZEOF_VOID_P == 4
4fe85b
+	  if (old_bar2)
4fe85b
+	    continue;
4fe85b
+#endif
4fe85b
 
4fe85b
 	  if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! ctx->found))
4fe85b
 	    {
4fe85b
@@ -140,12 +147,6 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
4fe85b
 	      if (find_line_len (ctx->fb_base, ctx->line_len))
4fe85b
 		ctx->found++;
4fe85b
 	    }
4fe85b
-
4fe85b
-	  if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
4fe85b
-	    {
4fe85b
-	      i++;
4fe85b
-	      addr += 4;
4fe85b
-	    }
4fe85b
 	}
4fe85b
     }
4fe85b
 
4fe85b
@@ -153,7 +154,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
4fe85b
 }
4fe85b
 
4fe85b
 static int
4fe85b
-find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len)
4fe85b
+find_framebuf (grub_uint64_t *fb_base, grub_uint32_t *line_len)
4fe85b
 {
4fe85b
   struct find_framebuf_ctx ctx = {
4fe85b
     .fb_base = fb_base,