1
#! /bin/sh /usr/share/dpatch/dpatch-run
2
## 06_CVE-2012-1836.dpatch by Jonathan Wiltshire <jmw@debian.org>
4
## All lines beginning with `## DP:' are a description of the patch.
5
## DP: Protect against buffer overflow in src/dns.cpp
6
## DP: CVE-2012-1836 (#667914)
9
diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' inspircd-1.1.22+dfsg~/src/dns.cpp inspircd-1.1.22+dfsg/src/dns.cpp
10
--- inspircd-1.1.22+dfsg~/src/dns.cpp 2012-04-07 23:14:55.000000000 +0100
11
+++ inspircd-1.1.22+dfsg/src/dns.cpp 2012-04-07 23:16:01.292193775 +0100
13
using irc::sockets::OpenTCPSocket;
14
using irc::sockets::NonBlocking;
16
+#define DN_COMP_BITMASK 0xC000 /* highest 6 bits in a DN label header */
18
/** Masks to mask off the responses we get from the DNSRequest methods
23
DNSRequest(InspIRCd* Instance, DNS* dns, int id, const std::string &original);
25
- DNSInfo ResultIsReady(DNSHeader &h, int length);
26
+ DNSInfo ResultIsReady(DNSHeader &h, unsigned length);
27
int SendRequests(const DNSHeader *header, const int length, QueryType qt);
31
/* Allocate the processing buffer */
32
DNSRequest::DNSRequest(InspIRCd* Instance, DNS* dns, int id, const std::string &original) : dnsobj(dns)
34
- res = new unsigned char[512];
35
+ /* hardening against overflow here: make our work buffer twice the theoretical
36
+ * maximum size so that hostile input doesn't screw us over.
38
+ res = new unsigned char[sizeof(DNSHeader) * 2];
41
RequestTimeout* RT = new RequestTimeout(Instance->Config->dns_timeout ? Instance->Config->dns_timeout : 5, Instance, this, id);
45
/** A result is ready, process it */
46
-DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length)
47
+DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, unsigned length)
62
+ * CNAME and PTR are compressed. We need to decompress them.
65
- /* CNAME and PTR have the same processing code */
69
while (q == 0 && i < length && o + 256 < 1023)
71
+ /* DN label found (byte over 63) */
72
if (header.payload[i] > 63)
74
memcpy(&ptr,&header.payload[i],2);
75
- i = ntohs(ptr) - 0xC000 - 12;
79
+ /* check that highest two bits are set. if not, we've been had */
80
+ if (!(i & DN_COMP_BITMASK))
81
+ return std::make_pair((unsigned char *) NULL, "DN label decompression header is bogus");
83
+ /* mask away the two highest bits. */
84
+ i &= ~DN_COMP_BITMASK;
86
+ /* and decrease length by 12 bytes. */
95
- memcpy(&res[o],&header.payload[i + 1],header.payload[i]);
97
+ if (o + header.payload[i] > sizeof(DNSHeader))
98
+ return std::make_pair((unsigned char *) NULL, "DN label decompression is impossible -- malformed/hostile packet?");
100
+ memcpy(&res[o], &header.payload[i + 1], header.payload[i]);
101
o += header.payload[i];
102
i += header.payload[i] + 1;
104
@@ -907,16 +930,21 @@
108
+ if (rr.rdlength != sizeof(struct in6_addr))
109
+ return std::make_pair((unsigned char *) NULL, "rr.rdlength is larger than 16 bytes for an ipv6 entry -- malformed/hostile packet?");
111
memcpy(res,&header.payload[i],rr.rdlength);
112
res[rr.rdlength] = 0;
115
+ if (rr.rdlength != sizeof(struct in_addr))
116
+ return std::make_pair((unsigned char *) NULL, "rr.rdlength is larger than 4 bytes for an ipv4 entry -- malformed/hostile packet?");
118
memcpy(res,&header.payload[i],rr.rdlength);
119
res[rr.rdlength] = 0;
122
- memcpy(res,&header.payload[i],rr.rdlength);
123
- res[rr.rdlength] = 0;
124
+ return std::make_pair((unsigned char *) NULL, "don't know how to handle undefined type (" + ConvToStr(rr.type) + ") -- rejecting");
127
return std::make_pair(res,"No error");;