diff options
author | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2022-12-12 13:48:33 +0100 |
---|---|---|
committer | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2022-12-12 14:39:17 +0100 |
commit | eb23e17fc7683fe2ef712e3b04b7b2a4a175dd3b (patch) | |
tree | c348863bf958ee84666a1bbcffccade543ab91bb /lib/privs.c | |
parent | Merge pull request #12487 from anlancs/fix/fix-doc-ospf (diff) | |
download | frr-eb23e17fc7683fe2ef712e3b04b7b2a4a175dd3b.tar.xz frr-eb23e17fc7683fe2ef712e3b04b7b2a4a175dd3b.zip |
lib: fix capability double resource allocation
Don't let `zprivs_caps_init` allocate resources without checking if
there were other caps previously allocated.
This fixes a memory leak that happens on daemons that `fork()` and reuse
the `<daemon>_di` (see `ldpd`/`lde`/`ldpe` code).
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
Diffstat (limited to 'lib/privs.c')
-rw-r--r-- | lib/privs.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/lib/privs.c b/lib/privs.c index 71416beeb..08461d8d5 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -261,8 +261,34 @@ zebra_privs_current_t zprivs_state_caps(void) return ZPRIVS_LOWERED; } +/** Release private cap state if allocated. */ +static void zprivs_state_free_caps(void) +{ + if (zprivs_state.syscaps_p) { + if (zprivs_state.syscaps_p->num) + XFREE(MTYPE_PRIVS, zprivs_state.syscaps_p->caps); + + XFREE(MTYPE_PRIVS, zprivs_state.syscaps_p); + } + + if (zprivs_state.syscaps_i) { + if (zprivs_state.syscaps_i->num) + XFREE(MTYPE_PRIVS, zprivs_state.syscaps_i->caps); + + XFREE(MTYPE_PRIVS, zprivs_state.syscaps_i); + } + + if (zprivs_state.caps) { + cap_free(zprivs_state.caps); + zprivs_state.caps = NULL; + } +} + static void zprivs_caps_init(struct zebra_privs_t *zprivs) { + /* Release allocated zcaps if this function was called before. */ + zprivs_state_free_caps(); + zprivs_state.syscaps_p = zcaps2sys(zprivs->caps_p, zprivs->cap_num_p); zprivs_state.syscaps_i = zcaps2sys(zprivs->caps_i, zprivs->cap_num_i); @@ -362,18 +388,7 @@ static void zprivs_caps_terminate(void) exit(1); } - /* free up private state */ - if (zprivs_state.syscaps_p && zprivs_state.syscaps_p->num) { - XFREE(MTYPE_PRIVS, zprivs_state.syscaps_p->caps); - XFREE(MTYPE_PRIVS, zprivs_state.syscaps_p); - } - - if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num) { - XFREE(MTYPE_PRIVS, zprivs_state.syscaps_i->caps); - XFREE(MTYPE_PRIVS, zprivs_state.syscaps_i); - } - - cap_free(zprivs_state.caps); + zprivs_state_free_caps(); } #else /* !HAVE_LCAPS */ #error "no Linux capabilities, dazed and confused..." |