From 31dbcb81fe7ac5e718bdcaba461eb01c1d73b600 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 18 Jan 2022 18:21:01 +0100 Subject: [PATCH] core: make nm_utils_get_nm_[ug]id() thread safe While NetworkManager is of course (mostly) single threaded, our static functions really should be thread safe. "mostly" single threaded because we have GDBus's worker thread, we use a thread for writing non-blocking SR-IOV sysctl, in the past (or still?) we used a thread for async glibc resolver. Anyway, a low-level function like must be thread safe, when it uses global data. Granted, the initialize-once pattern with the flag and the int variable, is probably in many cases good enough. But it makes me unhappy, the thought of accessing static data without a synchronized operation. --- src/core/nm-core-utils.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c index 1db74e5eb9..e05638e43c 100644 --- a/src/core/nm-core-utils.c +++ b/src/core/nm-core-utils.c @@ -5157,14 +5157,22 @@ nm_utils_spawn_helper_finish(GAsyncResult *result, GError **error) uid_t nm_utils_get_nm_uid(void) { - static uint8_t nm_uid_flag = 0; - static uid_t nm_uid; + static int u_static = -1; + int u; - if (!nm_uid_flag) { - nm_uid = geteuid(); - nm_uid_flag = 1; +again: + if ((u = g_atomic_int_get(&u_static)) == -1) { + uid_t u2; + + u2 = geteuid(); + u = u2; + nm_assert(u == u2); + nm_assert(u >= 0); + if (!g_atomic_int_compare_and_exchange(&u_static, -1, u)) + goto again; } - return nm_uid; + + return u; } /** @@ -5176,12 +5184,20 @@ nm_utils_get_nm_uid(void) gid_t nm_utils_get_nm_gid(void) { - static uint8_t nm_gid_flag = 0; - static gid_t nm_gid; + static int g_static = -1; + int g; - if (!nm_gid_flag) { - nm_gid = getegid(); - nm_gid_flag = 1; +again: + if ((g = g_atomic_int_get(&g_static)) == -1) { + gid_t g2; + + g2 = geteuid(); + g = g2; + nm_assert(g == g2); + nm_assert(g >= 0); + if (!g_atomic_int_compare_and_exchange(&g_static, -1, g)) + goto again; } - return nm_gid; + + return g; }