From eb877f17cdaffd7dfac6ed21b038b7280e143833 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Valverde?= <j@v6e.pt>
Date: Wed, 17 Apr 2024 11:59:06 +0200
Subject: [PATCH 1/1] addr_resolv: Fix a heap buffer overflow

Make sure we always pass at least 6 bytes to ws_manuf_lookup_str().

Fixes #19344.
---
 epan/addr_resolv.c                 | 30 +++++++++++++++++++++---------
 epan/addr_resolv.h                 |  4 ++--
 epan/address_types.c               |  4 ++--
 epan/dissectors/packet-ieee80211.c |  2 +-
 epan/dissectors/packet-ieee802a.c  |  2 +-
 epan/dissectors/packet-nhrp.c      |  4 ++--
 6 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/epan/addr_resolv.c b/epan/addr_resolv.c
index c65abf9..d853235 100644
--- a/epan/addr_resolv.c
+++ b/epan/addr_resolv.c
@@ -1366,12 +1366,15 @@ add_manuf_name(const guint8 *addr, unsigned int mask, gchar *name)
 } /* add_manuf_name */
 
 static hashmanuf_t *
-manuf_name_lookup(const guint8 *addr)
+manuf_name_lookup(const guint8 *addr, size_t size)
 {
     gint32       manuf_key = 0;
     guint8       oct;
     hashmanuf_t  *manuf_value;
 
+    if (size < 6)
+	return NULL;
+
     /* manuf needs only the 3 most significant octets of the ethernet address */
     manuf_key = addr[0];
     manuf_key = manuf_key<<8;
@@ -1507,6 +1510,7 @@ eth_addr_resolve(hashether_t *tp) {
     ether_t      *eth;
     hashmanuf_t *manuf_value;
     const guint8 *addr = tp->addr;
+    size_t addr_size = sizeof(tp->addr);
 
     if ( (eth = get_ethbyaddr(addr)) != NULL) {
         g_strlcpy(tp->resolved_name, eth->name, MAXNAMELEN);
@@ -1562,7 +1566,7 @@ eth_addr_resolve(hashether_t *tp) {
         }
 
         /* Now try looking in the manufacturer table. */
-        manuf_value = manuf_name_lookup(addr);
+        manuf_value = manuf_name_lookup(addr, addr_size);
         if ((manuf_value != NULL) && (manuf_value->status != HASHETHER_STATUS_UNRESOLVED)) {
             g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
                     manuf_value->resolved_name, addr[3], addr[4], addr[5]);
@@ -3086,11 +3090,11 @@ get_vlan_name(wmem_allocator_t *allocator, const guint16 id)
 } /* get_vlan_name */
 
 const gchar *
-get_manuf_name(const guint8 *addr)
+get_manuf_name(const guint8 *addr, size_t size)
 {
     hashmanuf_t *manuf_value;
 
-    manuf_value = manuf_name_lookup(addr);
+    manuf_value = manuf_name_lookup(addr, size);
     if (gbl_resolv_flags.mac_name && manuf_value->status != HASHETHER_STATUS_UNRESOLVED)
         return manuf_value->resolved_name;
 
@@ -3106,22 +3110,28 @@ uint_get_manuf_name(const guint oid)
     addr[0] = (oid >> 16) & 0xFF;
     addr[1] = (oid >> 8) & 0xFF;
     addr[2] = (oid >> 0) & 0xFF;
-    return get_manuf_name(addr);
+    return get_manuf_name(addr, sizeof(addr));
 }
 
 const gchar *
 tvb_get_manuf_name(tvbuff_t *tvb, gint offset)
 {
-    return get_manuf_name(tvb_get_ptr(tvb, offset, 3));
+    guint8 buf[6] = { 0 };
+    tvb_memcpy(tvb, buf, offset, 3);
+    return get_manuf_name(buf, sizeof(buf));
 }
 
+
 const gchar *
-get_manuf_name_if_known(const guint8 *addr)
+get_manuf_name_if_known(const guint8 *addr, size_t size)
 {
     hashmanuf_t *manuf_value;
     int manuf_key;
     guint8 oct;
 
+    if (size < 6)
+	return NULL;
+
     /* manuf needs only the 3 most significant octets of the ethernet address */
     manuf_key = addr[0];
     manuf_key = manuf_key<<8;
@@ -3156,7 +3166,9 @@ uint_get_manuf_name_if_known(const guint manuf_key)
 const gchar *
 tvb_get_manuf_name_if_known(tvbuff_t *tvb, gint offset)
 {
-    return get_manuf_name_if_known(tvb_get_ptr(tvb, offset, 3));
+    guint8 buf[6] = { 0 };
+    tvb_memcpy(tvb, buf, offset, 3);
+    return get_manuf_name_if_known(buf, sizeof(buf));
 }
 
 char* get_hash_manuf_resolved_name(hashmanuf_t* manuf)
@@ -3174,7 +3186,7 @@ eui64_to_display(wmem_allocator_t *allocator, const guint64 addr_eui64)
     /* Copy and convert the address to network byte order. */
     *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
 
-    manuf_value = manuf_name_lookup(addr);
+    manuf_value = manuf_name_lookup(addr, 8);
     if (!gbl_resolv_flags.mac_name || (manuf_value->status == HASHETHER_STATUS_UNRESOLVED)) {
         ret = wmem_strdup_printf(allocator, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]);
     } else {
diff --git a/epan/addr_resolv.h b/epan/addr_resolv.h
index 93a60e5..06b87e3 100644
--- a/epan/addr_resolv.h
+++ b/epan/addr_resolv.h
@@ -202,13 +202,13 @@ const gchar *get_ether_name_if_known(const guint8 *addr);
  * Given a sequence of 3 octets containing an OID, get_manuf_name()
  * returns the vendor name, or "%02x:%02x:%02x" if not known.
  */
-extern const gchar *get_manuf_name(const guint8 *addr);
+extern const gchar *get_manuf_name(const guint8 *addr, size_t size);
 
 /*
  * Given a sequence of 3 octets containing an OID, get_manuf_name_if_known()
  * returns the vendor name, or NULL if not known.
  */
-WS_DLL_PUBLIC const gchar *get_manuf_name_if_known(const guint8 *addr);
+WS_DLL_PUBLIC const gchar *get_manuf_name_if_known(const guint8 *addr, size_t size);
 
 /*
  * Given an integer containing a 24-bit OID, uint_get_manuf_name()
diff --git a/epan/address_types.c b/epan/address_types.c
index cd8440f..b1a684f 100644
--- a/epan/address_types.c
+++ b/epan/address_types.c
@@ -377,7 +377,7 @@ static const gchar* fcwwn_name_res_str(const address* addr)
     case FC_NH_NAA_IEEE_E:
 
         memcpy (oui, &addrp[2], 6);
-        return get_manuf_name(oui);
+        return get_manuf_name(oui, sizeof(oui));
 
     case FC_NH_NAA_IEEE_R:
         oui[0] = ((addrp[0] & 0x0F) << 4) | ((addrp[1] & 0xF0) >> 4);
@@ -387,7 +387,7 @@ static const gchar* fcwwn_name_res_str(const address* addr)
         oui[4] = ((addrp[4] & 0x0F) << 4) | ((addrp[5] & 0xF0) >> 4);
         oui[5] = ((addrp[5] & 0x0F) << 4) | ((addrp[6] & 0xF0) >> 4);
 
-        return get_manuf_name(oui);
+        return get_manuf_name(oui, sizeof(oui));
     }
 
     return "";
diff --git a/epan/dissectors/packet-ieee80211.c b/epan/dissectors/packet-ieee80211.c
index 612cd24..cc67f8b 100644
--- a/epan/dissectors/packet-ieee80211.c
+++ b/epan/dissectors/packet-ieee80211.c
@@ -9390,7 +9390,7 @@ oui_base_custom(gchar *result, guint32 oui)
   p_oui[2] = oui & 0xFF;
 
   /* Attempt an OUI lookup. */
-  manuf_name = get_manuf_name_if_known(p_oui);
+  manuf_name = get_manuf_name_if_known(p_oui, sizeof(p_oui));
   if (manuf_name == NULL) {
     /* Could not find an OUI. */
     g_snprintf(result, ITEM_LABEL_LENGTH, "%.2x-%.2x-%.2x", p_oui[0], p_oui[1], p_oui[2]);
diff --git a/epan/dissectors/packet-ieee802a.c b/epan/dissectors/packet-ieee802a.c
index 0d9f9c5..038bae4 100644
--- a/epan/dissectors/packet-ieee802a.c
+++ b/epan/dissectors/packet-ieee802a.c
@@ -96,7 +96,7 @@ dissect_ieee802a(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
 
 	tvb_memcpy(tvb, oui, 0, 3);
 	oui32 = oui[0] << 16 | oui[1] << 8 | oui[2];
-	manuf = get_manuf_name_if_known(oui);
+	manuf = get_manuf_name_if_known(oui, sizeof(oui));
 	pid = tvb_get_ntohs(tvb, 3);
 
 	col_add_fstr(pinfo->cinfo, COL_INFO, "OUI %s (%s), PID 0x%04X",
diff --git a/epan/dissectors/packet-nhrp.c b/epan/dissectors/packet-nhrp.c
index a09b730..252e2c9 100644
--- a/epan/dissectors/packet-nhrp.c
+++ b/epan/dissectors/packet-nhrp.c
@@ -910,10 +910,10 @@ static void dissect_nhrp_ext(tvbuff_t    *tvb,
 
                     tvb_memcpy(tvb, manuf, offset, 3);
                     vendor_tree = proto_tree_add_subtree_format(nhrp_tree, tvb, offset, len,
-                        ett_nhrp_vendor_ext, NULL, "Extension Data: Vendor ID=%s, Data=%s", get_manuf_name(manuf),
+                        ett_nhrp_vendor_ext, NULL, "Extension Data: Vendor ID=%s, Data=%s", get_manuf_name(manuf, sizeof(manuf)),
                         tvb_bytes_to_str(wmem_packet_scope(), tvb, offset + 3, len - 3));
                     proto_tree_add_bytes_format_value(vendor_tree, hf_nhrp_vendor_ext_id, tvb,
-                        offset, 3, manuf, "%s", get_manuf_name(manuf));
+                        offset, 3, manuf, "%s", get_manuf_name(manuf, sizeof(manuf)));
                     if (len > 3) {
                         proto_tree_add_item(vendor_tree, hf_nhrp_vendor_ext_data, tvb, offset + 3, len - 3, ENC_NA);
                     }
-- 
2.35.3

