46968b6
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
46968b6
From: Peter Jones <pjones@redhat.com>
46968b6
Date: Sun, 19 Jul 2020 17:27:00 -0400
46968b6
Subject: [PATCH] efi/ip[46]_config.c: fix some potential allocation overflows
46968b6
46968b6
In theory all of this data comes from the firmware stack and it should
46968b6
be safe, but it's better to be paranoid.
46968b6
46968b6
Signed-off-by: Peter Jones <pjones@redhat.com>
46968b6
---
46968b6
 grub-core/net/efi/ip4_config.c | 25 ++++++++++++++++++-------
46968b6
 grub-core/net/efi/ip6_config.c | 13 ++++++++++---
46968b6
 2 files changed, 28 insertions(+), 10 deletions(-)
46968b6
46968b6
diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c
46968b6
index 313c818b184..9725e928f7e 100644
46968b6
--- a/grub-core/net/efi/ip4_config.c
46968b6
+++ b/grub-core/net/efi/ip4_config.c
46968b6
@@ -4,15 +4,20 @@
46968b6
 #include <grub/misc.h>
46968b6
 #include <grub/net/efi.h>
46968b6
 #include <grub/charset.h>
46968b6
+#include <grub/safemath.h>
46968b6
 
46968b6
 char *
46968b6
 grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address)
46968b6
 {
46968b6
   char *hw_addr, *p;
46968b6
-  int sz, s;
46968b6
-  int i;
46968b6
+  grub_size_t sz, s, i;
46968b6
 
46968b6
-  sz = (int)hw_address_size * (sizeof ("XX:") - 1) + 1;
46968b6
+  if (grub_mul (hw_address_size, sizeof ("XX:") - 1, &sz) ||
46968b6
+      grub_add (sz, 1, &sz))
46968b6
+    {
46968b6
+      grub_errno = GRUB_ERR_OUT_OF_RANGE;
46968b6
+      return NULL;
46968b6
+    }
46968b6
 
46968b6
   hw_addr = grub_malloc (sz);
46968b6
   if (!hw_addr)
46968b6
@@ -20,7 +25,7 @@ grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_a
46968b6
 
46968b6
   p = hw_addr;
46968b6
   s = sz;
46968b6
-  for (i = 0; i < (int)hw_address_size; i++)
46968b6
+  for (i = 0; i < hw_address_size; i++)
46968b6
     {
46968b6
       grub_snprintf (p, sz, "%02x:", hw_address[i]);
46968b6
       p +=  sizeof ("XX:") - 1;
46968b6
@@ -238,14 +243,20 @@ grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev)
46968b6
 {
46968b6
   grub_efi_ip4_config2_interface_info_t *interface_info;
46968b6
   char **ret;
46968b6
-  int i, id;
46968b6
+  int id;
46968b6
+  grub_size_t i, nmemb;
46968b6
 
46968b6
   interface_info = efi_ip4_config_interface_info (dev->ip4_config);
46968b6
   if (!interface_info)
46968b6
     return NULL;
46968b6
 
46968b6
-  ret = grub_malloc (sizeof (*ret) * (interface_info->route_table_size + 1));
46968b6
+  if (grub_add (interface_info->route_table_size, 1, &nmemb))
46968b6
+    {
46968b6
+      grub_errno = GRUB_ERR_OUT_OF_RANGE;
46968b6
+      return NULL;
46968b6
+    }
46968b6
 
46968b6
+  ret = grub_calloc (nmemb, sizeof (*ret));
46968b6
   if (!ret)
46968b6
     {
46968b6
       grub_free (interface_info);
46968b6
@@ -253,7 +264,7 @@ grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev)
46968b6
     }
46968b6
 
46968b6
   id = 0;
46968b6
-  for (i = 0; i < (int)interface_info->route_table_size; i++)
46968b6
+  for (i = 0; i < interface_info->route_table_size; i++)
46968b6
     {
46968b6
       char *subnet, *gateway, *mask;
46968b6
       grub_uint32_t u32_subnet, u32_gateway;
46968b6
diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c
46968b6
index 017c4d05bc7..a46f6f9b685 100644
46968b6
--- a/grub-core/net/efi/ip6_config.c
46968b6
+++ b/grub-core/net/efi/ip6_config.c
46968b6
@@ -3,6 +3,7 @@
46968b6
 #include <grub/misc.h>
46968b6
 #include <grub/net/efi.h>
46968b6
 #include <grub/charset.h>
46968b6
+#include <grub/safemath.h>
46968b6
 
46968b6
 char *
46968b6
 grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address)
46968b6
@@ -228,14 +229,20 @@ grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev)
46968b6
 {
46968b6
   grub_efi_ip6_config_interface_info_t *interface_info;
46968b6
   char **ret;
46968b6
-  int i, id;
46968b6
+  int id;
46968b6
+  grub_size_t i, nmemb;
46968b6
 
46968b6
   interface_info = efi_ip6_config_interface_info (dev->ip6_config);
46968b6
   if (!interface_info)
46968b6
     return NULL;
46968b6
 
46968b6
-  ret = grub_malloc (sizeof (*ret) * (interface_info->route_count + 1));
46968b6
+  if (grub_add (interface_info->route_count, 1, &nmemb))
46968b6
+    {
46968b6
+      grub_errno = GRUB_ERR_OUT_OF_RANGE;
46968b6
+      return NULL;
46968b6
+    }
46968b6
 
46968b6
+  ret = grub_calloc (nmemb, sizeof (*ret));
46968b6
   if (!ret)
46968b6
     {
46968b6
       grub_free (interface_info);
46968b6
@@ -243,7 +250,7 @@ grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev)
46968b6
     }
46968b6
 
46968b6
   id = 0;
46968b6
-  for (i = 0; i < (int)interface_info->route_count ; i++)
46968b6
+  for (i = 0; i < interface_info->route_count ; i++)
46968b6
     {
46968b6
       char *gateway, *destination;
46968b6
       grub_uint64_t u64_gateway[2];