mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-10-14 10:29:33 +00:00
dhcp-common: fix OOB reads in DHCPv6 option_string() decoders
Two decoders in option_string() read beyond the end of the supplied option-value buffer when a malformed DHCPv6 option is received: 1. OT_RFC1035_NAME: after advancing i past the last label (i = l), val[i] was read at line 885 to decide whether to append a '.'. If the label ends exactly at opt_len, i == opt_len and val[i] is one byte past the option data. Fixed by guarding with i < opt_len before the read. 2. OT_CSTRING: the loop opened with while(1) and called GETSHORT (a 2-byte read) before checking that two bytes remained, so a 1- or 0-byte option value caused an immediate 1-byte OOB read. Additionally, if the length field exceeded the remaining option data the inner body-copy loop read past the end. Fixed by changing the loop condition to while(i+2 <= opt_len) and adding a check that the body fits before copying. Both reads land inside the received packet buffer (no crash), but they allow a DHCPv6 client to cause dnsmasq to read unrelated packet bytes and emit them in syslog output. Security: OOB reads of up to option-length bytes from a network-supplied DHCPv6 packet; reachable only with --log-dhcp enabled; no memory corruption, crash, or sensitive data disclosure beyond adjacent packet bytes. Signed-off-by: Dominik <dl6er@dl6er.de>
This commit is contained in:
1 parent
8ceb8ee9b5
commit
ca509cb611
1 file changed
+6
-7
+6
-7
@@ -892,24 +892,23 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
|
||||
unsigned char *p;
|
||||
|
||||
i = 0, j = 0;
|
||||
while (1)
|
||||
while (i + 2 <= opt_len)
|
||||
{
|
||||
p = &val[i];
|
||||
GETSHORT(len, p);
|
||||
if (i + 2 + len > opt_len)
|
||||
break; /* malformed: body extends beyond option */
|
||||
for (k = 0; k < len && j < buf_len; k++)
|
||||
{
|
||||
char c = *p++;
|
||||
if (isprint((unsigned char)c))
|
||||
buf[j++] = c;
|
||||
}
|
||||
i += len +2;
|
||||
if (i >= opt_len)
|
||||
break;
|
||||
|
||||
if (j < buf_len)
|
||||
i += len + 2;
|
||||
if (i < opt_len && j < buf_len)
|
||||
buf[j++] = ',';
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if ((ot[o].size & (OT_DEC | OT_TIME)) && opt_len != 0)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user