|
|
212ca88 |
From af17d2eb7f641c7014a84a71bc0c700b28f1e638 Mon Sep 17 00:00:00 2001
|
|
|
212ca88 |
From: Evgeny Uskov <eu@qrator.net>
|
|
|
212ca88 |
Date: Wed, 13 Jan 2016 13:58:00 +0300
|
|
|
212ca88 |
Subject: [PATCH 3/3] bgpd: Fix buffer overflow error in bgp_dump_routes_func
|
|
|
212ca88 |
|
|
|
212ca88 |
Now if the number of entries for some prefix is too large, multiple
|
|
|
212ca88 |
TABLE_DUMP_V2 records are created. In the previous version in such
|
|
|
212ca88 |
situation bgpd crashed with SIGABRT.
|
|
|
212ca88 |
|
|
|
212ca88 |
Resolves: #1331373
|
|
|
212ca88 |
Cherry-picked from: b4e011985232f28d98e4df88c7cb13ee8f95ef46
|
|
|
212ca88 |
Conflicts:
|
|
|
212ca88 |
bgpd/bgp_dump.c
|
|
|
212ca88 |
---
|
|
|
212ca88 |
bgpd/bgp_dump.c | 175 +++++++++++++++++++++++++++++++-------------------------
|
|
|
212ca88 |
1 file changed, 96 insertions(+), 79 deletions(-)
|
|
|
212ca88 |
|
|
|
212ca88 |
diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c
|
|
|
212ca88 |
index a3c9526..a8db612 100644
|
|
|
212ca88 |
--- a/bgpd/bgp_dump.c
|
|
|
212ca88 |
+++ b/bgpd/bgp_dump.c
|
|
|
212ca88 |
@@ -271,11 +271,98 @@ bgp_dump_routes_index_table(struct bgp *bgp)
|
|
|
212ca88 |
}
|
|
|
212ca88 |
|
|
|
212ca88 |
|
|
|
212ca88 |
+static struct bgp_info *
|
|
|
212ca88 |
+bgp_dump_route_node_record (int afi, struct bgp_node *rn,
|
|
|
212ca88 |
+ struct bgp_info *info, unsigned int seq)
|
|
|
212ca88 |
+{
|
|
|
212ca88 |
+ struct stream *obuf;
|
|
|
212ca88 |
+ size_t sizep;
|
|
|
212ca88 |
+ size_t endp;
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ obuf = bgp_dump_obuf;
|
|
|
212ca88 |
+ stream_reset (obuf);
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* MRT header */
|
|
|
212ca88 |
+ if (afi == AFI_IP)
|
|
|
212ca88 |
+ bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST);
|
|
|
212ca88 |
+ else if (afi == AFI_IP6)
|
|
|
212ca88 |
+ bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST);
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* Sequence number */
|
|
|
212ca88 |
+ stream_putl (obuf, seq);
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* Prefix length */
|
|
|
212ca88 |
+ stream_putc (obuf, rn->p.prefixlen);
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* Prefix */
|
|
|
212ca88 |
+ if (afi == AFI_IP)
|
|
|
212ca88 |
+ {
|
|
|
212ca88 |
+ /* We'll dump only the useful bits (those not 0), but have to
|
|
|
212ca88 |
+ * align on 8 bits */
|
|
|
212ca88 |
+ stream_write (obuf, (u_char *) &rn->p.u.prefix4,
|
|
|
212ca88 |
+ (rn->p.prefixlen + 7) / 8);
|
|
|
212ca88 |
+ }
|
|
|
212ca88 |
+ else if (afi == AFI_IP6)
|
|
|
212ca88 |
+ {
|
|
|
212ca88 |
+ /* We'll dump only the useful bits (those not 0), but have to
|
|
|
212ca88 |
+ * align on 8 bits */
|
|
|
212ca88 |
+ stream_write (obuf, (u_char *) &rn->p.u.prefix6,
|
|
|
212ca88 |
+ (rn->p.prefixlen + 7) / 8);
|
|
|
212ca88 |
+ }
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* Save where we are now, so we can overwride the entry count later */
|
|
|
212ca88 |
+ sizep = stream_get_endp (obuf);
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* Entry count */
|
|
|
212ca88 |
+ uint16_t entry_count = 0;
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* Entry count, note that this is overwritten later */
|
|
|
212ca88 |
+ stream_putw (obuf, 0);
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ endp = stream_get_endp (obuf);
|
|
|
212ca88 |
+ for (; info; info = info->next)
|
|
|
212ca88 |
+ {
|
|
|
212ca88 |
+ size_t cur_endp;
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* Peer index */
|
|
|
212ca88 |
+ stream_putw (obuf, info->peer->table_dump_index);
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* Originated */
|
|
|
212ca88 |
+#ifdef HAVE_CLOCK_MONOTONIC
|
|
|
212ca88 |
+ stream_putl (obuf, time (NULL) - (bgp_clock () - info->uptime));
|
|
|
212ca88 |
+#else
|
|
|
212ca88 |
+ stream_putl (obuf, info->uptime);
|
|
|
212ca88 |
+#endif /* HAVE_CLOCK_MONOTONIC */
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* Dump attribute. */
|
|
|
212ca88 |
+ /* Skip prefix & AFI/SAFI for MP_NLRI */
|
|
|
212ca88 |
+ bgp_dump_routes_attr (obuf, info->attr, &rn->p);
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ cur_endp = stream_get_endp (obuf);
|
|
|
212ca88 |
+ if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
|
|
|
212ca88 |
+ + BGP_DUMP_HEADER_SIZE)
|
|
|
212ca88 |
+ {
|
|
|
212ca88 |
+ stream_set_endp (obuf, endp);
|
|
|
212ca88 |
+ break;
|
|
|
212ca88 |
+ }
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ entry_count++;
|
|
|
212ca88 |
+ endp = cur_endp;
|
|
|
212ca88 |
+ }
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ /* Overwrite the entry count, now that we know the right number */
|
|
|
212ca88 |
+ stream_putw_at (obuf, sizep, entry_count);
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ bgp_dump_set_size (obuf, MSG_TABLE_DUMP_V2);
|
|
|
212ca88 |
+ fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
|
|
|
212ca88 |
+
|
|
|
212ca88 |
+ return info;
|
|
|
212ca88 |
+}
|
|
|
212ca88 |
+
|
|
|
212ca88 |
/* Runs under child process. */
|
|
|
212ca88 |
static unsigned int
|
|
|
212ca88 |
bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
|
|
|
212ca88 |
{
|
|
|
212ca88 |
- struct stream *obuf;
|
|
|
212ca88 |
struct bgp_info *info;
|
|
|
212ca88 |
struct bgp_node *rn;
|
|
|
212ca88 |
struct bgp *bgp;
|
|
|
212ca88 |
@@ -294,87 +381,17 @@ bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
|
|
|
212ca88 |
if(first_run)
|
|
|
212ca88 |
bgp_dump_routes_index_table(bgp);
|
|
|
212ca88 |
|
|
|
212ca88 |
- obuf = bgp_dump_obuf;
|
|
|
212ca88 |
- stream_reset(obuf);
|
|
|
212ca88 |
-
|
|
|
212ca88 |
/* Walk down each BGP route. */
|
|
|
212ca88 |
table = bgp->rib[afi][SAFI_UNICAST];
|
|
|
212ca88 |
|
|
|
212ca88 |
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
|
|
|
212ca88 |
{
|
|
|
212ca88 |
- if(!rn->info)
|
|
|
212ca88 |
- continue;
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- stream_reset(obuf);
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* MRT header */
|
|
|
212ca88 |
- if (afi == AFI_IP)
|
|
|
212ca88 |
- {
|
|
|
212ca88 |
- bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST);
|
|
|
212ca88 |
- }
|
|
|
212ca88 |
-#ifdef HAVE_IPV6
|
|
|
212ca88 |
- else if (afi == AFI_IP6)
|
|
|
212ca88 |
- {
|
|
|
212ca88 |
- bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST);
|
|
|
212ca88 |
- }
|
|
|
212ca88 |
-#endif /* HAVE_IPV6 */
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* Sequence number */
|
|
|
212ca88 |
- stream_putl(obuf, seq);
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* Prefix length */
|
|
|
212ca88 |
- stream_putc (obuf, rn->p.prefixlen);
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* Prefix */
|
|
|
212ca88 |
- if (afi == AFI_IP)
|
|
|
212ca88 |
- {
|
|
|
212ca88 |
- /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
|
|
|
212ca88 |
- stream_write(obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8);
|
|
|
212ca88 |
- }
|
|
|
212ca88 |
-#ifdef HAVE_IPV6
|
|
|
212ca88 |
- else if (afi == AFI_IP6)
|
|
|
212ca88 |
- {
|
|
|
212ca88 |
- /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
|
|
|
212ca88 |
- stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8);
|
|
|
212ca88 |
- }
|
|
|
212ca88 |
-#endif /* HAVE_IPV6 */
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* Save where we are now, so we can overwride the entry count later */
|
|
|
212ca88 |
- int sizep = stream_get_endp(obuf);
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* Entry count */
|
|
|
212ca88 |
- uint16_t entry_count = 0;
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* Entry count, note that this is overwritten later */
|
|
|
212ca88 |
- stream_putw(obuf, 0);
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- for (info = rn->info; info; info = info->next)
|
|
|
212ca88 |
- {
|
|
|
212ca88 |
- entry_count++;
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* Peer index */
|
|
|
212ca88 |
- stream_putw(obuf, info->peer->table_dump_index);
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* Originated */
|
|
|
212ca88 |
-#ifdef HAVE_CLOCK_MONOTONIC
|
|
|
212ca88 |
- stream_putl (obuf, time(NULL) - (bgp_clock() - info->uptime));
|
|
|
212ca88 |
-#else
|
|
|
212ca88 |
- stream_putl (obuf, info->uptime);
|
|
|
212ca88 |
-#endif /* HAVE_CLOCK_MONOTONIC */
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* Dump attribute. */
|
|
|
212ca88 |
- /* Skip prefix & AFI/SAFI for MP_NLRI */
|
|
|
212ca88 |
- bgp_dump_routes_attr (obuf, info->attr, &rn->p);
|
|
|
212ca88 |
- }
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- /* Overwrite the entry count, now that we know the right number */
|
|
|
212ca88 |
- stream_putw_at (obuf, sizep, entry_count);
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- seq++;
|
|
|
212ca88 |
-
|
|
|
212ca88 |
- bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
|
|
|
212ca88 |
- fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
|
|
|
212ca88 |
-
|
|
|
212ca88 |
+ info = rn->info;
|
|
|
212ca88 |
+ while (info)
|
|
|
212ca88 |
+ {
|
|
|
212ca88 |
+ info = bgp_dump_route_node_record(afi, rn, info, seq);
|
|
|
212ca88 |
+ seq++;
|
|
|
212ca88 |
+ }
|
|
|
212ca88 |
}
|
|
|
212ca88 |
|
|
|
212ca88 |
fflush (bgp_dump_routes.fp);
|
|
|
212ca88 |
@@ -854,8 +871,8 @@ bgp_dump_init (void)
|
|
|
212ca88 |
memset (&bgp_dump_updates, 0, sizeof (struct bgp_dump));
|
|
|
212ca88 |
memset (&bgp_dump_routes, 0, sizeof (struct bgp_dump));
|
|
|
212ca88 |
|
|
|
212ca88 |
- bgp_dump_obuf = stream_new (BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
|
|
|
212ca88 |
- + BGP_DUMP_HEADER_SIZE);
|
|
|
212ca88 |
+ bgp_dump_obuf = stream_new ((BGP_MAX_PACKET_SIZE << 1)
|
|
|
212ca88 |
+ + BGP_DUMP_MSG_HEADER + BGP_DUMP_HEADER_SIZE);
|
|
|
212ca88 |
|
|
|
212ca88 |
install_node (&bgp_dump_node, config_write_bgp_dump);
|
|
|
212ca88 |
|
|
|
212ca88 |
--
|
|
|
212ca88 |
2.7.4
|
|
|
212ca88 |
|