Skip to content

staticd: Fix SRv6 SID use-after-free on locator deletion#20660

Merged
ton31337 merged 2 commits intoFRRouting:masterfrom
cscarpitta:fix/fix_srv6_sid_user_after_free
Feb 4, 2026
Merged

staticd: Fix SRv6 SID use-after-free on locator deletion#20660
ton31337 merged 2 commits intoFRRouting:masterfrom
cscarpitta:fix/fix_srv6_sid_user_after_free

Conversation

@cscarpitta
Copy link
Contributor

When a locator is removed, we iterate over the list of SIDs and uninstall them from the data plane. However, the validity flag of
the SID remains set, and the locator pointer still points to the freed locator memory.

This causes issues in other parts of the code where we check the SID validity flag. Since the flag is still set, we assume the SID
is valid and attempt to access the locator pointer, resulting in use-after-free crashes.

Fix this by:

  • Unsetting the STATIC_FLAG_SRV6_SID_VALID flag to mark the SID as invalid when its locator is deleted
  • Setting the locator pointer to NULL to indicate that the SID no longer has a locator associated with it

This ensures that when the locator is removed, associated SIDs are properly marked as invalid and cannot accidentally reference freed memory.

=================================================================
==447373==ERROR: AddressSanitizer: heap-use-after-free on address 0x51200007b440 at pc 0xb38f5f9349d4 bp 0xffffdcc6c940 sp 0xffffdcc6c930
READ of size 24 at 0x51200007b440 thread T0
    #0 0xb38f5f9349d0 in is_srv6_sid_localonly staticd/static_zebra.c:1022
    #1 0xb38f5f9360dc in static_zebra_release_srv6_sid staticd/static_zebra.c:1220
    #2 0xb38f5f96b5a8 in static_srv6_sid_del staticd/static_srv6.c:252
    #3 0xb38f5f967090 in routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_destroy staticd/static_nb_config.c:1222
    #4 0xe57bf515e018 in nb_callback_destroy lib/northbound.c:1650
    #5 0xe57bf5160e08 in nb_callback_configuration lib/northbound.c:1968
    #6 0xe57bf51616bc in nb_transaction_process lib/northbound.c:2093
    #7 0xe57bf515c5c8 in nb_candidate_commit_apply lib/northbound.c:1411
    #8 0xe57bf51118d4 in mgmt_be_txn_proc_cfgapply lib/mgmt_be_client.c:614
    #9 0xe57bf5111e30 in be_client_handle_cfg_apply lib/mgmt_be_client.c:645
    #10 0xe57bf5114ff0 in be_client_handle_native_msg lib/mgmt_be_client.c:1001
    #11 0xe57bf511524c in mgmt_be_client_process_msg lib/mgmt_be_client.c:1040
    #12 0xe57bf5125984 in mgmt_msg_procbufs lib/mgmt_msg.c:199
    #13 0xe57bf5127944 in msg_conn_proc_msgs lib/mgmt_msg.c:520
    #14 0xe57bf5244f9c in event_call lib/event.c:2730
    #15 0xe57bf50cf9a4 in frr_run lib/libfrr.c:1258
    #16 0xb38f5f928548 in main staticd/static_main.c:220
    #17 0xe57bf4ae84c0 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #18 0xe57bf4ae8594 in __libc_start_main_impl ../csu/libc-start.c:360
    #19 0xb38f5f927eec in _start (/usr/lib/frr/staticd+0x27eec) (BuildId: 0cc9ca8acff6f00edfe8380e3ac4febc62c214df)

