mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-10-27 12:31:03 +00:00
rfc3315: fix integer underflow and heap overflow in log6_opts STATUS_CODE
In log6_opts(), the OPTION6_STATUS_CODE branch did: memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), opt6_len(opt)-2); daemon->namebuff[len + opt6_len(opt) - 2] = 0; Two bugs: 1. Integer underflow: if opt6_len(opt) < 2, the subtraction wraps to a huge size_t, making memcpy write gigabytes and crash with SIGSEGV. 2. Heap overflow: no upper-bound check. opt6_len() can return up to 65535, but daemon->namebuff is only (MAXDNAME*2)+1 = 2051 bytes. A STATUS_CODE payload larger than ~2045 bytes would overflow the heap buffer. Exploitability: log6_opts() is only ever called on daemon->outpacket, the outgoing DHCPv6 reply built by dnsmasq itself — NOT on incoming client packets. Consequently, these bugs are NOT directly triggerable by a remote attacker under the current code. The fix is defensive: put_opt6_short() (which writes STATUS_CODE options in outgoing packets) always produces opt6_len >= 2, so neither bug fires in practice today. However, the unchecked arithmetic is a latent hazard that could become exploitable if future refactoring passes incoming option data through log6_opts(): - Guard the block with opt6_len(opt) >= 2 to prevent underflow. - Cap slen to the remaining space in daemon->namebuff. Signed-off-by: Dominik <dl6er@dl6er.de>
This commit is contained in:
1 parent
ca509cb611
commit
3ea905b98b
1 file changed
+9
-3
+9
-3
@@ -2037,9 +2037,15 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
|
||||
}
|
||||
else if (type == OPTION6_STATUS_CODE)
|
||||
{
|
||||
int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
|
||||
memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), opt6_len(opt)-2);
|
||||
daemon->namebuff[len + opt6_len(opt) - 2] = 0;
|
||||
if (opt6_len(opt) >= 2)
|
||||
{
|
||||
int slen = opt6_len(opt) - 2;
|
||||
int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
|
||||
if (slen > (MAXDNAME * 2) - len - 1)
|
||||
slen = (MAXDNAME * 2) - len - 1;
|
||||
memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), slen);
|
||||
daemon->namebuff[len + slen] = 0;
|
||||
}
|
||||
optname = "status";
|
||||
}
|
||||
else
|
||||
|
||||
Reference in new issue
Block a user