Signed-off-by: Matthias Fischer matthias.fischer@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@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@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@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 +