diff options
| author | Stephen Worley <sworley@cumulusnetworks.com> | 2019-11-14 13:43:11 -0500 |
|---|---|---|
| committer | Stephen Worley <sworley@cumulusnetworks.com> | 2019-11-15 12:33:35 -0500 |
| commit | 257b245cd13e3d836093e8fb5c704d90ef978660 (patch) | |
| tree | ae4c481cfbe64e2e6f90d6a236ac8b5bcf487bfb | |
| parent | 1e5fe0e258a7c029eb2c9aa8b8f19a28196830da (diff) | |
zebra: default ns->info should be default zebra_ns
We were not connecting the default zebra_ns to the default
ns->info at namespace initialization in zebra. Thus, when
we tried to use the `ns_walk_func()` it would ignore the
default zebra_ns since there is no pointer to it from the
ns struct.
Fix this by connecting them in `zebra_ns_init()` and,
if the default ns is not found, exit with failure
since this is not recoverable.
This was found during a crash where we fail to cancel the kernel_read
thread at termination (via the `ns_walk_func()`) and then we
get a netlink notification trying to use the zns struct that has
already been freed.
```
(gdb) bt
\#0 0x00007fc1134dc7bb in raise () from /lib/x86_64-linux-gnu/libc.so.6
\#1 0x00007fc1134c7535 in abort () from /lib/x86_64-linux-gnu/libc.so.6
\#2 0x00007fc113996f8f in core_handler (signo=11, siginfo=0x7ffe5429d070, context=<optimized out>) at lib/sigevent.c:254
\#3 <signal handler called>
\#4 0x0000561880e15449 in if_lookup_by_index_per_ns (ns=0x0, ifindex=174) at zebra/interface.c:269
\#5 0x0000561880e1642c in if_up (ifp=ifp@entry=0x561883076c50) at zebra/interface.c:1043
\#6 0x0000561880e10723 in netlink_link_change (h=0x7ffe5429d8f0, ns_id=<optimized out>, startup=<optimized out>) at zebra/if_netlink.c:1384
\#7 0x0000561880e17e68 in netlink_parse_info (filter=filter@entry=0x561880e17680 <netlink_information_fetch>, nl=nl@entry=0x561882497238, zns=zns@entry=0x7ffe542a5940,
count=count@entry=5, startup=startup@entry=0) at zebra/kernel_netlink.c:932
\#8 0x0000561880e186a5 in kernel_read (thread=<optimized out>) at zebra/kernel_netlink.c:406
\#9 0x00007fc1139a4416 in thread_call (thread=thread@entry=0x7ffe542a5b70) at lib/thread.c:1599
\#10 0x00007fc113974ef8 in frr_run (master=0x5618823c9510) at lib/libfrr.c:1024
\#11 0x0000561880e0b916 in main (argc=8, argv=0x7ffe542a5f78) at zebra/main.c:483
```
Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com>
| -rw-r--r-- | zebra/zebra_errors.c | 6 | ||||
| -rw-r--r-- | zebra/zebra_errors.h | 1 | ||||
| -rw-r--r-- | zebra/zebra_ns.c | 17 |
3 files changed, 21 insertions, 3 deletions
diff --git a/zebra/zebra_errors.c b/zebra/zebra_errors.c index 5a0905d591..ef792d14c2 100644 --- a/zebra/zebra_errors.c +++ b/zebra/zebra_errors.c @@ -316,6 +316,12 @@ static struct log_ref ferr_zebra_err[] = { .description = "Zebra attempted to look up a interface for a particular vrf_id and interface index, but didn't find anything.", .suggestion = "If you entered a command to trigger this error, make sure you entered the arguments correctly. Check your config file for any potential errors. If these look correct, seek help.", }, + { + .code = EC_ZEBRA_NS_NO_DEFAULT, + .title = "Zebra NameSpace failed to find Default", + .description = "Zebra NameSpace subsystem failed to find a Default namespace during initialization.", + .suggestion = "Open an Issue with all relevant log files and restart FRR", + }, /* Warnings */ { .code = EC_ZEBRAING_LM_PROTO_MISMATCH, diff --git a/zebra/zebra_errors.h b/zebra/zebra_errors.h index f9ccc2db28..4625a03ae6 100644 --- a/zebra/zebra_errors.h +++ b/zebra/zebra_errors.h @@ -76,6 +76,7 @@ enum zebra_log_refs { EC_ZEBRA_NHG_SYNC, EC_ZEBRA_NHG_FIB_UPDATE, EC_ZEBRA_IF_LOOKUP_FAILED, + EC_ZEBRA_NS_NO_DEFAULT, /* warnings */ EC_ZEBRA_NS_NOTIFY_READ, EC_ZEBRAING_LM_PROTO_MISMATCH, diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 37f53bf911..4d971cc24f 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -37,6 +37,7 @@ #include "zebra_pbr.h" #include "rib.h" #include "table_manager.h" +#include "zebra_errors.h" extern struct zebra_privs_t zserv_privs; @@ -64,6 +65,9 @@ static int zebra_ns_new(struct ns *ns) { struct zebra_ns *zns; + if (!ns) + return -1; + if (IS_ZEBRA_DEBUG_EVENT) zlog_info("ZNS %s with id %u (created)", ns->name, ns->ns_id); @@ -175,19 +179,26 @@ int zebra_ns_final_shutdown(struct ns *ns) int zebra_ns_init(const char *optional_default_name) { + struct ns *default_ns; ns_id_t ns_id; ns_id_t ns_id_external; - dzns = zebra_ns_alloc(); - frr_with_privs(&zserv_privs) { ns_id = zebra_ns_id_get_default(); } ns_id_external = ns_map_nsid_with_external(ns_id, true); ns_init_management(ns_id_external, ns_id); + default_ns = ns_lookup(ns_get_default_id()); + if (!default_ns) { + flog_err(EC_ZEBRA_NS_NO_DEFAULT, + "%s: failed to find default ns", __func__); + exit(EXIT_FAILURE); /* This is non-recoverable */ + } + /* Do any needed per-NS data structure allocation. */ - dzns->if_table = route_table_init(); + zebra_ns_new(default_ns); + dzns = default_ns->info; /* Register zebra VRF callbacks, create and activate default VRF. */ zebra_vrf_init(); |
