From 28fb9f32d74e732e3bf4e12239756a2cc0c196d1 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 28 Jun 2021 10:19:16 -0400 Subject: [PATCH] TT#91151 init kernel SRTP keys lock-free prevents possible deadlocks Change-Id: I8057ac92b12bcbf36bbf63135870eef67acea89a --- kernel-module/xt_RTPENGINE.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 1eaf725e0..a89ce57a1 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -1609,8 +1609,9 @@ static int proc_list_show(struct seq_file *f, void *v) { // all outputs filled? _r_lock(&g->outputs_lock, flags); if (g->outputs_unfilled) { - seq_printf(f, " outputs not fully filled (%u missing)\n", g->outputs_unfilled); + unsigned int uf = g->outputs_unfilled; _r_unlock(&g->outputs_lock, flags); + seq_printf(f, " outputs not fully filled (%u missing)\n", uf); goto out; } _r_unlock(&g->outputs_lock, flags); @@ -2400,8 +2401,9 @@ static int table_add_destination(struct rtpengine_table *t, struct rtpengine_des _w_lock(&g->outputs_lock, flags); + err = -EBUSY; if (!g->outputs_unfilled) - panic("BUG num of unfilled outputs %u", g->outputs_unfilled); + goto out; // out of range entry? err = -ERANGE; @@ -2413,13 +2415,27 @@ static int table_add_destination(struct rtpengine_table *t, struct rtpengine_des if (g->outputs[i->num].output.src_addr.family) goto out; + g->outputs[i->num].output = i->output; + + // init crypto stuff lock free: the "output" is already filled so we + // know it's there, but outputs_unfilled hasn't been decreased yet, so + // this won't be used until we do, which makes it safe to do it lock + // free + + _w_unlock(&g->outputs_lock, flags); + spin_lock_init(&g->outputs[i->num].encrypt.lock); crypto_context_init(&g->outputs[i->num].encrypt, &i->output.encrypt); err = gen_session_keys(&g->outputs[i->num].encrypt, &i->output.encrypt); + + // re-acquire lock and finish up: decreasing outputs_unfillled to zero + // makes this usable + + _w_lock(&g->outputs_lock, flags); + if (err) goto out; - g->outputs[i->num].output = i->output; g->outputs_unfilled--; err = 0;