aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/services/dnsmasq/patches/0105-Optimse-RR-digest-calculation-in-DNSSEC.patch
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2021-01-11 01:03:03 +0100
committerHauke Mehrtens <hauke@hauke-m.de>2021-01-19 14:10:02 +0100
commit8055e38794741313f8f4e6059f83c71dc0ab1d1c (patch)
tree8a7f2e7015db5f51e2fb49c6f92a8accdfa3b4cb /package/network/services/dnsmasq/patches/0105-Optimse-RR-digest-calculation-in-DNSSEC.patch
parent733e62a8e14e639cdc719256ae644e6b1474614b (diff)
downloadupstream-8055e38794741313f8f4e6059f83c71dc0ab1d1c.tar.gz
upstream-8055e38794741313f8f4e6059f83c71dc0ab1d1c.tar.bz2
upstream-8055e38794741313f8f4e6059f83c71dc0ab1d1c.zip
dnsmasq: Backport some security updates
This fixes the following security problems in dnsmasq: * CVE-2020-25681: Dnsmasq versions before 2.83 is susceptible to a heap-based buffer overflow in sort_rrset() when DNSSEC is used. This can allow a remote attacker to write arbitrary data into target device's memory that can lead to memory corruption and other unexpected behaviors on the target device. * CVE-2020-25682: Dnsmasq versions before 2.83 is susceptible to buffer overflow in extract_name() function due to missing length check, when DNSSEC is enabled. This can allow a remote attacker to cause memory corruption on the target device. * CVE-2020-25683: Dnsmasq version before 2.83 is susceptible to a heap-based buffer overflow when DNSSEC is enabled. A remote attacker, who can create valid DNS replies, could use this flaw to cause an overflow in a heap- allocated memory. This flaw is caused by the lack of length checks in rtc1035.c:extract_name(), which could be abused to make the code execute memcpy() with a negative size in get_rdata() and cause a crash in Dnsmasq, resulting in a Denial of Service. * CVE-2020-25684: A lack of proper address/port check implemented in Dnsmasq version < 2.83 reply_query function makes forging replies easier to an off-path attacker. * CVE-2020-25685: A lack of query resource name (RRNAME) checks implemented in Dnsmasq's versions before 2.83 reply_query function allows remote attackers to spoof DNS traffic that can lead to DNS cache poisoning. * CVE-2020-25686: Multiple DNS query requests for the same resource name (RRNAME) by Dnsmasq versions before 2.83 allows for remote attackers to spoof DNS traffic, using a birthday attack (RFC 5452), that can lead to DNS cache poisoning. * CVE-2020-25687: Dnsmasq versions before 2.83 is vulnerable to a heap-based buffer overflow with large memcpy in sort_rrset() when DNSSEC is enabled. A remote attacker, who can create valid DNS replies, could use this flaw to cause an overflow in a heap-allocated memory. This flaw is caused by the lack of length checks in rtc1035.c:extract_name(), which could be abused to make the code execute memcpy() with a negative size in sort_rrset() and cause a crash in dnsmasq, resulting in a Denial of Service. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Diffstat (limited to 'package/network/services/dnsmasq/patches/0105-Optimse-RR-digest-calculation-in-DNSSEC.patch')
-rw-r--r--package/network/services/dnsmasq/patches/0105-Optimse-RR-digest-calculation-in-DNSSEC.patch122
1 files changed, 122 insertions, 0 deletions
diff --git a/package/network/services/dnsmasq/patches/0105-Optimse-RR-digest-calculation-in-DNSSEC.patch b/package/network/services/dnsmasq/patches/0105-Optimse-RR-digest-calculation-in-DNSSEC.patch
new file mode 100644
index 0000000000..10f966237b
--- /dev/null
+++ b/package/network/services/dnsmasq/patches/0105-Optimse-RR-digest-calculation-in-DNSSEC.patch
@@ -0,0 +1,122 @@
+From 059aded0700309308dafd9720b0313ce52f6e189 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Thu, 12 Nov 2020 23:09:15 +0000
+Subject: Optimse RR digest calculation in DNSSEC.
+
+If an RR is of a type which doesn't need canonicalisation,
+bypass the relatively slow canonicalisation code, and insert
+it direct into the digest.
+---
+ src/dnssec.c | 82 +++++++++++++++++++++++++++++++---------------------
+ 1 file changed, 49 insertions(+), 33 deletions(-)
+
+--- a/src/dnssec.c
++++ b/src/dnssec.c
+@@ -559,7 +559,7 @@ static int validate_rrset(time_t now, st
+ hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
+ from_wire(keyname);
+
+-#define RRBUFLEN 300 /* Most RRs are smaller than this. */
++#define RRBUFLEN 128 /* Most RRs are smaller than this. */
+
+ for (i = 0; i < rrsetidx; ++i)
+ {
+@@ -597,50 +597,66 @@ static int validate_rrset(time_t now, st
+ hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name_start);
+ hash->update(ctx, 4, p); /* class and type */
+ hash->update(ctx, 4, (unsigned char *)&nsigttl);
+-
+- p += 8; /* skip class, type, ttl */
++
++ p += 8; /* skip type, class, ttl */
+ GETSHORT(rdlen, p);
+ if (!CHECK_LEN(header, p, plen, rdlen))
+ return STAT_BOGUS;
+-
+- /* canonicalise rdata and calculate length of same, use
+- name buffer as workspace for get_rdata. */
+- state.ip = p;
+- state.op = NULL;
+- state.desc = rr_desc;
+- state.buff = name;
+- state.end = p + rdlen;
+-
+- for (j = 0; get_rdata(header, plen, &state); j++)
+- if (j < RRBUFLEN)
+- rrbuf[j] = *state.op;
+
+- len = htons((u16)j);
+- hash->update(ctx, 2, (unsigned char *)&len);
+-
+- /* If the RR is shorter than RRBUFLEN (most of them, in practice)
+- then we can just digest it now. If it exceeds RRBUFLEN we have to
+- go back to the start and do it in chunks. */
+- if (j >= RRBUFLEN)
++ /* Optimisation for RR types which need no cannonicalisation.
++ This includes DNSKEY DS NSEC and NSEC3, which are also long, so
++ it saves lots of calls to get_rdata, and avoids the pessimal
++ segmented insertion, even with a small rrbuf[].
++
++ If canonicalisation is not needed, a simple insertion into the hash works.
++ */
++ if (*rr_desc == (u16)-1)
++ {
++ len = htons(rdlen);
++ hash->update(ctx, 2, (unsigned char *)&len);
++ hash->update(ctx, rdlen, p);
++ }
++ else
+ {
++ /* canonicalise rdata and calculate length of same, use
++ name buffer as workspace for get_rdata. */
+ state.ip = p;
+ state.op = NULL;
+ state.desc = rr_desc;
+-
++ state.buff = name;
++ state.end = p + rdlen;
++
+ for (j = 0; get_rdata(header, plen, &state); j++)
++ if (j < RRBUFLEN)
++ rrbuf[j] = *state.op;
++
++ len = htons((u16)j);
++ hash->update(ctx, 2, (unsigned char *)&len);
++
++ /* If the RR is shorter than RRBUFLEN (most of them, in practice)
++ then we can just digest it now. If it exceeds RRBUFLEN we have to
++ go back to the start and do it in chunks. */
++ if (j >= RRBUFLEN)
+ {
+- rrbuf[j] = *state.op;
+-
+- if (j == RRBUFLEN - 1)
+- {
+- hash->update(ctx, RRBUFLEN, rrbuf);
+- j = -1;
+- }
++ state.ip = p;
++ state.op = NULL;
++ state.desc = rr_desc;
++
++ for (j = 0; get_rdata(header, plen, &state); j++)
++ {
++ rrbuf[j] = *state.op;
++
++ if (j == RRBUFLEN - 1)
++ {
++ hash->update(ctx, RRBUFLEN, rrbuf);
++ j = -1;
++ }
++ }
+ }
++
++ if (j != 0)
++ hash->update(ctx, j, rrbuf);
+ }
+-
+- if (j != 0)
+- hash->update(ctx, j, rrbuf);
+ }
+
+ hash->digest(ctx, hash->digest_size, digest);