Commit 452990d13e for frr
commit 452990d13e99bfc310faefd596840ac9249cc99e
Author: Akhilesh Akhade <aakhade@nvidia.com>
Date: Mon Nov 2 18:51:41 2026 +0200
zebra: fix crash on explicit Wide LIB start below Wide LIB start
The Explicit Wide LIB is the tail of the Wide LIB and has no end of its
own, but nothing kept its start inside the Wide LIB:
format usid-f3216
wide-local-id-block start 1000 end 1010
wide-local-id-block explicit start 0
The Wide LIB is an array of (wlib_end - wlib_start + 1) entries, indexed
by the offset of the SID function from wlib_start. The explicit
allocation path, however, decides that a function belongs to the Wide
LIB by comparing it against ewlib_start. A function below wlib_start
passes that check, and the unsigned offset wraps, so zebra indexes far
past the end of the array and faults.
Requesting a uA SID with function 500 against the ranges above indexes
the array at 500 - 1000, which wraps to 4294966796. At 32 bytes per
entry that is roughly 137 GB past the allocation.
Reject any configuration that would leave the Explicit Wide LIB start
below the Wide LIB start. The two ranges are configured independently
and either can be reset to its default, so all four commands that move
them are checked. Only the lower bound is enforced: an Explicit Wide LIB
start above wlib_end just leaves the range empty, which is harmless, and
rejecting it would make the Wide LIB impossible to move.
Clamp ewlib_start to wlib_start in the alloc and release paths as well.
That is unreachable once the ranges are validated, but the Wide LIB
index is otherwise unchecked, so it keeps a future caller from faulting.
Signed-off-by: Akhilesh Akhade <aakhade@nvidia.com>
diff --git a/zebra/zebra_srv6.c b/zebra/zebra_srv6.c
index 891f1d4071..6b89c13721 100644
--- a/zebra/zebra_srv6.c
+++ b/zebra/zebra_srv6.c
@@ -1546,7 +1546,11 @@ static bool alloc_srv6_sid_func_explicit(struct zebra_srv6_sid_block *block,
uint32_t elib_end = format->config.usid.elib_end;
uint32_t wlib_start = format->config.usid.wlib_start;
uint32_t wlib_end = format->config.usid.wlib_end;
- uint32_t ewlib_start = format->config.usid.ewlib_start;
+ /*
+ * The Wide LIB is indexed relative to wlib_start, so the EWLIB
+ * range must not start below it
+ */
+ uint32_t ewlib_start = MAX(format->config.usid.ewlib_start, wlib_start);
uint32_t ewlib_end = wlib_end;
uint32_t *sid_wide_func_ptr = NULL;
@@ -2203,7 +2207,11 @@ static bool release_srv6_sid_func_explicit(struct zebra_srv6_sid_block *block,
uint32_t elib_start = format->config.usid.elib_start;
uint32_t elib_end = format->config.usid.elib_end;
uint32_t wlib_start = format->config.usid.wlib_start;
- uint32_t ewlib_start = format->config.usid.ewlib_start;
+ /*
+ * The Wide LIB is indexed relative to wlib_start, so the EWLIB
+ * range must not start below it
+ */
+ uint32_t ewlib_start = MAX(format->config.usid.ewlib_start, wlib_start);
uint32_t ewlib_end = format->config.usid.wlib_end;
uint32_t *sid_wide_func_ptr = NULL;
diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c
index 4fdf184b41..79e495b250 100644
--- a/zebra/zebra_srv6_vty.c
+++ b/zebra/zebra_srv6_vty.c
@@ -1473,6 +1473,14 @@ DEFPY(srv6_sid_format_usid_wlib,
return CMD_WARNING_CONFIG_FAILED;
}
+ if (start > format->config.usid.ewlib_start) {
+ vty_out(vty,
+ "%% Wide LIB start (%" PRId64
+ ") cannot be greater than the Explicit Wide LIB start (%u)\n",
+ start, format->config.usid.ewlib_start);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
format->config.usid.wlib_start = start;
format->config.usid.wlib_end = end;
@@ -1493,19 +1501,28 @@ DEFPY(no_srv6_sid_format_usid_wlib,
"Specify the end value for the Wide LIB\n")
{
VTY_DECLVAR_CONTEXT(srv6_sid_format, format);
+ uint32_t wlib_start = 0, wlib_end = 0;
if (strmatch(format->name, SRV6_SID_FORMAT_USID_F3216_NAME)) {
- format->config.usid.wlib_start =
- SRV6_SID_FORMAT_USID_F3216_WLIB_START;
- format->config.usid.wlib_end =
- SRV6_SID_FORMAT_USID_F3216_WLIB_END;
+ wlib_start = SRV6_SID_FORMAT_USID_F3216_WLIB_START;
+ wlib_end = SRV6_SID_FORMAT_USID_F3216_WLIB_END;
} else if (strmatch(format->name, SRV6_SID_FORMAT_USID_F4816_NAME)) {
- format->config.usid.wlib_start = SRV6_SID_FORMAT_USID_F4816_WLIB_START;
- format->config.usid.wlib_end = SRV6_SID_FORMAT_USID_F4816_WLIB_END;
+ wlib_start = SRV6_SID_FORMAT_USID_F4816_WLIB_START;
+ wlib_end = SRV6_SID_FORMAT_USID_F4816_WLIB_END;
} else {
assert(0);
}
+ if (wlib_start > format->config.usid.ewlib_start) {
+ vty_out(vty,
+ "%% Default Wide LIB start (%u) would be greater than the Explicit Wide LIB start (%u), remove the Explicit Wide LIB first\n",
+ wlib_start, format->config.usid.ewlib_start);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ format->config.usid.wlib_start = wlib_start;
+ format->config.usid.wlib_end = wlib_end;
+
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
@@ -1522,6 +1539,14 @@ DEFPY(srv6_sid_format_usid_wide_lib_explicit,
{
VTY_DECLVAR_CONTEXT(srv6_sid_format, format);
+ if (start < format->config.usid.wlib_start) {
+ vty_out(vty,
+ "%% Explicit Wide LIB start (%" PRId64
+ ") cannot be less than Wide LIB start (%u)\n",
+ start, format->config.usid.wlib_start);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
format->config.usid.ewlib_start = start;
/* Notify zclients that the format has changed */
@@ -1540,15 +1565,24 @@ DEFPY(no_srv6_sid_format_usid_wide_lib_explicit,
"Specify the start value for the Explicit Wide LIB\n")
{
VTY_DECLVAR_CONTEXT(srv6_sid_format, format);
+ uint32_t ewlib_start = 0;
if (strmatch(format->name, SRV6_SID_FORMAT_USID_F3216_NAME))
- format->config.usid.ewlib_start =
- SRV6_SID_FORMAT_USID_F3216_EWLIB_START;
+ ewlib_start = SRV6_SID_FORMAT_USID_F3216_EWLIB_START;
else if (strmatch(format->name, SRV6_SID_FORMAT_USID_F4816_NAME))
- format->config.usid.ewlib_start = SRV6_SID_FORMAT_USID_F4816_EWLIB_START;
+ ewlib_start = SRV6_SID_FORMAT_USID_F4816_EWLIB_START;
else
assert(0);
+ if (ewlib_start < format->config.usid.wlib_start) {
+ vty_out(vty,
+ "%% Default Explicit Wide LIB start (%u) would be less than the Wide LIB start (%u), remove the Wide LIB first\n",
+ ewlib_start, format->config.usid.wlib_start);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ format->config.usid.ewlib_start = ewlib_start;
+
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);