zebra: fix heap-after-free on shutdown in netns mode

Seen with bfd_vrf_topo1 on Ubuntu 22.04 hwe.

Do not call ns_delete() from zebra_vrf_delete(), which calls
zebra_ns_delete().

- If a netns is removed from the system, vrf_delete()->zebra_vrf_delete()
  is called before calling ns_delete() (see zebra_ns_notify.c).
- If zebra is terminating, zebra_ns_final_shutdown() will call
  zebra_vrf_delete().

> ==616172==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000ae3a4 at pc 0x556cdc178d8f bp 0x7ffe4f41ace0 sp 0x7ffe4f41acd0
> READ of size 4 at 0x6160000ae3a4 thread T0
>     #0 0x556cdc178d8e in ctx_info_from_zns zebra/zebra_dplane.c:3394
>     #1 0x556cdc178f55 in dplane_ctx_ns_init zebra/zebra_dplane.c:3410
>     #2 0x556cdc17b829 in dplane_ctx_nexthop_init zebra/zebra_dplane.c:3759
>     #3 0x556cdc18095f in dplane_nexthop_update_internal zebra/zebra_dplane.c:4566
>     #4 0x556cdc1813f1 in dplane_nexthop_delete zebra/zebra_dplane.c:4793
>     #5 0x556cdc229234 in zebra_nhg_uninstall_kernel zebra/zebra_nhg.c:3484
>     #6 0x556cdc21f8fe in zebra_nhg_decrement_ref zebra/zebra_nhg.c:1804
>     #7 0x556cdc24b05a in route_entry_update_nhe zebra/zebra_rib.c:456
>     #8 0x556cdc255083 in rib_re_nhg_free zebra/zebra_rib.c:2633
>     #9 0x556cdc25e3bb in rib_unlink zebra/zebra_rib.c:4049
>     #10 0x556cdc24c9b0 in zebra_rtable_node_cleanup zebra/zebra_rib.c:903
>     #11 0x7fb25c173144 in route_node_free lib/table.c:75
>     #12 0x7fb25c17337f in route_table_free lib/table.c:111
>     #13 0x7fb25c172fe4 in route_table_finish lib/table.c:46
>     #14 0x556cdc266f62 in zebra_router_free_table zebra/zebra_router.c:191
>     #15 0x556cdc2673ef in zebra_router_terminate zebra/zebra_router.c:243
>     #16 0x556cdc10638b in zebra_finalize zebra/main.c:240
>     #17 0x7fb25c18e012 in event_call lib/event.c:2019
>     #18 0x7fb25c04afc6 in frr_run lib/libfrr.c:1247
>     #19 0x556cdc106deb in main zebra/main.c:543
>     #20 0x7fb25ba29d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
>     #21 0x7fb25ba29e3f in __libc_start_main_impl ../csu/libc-start.c:392
>     #22 0x556cdc0c7ed4 in _start (/usr/lib/frr/zebra+0x192ed4)
>
> 0x6160000ae3a4 is located 36 bytes inside of 592-byte region [0x6160000ae380,0x6160000ae5d0)
> freed by thread T0 here:
>     #0 0x7fb25c6b4537 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127
>     #1 0x7fb25c0790e3 in qfree lib/memory.c:131
>     #2 0x556cdc22d9c9 in zebra_ns_delete zebra/zebra_ns.c:261
>     #3 0x7fb25c0ac400 in ns_delete lib/netns_linux.c:319
>     #4 0x556cdc28026a in zebra_vrf_delete zebra/zebra_vrf.c:343
>     #5 0x7fb25c197443 in vrf_delete lib/vrf.c:282
>     #6 0x7fb25c1987e8 in vrf_terminate_single lib/vrf.c:601
>     #7 0x7fb25c197a7a in vrf_iterate lib/vrf.c:394
>     #8 0x7fb25c198834 in vrf_terminate lib/vrf.c:609
>     #9 0x556cdc106345 in zebra_finalize zebra/main.c:223
>     #10 0x7fb25c18e012 in event_call lib/event.c:2019
>     #11 0x7fb25c04afc6 in frr_run lib/libfrr.c:1247
>     #12 0x556cdc106deb in main zebra/main.c:543
>     #13 0x7fb25ba29d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
>
> previously allocated by thread T0 here:
>     #0 0x7fb25c6b4a57 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
>     #1 0x7fb25c078f91 in qcalloc lib/memory.c:106
>     #2 0x556cdc22d6a1 in zebra_ns_new zebra/zebra_ns.c:231
>     #3 0x556cdc22e30b in zebra_ns_init zebra/zebra_ns.c:429
>     #4 0x556cdc106cec in main zebra/main.c:480
>     #5 0x7fb25ba29d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
>
> SUMMARY: AddressSanitizer: heap-use-after-free zebra/zebra_dplane.c:3394 in ctx_info_from_zns

Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
This commit is contained in:
Louis Scalbert 2025-04-11 14:07:30 +02:00
parent dc37bff8c0
commit 4cd8ee27a3

View file

@ -339,11 +339,6 @@ static int zebra_vrf_delete(struct vrf *vrf)
otable_fini(&zvrf->other_tables);
XFREE(MTYPE_ZEBRA_VRF, zvrf);
if (vrf->ns_ctxt) {
ns_delete(vrf->ns_ctxt);
vrf->ns_ctxt = NULL;
}
vrf->info = NULL;
return 0;