Blob Blame History Raw
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Sun, 19 Jul 2020 17:27:00 -0400
Subject: [PATCH] efi/ip[46]_config.c: fix some potential allocation overflows

In theory all of this data comes from the firmware stack and it should
be safe, but it's better to be paranoid.

Signed-off-by: Peter Jones <pjones@redhat.com>
---
 grub-core/net/efi/ip4_config.c | 25 ++++++++++++++++++-------
 grub-core/net/efi/ip6_config.c | 13 ++++++++++---
 2 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c
index 313c818b184..9725e928f7e 100644
--- a/grub-core/net/efi/ip4_config.c
+++ b/grub-core/net/efi/ip4_config.c
@@ -4,15 +4,20 @@
 #include <grub/misc.h>
 #include <grub/net/efi.h>
 #include <grub/charset.h>
+#include <grub/safemath.h>
 
 char *
 grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address)
 {
   char *hw_addr, *p;
-  int sz, s;
-  int i;
+  grub_size_t sz, s, i;
 
-  sz = (int)hw_address_size * (sizeof ("XX:") - 1) + 1;
+  if (grub_mul (hw_address_size, sizeof ("XX:") - 1, &sz) ||
+      grub_add (sz, 1, &sz))
+    {
+      grub_errno = GRUB_ERR_OUT_OF_RANGE;
+      return NULL;
+    }
 
   hw_addr = grub_malloc (sz);
   if (!hw_addr)
@@ -20,7 +25,7 @@ grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_a
 
   p = hw_addr;
   s = sz;
-  for (i = 0; i < (int)hw_address_size; i++)
+  for (i = 0; i < hw_address_size; i++)
     {
       grub_snprintf (p, sz, "%02x:", hw_address[i]);
       p +=  sizeof ("XX:") - 1;
@@ -238,14 +243,20 @@ grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev)
 {
   grub_efi_ip4_config2_interface_info_t *interface_info;
   char **ret;
-  int i, id;
+  int id;
+  grub_size_t i, nmemb;
 
   interface_info = efi_ip4_config_interface_info (dev->ip4_config);
   if (!interface_info)
     return NULL;
 
-  ret = grub_malloc (sizeof (*ret) * (interface_info->route_table_size + 1));
+  if (grub_add (interface_info->route_table_size, 1, &nmemb))
+    {
+      grub_errno = GRUB_ERR_OUT_OF_RANGE;
+      return NULL;
+    }
 
+  ret = grub_calloc (nmemb, sizeof (*ret));
   if (!ret)
     {
       grub_free (interface_info);
@@ -253,7 +264,7 @@ grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev)
     }
 
   id = 0;
-  for (i = 0; i < (int)interface_info->route_table_size; i++)
+  for (i = 0; i < interface_info->route_table_size; i++)
     {
       char *subnet, *gateway, *mask;
       grub_uint32_t u32_subnet, u32_gateway;
diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c
index 017c4d05bc7..a46f6f9b685 100644
--- a/grub-core/net/efi/ip6_config.c
+++ b/grub-core/net/efi/ip6_config.c
@@ -3,6 +3,7 @@
 #include <grub/misc.h>
 #include <grub/net/efi.h>
 #include <grub/charset.h>
+#include <grub/safemath.h>
 
 char *
 grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address)
@@ -228,14 +229,20 @@ grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev)
 {
   grub_efi_ip6_config_interface_info_t *interface_info;
   char **ret;
-  int i, id;
+  int id;
+  grub_size_t i, nmemb;
 
   interface_info = efi_ip6_config_interface_info (dev->ip6_config);
   if (!interface_info)
     return NULL;
 
-  ret = grub_malloc (sizeof (*ret) * (interface_info->route_count + 1));
+  if (grub_add (interface_info->route_count, 1, &nmemb))
+    {
+      grub_errno = GRUB_ERR_OUT_OF_RANGE;
+      return NULL;
+    }
 
+  ret = grub_calloc (nmemb, sizeof (*ret));
   if (!ret)
     {
       grub_free (interface_info);
@@ -243,7 +250,7 @@ grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev)
     }
 
   id = 0;
-  for (i = 0; i < (int)interface_info->route_count ; i++)
+  for (i = 0; i < interface_info->route_count ; i++)
     {
       char *gateway, *destination;
       grub_uint64_t u64_gateway[2];