Skip to content

[Bug] raw-API DHCP server reads client option values without bounds checks (OOB read) #11913

Open

Description

@K-ANOY

RT-Thread Version

master @ 1c801efabc.

Affected area

Networking

Hardware/BSP vendor

Not applicable / Other

Architecture

Not applicable / Other

Board and hardware details

Not applicable.

Develop Toolchain

GCC

Describe the bug

The raw-API DHCP server parses client packets without bounding the option walk or the option-value reads.

components/net/lwip-dhcpd/dhcp_server_raw.c:296:

static u8_t *dhcp_server_option_find(u8_t *buf, u16_t len, u8_t option) {
    u8_t *end = buf + len;
    while ((buf < end) && (*buf != DHCP_OPTION_END)) {
        if (*buf == option) return buf;
        buf += (buf[1] + 2);        /* buf[1] read even when buf == end-1 */
    }
    return NULL;
}

buf[1] is read without verifying buf + 1 < end, so a final option header at end-1 reads one byte past the buffer. The function also only guarantees the returned pointer is < end, and the callers read the value with no length check:

node = dhcp_client_find_by_ip(dhcpserver, (ip4_addr_t *)(&opt[2]));  /* :209, reads 4 bytes */
msg_type = *(opt + 2);                                               /* :372 */

A REQUESTED_IP (50) or MESSAGE_TYPE (53) option placed at the tail lets opt[2]..opt[5] read up to 4 bytes past the buffer. The packet buffer is a fixed pbuf_alloc(PBUF_TRANSPORT, 1500, PBUF_RAM) (:331), so the over-reads land just past that heap allocation.

The sibling socket-based server dhcp_server.c performs exactly the checks this file omits (dhcp_opt + 2 > dhcp_opt_end, declared-length validation, length < 4 / length < 1), which confirms the raw variant is missing them.

Steps / trigger. Any host on the same L2 segment sends a DHCP packet to UDP/67 whose option area ends with a REQUESTED_IP / MESSAGE_TYPE option header positioned so its value bytes fall at or past the buffer end. No authentication. Reproduced at logic level under ASan (reports/repro/dhcpd-raw/).

Expected. Short or truncated options are rejected before their length/value bytes are read, as dhcp_server.c already does.

Actual. Out-of-bounds read of a few bytes past the 1500-byte heap allocation. The values are used only for dispatch / IP comparison and are not returned to the attacker, so the practical impact is a crash / DoS if the allocation abuts an unmapped page.

Suggested fix. Port the socket variant's checks: require buf + 1 < end before reading buf[1] and buf + 2 + buf[1] <= end before advancing; in each caller verify the matched option's declared length and that opt + 2 + opt[1] <= end before reading the value.

Other additional context

No response

Activity

  1. added
    bugThis PR/issue is a bug in the current code.
    on Oct 21, 2026
  2. github-actions commented on Oct 21, 2026

    @github-actions

    如需认领并处理此 Issue,请评论 /claim。

    To claim and work on this issue, comment /claim.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions