All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joshua G Lock <joshua.g.lock@linux.intel.com>
To: mariano.lopez@linux.intel.com, openembedded-core@lists.openembedded.org
Subject: Re: [PATCH v2][fido] dhcp: CVE-2015-8605
Date: Mon, 14 Mar 2016 14:34:32 +0000	[thread overview]
Message-ID: <1457966072.3209.5.camel@linux.intel.com> (raw)
In-Reply-To: <1457686029-40654-1-git-send-email-mariano.lopez@linux.intel.com>

On Fri, 2016-03-11 at 08:47 +0000, mariano.lopez@linux.intel.com wrote:
> From: Mariano Lopez <mariano.lopez@linux.intel.com>
> 
> ISC DHCP allows remote attackers to cause a denial of
> service (application crash) via an invalid length field
> in a UDP IPv4 packet.

Thanks Mariano,

I've queued this in my fido-next branch.

Regards,

Joshua

> 
> Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
> ---
>  .../dhcp/dhcp/CVE-2015-8605.patch                  | 101
> ++++++++++++++++
>  .../dhcp/dhcp/CVE-2015-8605_1.patch                | 131
> +++++++++++++++++++++
>  meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb       |   2 +
>  3 files changed, 234 insertions(+)
>  create mode 100644 meta/recipes-connectivity/dhcp/dhcp/CVE-2015-
> 8605.patch
>  create mode 100644 meta/recipes-connectivity/dhcp/dhcp/CVE-2015-
> 8605_1.patch
> 
> diff --git a/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605.patch
> b/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605.patch
> new file mode 100644
> index 0000000..05f1fa9
> --- /dev/null
> +++ b/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605.patch
> @@ -0,0 +1,101 @@
> +Solves CVE-2015-8605 that caused DoS when an invalid length field in
> IPv4 UDP
> +was received by the server.
> +
> +Upstream-Status: Backport (v4.3.3p1)
> +CVE: CVE-2015-8605
> +
> +From: https://source.isc.org/cgi-bin/gitweb.cgi?p=dhcp.git;a=commit;
> h=4ce21cb6301d665de01c1a6209e40f5f35072c0c
> +
> +Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
> +
> +====================================================================
> ===
> +diff --git a/common/packet.c b/common/packet.c
> +index b530432..e600e37 100644
> +--- a/common/packet.c
> ++++ b/common/packet.c
> +@@ -220,7 +220,28 @@ ssize_t decode_hw_header (interface, buf,
> bufix, from)
> + 	}
> + }
> + 
> +-/* UDP header and IP header decoded together for convenience. */
> ++/*!
> ++ *
> ++ * \brief UDP header and IP header decoded together for
> convenience.
> ++ *
> ++ * Attempt to decode the UDP and IP headers and, if necessary,
> checksum
> ++ * the packet.
> ++ *
> ++ * \param inteface - the interface on which the packet was recevied
> ++ * \param buf - a pointer to the buffer for the received packet
> ++ * \param bufix - where to start processing the buffer, previous
> ++ *                routines may have processed parts of the buffer
> already
> ++ * \param from - space to return the address of the packet sender
> ++ * \param buflen - remaining length of the buffer, this will have
> been
> ++ *                 decremented by bufix by the caller
> ++ * \param rbuflen - space to return the length of the payload from
> the udp
> ++ *                  header
> ++ * \param csum_ready - indication if the checksum is valid for use
> ++ *                     non-zero indicates the checksum should be
> validated
> ++ *
> ++ * \return - the index to the first byte of the udp payload (that
> is the
> ++ *           start of the DHCP packet
> ++ */
> + 
> + ssize_t
> + decode_udp_ip_header(struct interface_info *interface,
> +@@ -231,7 +252,7 @@ decode_udp_ip_header(struct interface_info
> *interface,
> +   unsigned char *data;
> +   struct ip ip;
> +   struct udphdr udp;
> +-  unsigned char *upp, *endbuf;
> ++  unsigned char *upp;
> +   u_int32_t ip_len, ulen, pkt_len;
> +   static unsigned int ip_packets_seen = 0;
> +   static unsigned int ip_packets_bad_checksum = 0;
> +@@ -241,11 +262,8 @@ decode_udp_ip_header(struct interface_info
> *interface,
> +   static unsigned int udp_packets_length_overflow = 0;
> +   unsigned len;
> + 
> +-  /* Designate the end of the input buffer for bounds checks. */
> +-  endbuf = buf + bufix + buflen;
> +-
> +   /* Assure there is at least an IP header there. */
> +-  if ((buf + bufix + sizeof(ip)) > endbuf)
> ++  if (sizeof(ip) > buflen)
> + 	  return -1;
> + 
> +   /* Copy the IP header into a stack aligned structure for
> inspection.
> +@@ -257,13 +275,17 @@ decode_udp_ip_header(struct interface_info
> *interface,
> +   ip_len = (*upp & 0x0f) << 2;
> +   upp += ip_len;
> + 
> +-  /* Check the IP packet length. */
> ++  /* Check packet lengths are within the buffer:
> ++   * first the ip header (ip_len)
> ++   * then the packet length from the ip header (pkt_len)
> ++   * then the udp header (ip_len + sizeof(udp)
> ++   * We are liberal in what we accept, the udp payload should fit
> within
> ++   * pkt_len, but we only check against the full buffer size.
> ++   */
> +   pkt_len = ntohs(ip.ip_len);
> +-  if (pkt_len > buflen)
> +-	return -1;
> +-
> +-  /* Assure after ip_len bytes that there is enough room for a UDP
> header. */
> +-  if ((upp + sizeof(udp)) > endbuf)
> ++  if ((ip_len > buflen) ||
> ++      (pkt_len > buflen) ||
> ++      ((ip_len + sizeof(udp)) > buflen))
> + 	  return -1;
> + 
> +   /* Copy the UDP header into a stack aligned structure for
> inspection. */
> +@@ -284,7 +306,8 @@ decode_udp_ip_header(struct interface_info
> *interface,
> + 	return -1;
> + 
> +   udp_packets_length_checked++;
> +-  if ((upp + ulen) > endbuf) {
> ++  /* verify that the payload length from the udp packet fits in the
> buffer */
> ++  if ((ip_len + ulen) > buflen) {
> + 	udp_packets_length_overflow++;
> + 	if (((udp_packets_length_checked > 4) &&
> + 	     (udp_packets_length_overflow != 0)) &&
> diff --git a/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-
> 8605_1.patch b/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-
> 8605_1.patch
> new file mode 100644
> index 0000000..aa93c5e
> --- /dev/null
> +++ b/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605_1.patch
> @@ -0,0 +1,131 @@
> +This patch is needed in order to apply the patch for CVE-2015-8605.
> +
> +Upstream-Status: Backport (4.3.2+)
> +
> +From: https://source.isc.org/cgi-bin/gitweb.cgi?p=dhcp.git;a=commit;
> h=0ce1aa94454ce9b50d592c08d7e0c559d38d3bc5
> +
> +Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
> +---
> +From 0ce1aa94454ce9b50d592c08d7e0c559d38d3bc5 Mon Sep 17 00:00:00
> 2001
> +From: Thomas Markwalder <tmark@isc.org>
> +Date: Mon, 8 Sep 2014 09:31:32 -0400
> +Subject: [PATCH] [master] Corrected error in UDP bad packet logging
> +
> +    Merges in rt36897
> +---
> + common/packet.c | 55 +++++++++++++++++++++++++++++++++++-----------
> ---------
> + 1 file changed, 35 insertions(+), 20 deletions(-)
> +
> +diff --git a/common/packet.c b/common/packet.c
> +index 45e96e8..7460f3d 100644
> +--- a/common/packet.c
> ++++ b/common/packet.c
> +@@ -3,7 +3,7 @@
> +    Packet assembly code, originally contributed by Archie Cobbs. */
> + 
> + /*
> +- * Copyright (c) 2009,2012 by Internet Systems Consortium, Inc.
> ("ISC")
> ++ * Copyright (c) 2009,2012,2014 by Internet Systems Consortium,
> Inc. ("ISC")
> +  * Copyright (c) 2004,2005,2007 by Internet Systems Consortium,
> Inc. ("ISC")
> +  * Copyright (c) 1996-2003 by Internet Software Consortium
> +  *
> +@@ -234,12 +234,12 @@ decode_udp_ip_header(struct interface_info
> *interface,
> +   unsigned char *upp, *endbuf;
> +   u_int32_t ip_len, ulen, pkt_len;
> +   u_int32_t sum, usum;
> +-  static int ip_packets_seen;
> +-  static int ip_packets_bad_checksum;
> +-  static int udp_packets_seen;
> +-  static int udp_packets_bad_checksum;
> +-  static int udp_packets_length_checked;
> +-  static int udp_packets_length_overflow;
> ++  static unsigned int ip_packets_seen = 0;
> ++  static unsigned int ip_packets_bad_checksum = 0;
> ++  static unsigned int udp_packets_seen = 0;
> ++  static unsigned int udp_packets_bad_checksum = 0;
> ++  static unsigned int udp_packets_length_checked = 0;
> ++  static unsigned int udp_packets_length_overflow = 0;
> +   unsigned len;
> + 
> +   /* Designate the end of the input buffer for bounds checks. */
> +@@ -287,10 +287,10 @@ decode_udp_ip_header(struct interface_info
> *interface,
> +   udp_packets_length_checked++;
> +   if ((upp + ulen) > endbuf) {
> + 	udp_packets_length_overflow++;
> +-	if ((udp_packets_length_checked > 4) &&
> +-	    ((udp_packets_length_checked /
> +-	      udp_packets_length_overflow) < 2)) {
> +-		log_info("%d udp packets in %d too long - dropped",
> ++	if (((udp_packets_length_checked > 4) &&
> ++	     (udp_packets_length_overflow != 0)) &&
> ++	    ((udp_packets_length_checked /
> udp_packets_length_overflow) < 2)) {
> ++		log_info("%u udp packets in %u too long - dropped",
> + 			 udp_packets_length_overflow,
> + 			 udp_packets_length_checked);
> + 		udp_packets_length_overflow = 0;
> +@@ -299,22 +299,31 @@ decode_udp_ip_header(struct interface_info
> *interface,
> + 	return -1;
> +   }
> + 
> +-  if ((ulen < sizeof(udp)) || ((upp + ulen) > endbuf))
> +-	return -1;
> ++  /* If at least 5 with less than 50% bad, start over */
> ++  if (udp_packets_length_checked > 4) {
> ++	udp_packets_length_overflow = 0;
> ++	udp_packets_length_checked = 0;
> ++  }
> + 
> +   /* Check the IP header checksum - it should be zero. */
> +-  ++ip_packets_seen;
> ++  ip_packets_seen++;
> +   if (wrapsum (checksum (buf + bufix, ip_len, 0))) {
> + 	  ++ip_packets_bad_checksum;
> +-	  if (ip_packets_seen > 4 &&
> +-	      (ip_packets_seen / ip_packets_bad_checksum) < 2) {
> +-		  log_info ("%d bad IP checksums seen in %d
> packets",
> ++	  if (((ip_packets_seen > 4) && (ip_packets_bad_checksum !=
> 0)) &&
> ++	      ((ip_packets_seen / ip_packets_bad_checksum) < 2)) {
> ++		  log_info ("%u bad IP checksums seen in %u
> packets",
> + 			    ip_packets_bad_checksum,
> ip_packets_seen);
> + 		  ip_packets_seen = ip_packets_bad_checksum = 0;
> + 	  }
> + 	  return -1;
> +   }
> + 
> ++  /* If at least 5 with less than 50% bad, start over */
> ++  if (ip_packets_seen > 4) {
> ++	ip_packets_bad_checksum = 0;
> ++	ip_packets_seen = 0;
> ++  }
> ++
> +   /* Copy out the IP source address... */
> +   memcpy(&from->sin_addr, &ip.ip_src, 4);
> + 
> +@@ -339,15 +348,21 @@ decode_udp_ip_header(struct interface_info
> *interface,
> +   udp_packets_seen++;
> +   if (usum && usum != sum) {
> + 	  udp_packets_bad_checksum++;
> +-	  if (udp_packets_seen > 4 &&
> +-	      (udp_packets_seen / udp_packets_bad_checksum) < 2) {
> +-		  log_info ("%d bad udp checksums in %d packets",
> ++	  if (((udp_packets_seen > 4) && (udp_packets_bad_checksum
> != 0)) &&
> ++	      ((udp_packets_seen / udp_packets_bad_checksum) < 2))
> {
> ++		  log_info ("%u bad udp checksums in %u packets",
> + 			    udp_packets_bad_checksum,
> udp_packets_seen);
> + 		  udp_packets_seen = udp_packets_bad_checksum = 0;
> + 	  }
> + 	  return -1;
> +   }
> + 
> ++  /* If at least 5 with less than 50% bad, start over */
> ++  if (udp_packets_seen > 4) {
> ++	udp_packets_bad_checksum = 0;
> ++	udp_packets_seen = 0;
> ++  }
> ++
> +   /* Copy out the port... */
> +   memcpy (&from -> sin_port, &udp.uh_sport, sizeof udp.uh_sport);
> + 
> +-- 
> +2.6.2
> +
> diff --git a/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb
> b/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb
> index d4414cc..4616693 100644
> --- a/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb
> +++ b/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb
> @@ -6,7 +6,9 @@ SRC_URI += "file://dhcp-3.0.3-dhclient-dbus.patch;str
> iplevel=0 \
>              file://fixsepbuild.patch \
>              file://dhclient-script-drop-resolv.conf.dhclient.patch \
>              file://replace-ifconfig-route.patch \
> +            file://CVE-2015-8605_1.patch \
>              file://dhcp-xen-checksum.patch \
> +            file://CVE-2015-8605.patch \
>             "
>  
>  SRC_URI[md5sum] = "b3a42ece3c7f2cd2e74a3e12ca881d20"


      reply	other threads:[~2016-03-14 14:34 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-11  8:47 [PATCH v2][fido] dhcp: CVE-2015-8605 mariano.lopez
2016-03-14 14:34 ` Joshua G Lock [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1457966072.3209.5.camel@linux.intel.com \
    --to=joshua.g.lock@linux.intel.com \
    --cc=mariano.lopez@linux.intel.com \
    --cc=openembedded-core@lists.openembedded.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.