diff --git a/0010-frr-reload-escape-strings.patch b/0010-frr-reload-escape-strings.patch new file mode 100644 index 0000000..e0ba9c7 --- /dev/null +++ b/0010-frr-reload-escape-strings.patch @@ -0,0 +1,245 @@ +diff --git a/tools/frr-reload.py b/tools/frr-reload.py +index 461f0e8..12c71de 100755 +--- a/tools/frr-reload.py ++++ b/tools/frr-reload.py +@@ -201,9 +201,9 @@ def get_normalized_es_id(line): + """ + The es-id or es-sys-mac need to be converted to lower case + """ +- sub_strs = ["evpn mh es-id", "evpn mh es-sys-mac"] ++ sub_strs = [r"evpn mh es-id", r"evpn mh es-sys-mac"] + for sub_str in sub_strs: +- obj = re.match(sub_str + " (?P\S*)", line) ++ obj = re.match(sub_str + r" (?P\S*)", line) + if obj: + line = "%s %s" % (sub_str, obj.group("esi").lower()) + break +@@ -228,7 +228,7 @@ def get_normalized_interface_vrf(line): + correctly and configurations are matched appropriately. + """ + +- intf_vrf = re.search("interface (\S+) vrf (\S+)", line) ++ intf_vrf = re.search(r"interface (\S+) vrf (\S+)", line) + if intf_vrf: + old_line = "vrf %s" % intf_vrf.group(2) + new_line = line.replace(old_line, "").strip() +@@ -813,7 +813,7 @@ def bgp_delete_nbr_remote_as_line(lines_to_add): + if ctx_keys[0] not in pg_dict: + pg_dict[ctx_keys[0]] = dict() + # find 'neighbor peer-group' +- re_pg = re.match("neighbor (\S+) peer-group$", line) ++ re_pg = re.match(r"neighbor (\S+) peer-group$", line) + if re_pg and re_pg.group(1) not in pg_dict[ctx_keys[0]]: + pg_dict[ctx_keys[0]][re_pg.group(1)] = { + "nbr": list(), +@@ -836,13 +836,13 @@ def bgp_delete_nbr_remote_as_line(lines_to_add): + if ctx_keys[0] in pg_dict: + for pg_key in pg_dict[ctx_keys[0]]: + # Find 'neighbor remote-as' +- pg_rmtas = "neighbor %s remote-as (\S+)" % pg_key ++ pg_rmtas = r"neighbor %s remote-as (\S+)" % pg_key + re_pg_rmtas = re.search(pg_rmtas, line) + if re_pg_rmtas: + pg_dict[ctx_keys[0]][pg_key]["remoteas"] = True + + # Find 'neighbor [interface] peer-group ' +- nb_pg = "neighbor (\S+) peer-group %s$" % pg_key ++ nb_pg = r"neighbor (\S+) peer-group %s$" % pg_key + re_nbr_pg = re.search(nb_pg, line) + if ( + re_nbr_pg +@@ -860,7 +860,7 @@ def bgp_delete_nbr_remote_as_line(lines_to_add): + and line + and line.startswith("neighbor ") + ): +- nbr_rmtas = "neighbor (\S+) remote-as.*" ++ nbr_rmtas = r"neighbor (\S+) remote-as.*" + re_nbr_rmtas = re.search(nbr_rmtas, line) + if re_nbr_rmtas and ctx_keys[0] in pg_dict: + for pg in pg_dict[ctx_keys[0]]: +@@ -889,8 +889,8 @@ def bgp_remove_neighbor_cfg(lines_to_del, del_nbr_dict): + ): + if ctx_keys[0] in del_nbr_dict: + for nbr in del_nbr_dict[ctx_keys[0]]: +- re_nbr_pg = re.search("neighbor (\S+) .*peer-group (\S+)", line) +- nb_exp = "neighbor %s .*" % nbr ++ re_nbr_pg = re.search(r"neighbor (\S+) .*peer-group (\S+)", line) ++ nb_exp = r"neighbor %s .*" % nbr + if not re_nbr_pg: + re_nb = re.search(nb_exp, line) + if re_nb: +@@ -988,7 +988,7 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del): + # neighbor uplink1 interface remote-as internal + # + # 'no neighbor peer [interface] remote-as <>' +- nb_remoteas = "neighbor (\S+) .*remote-as (\S+)" ++ nb_remoteas = r"neighbor (\S+) .*remote-as (\S+)" + re_nb_remoteas = re.search(nb_remoteas, line) + if re_nb_remoteas: + lines_to_del_to_app.append((ctx_keys, line)) +@@ -996,7 +996,7 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del): + # 'no neighbor peer [interface] peer-group <>' is in lines_to_del + # copy the neighbor and look for all config removal lines associated + # to neighbor and delete them from the lines_to_del +- re_nbr_pg = re.search("neighbor (\S+) .*peer-group (\S+)", line) ++ re_nbr_pg = re.search(r"neighbor (\S+) .*peer-group (\S+)", line) + if re_nbr_pg: + if ctx_keys[0] not in del_nbr_dict: + del_nbr_dict[ctx_keys[0]] = list() +@@ -1008,7 +1008,7 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del): + if ctx_keys[0] not in del_dict: + del_dict[ctx_keys[0]] = dict() + # find 'no neighbor peer-group' +- re_pg = re.match("neighbor (\S+) peer-group$", line) ++ re_pg = re.match(r"neighbor (\S+) peer-group$", line) + if re_pg and re_pg.group(1) not in del_dict[ctx_keys[0]]: + del_dict[ctx_keys[0]][re_pg.group(1)] = list() + found_pg_del_cmd = True +@@ -1035,7 +1035,7 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del): + if ctx_keys[0] in del_dict: + for pg_key in del_dict[ctx_keys[0]]: + # 'neighbor [interface] peer-group ' +- nb_pg = "neighbor (\S+) .*peer-group %s$" % pg_key ++ nb_pg = r"neighbor (\S+) .*peer-group %s$" % pg_key + re_nbr_pg = re.search(nb_pg, line) + if ( + re_nbr_pg +@@ -1053,13 +1053,13 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del): + if ctx_keys[0] in del_dict: + for pg in del_dict[ctx_keys[0]]: + for nbr in del_dict[ctx_keys[0]][pg]: +- nb_exp = "neighbor %s .*" % nbr ++ nb_exp = r"neighbor %s .*" % nbr + re_nb = re.search(nb_exp, line) + # add peer configs to delete list. + if re_nb and line not in lines_to_del_to_del: + lines_to_del_to_del.append((ctx_keys, line)) + +- pg_exp = "neighbor %s peer-group$" % pg ++ pg_exp = r"neighbor %s peer-group$" % pg + re_pg = re.match(pg_exp, line) + if re_pg: + lines_to_del_to_app.append((ctx_keys, line)) +@@ -1093,7 +1093,7 @@ def pim_delete_move_lines(lines_to_add, lines_to_del): + + # no ip msdp peer <> does not accept source so strip it off. + if line and line.startswith("ip msdp peer "): +- pim_msdp_peer = re.search("ip msdp peer (\S+) source (\S+)", line) ++ pim_msdp_peer = re.search(r"ip msdp peer (\S+) source (\S+)", line) + if pim_msdp_peer: + source_sub_str = "source %s" % pim_msdp_peer.group(2) + new_line = line.replace(source_sub_str, "").strip() +@@ -1186,10 +1186,10 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): + # + # If so then chop the del line and the corresponding add lines + re_swpx_int_peergroup = re.search( +- "neighbor (\S+) interface peer-group (\S+)", line ++ r"neighbor (\S+) interface peer-group (\S+)", line + ) + re_swpx_int_v6only_peergroup = re.search( +- "neighbor (\S+) interface v6only peer-group (\S+)", line ++ r"neighbor (\S+) interface v6only peer-group (\S+)", line + ) + + if re_swpx_int_peergroup or re_swpx_int_v6only_peergroup: +@@ -1246,7 +1246,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): + + if re_nbr_bfd_timers: + nbr = re_nbr_bfd_timers.group(1) +- bfd_nbr = "neighbor %s" % nbr ++ bfd_nbr = r"neighbor %s" % nbr + bfd_search_string = bfd_nbr + r" bfd (\S+) (\S+) (\S+)" + + for ctx_keys, add_line in lines_to_add: +@@ -1271,13 +1271,13 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): + # they actually match and if we are going from a very old style + # command such that the neighbor command is under the `router + # bgp ..` node that we need to handle that appropriately +- re_nbr_rm = re.search("neighbor(.*)route-map(.*)(in|out)$", line) ++ re_nbr_rm = re.search(r"neighbor(.*)route-map(.*)(in|out)$", line) + if re_nbr_rm: + adjust_for_bgp_node = 0 + neighbor_name = re_nbr_rm.group(1) + rm_name_del = re_nbr_rm.group(2) + dir = re_nbr_rm.group(3) +- search = "neighbor%sroute-map(.*)%s" % (neighbor_name, dir) ++ search = r"neighbor%sroute-map(.*)%s" % (neighbor_name, dir) + save_line = "EMPTY" + for ctx_keys_al, add_line in lines_to_add: + if ctx_keys_al[0].startswith("router bgp"): +@@ -1330,10 +1330,10 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): + # + # If so then chop the del line and the corresponding add lines + re_swpx_int_remoteas = re.search( +- "neighbor (\S+) interface remote-as (\S+)", line ++ r"neighbor (\S+) interface remote-as (\S+)", line + ) + re_swpx_int_v6only_remoteas = re.search( +- "neighbor (\S+) interface v6only remote-as (\S+)", line ++ r"neighbor (\S+) interface v6only remote-as (\S+)", line + ) + + if re_swpx_int_remoteas or re_swpx_int_v6only_remoteas: +@@ -1373,7 +1373,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): + # unnecessary session resets. + if "multipath-relax" in line: + re_asrelax_new = re.search( +- "^bgp\s+bestpath\s+as-path\s+multipath-relax$", line ++ r"^bgp\s+bestpath\s+as-path\s+multipath-relax$", line + ) + old_asrelax_cmd = "bgp bestpath as-path multipath-relax no-as-set" + found_asrelax_old = line_exist(lines_to_add, ctx_keys, old_asrelax_cmd) +@@ -1398,7 +1398,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): + # the new syntax. This causes an unnecessary 'no import-table' followed + # by the same old 'ip import-table' which causes perturbations in + # announced routes leading to traffic blackholes. Fix this issue. +- re_importtbl = re.search("^ip\s+import-table\s+(\d+)$", ctx_keys[0]) ++ re_importtbl = re.search(r"^ip\s+import-table\s+(\d+)$", ctx_keys[0]) + if re_importtbl: + table_num = re_importtbl.group(1) + for ctx in lines_to_add: +@@ -1419,7 +1419,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): + # access-list FOO seq 5 permit 2.2.2.2/32 + # ipv6 access-list BAR seq 5 permit 2:2:2::2/128 + re_acl_pfxlst = re.search( +- "^(ip |ipv6 |)(prefix-list|access-list)(\s+\S+\s+)(seq \d+\s+)(permit|deny)(.*)$", ++ r"^(ip |ipv6 |)(prefix-list|access-list)(\s+\S+\s+)(seq \d+\s+)(permit|deny)(.*)$", + ctx_keys[0], + ) + if re_acl_pfxlst: +@@ -1452,7 +1452,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): + # bgp large-community-list standard llist seq 5 permit 65001:65001:1 + # bgp extcommunity-list standard elist seq 5 permit soo 123:123 + re_bgp_lists = re.search( +- "^(bgp )(community-list|large-community-list|extcommunity-list)(\s+\S+\s+)(\S+\s+)(seq \d+\s+)(permit|deny)(.*)$", ++ r"^(bgp )(community-list|large-community-list|extcommunity-list)(\s+\S+\s+)(\S+\s+)(seq \d+\s+)(permit|deny)(.*)$", + ctx_keys[0], + ) + if re_bgp_lists: +@@ -1481,7 +1481,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): + # Examples: + # bgp as-path access-list important_internet_bgp_as_numbers seq 30 permit _40841_" + re_bgp_as_path = re.search( +- "^(bgp )(as-path )(access-list )(\S+\s+)(seq \d+\s+)(permit|deny)(.*)$", ++ r"^(bgp )(as-path )(access-list )(\S+\s+)(seq \d+\s+)(permit|deny)(.*)$", + ctx_keys[0], + ) + if re_bgp_as_path: +@@ -1511,7 +1511,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): + and ctx_keys[2].startswith("vni") + ): + re_route_target = ( +- re.search("^route-target import (.*)$", line) ++ re.search(r"^route-target import (.*)$", line) + if line is not None + else False + ) +@@ -1648,7 +1648,7 @@ def compare_context_objects(newconf, running): + pcclist_to_del = [] + candidates_to_add = [] + delete_bgpd = False +- area_stub_no_sum = "area (\S+) stub no-summary" ++ area_stub_no_sum = r"area (\S+) stub no-summary" + deleted_keychains = [] + + # Find contexts that are in newconf but not in running diff --git a/frr.spec b/frr.spec index 0b91d08..b48b3b0 100644 --- a/frr.spec +++ b/frr.spec @@ -9,7 +9,7 @@ Name: frr Version: 10.1 -Release: 9%{?dist} +Release: 10%{?dist} Summary: Routing daemon License: GPL-2.0-or-later AND ISC AND LGPL-2.0-or-later AND BSD-2-Clause AND BSD-3-Clause AND (GPL-2.0-or-later OR ISC) AND MIT URL: http://www.frrouting.org @@ -30,6 +30,7 @@ Patch0006: 0006-noprefixroute-network-manager.patch Patch0007: 0007-CVE-2024-44070.patch Patch0008: 0008-bfd-bgp-shutdown-notification.patch Patch0009: 0009-bgp-bfd-drop-connection.patch +Patch0010: 0010-frr-reload-escape-strings.patch BuildRequires: autoconf BuildRequires: automake @@ -280,6 +281,9 @@ rm tests/lib/*grpc* %endif %changelog +* Tue Feb 11 2025 Michal Ruprich - 10.1-10 +- RHEL-78638 - frr-reload.py suffers from unescaped regex sequences + * Tue Feb 11 2025 Michal Ruprich - 10.1-9 - Resolves: RHEL-67011 - BGP with BFD has a dropped Connection before peering established