Source: connman Version: 2.0-2 Severity: important Tags: security upstream patch
Hi, CVE-2026-115863 has no Debian bug yet, so I am filing this one so that the fix does not get lost. get_domains() in gdhcp/client.c copies a fixed NS_MAXDNAME bytes from the DHCPv6 DOMAIN_LIST option into a stack buffer, regardless of the option length, and then walks the labels with no bound. It is reached from a DHCPv6 reply, and connmand runs as root. Per the CVE description, an on-link attacker can trigger it without authentication. The function is the same in 2.0-2 (sid), 1.44-3 (trixie) and 1.41-3 (bookworm). Upstream HEAD 9e46e4a0, the latest commit I could fetch, does not change it. Andrei Miu posted a fix to the connman list on 2026-10-23 (the thread is linked from the tracker entry). The only reply so far is an unrelated form letter, and it has not been applied upstream. I have attached that patch unchanged. What I checked: - The patch applies to all three versions, with line offsets only on 1.44-3 and 1.41-3. - I extracted the function before and after the patch and ran eight valid DOMAIN_LIST values through it under ASan/UBSan, on all three versions: single names, 63-byte labels, and lists of up to 40 names. The output was identical before and after, with no sanitizer reports. - From reading the patch, the copy is now bounded by the option length, the buffer is NUL-terminated, and the label walk stops at the end of the copied data. What I did not test: I did not reproduce the overflow, and I did not run malformed input through the patched code. I also did not do a full package build or a run against a real DHCPv6 server. The function was compiled on its own with a minimal stand-in for the GList calls. Regards, Sumit Verma
From 9c2e3f0f85370ecee33e09bfce1b8aa8c1c554d4 Mon Sep 17 00:00:00 2001 From: Andrei Miu <[email protected]> Date: Thu, 23 Oct 2026 10:00:00 +0200 Subject: [PATCH] gdhcp: fix stack buffer overflow in get_domains() get_domains() copied a fixed NS_MAXDNAME (1025) bytes from the DOMAIN_LIST (option 24) value into the 1026-byte stack buffer dns_name regardless of the actual option length, and then walked DNS labels with an unbounded 'c += jump + 1' loop. A crafted DHCPv6 REPLY with a DOMAIN_LIST option of >= 1025 non-zero bytes makes the label walk leave the buffer and read/write '.' past its end in attacker-chosen strides (stride = label byte + 1), i.e. out-of-bounds writes into the canary/saved registers territory of connmand (running as root). On stack-zeroing kernels the walk performs an out-of-bounds read instead and exits at the first zero byte. DHCPv6 REPLY messages are unauthenticated and the transaction id and CLIENTID DUID are observable on the wire (INFORMATION-REQUEST is multicast to ff02::1:2), so any on-link attacker can trigger this. Fix by bounding the copy to the remaining option length, NUL-terminating the buffer, and stopping the label walk at the end of the copied data. Fixes: bb06c47101ca24 ("gdhcp: Domain search list DHCPv6 option is checked") --- gdhcp/client.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/gdhcp/client.c b/gdhcp/client.c index 976773ac..b594e349 100644 --- a/gdhcp/client.c +++ b/gdhcp/client.c @@ -2217,13 +2217,25 @@ static GList *get_domains(int maxlen, unsigned char *value) return NULL; while (pos < maxlen) { - strncpy(dns_name, (char *)&value[pos], NS_MAXDNAME); + int name_len = maxlen - pos; + char *name_end; + if (name_len > NS_MAXDNAME) + name_len = NS_MAXDNAME; + + memcpy(dns_name, &value[pos], name_len); + dns_name[name_len] = '\0'; + + name_end = dns_name + name_len; c = (unsigned char *)dns_name; while (c && *c) { int jump; + char *label = (char *)c; + jump = *c; - *c = '.'; + if (label + jump + 1 > name_end) + break; + *label = '.'; c += jump + 1; } list = g_list_prepend(list, g_strdup(&dns_name[1])); -- 2.55.0

