Rebase to 2.78
Signed-off-by: Petr Menšík <pemensik@redhat.com>
This commit is contained in:
parent
35c602043d
commit
1447e0aebc
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,3 +25,4 @@ dnsmasq-2.52.tar.lzma
|
||||
/dnsmasq-2.76.tar.xz
|
||||
/dnsmasq-2.77rc2.tar.xz
|
||||
/dnsmasq-2.77.tar.xz
|
||||
/dnsmasq-2.78.tar.xz
|
||||
|
@ -1,75 +0,0 @@
|
||||
From 63437ffbb58837b214b4b92cb1c54bc5f3279928 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Wed, 6 Sep 2017 22:34:21 +0100
|
||||
Subject: [PATCH] Fix CVE-2017-13704, which resulted in a crash on a large DNS
|
||||
query.
|
||||
|
||||
A DNS query recieved by UDP which exceeds 512 bytes (or the EDNS0 packet size,
|
||||
if different.) is enough to cause SIGSEGV.
|
||||
---
|
||||
src/auth.c | 5 -----
|
||||
src/forward.c | 8 ++++++++
|
||||
src/rfc1035.c | 5 -----
|
||||
3 files changed, 8 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/auth.c b/src/auth.c
|
||||
index 2c24e16..7f95f98 100644
|
||||
--- a/src/auth.c
|
||||
+++ b/src/auth.c
|
||||
@@ -119,11 +119,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
struct cname *a, *candidate;
|
||||
unsigned int wclen;
|
||||
|
||||
- /* 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/forward.c b/src/forward.c
|
||||
index f22556a..e3fa94b 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -1188,6 +1188,10 @@ void receive_query(struct listener *listen, time_t now)
|
||||
(msg.msg_flags & MSG_TRUNC) ||
|
||||
(header->hb3 & HB3_QR))
|
||||
return;
|
||||
+
|
||||
+ /* Clear buffer beyond request to avoid risk of
|
||||
+ information disclosure. */
|
||||
+ memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
|
||||
|
||||
source_addr.sa.sa_family = listen->family;
|
||||
|
||||
@@ -1688,6 +1692,10 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
|
||||
if (size < (int)sizeof(struct dns_header))
|
||||
continue;
|
||||
+
|
||||
+ /* Clear buffer beyond request to avoid risk of
|
||||
+ information disclosure. */
|
||||
+ memset(payload + size, 0, 65536 - size);
|
||||
|
||||
query_count++;
|
||||
|
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c
|
||||
index 26f5301..af2fe46 100644
|
||||
--- a/src/rfc1035.c
|
||||
+++ b/src/rfc1035.c
|
||||
@@ -1223,11 +1223,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
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 ||
|
||||
ntohs(header->qdcount) == 0 ||
|
||||
--
|
||||
2.9.5
|
||||
|
@ -1,68 +0,0 @@
|
||||
From 62cb936cb7ad5f219715515ae7d32dd281a5aa1f Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Tue, 26 Sep 2017 22:00:11 +0100
|
||||
Subject: [PATCH 10/10] Security fix, CVE-2017-14491, DNS heap buffer overflow.
|
||||
|
||||
Further fix to 0549c73b7ea6b22a3c49beb4d432f185a81efcbc
|
||||
Handles case when RR name is not a pointer to the question,
|
||||
only occurs for some auth-mode replies, therefore not
|
||||
detected by fuzzing (?)
|
||||
---
|
||||
src/rfc1035.c | 27 +++++++++++++++------------
|
||||
1 file changed, 15 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c
|
||||
index 27af023..56ab88b 100644
|
||||
--- a/src/rfc1035.c
|
||||
+++ b/src/rfc1035.c
|
||||
@@ -1086,32 +1086,35 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
||||
|
||||
va_start(ap, format); /* make ap point to 1st unamed argument */
|
||||
|
||||
- /* nameoffset (1 or 2) + type (2) + class (2) + ttl (4) + 0 (2) */
|
||||
- CHECK_LIMIT(12);
|
||||
-
|
||||
if (nameoffset > 0)
|
||||
{
|
||||
+ CHECK_LIMIT(2);
|
||||
PUTSHORT(nameoffset | 0xc000, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *name = va_arg(ap, char *);
|
||||
- if (name)
|
||||
- p = do_rfc1035_name(p, name, limit);
|
||||
- if (!p)
|
||||
- {
|
||||
- va_end(ap);
|
||||
- goto truncated;
|
||||
- }
|
||||
-
|
||||
+ if (name && !(p = do_rfc1035_name(p, name, limit)))
|
||||
+ {
|
||||
+ va_end(ap);
|
||||
+ goto truncated;
|
||||
+ }
|
||||
+
|
||||
if (nameoffset < 0)
|
||||
{
|
||||
+ CHECK_LIMIT(2);
|
||||
PUTSHORT(-nameoffset | 0xc000, p);
|
||||
}
|
||||
else
|
||||
- *p++ = 0;
|
||||
+ {
|
||||
+ CHECK_LIMIT(1);
|
||||
+ *p++ = 0;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ /* type (2) + class (2) + ttl (4) + rdlen (2) */
|
||||
+ CHECK_LIMIT(10);
|
||||
+
|
||||
PUTSHORT(type, p);
|
||||
PUTSHORT(class, p);
|
||||
PUTLONG(ttl, p); /* TTL */
|
||||
--
|
||||
2.9.5
|
||||
|
@ -1,263 +0,0 @@
|
||||
From 445282d13b90712ef90d2c2141d0e19bb1d896d2 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Mon, 25 Sep 2017 18:17:11 +0100
|
||||
Subject: [PATCH] Security fix, CVE-2017-14491 DNS heap buffer overflow.
|
||||
|
||||
Fix heap overflow in DNS code. This is a potentially serious
|
||||
security hole. It allows an attacker who can make DNS
|
||||
requests to dnsmasq, and who controls the contents of
|
||||
a domain, which is thereby queried, to overflow
|
||||
(by 2 bytes) a heap buffer and either crash, or
|
||||
even take control of, dnsmasq.
|
||||
|
||||
(original commit 0549c73b7ea6b22a3c49beb4d432f185a81efcbc)
|
||||
---
|
||||
src/dnsmasq.h | 2 +-
|
||||
src/dnssec.c | 2 +-
|
||||
src/option.c | 2 +-
|
||||
src/rfc1035.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
|
||||
src/rfc2131.c | 4 ++--
|
||||
src/rfc3315.c | 4 ++--
|
||||
src/util.c | 7 ++++++-
|
||||
7 files changed, 54 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
||||
index 06fae35..7a18898 100644
|
||||
--- a/src/dnsmasq.h
|
||||
+++ b/src/dnsmasq.h
|
||||
@@ -1179,7 +1179,7 @@ u32 rand32(void);
|
||||
u64 rand64(void);
|
||||
int legal_hostname(char *c);
|
||||
char *canonicalise(char *s, int *nomem);
|
||||
-unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
|
||||
+unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
|
||||
void *safe_malloc(size_t size);
|
||||
void safe_pipe(int *fd, int read_noblock);
|
||||
void *whine_malloc(size_t size);
|
||||
diff --git a/src/dnssec.c b/src/dnssec.c
|
||||
index 3330eef..b6cb55f 100644
|
||||
--- a/src/dnssec.c
|
||||
+++ b/src/dnssec.c
|
||||
@@ -2230,7 +2230,7 @@ size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char
|
||||
|
||||
p = (unsigned char *)(header+1);
|
||||
|
||||
- p = do_rfc1035_name(p, name);
|
||||
+ p = do_rfc1035_name(p, name, NULL);
|
||||
*p++ = 0;
|
||||
PUTSHORT(type, p);
|
||||
PUTSHORT(class, p);
|
||||
diff --git a/src/option.c b/src/option.c
|
||||
index 064ef62..22bd19a 100644
|
||||
--- a/src/option.c
|
||||
+++ b/src/option.c
|
||||
@@ -1415,7 +1415,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
||||
}
|
||||
|
||||
p = newp;
|
||||
- end = do_rfc1035_name(p + len, dom);
|
||||
+ end = do_rfc1035_name(p + len, dom, NULL);
|
||||
*end++ = 0;
|
||||
len = end - p;
|
||||
free(dom);
|
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c
|
||||
index 1671883..3397a26 100644
|
||||
--- a/src/rfc1035.c
|
||||
+++ b/src/rfc1035.c
|
||||
@@ -1062,6 +1062,7 @@ int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bog
|
||||
return 0;
|
||||
}
|
||||
|
||||
+
|
||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
|
||||
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
|
||||
{
|
||||
@@ -1071,12 +1072,21 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
||||
unsigned short usval;
|
||||
long lval;
|
||||
char *sval;
|
||||
+#define CHECK_LIMIT(size) \
|
||||
+ if (limit && p + (size) > (unsigned char*)limit) \
|
||||
+ { \
|
||||
+ va_end(ap); \
|
||||
+ goto truncated; \
|
||||
+ }
|
||||
|
||||
if (truncp && *truncp)
|
||||
return 0;
|
||||
-
|
||||
+
|
||||
va_start(ap, format); /* make ap point to 1st unamed argument */
|
||||
-
|
||||
+
|
||||
+ /* nameoffset (1 or 2) + type (2) + class (2) + ttl (4) + 0 (2) */
|
||||
+ CHECK_LIMIT(12);
|
||||
+
|
||||
if (nameoffset > 0)
|
||||
{
|
||||
PUTSHORT(nameoffset | 0xc000, p);
|
||||
@@ -1085,7 +1095,13 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
||||
{
|
||||
char *name = va_arg(ap, char *);
|
||||
if (name)
|
||||
- p = do_rfc1035_name(p, name);
|
||||
+ p = do_rfc1035_name(p, name, limit);
|
||||
+ if (!p)
|
||||
+ {
|
||||
+ va_end(ap);
|
||||
+ goto truncated;
|
||||
+ }
|
||||
+
|
||||
if (nameoffset < 0)
|
||||
{
|
||||
PUTSHORT(-nameoffset | 0xc000, p);
|
||||
@@ -1106,6 +1122,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
case '6':
|
||||
+ CHECK_LIMIT(IN6ADDRSZ);
|
||||
sval = va_arg(ap, char *);
|
||||
memcpy(p, sval, IN6ADDRSZ);
|
||||
p += IN6ADDRSZ;
|
||||
@@ -1113,36 +1130,47 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
||||
#endif
|
||||
|
||||
case '4':
|
||||
+ CHECK_LIMIT(INADDRSZ);
|
||||
sval = va_arg(ap, char *);
|
||||
memcpy(p, sval, INADDRSZ);
|
||||
p += INADDRSZ;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
+ CHECK_LIMIT(1);
|
||||
usval = va_arg(ap, int);
|
||||
*p++ = usval;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
+ CHECK_LIMIT(2);
|
||||
usval = va_arg(ap, int);
|
||||
PUTSHORT(usval, p);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
+ CHECK_LIMIT(4);
|
||||
lval = va_arg(ap, long);
|
||||
PUTLONG(lval, p);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
- /* get domain-name answer arg and store it in RDATA field */
|
||||
- if (offset)
|
||||
- *offset = p - (unsigned char *)header;
|
||||
- p = do_rfc1035_name(p, va_arg(ap, char *));
|
||||
- *p++ = 0;
|
||||
+ /* get domain-name answer arg and store it in RDATA field */
|
||||
+ if (offset)
|
||||
+ *offset = p - (unsigned char *)header;
|
||||
+ p = do_rfc1035_name(p, va_arg(ap, char *), limit);
|
||||
+ if (!p)
|
||||
+ {
|
||||
+ va_end(ap);
|
||||
+ goto truncated;
|
||||
+ }
|
||||
+ CHECK_LIMIT(1);
|
||||
+ *p++ = 0;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
usval = va_arg(ap, int);
|
||||
+ CHECK_LIMIT(usval);
|
||||
sval = va_arg(ap, char *);
|
||||
if (usval != 0)
|
||||
memcpy(p, sval, usval);
|
||||
@@ -1154,20 +1182,24 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
||||
usval = sval ? strlen(sval) : 0;
|
||||
if (usval > 255)
|
||||
usval = 255;
|
||||
+ CHECK_LIMIT(usval + 1);
|
||||
*p++ = (unsigned char)usval;
|
||||
memcpy(p, sval, usval);
|
||||
p += usval;
|
||||
break;
|
||||
}
|
||||
|
||||
+#undef CHECK_LIMIT
|
||||
va_end(ap); /* clean up variable argument pointer */
|
||||
|
||||
j = p - sav - 2;
|
||||
- PUTSHORT(j, sav); /* Now, store real RDLength */
|
||||
+ /* this has already been checked against limit before */
|
||||
+ PUTSHORT(j, sav); /* Now, store real RDLength */
|
||||
|
||||
/* check for overflow of buffer */
|
||||
if (limit && ((unsigned char *)limit - p) < 0)
|
||||
{
|
||||
+truncated:
|
||||
if (truncp)
|
||||
*truncp = 1;
|
||||
return 0;
|
||||
diff --git a/src/rfc2131.c b/src/rfc2131.c
|
||||
index a679470..052498c 100644
|
||||
--- a/src/rfc2131.c
|
||||
+++ b/src/rfc2131.c
|
||||
@@ -2454,10 +2454,10 @@ static void do_options(struct dhcp_context *context,
|
||||
|
||||
if (fqdn_flags & 0x04)
|
||||
{
|
||||
- p = do_rfc1035_name(p, hostname);
|
||||
+ p = do_rfc1035_name(p, hostname, NULL);
|
||||
if (domain)
|
||||
{
|
||||
- p = do_rfc1035_name(p, domain);
|
||||
+ p = do_rfc1035_name(p, domain, NULL);
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c
|
||||
index 054ecd0..715b6db 100644
|
||||
--- a/src/rfc3315.c
|
||||
+++ b/src/rfc3315.c
|
||||
@@ -1479,10 +1479,10 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
|
||||
if ((p = expand(len + 2)))
|
||||
{
|
||||
*(p++) = state->fqdn_flags;
|
||||
- p = do_rfc1035_name(p, state->hostname);
|
||||
+ p = do_rfc1035_name(p, state->hostname, NULL);
|
||||
if (state->send_domain)
|
||||
{
|
||||
- p = do_rfc1035_name(p, state->send_domain);
|
||||
+ p = do_rfc1035_name(p, state->send_domain, NULL);
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
diff --git a/src/util.c b/src/util.c
|
||||
index 145e53a..471faa9 100644
|
||||
--- a/src/util.c
|
||||
+++ b/src/util.c
|
||||
@@ -227,15 +227,20 @@ char *canonicalise(char *in, int *nomem)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
|
||||
+unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
|
||||
{
|
||||
int j;
|
||||
|
||||
while (sval && *sval)
|
||||
{
|
||||
+ if (limit && p + 1 > (unsigned char*)limit)
|
||||
+ return p;
|
||||
+
|
||||
unsigned char *cp = p++;
|
||||
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
||||
{
|
||||
+ if (limit && p + 1 > (unsigned char*)limit)
|
||||
+ return p;
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
||||
*p++ = (*(++sval))-1;
|
||||
--
|
||||
2.9.5
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 24036ea507862c7b7898b68289c8130f85599c10 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Mon, 25 Sep 2017 18:47:15 +0100
|
||||
Subject: [PATCH 3/9] Security fix, CVE-2017-14492, DHCPv6 RA heap overflow.
|
||||
|
||||
Fix heap overflow in IPv6 router advertisement code.
|
||||
This is a potentially serious security hole, as a
|
||||
crafted RA request can overflow a buffer and crash or
|
||||
control dnsmasq. Attacker must be on the local network.
|
||||
---
|
||||
src/radv.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/radv.c b/src/radv.c
|
||||
index 1032189..9b7e52c 100644
|
||||
--- a/src/radv.c
|
||||
+++ b/src/radv.c
|
||||
@@ -198,6 +198,9 @@ void icmp6_packet(time_t now)
|
||||
/* look for link-layer address option for logging */
|
||||
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
||||
{
|
||||
+ if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) {
|
||||
+ return;
|
||||
+ }
|
||||
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
|
||||
mac = daemon->namebuff;
|
||||
}
|
||||
--
|
||||
2.9.5
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 3d4ff1ba8419546490b464418223132529514033 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Mon, 25 Sep 2017 18:52:50 +0100
|
||||
Subject: [PATCH 4/9] Security fix, CVE-2017-14493, DHCPv6 - Stack buffer
|
||||
overflow.
|
||||
|
||||
Fix stack overflow in DHCPv6 code. An attacker who can send
|
||||
a DHCPv6 request to dnsmasq can overflow the stack frame and
|
||||
crash or control dnsmasq.
|
||||
---
|
||||
src/rfc3315.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c
|
||||
index 1687931..920907c 100644
|
||||
--- a/src/rfc3315.c
|
||||
+++ b/src/rfc3315.c
|
||||
@@ -206,6 +206,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
/* RFC-6939 */
|
||||
if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
|
||||
{
|
||||
+ if (opt6_len(opt) - 2 > DHCP_CHADDR_MAX) {
|
||||
+ return 0;
|
||||
+ }
|
||||
state->mac_type = opt6_uint(opt, 0, 2);
|
||||
state->mac_len = opt6_len(opt) - 2;
|
||||
memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
|
||||
--
|
||||
2.9.5
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 33e3f1029c9ec6c63e430ff51063a6301d4b2262 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Mon, 25 Sep 2017 20:05:11 +0100
|
||||
Subject: [PATCH 5/9] Security fix, CVE-2017-14494, Infoleak handling DHCPv6
|
||||
forwarded requests.
|
||||
|
||||
Fix information leak in DHCPv6. A crafted DHCPv6 packet can
|
||||
cause dnsmasq to forward memory from outside the packet
|
||||
buffer to a DHCPv6 server when acting as a relay.
|
||||
---
|
||||
src/rfc3315.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c
|
||||
index 920907c..4ca43e0 100644
|
||||
--- a/src/rfc3315.c
|
||||
+++ b/src/rfc3315.c
|
||||
@@ -216,6 +216,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
|
||||
for (opt = opts; opt; opt = opt6_next(opt, end))
|
||||
{
|
||||
+ if (opt6_ptr(opt, 0) + opt6_len(opt) >= end) {
|
||||
+ return 0;
|
||||
+ }
|
||||
int o = new_opt6(opt6_type(opt));
|
||||
if (opt6_type(opt) == OPTION6_RELAY_MSG)
|
||||
{
|
||||
--
|
||||
2.9.5
|
||||
|
@ -1,41 +0,0 @@
|
||||
From 51eadb692a5123b9838e5a68ecace3ac579a3a45 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Mon, 25 Sep 2017 20:16:50 +0100
|
||||
Subject: [PATCH 7/9] Security fix, CVE-2017-14495, OOM in DNS response
|
||||
creation.
|
||||
|
||||
Fix out-of-memory Dos vulnerability. An attacker which can
|
||||
send malicious DNS queries to dnsmasq can trigger memory
|
||||
allocations in the add_pseudoheader function
|
||||
The allocated memory is never freed which leads to a DoS
|
||||
through memory exhaustion. dnsmasq is vulnerable only
|
||||
if one of the following option is specified:
|
||||
--add-mac, --add-cpe-id or --add-subnet.
|
||||
---
|
||||
src/edns0.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/edns0.c b/src/edns0.c
|
||||
index 95b74ee..89b2692 100644
|
||||
--- a/src/edns0.c
|
||||
+++ b/src/edns0.c
|
||||
@@ -192,9 +192,15 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
!(p = skip_section(p,
|
||||
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
||||
header, plen)))
|
||||
+ {
|
||||
+ free(buff);
|
||||
return plen;
|
||||
+ }
|
||||
if (p + 11 > limit)
|
||||
- return plen; /* Too big */
|
||||
+ {
|
||||
+ free(buff);
|
||||
+ return plen; /* Too big */
|
||||
+ }
|
||||
*p++ = 0; /* empty name */
|
||||
PUTSHORT(T_OPT, p);
|
||||
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
|
||||
--
|
||||
2.9.5
|
||||
|
@ -1,66 +0,0 @@
|
||||
From 897c113fda0886a28a986cc6ba17bb93bd6cb1c7 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Mon, 25 Sep 2017 20:11:58 +0100
|
||||
Subject: [PATCH 6/9] Security fix, CVE-2017-14496, Integer underflow in DNS
|
||||
response creation.
|
||||
|
||||
Fix DoS in DNS. Invalid boundary checks in the
|
||||
add_pseudoheader function allows a memcpy call with negative
|
||||
size An attacker which can send malicious DNS queries
|
||||
to dnsmasq can trigger a DoS remotely.
|
||||
dnsmasq is vulnerable only if one of the following option is
|
||||
specified: --add-mac, --add-cpe-id or --add-subnet.
|
||||
---
|
||||
src/edns0.c | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/edns0.c b/src/edns0.c
|
||||
index f5b798c..95b74ee 100644
|
||||
--- a/src/edns0.c
|
||||
+++ b/src/edns0.c
|
||||
@@ -144,7 +144,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
GETSHORT(len, p);
|
||||
|
||||
/* malformed option, delete the whole OPT RR and start again. */
|
||||
- if (i + len > rdlen)
|
||||
+ if (i + 4 + len > rdlen)
|
||||
{
|
||||
rdlen = 0;
|
||||
is_last = 0;
|
||||
@@ -193,6 +193,8 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
||||
header, plen)))
|
||||
return plen;
|
||||
+ if (p + 11 > limit)
|
||||
+ return plen; /* Too big */
|
||||
*p++ = 0; /* empty name */
|
||||
PUTSHORT(T_OPT, p);
|
||||
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
|
||||
@@ -204,6 +206,11 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
/* Copy back any options */
|
||||
if (buff)
|
||||
{
|
||||
+ if (p + rdlen > limit)
|
||||
+ {
|
||||
+ free(buff);
|
||||
+ return plen; /* Too big */
|
||||
+ }
|
||||
memcpy(p, buff, rdlen);
|
||||
free(buff);
|
||||
p += rdlen;
|
||||
@@ -220,8 +227,12 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
/* Add new option */
|
||||
if (optno != 0 && replace != 2)
|
||||
{
|
||||
+ if (p + 4 > limit)
|
||||
+ return plen; /* Too big */
|
||||
PUTSHORT(optno, p);
|
||||
PUTSHORT(optlen, p);
|
||||
+ if (p + optlen > limit)
|
||||
+ return plen; /* Too big */
|
||||
memcpy(p, opt, optlen);
|
||||
p += optlen;
|
||||
PUTSHORT(p - datap, lenp);
|
||||
--
|
||||
2.9.5
|
||||
|
@ -1,44 +0,0 @@
|
||||
From a3303e196e5d304ec955c4d63afb923ade66c6e8 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Thu, 7 Sep 2017 20:45:00 +0100
|
||||
Subject: [PATCH] Don't return arcount=1 if EDNS0 RR won't fit in the packet.
|
||||
|
||||
Omitting the EDNS0 RR but setting arcount gives a malformed packet.
|
||||
Also, don't accept UDP packet size less than 512 in recieved EDNS0.
|
||||
---
|
||||
src/edns0.c | 5 ++++-
|
||||
src/forward.c | 2 ++
|
||||
2 files changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/edns0.c b/src/edns0.c
|
||||
index 3fde17f..f5b798c 100644
|
||||
--- a/src/edns0.c
|
||||
+++ b/src/edns0.c
|
||||
@@ -208,7 +208,10 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
free(buff);
|
||||
p += rdlen;
|
||||
}
|
||||
- header->arcount = htons(ntohs(header->arcount) + 1);
|
||||
+
|
||||
+ /* Only bump arcount if RR is going to fit */
|
||||
+ if (((ssize_t)optlen) <= (limit - (p + 4)))
|
||||
+ header->arcount = htons(ntohs(header->arcount) + 1);
|
||||
}
|
||||
|
||||
if (((ssize_t)optlen) > (limit - (p + 4)))
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index e3fa94b..942b02d 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -1412,6 +1412,8 @@ void receive_query(struct listener *listen, time_t now)
|
||||
defaults to 512 */
|
||||
if (udp_size > daemon->edns_pktsz)
|
||||
udp_size = daemon->edns_pktsz;
|
||||
+ else if (udp_size < PACKETSZ)
|
||||
+ udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
|
||||
}
|
||||
|
||||
#ifdef HAVE_AUTH
|
||||
--
|
||||
2.9.5
|
||||
|
@ -1,63 +0,0 @@
|
||||
From 6a0b00f0d66490e074323d04782e75c4ba8a3f8d Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Mon, 25 Sep 2017 20:19:55 +0100
|
||||
Subject: [PATCH 8/9] Misc code cleanups arising from Google analysis. No
|
||||
security impleications or CVEs.
|
||||
|
||||
---
|
||||
src/edns0.c | 2 +-
|
||||
src/rfc1035.c | 4 +++-
|
||||
src/rfc2131.c | 2 +-
|
||||
3 files changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/edns0.c b/src/edns0.c
|
||||
index 89b2692..7ed5a47 100644
|
||||
--- a/src/edns0.c
|
||||
+++ b/src/edns0.c
|
||||
@@ -159,7 +159,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
/* delete option if we're to replace it. */
|
||||
p -= 4;
|
||||
rdlen -= len + 4;
|
||||
- memcpy(p, p+len+4, rdlen - i);
|
||||
+ memmove(p, p+len+4, rdlen - i);
|
||||
PUTSHORT(rdlen, lenp);
|
||||
lenp -= 2;
|
||||
}
|
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c
|
||||
index 826f8a4..27af023 100644
|
||||
--- a/src/rfc1035.c
|
||||
+++ b/src/rfc1035.c
|
||||
@@ -37,7 +37,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||
/* end marker */
|
||||
{
|
||||
/* check that there are the correct no of bytes after the name */
|
||||
- if (!CHECK_LEN(header, p, plen, extrabytes))
|
||||
+ if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes))
|
||||
return 0;
|
||||
|
||||
if (isExtract)
|
||||
@@ -498,6 +498,8 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *
|
||||
{
|
||||
unsigned int i, len = *p1;
|
||||
unsigned char *p2 = p1;
|
||||
+ if ((p1 + len - p) >= rdlen)
|
||||
+ return 0; /* bad packet */
|
||||
/* make counted string zero-term and sanitise */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
diff --git a/src/rfc2131.c b/src/rfc2131.c
|
||||
index f7c1f80..f3a7e53 100644
|
||||
--- a/src/rfc2131.c
|
||||
+++ b/src/rfc2131.c
|
||||
@@ -157,7 +157,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
for (offset = 0; offset < (len - 5); offset += elen + 5)
|
||||
{
|
||||
elen = option_uint(opt, offset + 4 , 1);
|
||||
- if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
|
||||
+ if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len)
|
||||
{
|
||||
unsigned char *x = option_ptr(opt, offset + 5);
|
||||
unsigned char *y = option_ptr(opt, offset + elen + 5);
|
||||
--
|
||||
2.9.5
|
||||
|
@ -1,44 +0,0 @@
|
||||
From b476faf1c4f96c093ea1a8a0c824dea9f55b665f Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hesse <list@eworm.de>
|
||||
Date: Mon, 25 Sep 2017 17:36:24 +0100
|
||||
Subject: [PATCH] Do not include stdio.h before dnsmasq.h
|
||||
|
||||
We define some constants in dnsmasq.h, which have an influence on
|
||||
stdio.h. So do not include stdio.h before dnsmasq.h.
|
||||
---
|
||||
src/dnsmasq.h | 6 ++++++
|
||||
src/helper.c | 1 -
|
||||
2 files changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
||||
index 7a18898..421488b 100644
|
||||
--- a/src/dnsmasq.h
|
||||
+++ b/src/dnsmasq.h
|
||||
@@ -16,6 +16,12 @@
|
||||
|
||||
#define COPYRIGHT "Copyright (c) 2000-2016 Simon Kelley"
|
||||
|
||||
+/* We do defines that influence behavior of stdio.h, so complain
|
||||
+ if included too early. */
|
||||
+#ifdef _STDIO_H
|
||||
+# error "Header file stdio.h included too early!"
|
||||
+#endif
|
||||
+
|
||||
#ifndef NO_LARGEFILE
|
||||
/* Ensure we can use files >2GB (log files may grow this big) */
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
diff --git a/src/helper.c b/src/helper.c
|
||||
index 4fffa27..68ce9a7 100644
|
||||
--- a/src/helper.c
|
||||
+++ b/src/helper.c
|
||||
@@ -14,7 +14,6 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
-#include <stdio.h>
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_SCRIPT
|
||||
--
|
||||
2.9.5
|
||||
|
34
dnsmasq.spec
34
dnsmasq.spec
@ -12,8 +12,8 @@
|
||||
%define _hardened_build 1
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.77
|
||||
Release: 9%{?extraversion:.%{extraversion}}%{?dist}
|
||||
Version: 2.78
|
||||
Release: 1%{?extraversion:.%{extraversion}}%{?dist}
|
||||
Summary: A lightweight DHCP/caching DNS server
|
||||
|
||||
Group: System Environment/Daemons
|
||||
@ -22,18 +22,8 @@ URL: http://www.thekelleys.org.uk/dnsmasq/
|
||||
Source0: http://www.thekelleys.org.uk/dnsmasq/%{?extrapath}%{name}-%{version}%{?extraversion}.tar.xz
|
||||
Source1: %{name}.service
|
||||
|
||||
Patch1: dnsmasq-2.77-CVE-2017-13704.patch
|
||||
Patch2: dnsmasq-2.77-CVE-2017-14491.patch
|
||||
Patch3: dnsmasq-2.77-CVE-2017-14492.patch
|
||||
Patch4: dnsmasq-2.77-CVE-2017-14493.patch
|
||||
Patch5: dnsmasq-2.77-CVE-2017-14494.patch
|
||||
Patch6: dnsmasq-2.77-CVE-2017-14496.patch
|
||||
Patch7: dnsmasq-2.77-CVE-2017-14495.patch
|
||||
Patch8: dnsmasq-2.77-misc-cleanups.patch
|
||||
Patch9: dnsmasq-2.77-CVE-2017-14491-2.patch
|
||||
Patch10: dnsmasq-2.77-stdio.h.patch
|
||||
Patch11: dnsmasq-2.77-arcount.patch
|
||||
Patch12: dnsmasq-2.77-underflow.patch
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1495409
|
||||
Patch1: dnsmasq-2.77-underflow.patch
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
|
||||
@ -68,18 +58,7 @@ query/remove a DHCP server's leases.
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}%{?extraversion}
|
||||
%patch1 -p1 -b .CVE-2017-13704
|
||||
%patch2 -p1 -b .CVE-2017-14491
|
||||
%patch3 -p1 -b .CVE-2017-14492
|
||||
%patch4 -p1 -b .CVE-2017-14493
|
||||
%patch5 -p1 -b .CVE-2017-14494
|
||||
%patch6 -p1 -b .CVE-2017-14496
|
||||
%patch7 -p1 -b .CVE-2017-14495
|
||||
%patch8 -p1 -b .misc-cleanups
|
||||
%patch9 -p1 -b .CVE-2017-14491-2
|
||||
%patch10 -p1 -b .stdio.h
|
||||
%patch11 -p1 -b .arcount
|
||||
%patch12 -p1 -b .underflow
|
||||
%patch1 -p1 -b .underflow
|
||||
|
||||
# use /var/lib/dnsmasq instead of /var/lib/misc
|
||||
for file in dnsmasq.conf.example man/dnsmasq.8 man/es/dnsmasq.8 src/config.h; do
|
||||
@ -166,6 +145,9 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{_mandir}/man1/dhcp_*
|
||||
|
||||
%changelog
|
||||
* Tue Oct 03 2017 Petr Menšík <pemensik@redhat.com> - 2.78-1
|
||||
- Rebase to 2.78
|
||||
|
||||
* Tue Oct 03 2017 Petr Menšík <pemensik@redhat.com> - 2.77-9
|
||||
- More patches related to CVE-2017-14491
|
||||
|
||||
|
2
sources
2
sources
@ -1 +1 @@
|
||||
SHA512 (dnsmasq-2.77.tar.xz) = 6ca98a71a8fdfd606e29c58b34dadfa63148c39f931570cca67a287e044d52c6ec2f8acbf5620ada3312e9db3a2fd63877188d829c070beaa730607e3309e768
|
||||
SHA512 (dnsmasq-2.78.tar.xz) = 9b79b84e5a768d52f90f6335ccef2c404ecd7a13e78e49f4cd0755fffc6cf34d0dc96ad4c72cad1dab3c5743a8d0d789b3e9b6e625b03c5675bb898ca61a698b
|
||||
|
Loading…
Reference in New Issue
Block a user