summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHauke Mehrtens2026-05-23 12:05:18 +0000
committerHauke Mehrtens2026-06-18 00:34:57 +0000
commit6907f28f9ddeef9f69f5ee10bbc9ba8adc0ef57f (patch)
tree1e0cd3ac3fb3f756ecec9655dc618a3e3a1b4a78
parentedf2e523b7ae23830a7377343b66c7675c7703c7 (diff)
downloadodhcpd-6907f28f9ddeef9f69f5ee10bbc9ba8adc0ef57f.tar.gz
dhcpv6: fix out-of-bounds read in self-loop detection memcmp
The "talk to ourself" guard in handle_client_request() compares the configured server DUID against the received client DUID. Both length fields are stored in network byte order (set via htons()), but the memcmp() length argument was passed as the htons-encoded value rather than the host-order length. On little-endian hosts this multiplies the true length by 256, so for a typical 14-byte DUID the memcmp reads 3584 bytes from a 130-byte stack buffer, an attacker-reachable OOB read of stack memory. Use ntohs(dest.serverid_length) so memcmp gets the actual DUID length. Assisted-by: Claude:claude-opus-4-7 Link: https://github.com/openwrt/odhcpd/pull/401 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> (cherry picked from commit ed38cffa927d5fd450d20bfd3f7fb8d8e8fff301)
-rw-r--r--src/dhcpv6.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index a211b25..868740f 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -715,10 +715,10 @@ static void handle_client_request(void *addr, void *data, size_t len,
}
}
- if (dest.serverid_length == clientid.len &&
- !memcmp(clientid.buf, dest.serverid_buf, dest.serverid_length)) {
+ if (dest.serverid_length == clientid.len &&
+ !memcmp(clientid.buf, dest.serverid_buf, ntohs(dest.serverid_length))) {
/* Bail if we are in a network loop where we talk with ourself */
- return;
+ return;
}
if (!IN6_IS_ADDR_MULTICAST((struct in6_addr *)dest_addr) && iov[IOV_NESTED].iov_len == 0 &&