0x51200007b440 is located 256 bytes inside of 288-byte region [0x51200007b340,0x51200007b460)
freed by thread T0 here:
    #0 0xe57bf56561b4 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0xe57bf510ad94 in qfree lib/memory.c:136
    #2 0xb38f5f96b430 in static_srv6_locator_free staticd/static_srv6.c:231
    #3 0xb38f5f937888 in static_zebra_process_srv6_locator_delete staticd/static_zebra.c:1378
    #4 0xe57bf52b6ca4 in zclient_read lib/zclient.c:4870
    #5 0xe57bf5244f9c in event_call lib/event.c:2730
    #6 0xe57bf50cf9a4 in frr_run lib/libfrr.c:1258
    #7 0xb38f5f928548 in main staticd/static_main.c:220
    #8 0xe57bf4ae84c0 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #9 0xe57bf4ae8594 in __libc_start_main_impl ../csu/libc-start.c:360
    #10 0xb38f5f927eec in _start (/usr/lib/frr/staticd+0x27eec) (BuildId: 0cc9ca8acff6f00edfe8380e3ac4febc62c214df)

previously allocated by thread T0 here:
    #0 0xe57bf565709c in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0xe57bf510ac54 in qcalloc lib/memory.c:111
    #2 0xb38f5f96b3f4 in static_srv6_locator_alloc staticd/static_srv6.c:223
    #3 0xb38f5f9366ac in static_zebra_process_srv6_locator_internal staticd/static_zebra.c:1281
    #4 0xb38f5f937044 in static_zebra_process_srv6_locator_add staticd/static_zebra.c:1323
    #5 0xe57bf52b6ca4 in zclient_read lib/zclient.c:4870
    #6 0xe57bf5244f9c in event_call lib/event.c:2730
    #7 0xe57bf50cf9a4 in frr_run lib/libfrr.c:1258
    #8 0xb38f5f928548 in main staticd/static_main.c:220
    #9 0xe57bf4ae84c0 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #10 0xe57bf4ae8594 in __libc_start_main_impl ../csu/libc-start.c:360
    #11 0xb38f5f927eec in _start (/usr/lib/frr/staticd+0x27eec) (BuildId: 0cc9ca8acff6f00edfe8380e3ac4febc62c214df)

When a locator is removed, we iterate over the list of SIDs and
uninstall them from the data plane. However, the validity flag of
the SID remains set, and the locator pointer still points to the
freed locator memory.

This causes issues in other parts of the code where we check the
SID validity flag. Since the flag is still set, we assume the SID
is valid and attempt to access the locator pointer, resulting in
use-after-free crashes.

Fix this by:
- Unsetting the STATIC_FLAG_SRV6_SID_VALID flag to mark the SID
  as invalid when its locator is deleted
- Setting the locator pointer to NULL to indicate that the SID
  no longer has a locator associated with it

This ensures that when the locator is removed, associated SIDs are
properly marked as invalid and cannot accidentally reference freed
memory.

Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
Add a test case that reproduces and validates the fix for the
locator deletion crash issue.

Without the fix, removing a locator leaves SIDs with the validity
flag set and a dangling pointer to the freed locator. Attempting
to remove those SIDs from configuration causes a use-after-free
crash when the code checks the validity flag and accesses the
freed locator pointer.

The test reproduces this by:
1. Removing a locator
2. Removing specific SIDs (crash point without the fix)
3. Re-adding the locator
4. Re-adding the removed SIDs

With the fix, the test passes and verifies that the locator
removal/re-addition workflow handles SID lifecycle correctly,
preventing future regressions.

Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
@frrbot frrbot bot added staticd tests Topotests, make check, etc labels Feb 2, 2026
@greptile-apps
Copy link

greptile-apps bot commented Feb 2, 2026

Greptile Overview

Greptile Summary

This PR fixes a critical heap-use-after-free bug in the staticd daemon's SRv6 SID handling code. The bug occurred when a locator was deleted and then individual SIDs were removed from configuration.

Root Cause:
When static_zebra_process_srv6_locator_delete() was called to remove a locator, it would:

  1. Iterate through all SIDs associated with that locator
  2. Uninstall them from the data plane via static_zebra_srv6_sid_uninstall()
  3. Free the locator memory

However, the SID objects still maintained:

  • A pointer to the now-freed locator (sid->locator)
  • The STATIC_FLAG_SRV6_SID_VALID flag set to true

Later, when a SID was deleted from configuration via static_srv6_sid_del() at staticd/static_srv6.c:243, the code would check the validity flag, find it set, and call static_zebra_release_srv6_sid() at staticd/static_zebra.c:1220. This function would then call is_srv6_sid_localonly(sid) at line 1221, which dereferences sid->locator->prefix and sid->locator->block_bits_length, causing a heap-use-after-free crash.

