summaryrefslogtreecommitdiffstats
path: root/lib/privs.c
diff options
context:
space:
mode:
authorRafael Zalamena <rzalamena@opensourcerouting.org>2022-12-12 13:48:33 +0100
committerRafael Zalamena <rzalamena@opensourcerouting.org>2022-12-12 14:39:17 +0100
commiteb23e17fc7683fe2ef712e3b04b7b2a4a175dd3b (patch)
treec348863bf958ee84666a1bbcffccade543ab91bb /lib/privs.c
parentMerge pull request #12487 from anlancs/fix/fix-doc-ospf (diff)
downloadfrr-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.c39
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..."