From 39b52d0fd015382a5089f57b4559a97340c7d4fc Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 24 Sep 2020 19:35:57 +0200 Subject: [PATCH] shared: add nm_utils_uid_to_name()/nm_utils_name_to_uid() helpers These are inspired by systemd. We should replace our calls to getpwuid() and getpwnam() with their thread safe variants. We run possibly multiple threads (e.g. helper threads from GDBus and GResolver). It's hard to be sure that they don't also access the functions. --- shared/nm-glib-aux/nm-shared-utils.c | 79 ++++++++++++++++++++++++++++ shared/nm-glib-aux/nm-shared-utils.h | 3 ++ 2 files changed, 82 insertions(+) diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c index 57c1caeb6b..38a680928e 100644 --- a/shared/nm-glib-aux/nm-shared-utils.c +++ b/shared/nm-glib-aux/nm-shared-utils.c @@ -7,6 +7,7 @@ #include "nm-shared-utils.h" +#include #include #include #include @@ -5636,3 +5637,81 @@ nm_utils_is_specific_hostname (const char *name) return TRUE; } + +/*****************************************************************************/ + +/* taken from systemd's uid_to_name(). */ +char * +nm_utils_uid_to_name (uid_t uid) +{ + gs_free char *buf_heap = NULL; + char buf_stack[4096]; + gsize bufsize; + char *buf; + + bufsize = sizeof (buf_stack); + buf = buf_stack; + + for (;;) { + struct passwd pwbuf; + struct passwd *pw = NULL; + int r; + + r = getpwuid_r (uid, &pwbuf, buf, bufsize, &pw); + if ( r == 0 + && pw) + return nm_strdup_not_empty (pw->pw_name); + + if (r != ERANGE) + return NULL; + + if (bufsize > G_MAXSIZE / 2u) + return NULL; + + bufsize *= 2u; + g_free (buf_heap); + buf_heap = g_malloc (bufsize); + buf = buf_heap; + } +} + +/* taken from systemd's nss_user_record_by_name() */ +gboolean +nm_utils_name_to_uid (const char *name, uid_t *out_uid) +{ + gs_free char *buf_heap = NULL; + char buf_stack[4096]; + gsize bufsize; + char *buf; + + if (!name) + return nm_assert_unreachable_val (FALSE); + + bufsize = sizeof (buf_stack); + buf = buf_stack; + + for (;;) { + struct passwd *result; + struct passwd pwd; + int r; + + r = getpwnam_r (name, &pwd, buf, bufsize, &result); + if (r == 0) { + if (!result) + return FALSE; + NM_SET_OUT (out_uid, pwd.pw_uid); + return TRUE; + } + + if (r != ERANGE) + return FALSE; + + if (bufsize > G_MAXSIZE / 2u) + return FALSE; + + bufsize *= 2u; + g_free (buf_heap); + buf_heap = g_malloc (bufsize); + buf = buf_heap; + } +} diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h index 28a519ae44..f4caf3d74c 100644 --- a/shared/nm-glib-aux/nm-shared-utils.h +++ b/shared/nm-glib-aux/nm-shared-utils.h @@ -2339,4 +2339,7 @@ gboolean nm_utils_is_localhost (const char *name); gboolean nm_utils_is_specific_hostname (const char *name); +char *nm_utils_uid_to_name (uid_t uid); +gboolean nm_utils_name_to_uid (const char *name, uid_t *out_uid); + #endif /* __NM_SHARED_UTILS_H__ */