forked from Mirror/frr

- Addressed memory leak by removing `&c->peer_notifier` from the notifier list on termination. Retaining it caused the notifier list to stay active, preventing the deletion of `c->cur.peer` thereby causing a memory leak. - Reordered termination steps to call `vrf_terminate` before `nhrp_vc_terminate`, preventing a heap-use-after-free issue when `nhrp_vc_notify_del` is invoked in `nhrp_peer_check_delete`. - Added an if statement to avoid passing NULL as hash to `hash_release`, which leads to a SIGSEGV. The ASan leak log for reference: ``` *********************************************************************************** Address Sanitizer Error detected in nhrp_topo.test_nhrp_topo/r1.asan.nhrpd.20265 ================================================================= ==20265==ERROR: LeakSanitizer: detected memory leaks Direct leak of 112 byte(s) in 1 object(s) allocated from: #0 0x7f80270c9b40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40) #1 0x7f8026ac1eb8 in qmalloc lib/memory.c:100 #2 0x560fd648f0a6 in nhrp_peer_create nhrpd/nhrp_peer.c:175 #3 0x7f8026a88d3f in hash_get lib/hash.c:147 #4 0x560fd6490a5d in nhrp_peer_get nhrpd/nhrp_peer.c:228 #5 0x560fd648a51a in nhrp_nhs_resolve_cb nhrpd/nhrp_nhs.c:297 #6 0x7f80266b000f in resolver_cb_literal lib/resolver.c:234 #7 0x7f8026b62e0e in event_call lib/event.c:1969 #8 0x7f8026aa5437 in frr_run lib/libfrr.c:1213 #9 0x560fd6488b4f in main nhrpd/nhrp_main.c:166 #10 0x7f8025eb2c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86) SUMMARY: AddressSanitizer: 112 byte(s) leaked in 1 allocation(s). *********************************************************************************** *********************************************************************************** Address Sanitizer Error detected in nhrp_topo.test_nhrp_topo/r2.asan.nhrpd.20400 ================================================================= ==20400==ERROR: LeakSanitizer: detected memory leaks Direct leak of 112 byte(s) in 1 object(s) allocated from: #0 0x7fb6e3ca5b40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40) #1 0x7fb6e369deb8 in qmalloc lib/memory.c:100 #2 0x562652de40a6 in nhrp_peer_create nhrpd/nhrp_peer.c:175 #3 0x7fb6e3664d3f in hash_get lib/hash.c:147 #4 0x562652de5a5d in nhrp_peer_get nhrpd/nhrp_peer.c:228 #5 0x562652de1e8e in nhrp_packet_recvraw nhrpd/nhrp_packet.c:325 #6 0x7fb6e373ee0e in event_call lib/event.c:1969 #7 0x7fb6e3681437 in frr_run lib/libfrr.c:1213 #8 0x562652dddb4f in main nhrpd/nhrp_main.c:166 #9 0x7fb6e2a8ec86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86) SUMMARY: AddressSanitizer: 112 byte(s) leaked in 1 allocation(s). *********************************************************************************** ``` Signed-off-by: Keelan Cannoo <keelan.cannoo@icloud.com>
169 lines
3.1 KiB
C
169 lines
3.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/* NHRP daemon main functions
|
|
* Copyright (c) 2014-2015 Timo Teräs
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "zebra.h"
|
|
#include "privs.h"
|
|
#include "getopt.h"
|
|
#include "frrevent.h"
|
|
#include "sigevent.h"
|
|
#include "lib/version.h"
|
|
#include "log.h"
|
|
#include "memory.h"
|
|
#include "command.h"
|
|
#include "libfrr.h"
|
|
#include "filter.h"
|
|
|
|
#include "nhrpd.h"
|
|
#include "nhrp_errors.h"
|
|
|
|
DEFINE_MGROUP(NHRPD, "NHRP");
|
|
|
|
unsigned int debug_flags = 0;
|
|
|
|
struct event_loop *master;
|
|
struct timeval current_time;
|
|
|
|
/* nhrpd options. */
|
|
struct option longopts[] = {{0}};
|
|
|
|
/* nhrpd privileges */
|
|
static zebra_capabilities_t _caps_p[] = {
|
|
ZCAP_NET_RAW, ZCAP_NET_ADMIN,
|
|
ZCAP_DAC_OVERRIDE, /* for now needed to write to
|
|
/proc/sys/net/ipv4/<if>/send_redirect */
|
|
};
|
|
|
|
struct zebra_privs_t nhrpd_privs = {
|
|
#if defined(FRR_USER) && defined(FRR_GROUP)
|
|
.user = FRR_USER,
|
|
.group = FRR_GROUP,
|
|
#endif
|
|
#ifdef VTY_GROUP
|
|
.vty_group = VTY_GROUP,
|
|
#endif
|
|
.caps_p = _caps_p,
|
|
.cap_num_p = array_size(_caps_p),
|
|
.cap_num_i = 0
|
|
};
|
|
|
|
|
|
static void parse_arguments(int argc, char **argv)
|
|
{
|
|
int opt;
|
|
|
|
while (1) {
|
|
opt = frr_getopt(argc, argv, 0);
|
|
if (opt < 0)
|
|
break;
|
|
|
|
switch (opt) {
|
|
case 0:
|
|
break;
|
|
default:
|
|
frr_help_exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void nhrp_sigusr1(void)
|
|
{
|
|
zlog_rotate();
|
|
}
|
|
|
|
static void nhrp_request_stop(void)
|
|
{
|
|
debugf(NHRP_DEBUG_COMMON, "Exiting...");
|
|
frr_early_fini();
|
|
|
|
nhrp_shortcut_terminate();
|
|
nhrp_nhs_terminate();
|
|
nhrp_zebra_terminate();
|
|
vici_terminate();
|
|
evmgr_terminate();
|
|
vrf_terminate();
|
|
nhrp_vc_terminate();
|
|
|
|
debugf(NHRP_DEBUG_COMMON, "Done.");
|
|
frr_fini();
|
|
|
|
exit(0);
|
|
}
|
|
|
|
static struct frr_signal_t sighandlers[] = {
|
|
{
|
|
.signal = SIGUSR1,
|
|
.handler = &nhrp_sigusr1,
|
|
},
|
|
{
|
|
.signal = SIGINT,
|
|
.handler = &nhrp_request_stop,
|
|
},
|
|
{
|
|
.signal = SIGTERM,
|
|
.handler = &nhrp_request_stop,
|
|
},
|
|
};
|
|
|
|
static const struct frr_yang_module_info *const nhrpd_yang_modules[] = {
|
|
&frr_filter_info,
|
|
&frr_interface_info,
|
|
&frr_vrf_info,
|
|
};
|
|
|
|
FRR_DAEMON_INFO(nhrpd, NHRP, .vty_port = NHRP_VTY_PORT,
|
|
|
|
.proghelp = "Implementation of the NHRP routing protocol.",
|
|
|
|
.signals = sighandlers, .n_signals = array_size(sighandlers),
|
|
|
|
.privs = &nhrpd_privs, .yang_modules = nhrpd_yang_modules,
|
|
.n_yang_modules = array_size(nhrpd_yang_modules),
|
|
);
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
frr_preinit(&nhrpd_di, argc, argv);
|
|
frr_opt_add("", longopts, "");
|
|
|
|
parse_arguments(argc, argv);
|
|
|
|
/* Library inits. */
|
|
master = frr_init();
|
|
nhrp_error_init();
|
|
vrf_init(NULL, NULL, NULL, NULL);
|
|
nhrp_interface_init();
|
|
resolver_init(master);
|
|
|
|
/*
|
|
* Run with elevated capabilities, as for all netlink activity
|
|
* we need privileges anyway.
|
|
* The assert is for clang SA code where it does
|
|
* not see the change function being set in lib
|
|
*/
|
|
assert(nhrpd_privs.change);
|
|
nhrpd_privs.change(ZPRIVS_RAISE);
|
|
|
|
evmgr_init();
|
|
nhrp_vc_init();
|
|
nhrp_packet_init();
|
|
vici_init();
|
|
if_zapi_callbacks(nhrp_ifp_create, nhrp_ifp_up,
|
|
nhrp_ifp_down, nhrp_ifp_destroy);
|
|
nhrp_zebra_init();
|
|
nhrp_shortcut_init();
|
|
|
|
nhrp_config_init();
|
|
|
|
frr_config_fork();
|
|
frr_run(master);
|
|
return 0;
|
|
}
|