Signed-off-by: Matthias Fischer <matthias.fischer(a)ipfire.org>
---
lfs/dnsmasq | 3 +
...q-Add-support-to-read-ISC-DHCP-lease-file.patch | 6 +-
...put_to_reduce_risk_of_information_leakage.patch | 169 +++++++++++++++++++++
...on_transmission_in_case_of_retransmission.patch | 54 +++++++
...n_buffer_sizes_for_leasefile_parsing_code.patch | 103 +++++++++++++
5 files changed, 332 insertions(+), 3 deletions(-)
create mode 100644 src/patches/dnsmasq/010-Zero_packet_buffers_before_building_output_to_reduce_risk_of_information_leakage.patch
create mode 100644 src/patches/dnsmasq/011-Dont_reset_packet_length_on_transmission_in_case_of_retransmission.patch
create mode 100644 src/patches/dnsmasq/012-Compile-time_check_on_buffer_sizes_for_leasefile_parsing_code.patch
diff --git a/lfs/dnsmasq b/lfs/dnsmasq
index a0fdc50..eb0f0ba 100644
--- a/lfs/dnsmasq
+++ b/lfs/dnsmasq
@@ -82,6 +82,9 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/007-Fix_logic_error_in_Linux_netlink_code.patch
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/008-Fix_problem_with_--dnssec-timestamp.patch
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/009-malloc_memset_calloc_for_efficiency.patch
+ cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/010-Zero_packet_buffers_before_building_output_to_reduce_risk_of_information_leakage.patch
+ cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/011-Dont_reset_packet_length_on_transmission_in_case_of_retransmission.patch
+ cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/012-Compile-time_check_on_buffer_sizes_for_leasefile_parsing_code.patch
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch
cd $(DIR_APP) && sed -i src/config.h \
diff --git a/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch b/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch
index 25feb8d..97b7749 100644
--- a/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch
+++ b/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch
@@ -42,7 +42,7 @@
--- a/src/dnsmasq.c Thu Jul 30 20:59:06 2015
+++ b/src/dnsmasq.c Wed Dec 16 19:38:32 2015
-@@ -1016,6 +1016,11 @@
+@@ -1017,6 +1017,11 @@
poll_resolv(0, daemon->last_resolv != 0, now);
daemon->last_resolv = now;
@@ -56,7 +56,7 @@
--- a/src/dnsmasq.h Wed Dec 16 19:24:12 2015
+++ b/src/dnsmasq.h Wed Dec 16 19:40:11 2015
-@@ -1514,6 +1514,11 @@
+@@ -1516,6 +1516,11 @@
void poll_listen(int fd, short event);
int do_poll(int timeout);
@@ -341,7 +341,7 @@
+#endif
--- a/src/option.c Wed Dec 16 19:24:12 2015
+++ b/src/option.c Wed Dec 16 19:42:48 2015
-@@ -1770,7 +1770,7 @@
+@@ -1771,7 +1771,7 @@
ret_err(_("bad MX target"));
break;
diff --git a/src/patches/dnsmasq/010-Zero_packet_buffers_before_building_output_to_reduce_risk_of_information_leakage.patch b/src/patches/dnsmasq/010-Zero_packet_buffers_before_building_output_to_reduce_risk_of_information_leakage.patch
new file mode 100644
index 0000000..a8c10a4
--- /dev/null
+++ b/src/patches/dnsmasq/010-Zero_packet_buffers_before_building_output_to_reduce_risk_of_information_leakage.patch
@@ -0,0 +1,169 @@
+From fa78573778cb23337f67f5d0c9de723169919047 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)thekelleys.org.uk>
+Date: Fri, 22 Jul 2016 20:56:01 +0100
+Subject: [PATCH] Zero packet buffers before building output, to reduce risk
+ of information leakage.
+
+---
+ src/auth.c | 5 +++++
+ src/dnsmasq.h | 1 +
+ src/outpacket.c | 10 ++++++++++
+ src/radv.c | 2 +-
+ src/rfc1035.c | 5 +++++
+ src/rfc3315.c | 6 +++---
+ src/slaac.c | 2 +-
+ src/tftp.c | 5 ++++-
+ 8 files changed, 30 insertions(+), 6 deletions(-)
+
+diff --git a/src/auth.c b/src/auth.c
+index 198572d..3c5c37f 100644
+--- a/src/auth.c
++++ b/src/auth.c
+@@ -101,6 +101,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
+ struct all_addr addr;
+ struct cname *a;
+
++ /* Clear buffer beyond request to avoid risk of
++ information disclosure. */
++ memset(((char *)header) + qlen, 0,
++ (limit - ((char *)header)) - qlen);
++
+ if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
+ return 0;
+
+diff --git a/src/dnsmasq.h b/src/dnsmasq.h
+index be27ae0..2bda5d0 100644
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -1471,6 +1471,7 @@ void log_relay(int family, struct dhcp_relay *relay);
+ /* outpacket.c */
+ #ifdef HAVE_DHCP6
+ void end_opt6(int container);
++void reset_counter(void);
+ int save_counter(int newval);
+ void *expand(size_t headroom);
+ int new_opt6(int opt);
+diff --git a/src/outpacket.c b/src/outpacket.c
+index a414efa..2caacd9 100644
+--- a/src/outpacket.c
++++ b/src/outpacket.c
+@@ -29,9 +29,19 @@ void end_opt6(int container)
+ PUTSHORT(len, p);
+ }
+
++void reset_counter(void)
++{
++ /* Clear out buffer when starting from begining */
++ if (daemon->outpacket.iov_base)
++ memset(daemon->outpacket.iov_base, 0, daemon->outpacket.iov_len);
++
++ save_counter(0);
++}
++
+ int save_counter(int newval)
+ {
+ int ret = outpacket_counter;
++
+ if (newval != -1)
+ outpacket_counter = newval;
+
+diff --git a/src/radv.c b/src/radv.c
+index faa0f6d..39c9217 100644
+--- a/src/radv.c
++++ b/src/radv.c
+@@ -261,7 +261,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
+ parm.adv_interval = calc_interval(ra_param);
+ parm.prio = calc_prio(ra_param);
+
+- save_counter(0);
++ reset_counter();
+
+ if (!(ra = expand(sizeof(struct ra_packet))))
+ return;
+diff --git a/src/rfc1035.c b/src/rfc1035.c
+index 24d08c1..9e730a9 100644
+--- a/src/rfc1035.c
++++ b/src/rfc1035.c
+@@ -1209,6 +1209,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
+ int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
+ struct mx_srv_record *rec;
+ size_t len;
++
++ /* Clear buffer beyond request to avoid risk of
++ information disclosure. */
++ memset(((char *)header) + qlen, 0,
++ (limit - ((char *)header)) - qlen);
+
+ if (ntohs(header->ancount) != 0 ||
+ ntohs(header->nscount) != 0 ||
+diff --git a/src/rfc3315.c b/src/rfc3315.c
+index 3f4d69c..e1271a1 100644
+--- a/src/rfc3315.c
++++ b/src/rfc3315.c
+@@ -89,7 +89,7 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *if
+ for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
+ vendor->netid.next = &vendor->netid;
+
+- save_counter(0);
++ reset_counter();
+ state.context = context;
+ state.interface = interface;
+ state.iface_name = iface_name;
+@@ -2084,7 +2084,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
+ if (hopcount > 32)
+ return;
+
+- save_counter(0);
++ reset_counter();
+
+ if ((header = put_opt6(NULL, 34)))
+ {
+@@ -2161,7 +2161,7 @@ unsigned short relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival
+ (!relay->interface || wildcard_match(relay->interface, arrival_interface)))
+ break;
+
+- save_counter(0);
++ reset_counter();
+
+ if (relay)
+ {
+diff --git a/src/slaac.c b/src/slaac.c
+index 07b8ba4..bd6c9b4 100644
+--- a/src/slaac.c
++++ b/src/slaac.c
+@@ -146,7 +146,7 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
+ struct ping_packet *ping;
+ struct sockaddr_in6 addr;
+
+- save_counter(0);
++ reset_counter();
+
+ if (!(ping = expand(sizeof(struct ping_packet))))
+ continue;
+diff --git a/src/tftp.c b/src/tftp.c
+index 3e1b5c5..618c406 100644
+--- a/src/tftp.c
++++ b/src/tftp.c
+@@ -662,8 +662,9 @@ static ssize_t tftp_err(int err, char *packet, char *message, char *file)
+ ssize_t len, ret = 4;
+ char *errstr = strerror(errno);
+
++ memset(packet, 0, daemon->packet_buff_sz);
+ sanitise(file);
+-
++
+ mess->op = htons(OP_ERR);
+ mess->err = htons(err);
+ len = snprintf(mess->message, MAXMESSAGE, message, file, errstr);
+@@ -684,6 +685,8 @@ static ssize_t tftp_err_oops(char *packet, char *file)
+ /* return -1 for error, zero for done. */
+ static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
+ {
++ memset(packet, 0, daemon->packet_buff_sz);
++
+ if (transfer->block == 0)
+ {
+ /* send OACK */
+--
+1.7.10.4
+
diff --git a/src/patches/dnsmasq/011-Dont_reset_packet_length_on_transmission_in_case_of_retransmission.patch b/src/patches/dnsmasq/011-Dont_reset_packet_length_on_transmission_in_case_of_retransmission.patch
new file mode 100644
index 0000000..ab8ba28
--- /dev/null
+++ b/src/patches/dnsmasq/011-Dont_reset_packet_length_on_transmission_in_case_of_retransmission.patch
@@ -0,0 +1,54 @@
+From 6b1c464d6de3d7d2afc9b53afe78cda6d6e3316f Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)thekelleys.org.uk>
+Date: Fri, 22 Jul 2016 20:59:16 +0100
+Subject: [PATCH] Don't reset packet length on transmission, in case of
+ retransmission.
+
+---
+ src/radv.c | 2 +-
+ src/rfc3315.c | 2 +-
+ src/slaac.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/radv.c b/src/radv.c
+index 39c9217..ffc37f2 100644
+--- a/src/radv.c
++++ b/src/radv.c
+@@ -528,7 +528,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
+ }
+
+ while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
+- save_counter(0), 0, (struct sockaddr *)&addr,
++ save_counter(-1), 0, (struct sockaddr *)&addr,
+ sizeof(addr))));
+
+ }
+diff --git a/src/rfc3315.c b/src/rfc3315.c
+index e1271a1..c7bf46f 100644
+--- a/src/rfc3315.c
++++ b/src/rfc3315.c
+@@ -2127,7 +2127,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
+ my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast to DHCPv6 server without correct interface"));
+ }
+
+- send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(0), &to, &from, 0);
++ send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0);
+
+ if (option_bool(OPT_LOG_OPTS))
+ {
+diff --git a/src/slaac.c b/src/slaac.c
+index bd6c9b4..7ecf127 100644
+--- a/src/slaac.c
++++ b/src/slaac.c
+@@ -164,7 +164,7 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
+ addr.sin6_port = htons(IPPROTO_ICMPV6);
+ addr.sin6_addr = slaac->addr;
+
+- if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
++ if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(-1), 0,
+ (struct sockaddr *)&addr, sizeof(addr)) == -1 &&
+ errno == EHOSTUNREACH)
+ slaac->ping_time = 0; /* Give up */
+--
+1.7.10.4
+
diff --git a/src/patches/dnsmasq/012-Compile-time_check_on_buffer_sizes_for_leasefile_parsing_code.patch b/src/patches/dnsmasq/012-Compile-time_check_on_buffer_sizes_for_leasefile_parsing_code.patch
new file mode 100644
index 0000000..c71f470
--- /dev/null
+++ b/src/patches/dnsmasq/012-Compile-time_check_on_buffer_sizes_for_leasefile_parsing_code.patch
@@ -0,0 +1,103 @@
+From bf4e62c19e619f7edf8d03d58d33a5752f190bfd Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)thekelleys.org.uk>
+Date: Fri, 22 Jul 2016 21:37:59 +0100
+Subject: [PATCH] Compile-time check on buffer sizes for leasefile parsing
+ code.
+
+---
+ src/dhcp-common.c | 16 ++++++++--------
+ src/dhcp-protocol.h | 4 ++++
+ src/lease.c | 9 ++++++++-
+ src/rfc3315.c | 2 +-
+ 4 files changed, 21 insertions(+), 10 deletions(-)
+
+diff --git a/src/dhcp-common.c b/src/dhcp-common.c
+index 08528e8..ecc752b 100644
+--- a/src/dhcp-common.c
++++ b/src/dhcp-common.c
+@@ -20,11 +20,11 @@
+
+ void dhcp_common_init(void)
+ {
+- /* These each hold a DHCP option max size 255
+- and get a terminating zero added */
+- daemon->dhcp_buff = safe_malloc(256);
+- daemon->dhcp_buff2 = safe_malloc(256);
+- daemon->dhcp_buff3 = safe_malloc(256);
++ /* These each hold a DHCP option max size 255
++ and get a terminating zero added */
++ daemon->dhcp_buff = safe_malloc(DHCP_BUFF_SZ);
++ daemon->dhcp_buff2 = safe_malloc(DHCP_BUFF_SZ);
++ daemon->dhcp_buff3 = safe_malloc(DHCP_BUFF_SZ);
+
+ /* dhcp_packet is used by v4 and v6, outpacket only by v6
+ sizeof(struct dhcp_packet) is as good an initial size as any,
+@@ -855,14 +855,14 @@ void log_context(int family, struct dhcp_context *context)
+ if (context->flags & CONTEXT_RA_STATELESS)
+ {
+ if (context->flags & CONTEXT_TEMPLATE)
+- strncpy(daemon->dhcp_buff, context->template_interface, 256);
++ strncpy(daemon->dhcp_buff, context->template_interface, DHCP_BUFF_SZ);
+ else
+ strcpy(daemon->dhcp_buff, daemon->addrbuff);
+ }
+ else
+ #endif
+- inet_ntop(family, start, daemon->dhcp_buff, 256);
+- inet_ntop(family, end, daemon->dhcp_buff3, 256);
++ inet_ntop(family, start, daemon->dhcp_buff, DHCP_BUFF_SZ);
++ inet_ntop(family, end, daemon->dhcp_buff3, DHCP_BUFF_SZ);
+ my_syslog(MS_DHCP | LOG_INFO,
+ (context->flags & CONTEXT_RA_STATELESS) ?
+ _("%s stateless on %s%.0s%.0s%s") :
+diff --git a/src/dhcp-protocol.h b/src/dhcp-protocol.h
+index a31d829..0ea449b 100644
+--- a/src/dhcp-protocol.h
++++ b/src/dhcp-protocol.h
+@@ -19,6 +19,10 @@
+ #define DHCP_CLIENT_ALTPORT 1068
+ #define PXE_PORT 4011
+
++/* These each hold a DHCP option max size 255
++ and get a terminating zero added */
++#define DHCP_BUFF_SZ 256
++
+ #define BOOTREQUEST 1
+ #define BOOTREPLY 2
+ #define DHCP_COOKIE 0x63825363
+diff --git a/src/lease.c b/src/lease.c
+index 20cac90..ca62cc5 100644
+--- a/src/lease.c
++++ b/src/lease.c
+@@ -65,7 +65,14 @@ void lease_init(time_t now)
+ }
+
+ /* client-id max length is 255 which is 255*2 digits + 254 colons
+- borrow DNS packet buffer which is always larger than 1000 bytes */
++ borrow DNS packet buffer which is always larger than 1000 bytes
++
++ Check various buffers are big enough for the code below */
++
++#if (DHCP_BUFF_SZ < 255) || (MAXDNAME < 64) || (PACKETSZ+MAXDNAME+RRFIXEDSZ < 764)
++# error Buffer size breakage in leasfile parsing.
++#endif
++
+ if (leasestream)
+ while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2)
+ {
+diff --git a/src/rfc3315.c b/src/rfc3315.c
+index c7bf46f..568b0c8 100644
+--- a/src/rfc3315.c
++++ b/src/rfc3315.c
+@@ -1975,7 +1975,7 @@ static void log6_packet(struct state *state, char *type, struct in6_addr *addr,
+
+ if (addr)
+ {
+- inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255);
++ inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, DHCP_BUFF_SZ - 1);
+ strcat(daemon->dhcp_buff2, " ");
+ }
+ else
+--
+1.7.10.4
+
--
2.9.2