If a second context is created, the second call to nft_ctx_free() leads to freeing invalid pointers in nft_exit(). Fix this by introducing a reference counter so that neither nft_init() nor nft_exit() run more than once in a row. This reference counter has to be protected from parallel access. Do this using a mutex in a way that once nft_init() returns, the first call to that function running in parallel is guaranteed to be finished - otherwise it could happen that things being initialized in one thread are already accessed in another one. Signed-off-by: Phil Sutter <phil@xxxxxx> --- src/libnftables.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libnftables.c b/src/libnftables.c index e8fa6742f7d17..9df9658930c39 100644 --- a/src/libnftables.c +++ b/src/libnftables.c @@ -14,6 +14,7 @@ #include <iface.h> #include <errno.h> +#include <pthread.h> #include <stdlib.h> #include <string.h> @@ -102,8 +103,16 @@ err1: return ret; } +static int nft_refcnt; +static pthread_mutex_t nft_refcnt_mutex = PTHREAD_MUTEX_INITIALIZER; + static void nft_init(void) { + pthread_mutex_lock(&nft_refcnt_mutex); + + if (nft_refcnt++) + goto unlock; + mark_table_init(); realm_table_rt_init(); devgroup_table_init(); @@ -113,15 +122,26 @@ static void nft_init(void) #ifdef HAVE_LIBXTABLES xt_init(); #endif + +unlock: + pthread_mutex_unlock(&nft_refcnt_mutex); } static void nft_exit(void) { + pthread_mutex_lock(&nft_refcnt_mutex); + + if (--nft_refcnt) + goto unlock; + ct_label_table_exit(); realm_table_rt_exit(); devgroup_table_exit(); realm_table_meta_exit(); mark_table_exit(); + +unlock: + pthread_mutex_unlock(&nft_refcnt_mutex); } int nft_ctx_add_include_path(struct nft_ctx *ctx, const char *path) -- 2.13.1 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html