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

akuster808 akuster808 at gmail.com
Thu Oct 20 23:38:53 UTC 2016


On 10/20/16 3:33 PM, André Draszik wrote:
> Backport patch to fix CVE-2016-5180 from c-ares upstream:
>   https://c-ares.haxx.se/adv_20160929.html

awesome. Once this hits master I will pull it over.

 Thanks,
Armin
>
> 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"





More information about the Openembedded-devel mailing list