The Fix:
The fix adds two critical lines in static_zebra_process_srv6_locator_delete() after uninstalling each SID:

  • sid->locator = NULL - prevents any code from dereferencing the freed locator
  • UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID) - marks the SID as invalid so static_zebra_release_srv6_sid() won't be called

Test Coverage:
A comprehensive test test_srv6_static_sids_locator_removal_and_readd() was added that:

  1. Removes a locator (uninstalls all SIDs from dataplane)
  2. Removes specific SIDs from configuration while the locator is absent (where the crash would occur)
  3. Re-adds the locator and verifies remaining SIDs are programmed correctly
  4. Re-adds the removed SIDs to restore full configuration

This test validates the fix prevents the crash and ensures proper state management during locator lifecycle operations.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The fix is a minimal, surgical change that adds exactly two lines to prevent a well-documented use-after-free crash. The solution is correct, follows best practices for resource management, and is supported by comprehensive test coverage that validates the exact crash scenario
  • No files require special attention

Important Files Changed

Filename Overview
staticd/static_zebra.c Adds two critical lines to prevent use-after-free by nulling locator pointer and clearing validity flag when locator is deleted
tests/topotests/static_srv6_sids/test_static_srv6_sids.py Adds comprehensive test verifying locator removal/re-addition workflow and SID deletion without crash

Sequence Diagram

sequenceDiagram
    participant Config as Configuration
    participant StaticZebra as static_zebra.c
    participant StaticSrv6 as static_srv6.c
    participant Locator as Locator Memory
    participant SID as SID Object

    Note over Config,SID: Locator Deletion Flow
    Config->>StaticZebra: Delete locator MAIN
    StaticZebra->>StaticZebra: static_zebra_process_srv6_locator_delete()
    
    loop For each SID using this locator
        StaticZebra->>StaticZebra: Check STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA
        StaticZebra->>StaticZebra: static_zebra_srv6_sid_uninstall(sid)
        Note over StaticZebra,SID: NEW FIX - Clear stale references
        StaticZebra->>SID: sid->locator = NULL
        StaticZebra->>SID: UNSET_FLAG(STATIC_FLAG_SRV6_SID_VALID)
    end
    
    StaticZebra->>Locator: Free locator memory
    Note over Locator: Memory freed
    
    Note over Config,SID: SID Deletion Flow (after locator freed)
    Config->>StaticSrv6: Delete SID from config
    StaticSrv6->>StaticSrv6: static_srv6_sid_del(sid)
    StaticSrv6->>StaticSrv6: Check STATIC_FLAG_SRV6_SID_VALID
    
    alt Flag is SET (without fix)
        StaticSrv6->>StaticZebra: static_zebra_release_srv6_sid(sid)
        StaticZebra->>StaticZebra: is_srv6_sid_localonly(sid)
        StaticZebra->>Locator: Access sid->locator->prefix
        Note over StaticZebra,Locator: CRASH - use-after-free
    else Flag is UNSET (with fix)
        Note over StaticSrv6: Skip release - no crash
    end
Loading

@cscarpitta
Copy link
Contributor Author

ci:rerun

Copy link

@ahsalam ahsalam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!
This fixes the issue reported in SONiC sonic-net/sonic-buildimage#22690. Thanks

Copy link
Contributor

@GaladrielZhao GaladrielZhao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Thanks for the fix.

@ton31337
Copy link
Member

ton31337 commented Feb 4, 2026

@Mergifyio backport dev/10.6 stable/10.5 stable/10.4 stable/10.3 stable/10.2

@mergify
Copy link

mergify bot commented Feb 4, 2026

backport dev/10.6 stable/10.5 stable/10.4 stable/10.3 stable/10.2

✅ Backports have been created

Details

Cherry-pick of 66527dd has failed:

On branch mergify/bp/stable/10.5/pr-20660
Your branch is up to date with 'origin/stable/10.5'.

