[oe] [meta-networking][morty][PATCH] c-ares: fix CVE-2016-5180

André Draszik git at andred.net
Thu Oct 20 22:33:21 UTC 2016


Backport patch to fix CVE-2016-5180 from c-ares upstream:
  https://c-ares.haxx.se/adv_20160929.html

Signed-off-by: André Draszik <git at andred.net>
---
 .../c-ares/c-ares/CVE-2016-5180.patch              | 166 +++++++++++++++++++++
 .../recipes-support/c-ares/c-ares_1.11.0.bb        |   1 +
 2 files changed, 167 insertions(+)
 create mode 100644 meta-networking/recipes-support/c-ares/c-ares/CVE-2016-5180.patch

diff --git a/meta-networking/recipes-support/c-ares/c-ares/CVE-2016-5180.patch b/meta-networking/recipes-support/c-ares/c-ares/CVE-2016-5180.patch
new file mode 100644
index 0000000..0b4fbb4
--- /dev/null
+++ b/meta-networking/recipes-support/c-ares/c-ares/CVE-2016-5180.patch
@@ -0,0 +1,166 @@
+From 115fe381c75147352d7a8d21aa3ffb85ca367219 Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel at haxx.se>
+Date: Fri, 23 Sep 2016 14:44:11 +0200
+Subject: [PATCH] ares_create_query: avoid single-byte buffer overwrite
+
+... when the name ends with an escaped dot.
+
+CVE-2016-5180
+
+Bug: https://c-ares.haxx.se/adv_20160929.html
+---
+Upstream-Status: Backport [https://c-ares.haxx.se/adv_20160929.html]
+CVE: CVE-2016-5180
+Signed-off-by: André Draszik <git at andred.net>
+ ares_create_query.c | 84 +++++++++++++++++++++++++----------------------------
+ 1 file changed, 39 insertions(+), 45 deletions(-)
+
+diff --git a/ares_create_query.c b/ares_create_query.c
+index a34dda7..7f4c52d 100644
+--- a/ares_create_query.c
++++ b/ares_create_query.c
+@@ -83,61 +83,35 @@
+  * label.  The list is terminated by a label of length zero (which can
+  * be thought of as the root domain).
+  */
+ 
+ int ares_create_query(const char *name, int dnsclass, int type,
+-                      unsigned short id, int rd, unsigned char **buf,
+-                      int *buflen, int max_udp_size)
++                      unsigned short id, int rd, unsigned char **bufp,
++                      int *buflenp, int max_udp_size)
+ {
+-  int len;
++  size_t len;
+   unsigned char *q;
+   const char *p;
++  size_t buflen;
++  unsigned char *buf;
+ 
+   /* Set our results early, in case we bail out early with an error. */
+-  *buflen = 0;
+-  *buf = NULL;
++  *buflenp = 0;
++  *bufp = NULL;
+ 
+-  /* Compute the length of the encoded name so we can check buflen.
+-   * Start counting at 1 for the zero-length label at the end. */
+-  len = 1;
+-  for (p = name; *p; p++)
+-    {
+-      if (*p == '\\' && *(p + 1) != 0)
+-        p++;
+-      len++;
+-    }
+-  /* If there are n periods in the name, there are n + 1 labels, and
+-   * thus n + 1 length fields, unless the name is empty or ends with a
+-   * period.  So add 1 unless name is empty or ends with a period.
++  /* Allocate a memory area for the maximum size this packet might need. +2
++   * is for the length byte and zero termination if no dots or ecscaping is
++   * used.
+    */
+-  if (*name && *(p - 1) != '.')
+-    len++;
+-
+-  /* Immediately reject names that are longer than the maximum of 255
+-   * bytes that's specified in RFC 1035 ("To simplify implementations,
+-   * the total length of a domain name (i.e., label octets and label
+-   * length octets) is restricted to 255 octets or less."). We aren't
+-   * doing this just to be a stickler about RFCs. For names that are
+-   * too long, 'dnscache' closes its TCP connection to us immediately
+-   * (when using TCP) and ignores the request when using UDP, and
+-   * BIND's named returns ServFail (TCP or UDP). Sending a request
+-   * that we know will cause 'dnscache' to close the TCP connection is
+-   * painful, since that makes any other outstanding requests on that
+-   * connection fail. And sending a UDP request that we know
+-   * 'dnscache' will ignore is bad because resources will be tied up
+-   * until we time-out the request.
+-   */
+-  if (len > MAXCDNAME)
+-    return ARES_EBADNAME;
+-
+-  *buflen = len + HFIXEDSZ + QFIXEDSZ + (max_udp_size ? EDNSFIXEDSZ : 0);
+-  *buf = ares_malloc(*buflen);
+-  if (!*buf)
+-      return ARES_ENOMEM;
++  len = strlen(name) + 2 + HFIXEDSZ + QFIXEDSZ +
++    (max_udp_size ? EDNSFIXEDSZ : 0);
++  buf = ares_malloc(len);
++  if (!buf)
++    return ARES_ENOMEM;
+ 
+   /* Set up the header. */
+-  q = *buf;
++  q = buf;
+   memset(q, 0, HFIXEDSZ);
+   DNS_HEADER_SET_QID(q, id);
+   DNS_HEADER_SET_OPCODE(q, QUERY);
+   if (rd) {
+     DNS_HEADER_SET_RD(q, 1);
+@@ -157,23 +131,27 @@ int ares_create_query(const char *name, int dnsclass, int type,
+ 
+   /* Start writing out the name after the header. */
+   q += HFIXEDSZ;
+   while (*name)
+     {
+-      if (*name == '.')
++      if (*name == '.') {
++        free (buf);
+         return ARES_EBADNAME;
++      }
+ 
+       /* Count the number of bytes in this label. */
+       len = 0;
+       for (p = name; *p && *p != '.'; p++)
+         {
+           if (*p == '\\' && *(p + 1) != 0)
+             p++;
+           len++;
+         }
+-      if (len > MAXLABEL)
++      if (len > MAXLABEL) {
++        free (buf);
+         return ARES_EBADNAME;
++      }
+ 
+       /* Encode the length and copy the data. */
+       *q++ = (unsigned char)len;
+       for (p = name; *p && *p != '.'; p++)
+         {
+@@ -193,16 +171,32 @@ int ares_create_query(const char *name, int dnsclass, int type,
+ 
+   /* Finish off the question with the type and class. */
+   DNS_QUESTION_SET_TYPE(q, type);
+   DNS_QUESTION_SET_CLASS(q, dnsclass);
+ 
++  q += QFIXEDSZ;
+   if (max_udp_size)
+   {
+-      q += QFIXEDSZ;
+       memset(q, 0, EDNSFIXEDSZ);
+       q++;
+       DNS_RR_SET_TYPE(q, T_OPT);
+       DNS_RR_SET_CLASS(q, max_udp_size);
++      q += (EDNSFIXEDSZ-1);
++  }
++  buflen = (q - buf);
++
++  /* Reject names that are longer than the maximum of 255 bytes that's
++   * specified in RFC 1035 ("To simplify implementations, the total length of
++   * a domain name (i.e., label octets and label length octets) is restricted
++   * to 255 octets or less."). */
++  if (buflen > (MAXCDNAME + HFIXEDSZ + QFIXEDSZ +
++                (max_udp_size ? EDNSFIXEDSZ : 0))) {
++    free (buf);
++    return ARES_EBADNAME;
+   }
+ 
++  /* we know this fits in an int at this point */
++  *buflenp = (int) buflen;
++  *bufp = buf;
++
+   return ARES_SUCCESS;
+ }
+-- 
+2.9.3
+
diff --git a/meta-networking/recipes-support/c-ares/c-ares_1.11.0.bb b/meta-networking/recipes-support/c-ares/c-ares_1.11.0.bb
index c98be7d..bea2332 100644
--- a/meta-networking/recipes-support/c-ares/c-ares_1.11.0.bb
+++ b/meta-networking/recipes-support/c-ares/c-ares_1.11.0.bb
@@ -7,6 +7,7 @@ LICENSE = "MIT"
 LIC_FILES_CHKSUM = "file://ares_init.c;beginline=1;endline=3;md5=53f5ecf4c22c37cf1ddd1ef8f8eccce0"
 
 SRC_URI = "http://c-ares.haxx.se/download/${BP}.tar.gz \
+           file://CVE-2016-5180.patch \
            file://0001-configure.ac-don-t-override-passed-cflags.patch \
 "
 SRC_URI[md5sum] = "d5c6d522cfc54bb6f215a0b7912d46be"
-- 
2.9.3




More information about the Openembedded-devel mailing list