Commit f47da9da57 for frr

commit f47da9da57b8a203826d12d4a454e7a6a4b3c941
Author: Rajasekar Raja <rajasekarr@nvidia.com>
Date:   Mon Oct 19 13:14:33 2026 -0700

    staticd: fix crash when removing an SRv6 SID on a missing locator

    staticd can have two SIDs with the same address and different prefix
    lengths. For example, fcbb:bbbb:1::/64 on a locator that does not exist
    yet, and fcbb:bbbb:1::/48 on locator MAIN.

    When zebra allocates the /48, its message back to staticd has the
    address but not the prefix length. staticd gave it to the first SID
    in its list with that address. If that was the /64, the /64 was marked
    as allocated instead of the /48, and the /48 was never installed.

    Steps to reproduce:
      segment-routing
       srv6
        locators
         locator MAIN
          prefix fcbb:bbbb:1::/48 block-len 32 node-len 16 func-bits 16
        static-sids
         sid fcbb:bbbb:1::/64 locator LOC_X behavior uN
         sid fcbb:bbbb:1::/48 locator MAIN behavior uN

    Once zebra has allocated the /48, remove the /64:
      segment-routing
       srv6
        static-sids
         no sid fcbb:bbbb:1::/64

    Removing the /64 crashes staticd. Releasing a SID reads its locator,
    and the /64 has none:

      ERROR: AddressSanitizer: SEGV on unknown address 0x000000000100 (pc 0xaaaae589c81c bp 0xfffff4b6d1a0 sp 0xfffff4b6d0e0 T0)
      ==40776==The signal is caused by a READ memory access.
      ==40776==Hint: address points to the zero page.
          #0 0xaaaae589c81c in is_srv6_sid_localonly staticd/static_zebra.c:1037
          #1 0xaaaae58a4ae8 in static_zebra_release_srv6_sid staticd/static_zebra.c:1235
          #2 0xaaaae58c3998 in static_srv6_sid_del staticd/static_srv6.c:252
          #3 0xaaaae58c0be8 in routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_destroy staticd/static_nb_config.c:1515
          #4 0xffff8503b168 in nb_callback_destroy lib/northbound.c:1687
          #5 0xffff8503b168 in nb_callback_configuration lib/northbound.c:2011
          #6 0xffff8503b9d4 in nb_transaction_process lib/northbound.c:2136
          #7 0xffff8503b9d4 in nb_candidate_commit_apply lib/northbound.c:1448
          #8 0xffff8500cddc in mgmt_be_txn_proc_cfgapply lib/mgmt_be_client.c:618
          #9 0xffff850105a0 in be_client_handle_cfg_apply lib/mgmt_be_client.c:651
          #10 0xffff850105a0 in be_client_handle_native_msg lib/mgmt_be_client.c:1032
          #11 0xffff850105a0 in mgmt_be_client_process_msg lib/mgmt_be_client.c:1071
          #12 0xffff850105a0 in mgmt_be_client_process_msg lib/mgmt_be_client.c:1058
          #13 0xffff85018984 in mgmt_msg_procbufs lib/mgmt_msg.c:176
          #14 0xffff85018aac in msg_conn_proc_msgs lib/mgmt_msg.c:533
          #15 0xffff850babe8 in event_call lib/event.c:2744
          #16 0xffff84fe94b4 in frr_run lib/libfrr.c:1258
          #17 0xaaaae589b540 in main staticd/static_main.c:220
          #18 0xffff84a973fc in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
          #19 0xffff84a974d4 in __libc_start_main_impl ../csu/libc-start.c:392
          #20 0xaaaae589bd2c in _start (/usr/lib/frr/staticd+0x2bd2c)
      SUMMARY: AddressSanitizer: SEGV staticd/static_zebra.c:1037 in is_srv6_sid_localonly

    Only match a SID that has a locator, and also compare the locator name
    that zebra sends. staticd decoded that name until commit c6aeb74e9847
    ("*: don't use static char buffer in srv6 zapi code") but never used
    it, so that commit dropped it. Also check for a missing locator in
    static_zebra_release_srv6_sid(), as install and uninstall already do.

    Signed-off-by: Rajasekar Raja <rajasekarr@nvidia.com>

diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index 70bb91da62..bd66955c31 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -1156,6 +1156,11 @@ extern void static_zebra_release_srv6_sid(struct static_srv6_sid *sid)
 	if (!sid || !CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID))
 		return;

+	if (!sid->locator) {
+		zlog_err("Failed to release SID %pFX: missing locator information", &sid->addr);
+		return;
+	}
+
 	/* convert `srv6_endpoint_behavior_codepoint` to `seg6local_action_t` */
 	switch (sid->behavior) {
 	case SRV6_ENDPOINT_BEHAVIOR_END:
@@ -1395,23 +1400,46 @@ static int static_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
 	return 0;
 }

+/*
+ * Configured SIDs can share an address and differ only in prefix length, and
+ * only a SID with a resolved locator can have asked zebra for one.
+ */
+static struct static_srv6_sid *static_zebra_srv6_sid_notify_lookup(const struct in6_addr *sid_addr,
+								   const char *locator_name)
+{
+	struct static_srv6_sid *sid;
+	struct listnode *node;
+
+	for (ALL_LIST_ELEMENTS_RO(srv6_sids, node, sid)) {
+		if (!sid->locator || !IPV6_ADDR_SAME(&sid->addr.prefix, sid_addr))
+			continue;
+
+		if (locator_name[0] != '\0' &&
+		    strncmp(sid->locator->name, locator_name, sizeof(sid->locator->name)) != 0)
+			continue;
+
+		return sid;
+	}
+
+	return NULL;
+}
+
 static int static_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS)
 {
 	struct srv6_sid_ctx ctx;
 	struct in6_addr sid_addr;
 	enum zapi_srv6_sid_notify note;
 	uint32_t sid_func;
-	struct listnode *node;
 	char buf[256];
+	char locator_name[SRV6_LOCNAME_SIZE] = {};
 	struct static_srv6_sid *sid = NULL;
-	bool found = false;

 	if (!srv6_locators)
 		return -1;

 	/* Decode the received notification message */
 	if (!zapi_srv6_sid_notify_decode(zclient->ibuf, &ctx, &sid_addr, &sid_func, NULL, &note,
-					 NULL, 0)) {
+					 locator_name, sizeof(locator_name))) {
 		zlog_err("%s : error in msg decode", __func__);
 		return -1;
 	}
@@ -1428,14 +1456,8 @@ static int static_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS)
 		DEBUGD(&static_dbg_srv6, "%s: SRv6 SID %pI6 %s ALLOCATED", __func__, &sid_addr,
 		       srv6_sid_ctx2str(buf, sizeof(buf), &ctx));

-		for (ALL_LIST_ELEMENTS_RO(srv6_sids, node, sid)) {
-			if (IPV6_ADDR_SAME(&sid->addr.prefix, &sid_addr)) {
-				found = true;
-				break;
-			}
-		}
-
-		if (!found || !sid) {
+		sid = static_zebra_srv6_sid_notify_lookup(&sid_addr, locator_name);
+		if (!sid) {
 			zlog_err("SRv6 SID %pI6 %s: not found", &sid_addr,
 				 srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
 			return 0;
@@ -1458,14 +1480,8 @@ static int static_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS)
 		DEBUGD(&static_dbg_srv6, "%s: SRv6 SID %pI6 %s: RELEASED", __func__, &sid_addr,
 		       srv6_sid_ctx2str(buf, sizeof(buf), &ctx));

-		for (ALL_LIST_ELEMENTS_RO(srv6_sids, node, sid)) {
-			if (IPV6_ADDR_SAME(&sid->addr.prefix, &sid_addr)) {
-				found = true;
-				break;
-			}
-		}
-
-		if (!found || !sid) {
+		sid = static_zebra_srv6_sid_notify_lookup(&sid_addr, locator_name);
+		if (!sid) {
 			zlog_err("SRv6 SID %pI6 %s: not found", &sid_addr,
 				 srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
 			return 0;