RFC 8415 doesn't exclude the possiblity that a relay-forward
message could contain _more_than_one relay-message option. The
existing code could, under certain circumstances, access freed
stack memory in this case.
Thanks to Dejan Alvadzijevic and his fuzzer for finding this
condition.
This patch fixes things so that dnsmasq does at least sensible
things with multiple relay-message options, and no longer
has the (remote) possibility of accessing dead memory.
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>
The code sending vendorclass data to the DHCP script
was confused about the format of the vendorclass in
the DHCP packet, resulting in broken data passed
to the packet.
Change the behaviour of the DHVPv6 server when a REBIND message
is received but no lease exists. Under these circumstances a new
lease is created _only_ when the --dhcp-authoritative option is
set. This matches the behavior of the DHCPv4 server.
I am attaching an incremental git-am ready patch to go on top your Git HEAD,
to fix all sorts of issues and make this conforming C99 with default
options set,
and fix another load of warnings you receive when setting the compiler
to pick the nits,
-pedantic-errors -std=c99 (or c11, c18, c2x).
It changes many void * to uint8_t * to make the "increment by bytes"
explicit.
You can't do:
void *foo;
// ...
foo += 2.
This acts almost exactly like --dhcp-option except that the defined option
is only sent when replying to PXE clients. More importantly, these
options are sent in reply PXE clients when dnsmasq in acting in PXE
proxy mode. In PXE proxy mode, the set of options sent is defined by
the PXE standard and the normal set of options is not sent. This config
allows arbitrary options in PXE-proxy replies. A typical use-case is
to send option 175 to iPXE. Thanks to Jason Berry for finding the
requirement for this.
Tweak things so that packets relayed towards a server
have source address on the server-facing network, not the
client-facing network. Thanks to Luis Thomas for spotting this
and initial patch.
This change also removes a previous bug
where --dhcp-alternate-port would affect the port used
to relay _to_ as well as the port being listened on.
The new feature allows configuration to provide bug-for-bug
compatibility, if required. Thanks to Damian Kaczkowski
for the feature suggestion.
On machines with many interfaces, enumerating them
via netlink on each packet reciept is slow,
and unneccesary. All we need is the local address->interface
mapping, which can be cached in the relay structures.
Error with prefixed address assignment. When it is calculating number of
addresses from prefixlen, it rotates only 32bit int instead of 64b uint.
Only result is assigned to 64b variable.
Two examples:
dhcp-host=[2000::1230:0:0/92],correct-prefix
dhcp-host=[2000::1234:5678:0/92],incorrect-prefix
If prefix length is lower than 96, the result is zero. It means
incorrect-prefix is not refused as it should. Fix is simple, attaching
patch with it. Just rotate 64b int.
There was discussion in the past regarding DHCPv6 NTP server option
which needs special subclassing per RFC5908.
Patch adds support for unicast, multicast IPv6 address and for FQDN string,
preserving possibly used (as suggested earlier) hex value.
Unfortunately it's still not fully free from limitations - only address list or
only fqdn value list is possible, not mixed due current
state option parsing & flagging.
rfc3315.c:1711:28: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
if (!(addr_list->flags && ADDRLIST_DECLINED) ||
^ ~~~~~~~~~~~~~~~~~
It's a flag bit so should be bitwise '&' operator
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
When dhcp-host options can have many IPv6 addresses, we need
to deal with one of them being declined by a client. The other
addresses are still valid.
It seems that this logic never worked, even with only one address, since
the DECLINED flag was never tested.