You are currently cherry-picking commit 66527ddcd.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   staticd/static_zebra.c

no changes added to commit (use "git add" and/or "git commit -a")

Cherry-pick of 2a5118f has failed:

On branch mergify/bp/stable/10.5/pr-20660
Your branch is ahead of 'origin/stable/10.5' by 1 commit.
  (use "git push" to publish your local commits)

You are currently cherry-picking commit 2a5118f0a.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   tests/topotests/static_srv6_sids/test_static_srv6_sids.py

no changes added to commit (use "git add" and/or "git commit -a")

To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally

Cherry-pick of 66527dd has failed:

On branch mergify/bp/stable/10.4/pr-20660
Your branch is up to date with 'origin/stable/10.4'.

You are currently cherry-picking commit 66527ddcd.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   staticd/static_zebra.c

no changes added to commit (use "git add" and/or "git commit -a")

Cherry-pick of 2a5118f has failed:

On branch mergify/bp/stable/10.4/pr-20660
Your branch is ahead of 'origin/stable/10.4' by 1 commit.
  (use "git push" to publish your local commits)

You are currently cherry-picking commit 2a5118f0a.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   tests/topotests/static_srv6_sids/test_static_srv6_sids.py

no changes added to commit (use "git add" and/or "git commit -a")

To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally

Cherry-pick of 66527dd has failed:

On branch mergify/bp/stable/10.3/pr-20660
Your branch is up to date with 'origin/stable/10.3'.

You are currently cherry-picking commit 66527ddcd.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   staticd/static_zebra.c

no changes added to commit (use "git add" and/or "git commit -a")

Cherry-pick of 2a5118f has failed:

On branch mergify/bp/stable/10.3/pr-20660
Your branch is ahead of 'origin/stable/10.3' by 1 commit.
  (use "git push" to publish your local commits)

You are currently cherry-picking commit 2a5118f0a.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   tests/topotests/static_srv6_sids/test_static_srv6_sids.py

no changes added to commit (use "git add" and/or "git commit -a")

To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally

Cherry-pick of 66527dd has failed:

On branch mergify/bp/stable/10.2/pr-20660
Your branch is up to date with 'origin/stable/10.2'.

You are currently cherry-picking commit 66527ddcd.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   staticd/static_zebra.c

no changes added to commit (use "git add" and/or "git commit -a")

Cherry-pick of 2a5118f has failed:

On branch mergify/bp/stable/10.2/pr-20660
Your branch is ahead of 'origin/stable/10.2' by 1 commit.
  (use "git push" to publish your local commits)

You are currently cherry-picking commit 2a5118f0a.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add/rm <file>..." as appropriate to mark resolution)
	deleted by us:   tests/topotests/static_srv6_sids/test_static_srv6_sids.py

no changes added to commit (use "git add" and/or "git commit -a")

To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally

@ton31337 ton31337 merged commit 5962985 into FRRouting:master Feb 4, 2026
30 of 51 checks passed
cscarpitta added a commit to cscarpitta/sonic-buildimage that referenced this pull request Feb 4, 2026
Port upstream FRR pull request into SONiC: FRRouting/frr#20660

Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
cscarpitta added a commit to cscarpitta/sonic-buildimage that referenced this pull request Feb 4, 2026
Port upstream FRR pull request into SONiC: FRRouting/frr#20660

Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
Jafaral added a commit that referenced this pull request Feb 5, 2026
…se_after_free_10.4

staticd: Fix SRv6 SID use-after-free on locator deletion (backport #20660 for 10.4)
Jafaral added a commit that referenced this pull request Feb 5, 2026
…se_after_free_10.5

staticd: Fix SRv6 SID use-after-free on locator deletion (backport #20660 for 10.5)
ton31337 added a commit that referenced this pull request Feb 5, 2026
…se_after_free_10.3

staticd: Fix SRv6 SID use-after-free on locator deletion (backport #20660 for 10.3)
ton31337 added a commit that referenced this pull request Feb 5, 2026
staticd: Fix SRv6 SID use-after-free on locator deletion (backport #20660)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants