~ubuntu-branches/ubuntu/precise/inspircd/precise

« back to all changes in this revision

Viewing changes to debian/patches/06_CVE-2012-1836.dpatch

  • Committer: Package Import Robot
  • Author(s): Julian Taylor
  • Date: 2012-04-15 20:33:41 UTC
  • Revision ID: package-import@ubuntu.com-20120415203341-eybvxe39axpnj02k
Tags: 1.1.22+dfsg-4ubuntu2
* SECURITY UPDATE: remote code execution (LP: #982509)
 - debian/patches/06_CVE-2012-1836.dpatch:
   Fix buffer overflow in dns.cpp, thanks to Jonathan Wiltshire
 - CVE-2012-1836

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /bin/sh /usr/share/dpatch/dpatch-run
 
2
## 06_CVE-2012-1836.dpatch by Jonathan Wiltshire <jmw@debian.org>
 
3
##
 
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)
 
7
 
 
8
@DPATCH@
 
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
 
12
@@ -45,6 +45,8 @@
 
13
 using irc::sockets::OpenTCPSocket;
 
14
 using irc::sockets::NonBlocking;
 
15
 
 
16
+#define DN_COMP_BITMASK        0xC000          /* highest 6 bits in a DN label header */
 
17
+
 
18
 /** Masks to mask off the responses we get from the DNSRequest methods
 
19
  */
 
20
 enum QueryInfo
 
21
@@ -105,7 +107,7 @@
 
22
 
 
23
        DNSRequest(InspIRCd* Instance, DNS* dns, int id, const std::string &original);
 
24
        ~DNSRequest();
 
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);
 
28
 };
 
29
 
 
30
@@ -155,7 +157,10 @@
 
31
 /* Allocate the processing buffer */
 
32
 DNSRequest::DNSRequest(InspIRCd* Instance, DNS* dns, int id, const std::string &original) : dnsobj(dns)
 
33
 {
 
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.
 
37
+        */
 
38
+       res = new unsigned char[sizeof(DNSHeader) * 2];
 
39
        *res = 0;
 
40
        orig = original;
 
41
        RequestTimeout* RT = new RequestTimeout(Instance->Config->dns_timeout ? Instance->Config->dns_timeout : 5, Instance, this, id);
 
42
@@ -776,11 +781,11 @@
 
43
 }
 
44
 
 
45
 /** A result is ready, process it */
 
46
-DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length)
 
47
+DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, unsigned length)
 
48
 {
 
49
-       int i = 0;
 
50
+       unsigned i = 0, o;
 
51
        int q = 0;
 
52
-       int curanswer, o;
 
53
+       int curanswer;
 
54
        ResourceRecord rr;
 
55
        unsigned short ptr;
 
56
 
 
57
@@ -875,17 +880,31 @@
 
58
 
 
59
        switch (rr.type)
 
60
        {
 
61
+               /*
 
62
+                * CNAME and PTR are compressed.  We need to decompress them.
 
63
+                */
 
64
                case DNS_QUERY_CNAME:
 
65
-                       /* CNAME and PTR have the same processing code */
 
66
                case DNS_QUERY_PTR:
 
67
                        o = 0;
 
68
                        q = 0;
 
69
                        while (q == 0 && i < length && o + 256 < 1023)
 
70
                        {
 
71
+                               /* DN label found (byte over 63) */
 
72
                                if (header.payload[i] > 63)
 
73
                                {
 
74
                                        memcpy(&ptr,&header.payload[i],2);
 
75
-                                       i = ntohs(ptr) - 0xC000 - 12;
 
76
+
 
77
+                                       i = ntohs(ptr);
 
78
+
 
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");
 
82
+
 
83
+                                       /* mask away the two highest bits. */
 
84
+                                       i &= ~DN_COMP_BITMASK;
 
85
+
 
86
+                                       /* and decrease length by 12 bytes. */
 
87
+                                       i =- 12;
 
88
                                }
 
89
                                else
 
90
                                {
 
91
@@ -898,7 +917,11 @@
 
92
                                                res[o] = 0;
 
93
                                                if (o != 0)
 
94
                                                        res[o++] = '.';
 
95
-                                               memcpy(&res[o],&header.payload[i + 1],header.payload[i]);
 
96
+
 
97
+                                               if (o + header.payload[i] > sizeof(DNSHeader))
 
98
+                                                       return std::make_pair((unsigned char *) NULL, "DN label decompression is impossible -- malformed/hostile packet?");
 
99
+
 
100
+                                               memcpy(&res[o], &header.payload[i + 1], header.payload[i]);
 
101
                                                o += header.payload[i];
 
102
                                                i += header.payload[i] + 1;
 
103
                                        }
 
104
@@ -907,16 +930,21 @@
 
105
                        res[o] = 0;
 
106
                break;
 
107
                case DNS_QUERY_AAAA:
 
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?");
 
110
+
 
111
                        memcpy(res,&header.payload[i],rr.rdlength);
 
112
                        res[rr.rdlength] = 0;
 
113
                break;
 
114
                case DNS_QUERY_A:
 
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?");
 
117
+
 
118
                        memcpy(res,&header.payload[i],rr.rdlength);
 
119
                        res[rr.rdlength] = 0;
 
120
                break;
 
121
                default:
 
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");
 
125
                break;
 
126
        }
 
127
        return std::make_pair(res,"No error");;