From c26cda4003d766a5debf8bb3e228d9a73a0d5eaa Mon Sep 17 00:00:00 2001 From: Michal Sekletar Date: Oct 24 2016 15:20:54 +0000 Subject: Fix for CVE-2016-2342 Resolves: #1316572 --- diff --git a/0002-bgpd-Fix-VU-270232-VPNv4-NLRI-parser-memcpys-to-stac.patch b/0002-bgpd-Fix-VU-270232-VPNv4-NLRI-parser-memcpys-to-stac.patch new file mode 100644 index 0000000..415f773 --- /dev/null +++ b/0002-bgpd-Fix-VU-270232-VPNv4-NLRI-parser-memcpys-to-stac.patch @@ -0,0 +1,144 @@ +From 7819e36e64189f2073eff16dd9359b8192605a7b Mon Sep 17 00:00:00 2001 +From: Donald Sharp +Date: Wed, 27 Jan 2016 16:54:45 +0000 +Subject: [PATCH] bgpd: Fix VU#270232, VPNv4 NLRI parser memcpys to stack on + unchecked length + +Address CERT vulnerability report VU#270232, memcpy to stack data structure +based on length field from packet data whose length field upper-bound was +not properly checked. + +This likely allows BGP peers that are enabled to send Labeled-VPN SAFI +routes to Quagga bgpd to remotely exploit Quagga bgpd. + +Mitigation: Do not enable Labeled-VPN SAFI with untrusted neighbours. + +Impact: Labeled-VPN SAFI is not enabled by default. + +* bgp_mplsvpn.c: (bgp_nlri_parse_vpnv4) The prefixlen is checked for + lower-bound, but not for upper-bound against received data length. + The packet data is then memcpy'd to the stack based on the prefixlen. + + Extend the prefixlen check to ensure it is within the bound of the NLRI + packet data AND the on-stack prefix structure AND the maximum size for the + address family. + +Reported-by: Kostya Kortchinsky + +This commit a joint effort between: + +Lou Berger +Donald Sharp +Paul Jakma / + +Resolves: #1316572 +Cherry-picked from: a3bc7e9400b214a0f078fdb19596ba54214a1442) +Conflicts: + bgpd/bgp_mplsvpn.c +--- + bgpd/bgp_mplsvpn.c | 55 +++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 36 insertions(+), 19 deletions(-) + +diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c +index 3d2dade..42eba55 100644 +--- a/bgpd/bgp_mplsvpn.c ++++ b/bgpd/bgp_mplsvpn.c +@@ -101,6 +101,7 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, + pnt = packet->nlri; + lim = pnt + packet->length; + ++#define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */ + for (; pnt < lim; pnt += psize) + { + /* Clear prefix structure. */ +@@ -108,20 +109,38 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, + + /* Fetch prefix length. */ + prefixlen = *pnt++; +- p.family = AF_INET; ++ p.family = afi2family (packet->afi); + psize = PSIZE (prefixlen); +- +- if (prefixlen < 88) +- { +- zlog_err ("prefix length is less than 88: %d", prefixlen); +- return -1; +- } +- +- /* XXX: Not doing anything with the label */ +- decode_label (pnt); +- ++ ++ /* sanity check against packet data */ ++ if (prefixlen < VPN_PREFIXLEN_MIN_BYTES*8 || (pnt + psize) > lim) ++ { ++ zlog_err ("prefix length (%d) is less than 88" ++ " or larger than received (%u)", ++ prefixlen, (uint)(lim-pnt)); ++ return -1; ++ } ++ ++ /* sanity check against storage for the IP address portion */ ++ if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t) sizeof(p.u)) ++ { ++ zlog_err ("prefix length (%d) exceeds prefix storage (%zu)", ++ prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, sizeof(p.u)); ++ return -1; ++ } ++ ++ /* Sanity check against max bitlen of the address family */ ++ if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen (&p)) ++ { ++ zlog_err ("prefix length (%d) exceeds family (%u) max byte length (%u)", ++ prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, ++ p.family, prefix_blen (&p)); ++ return -1; ++ ++ } ++ + /* Copyr label to prefix. */ +- tagpnt = pnt;; ++ tagpnt = pnt; + + /* Copy routing distinguisher to rd. */ + memcpy (&prd.val, pnt + 3, 8); +@@ -140,8 +159,9 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, + return -1; + } + +- p.prefixlen = prefixlen - 88; +- memcpy (&p.u.prefix, pnt + 11, psize - 11); ++ p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8; ++ memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, ++ psize - VPN_PREFIXLEN_MIN_BYTES); + + #if 0 + if (type == RD_TYPE_AS) +@@ -152,9 +172,6 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, + rd_ip.val, inet_ntoa (p.u.prefix4), p.prefixlen); + #endif /* 0 */ + +- if (pnt + psize > lim) +- return -1; +- + if (attr) + bgp_update (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0); +@@ -162,12 +179,12 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, + bgp_withdraw (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt); + } +- + /* Packet length consistency check. */ + if (pnt != lim) + return -1; +- ++ + return 0; ++#undef VPN_PREFIXLEN_MIN_BYTES + } + + int +-- +2.7.4 + diff --git a/quagga.spec b/quagga.spec index bb61d6e..f8b7c18 100644 --- a/quagga.spec +++ b/quagga.spec @@ -28,6 +28,7 @@ Provides: routingdaemon = %{version}-%{release} Obsoletes: quagga-sysvinit Patch0: 0001-systemd-various-service-file-improvements.patch +Patch1: 0002-bgpd-Fix-VU-270232-VPNv4-NLRI-parser-memcpys-to-stac.patch %define __perl_requires %{SOURCE1} @@ -226,6 +227,7 @@ fi %changelog * Fri Oct 21 2016 Michal Sekletar - 0.99.24.1-3 - make routing daemons pull network.target into the boot transaction (#1387654) +- fix for CVE-2016-2342 (#1316572) * Mon Jul 27 2015 Richard W.M. Jones - 0.99.24.1-2 - Bump version to rebuild against new RPM in Rawhide.