CVE-2024-24476: Insufficient Information (NVD-CWE-noinfo)
value: A buffer overflow in Wireshark before 4.2.0 allows a remote attacker to cause a denial of service via the pan/addr_resolv.c, and ws_manuf_lookup_str(), size components. NOTE: this is disputed by the vendor because neither release 4.2.0 nor any other release was affected.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-02-21T19:15Z
Repository: https://github.com/wireshark/wireshark
Language: C
Files changed: epan/addr_resolv.c, epan/addr_resolv.h, epan/address_types.c
Commit date: 2023-09-16 12:21:42 +0100
Commit message: addr_resolv: Fix a heap buffer overflow

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

Fixes #19344.

Diff: diff --git a/epan/addr_resolv.c b/epan/addr_resolv.c
index d9ad4921f92..8b6af813aa1 100644
--- a/epan/addr_resolv.c
+++ b/epan/addr_resolv.c
@@ -1667,16 +1667,18 @@ add_manuf_name(const guint8 *addr, unsigned int mask, gchar *name, gchar *longna
         break;
     }
 } /* add_manuf_name */
 
 static hashmanuf_t *
-manuf_name_lookup(const guint8 *addr)
+manuf_name_lookup(const guint8 *addr, size_t size)
 {
     guint32       manuf_key;
     guint8       oct;
     hashmanuf_t  *manuf_value;
 
+    ws_return_val_if(size < 6, NULL);
+
     /* manuf needs only the 3 most significant octets of the ethernet address */
     manuf_key = addr[0];
     manuf_key = manuf_key<<8;
     oct = addr[1];
     manuf_key = manuf_key | oct;
@@ -1868,10 +1870,11 @@ ethers_cleanup(void)
 static hashether_t *
 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) {
         (void) g_strlcpy(tp->resolved_name, eth->name, MAXNAMELEN);
         tp->status = HASHETHER_STATUS_RESOLVED_NAME;
         return tp;
@@ -1914,11 +1917,11 @@ eth_addr_resolve(hashether_t *tp) {
                 return tp;
             }
         } while (mask--);
 
         /* 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)) {
             snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
                     manuf_value->resolved_name, addr[3], addr[4], addr[5]);
             tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
             return tp;
@@ -3482,35 +3485,39 @@ get_vlan_name(wmem_allocator_t *allocator, const guint16 id)
     return wmem_strdup(allocator, vlan_name_lookup(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;
 
     return manuf_value->hexaddr;
 
 } /* get_manuf_name */
 
 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;
     guint manuf_key;
     guint8 oct;
 
+    ws_return_val_if(size != 6, NULL);
+
     /* manuf needs only the 3 most significant octets of the ethernet address */
     manuf_key = addr[0];
     manuf_key = manuf_key<<8;
     oct = addr[1];
     manuf_key = manuf_key | oct;
@@ -3562,11 +3569,13 @@ uint_get_manuf_name_if_known(const guint32 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)
 {
     return manuf->resolved_longname;
@@ -3580,11 +3589,11 @@ eui64_to_display(wmem_allocator_t *allocator, const guint64 addr_eui64)
     gchar *ret;
 
     /* 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 {
         ret = wmem_strdup_printf(allocator, "%s_%02x:%02x:%02x:%02x:%02x", manuf_value->resolved_name, addr[3], addr[4], addr[5], addr[6], addr[7]);
     }
diff --git a/epan/addr_resolv.h b/epan/addr_resolv.h
index b4cbe749f9b..fb38eb4659d 100644
--- a/epan/addr_resolv.h
+++ b/epan/addr_resolv.h
@@ -223,17 +223,17 @@ 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_if_known()
  * returns the vendor name, or NULL if not known.
  */
diff --git a/epan/address_types.c b/epan/address_types.c
index 1985ba19e22..c0bb05cf149 100644
--- a/epan/address_types.c
+++ b/epan/address_types.c
@@ -381,21 +381,21 @@ static const gchar* fcwwn_name_res_str(const address* addr)
 
     case FC_NH_NAA_IEEE:
     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);
         oui[1] = ((addrp[1] & 0x0F) << 4) | ((addrp[2] & 0xF0) >> 4);
         oui[2] = ((addrp[2] & 0x0F) << 4) | ((addrp[3] & 0xF0) >> 4);
         oui[3] = ((addrp[3] & 0x0F) << 4) | ((addrp[4] & 0xF0) >> 4);
         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 "";
 }
 

Vulnerable code: manuf_name_lookup(const guint8 *addr)
        manuf_value = manuf_name_lookup(addr);
get_manuf_name(const guint8 *addr)
    manuf_value = manuf_name_lookup(addr);
    return get_manuf_name(tvb_get_ptr(tvb, offset, 3));
get_manuf_name_if_known(const guint8 *addr)
    return get_manuf_name_if_known(tvb_get_ptr(tvb, offset, 3));
    manuf_value = manuf_name_lookup(addr);
extern const gchar *get_manuf_name(const guint8 *addr);
WS_DLL_PUBLIC const gchar *get_manuf_name_if_known(const guint8 *addr);
        return get_manuf_name(oui);
        return get_manuf_name(oui);
Fixed code: manuf_name_lookup(const guint8 *addr, size_t size)
    ws_return_val_if(size < 6, NULL);

    size_t addr_size = sizeof(tp->addr);
        manuf_value = manuf_name_lookup(addr, addr_size);
get_manuf_name(const guint8 *addr, size_t size)
    manuf_value = manuf_name_lookup(addr, size);
    guint8 buf[6] = { 0 };
    tvb_memcpy(tvb, buf, offset, 3);
    return get_manuf_name(buf, sizeof(buf));
get_manuf_name_if_known(const guint8 *addr, size_t size)
    ws_return_val_if(size != 6, NULL);

    guint8 buf[6] = { 0 };
    tvb_memcpy(tvb, buf, offset, 3);
    return get_manuf_name_if_known(buf, sizeof(buf));
    manuf_value = manuf_name_lookup(addr, 8);
extern const gchar *get_manuf_name(const guint8 *addr, size_t size);
WS_DLL_PUBLIC const gchar *get_manuf_name_if_known(const guint8 *addr, size_t size);
        return get_manuf_name(oui, sizeof(oui));
        return get_manuf_name(oui, sizeof(oui));