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, ¬e,
- 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;