summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2016-01-27 16:54:45 +0000
committerPaul Jakma <paul.jakma@hpe.com>2016-02-10 15:02:07 +0000
commita3bc7e9400b214a0f078fdb19596ba54214a1442 (patch)
tree5268048e32b24b2bac3c8a55f41ef25a0b15ff91 /bgpd
parenteae18d16fefed42af33e63e096a2889b9c70b9cb (diff)
downloadquagga-a3bc7e9400b214a0f078fdb19596ba54214a1442.tar.bz2
quagga-a3bc7e9400b214a0f078fdb19596ba54214a1442.tar.xz
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 <kostyak@google.com> This commit a joint effort between: Lou Berger <lberger@labn.net> Donald Sharp <sharpd@cumulusnetworks.com> Paul Jakma <paul.jakma@hpe.com> / <paul@jakma.org>
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_mplsvpn.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index a72d5ede..75c90cd7 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,17 +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;
- }
-
+
+ /* 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);
@@ -137,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)
@@ -149,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);
@@ -159,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