From 7d0b643e9f1f4dfcae2e0e86dc0efea5e559bb22 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 16 Dec 2022 18:11:33 +0100 Subject: [PATCH] l3cfg: make nm_l3_config_data_cmp_full() thread-safe Let's not have unexpected, non-thread-safe functions somewhere deep down. NML3ConfigData -- as a data structure -- is not thread-safe, nor aims it to be. However, our code(!) should be thread-safe. That means, it should be possible to call our code on separate data from multiple threads. Violating that is a code smell and a foot gun. This basically means that code should not access global data (unless thread-local) or that the access to global-data needs to be synchronized. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1806 --- src/core/nm-l3-config-data.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 347332933a..030c1101f5 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -2231,14 +2231,23 @@ static const NML3ConfigData * get_empty_l3cd(void) { static NML3ConfigData *empty_l3cd; + NML3ConfigData *l3cd; - if (!empty_l3cd) { - empty_l3cd = - nm_l3_config_data_new(nm_dedup_multi_index_new(), 1, NM_IP_CONFIG_SOURCE_UNKNOWN); - empty_l3cd->ifindex = 0; +again: + l3cd = g_atomic_pointer_get(&empty_l3cd); + if (G_UNLIKELY(!l3cd)) { + l3cd = nm_l3_config_data_new(nm_dedup_multi_index_new(), 1, NM_IP_CONFIG_SOURCE_UNKNOWN); + l3cd->ifindex = 0; + + nm_l3_config_data_seal(l3cd); + + if (!g_atomic_pointer_compare_and_exchange(&empty_l3cd, NULL, l3cd)) { + nm_l3_config_data_unref(l3cd); + goto again; + } } - return empty_l3cd; + return l3cd; } int