]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: Prevent crash in bgp_table_range_lookup
authorDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 2 Dec 2019 14:37:47 +0000 (09:37 -0500)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 3 Dec 2019 00:08:16 +0000 (19:08 -0500)
The function bgp_table_range_lookup attempts to walk down
the table node data structures to find a list of matching
nodes.  We need to guard against the current node from
not matching and not having anything in the child nodes.
Add a bit of code to guard against this.

Traceback that lead me down this path:

Nov 24 12:22:38 frr bgpd[20257]: Received signal 11 at 1574616158 (si_addr 0x2, PC 0x46cdc3); aborting...
Nov 24 12:22:38 frr bgpd[20257]: Backtrace for 11 stack frames:
Nov 24 12:22:38 frr bgpd[20257]: /lib64/libfrr.so.0(zlog_backtrace_sigsafe+0x67) [0x7fd1ad445957]
Nov 24 12:22:38 frr bgpd[20257]: /lib64/libfrr.so.0(zlog_signal+0x113) [0x7fd1ad445db3]1ad445957]
Nov 24 12:22:38 frr bgpd[20257]: /lib64/libfrr.so.0(+0x70e65) [0x7fd1ad465e65]ad445db3]1ad445957]
Nov 24 12:22:38 frr bgpd[20257]: /lib64/libpthread.so.0(+0xf5f0) [0x7fd1abd605f0]45db3]1ad445957]
Nov 24 12:22:38 frr bgpd[20257]: /usr/lib/frr/bgpd(bgp_table_range_lookup+0x63) [0x46cdc3]445957]
Nov 24 12:22:38 frr bgpd[20257]: /usr/lib64/frr/modules/bgpd_rpki.so(+0x4f0d) [0x7fd1a934ff0d]57]
Nov 24 12:22:38 frr bgpd[20257]: /lib64/libfrr.so.0(thread_call+0x60) [0x7fd1ad4736e0]934ff0d]57]
Nov 24 12:22:38 frr bgpd[20257]: /lib64/libfrr.so.0(frr_run+0x128) [0x7fd1ad443ab8]e0]934ff0d]57]
Nov 24 12:22:38 frr bgpd[20257]: /usr/lib/frr/bgpd(main+0x2e3) [0x41c043]1ad443ab8]e0]934ff0d]57]
Nov 24 12:22:38 frr bgpd[20257]: /lib64/libc.so.6(__libc_start_main+0xf5) [0x7fd1ab9a5505]f0d]57]
Nov 24 12:22:38 frr bgpd[20257]: /usr/lib/frr/bgpd() [0x41d9bb]main+0xf5) [0x7fd1ab9a5505]f0d]57]
Nov 24 12:22:38 frr bgpd[20257]: in thread bgpd_sync_callback scheduled from bgpd/bgp_rpki.c:351#012; aborting...
Nov 24 12:22:38 frr watchfrr[6779]: [EC 268435457] bgpd state -> down : read returned EOF
Nov 24 12:22:38 frr zebra[5952]: [EC 4043309116] Client 'bgp' encountered an error and is shutting down.
Nov 24 12:22:38 frr zebra[5952]: zebra/zebra_ptm.c:1345 failed to find process pid registration
Nov 24 12:22:38 frr zebra[5952]: client 15 disconnected. 0 bgp routes removed from the rib

I am not really 100% sure what we are really trying to do with this function, but we must
guard against child nodes not having any data.

Fixes: #5440
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
bgpd/bgp_table.c

index 53175bfccf05828d513c1c0626541053ac35c2f1..b75246b172c606d9379afa7b1e529d21ac211346 100644 (file)
@@ -159,7 +159,8 @@ void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p,
        if (node == NULL)
                return;
 
-       while (node->p.prefixlen <= p->prefixlen && prefix_match(&node->p, p)) {
+       while (node &&
+              node->p.prefixlen <= p->prefixlen && prefix_match(&node->p, p)) {
                if (bgp_node_has_bgp_path_info_data(node)
                    && node->p.prefixlen == p->prefixlen) {
                        matched = node;
@@ -169,14 +170,20 @@ void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p,
                        &p->u.prefix, node->p.prefixlen)]);
        }
 
+       if (!node)
+               return;
+
        if (matched == NULL && node->p.prefixlen <= maxlen
            && prefix_match(p, &node->p) && node->parent == NULL)
                matched = node;
        else if ((matched == NULL && node->p.prefixlen > maxlen) || !node->parent)
                return;
-       else if (matched == NULL)
+       else if (matched == NULL && node->parent)
                matched = node = bgp_node_from_rnode(node->parent);
 
+       if (!matched)
+               return;
+
        if (bgp_node_has_bgp_path_info_data(matched)) {
                bgp_lock_node(matched);
                listnode_add(matches, matched);