From 86b61156743b7ebdc049450a6f88452890fd9a61 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 13 Aug 2012 15:30:39 +0200 Subject: Use PTHREAD_MUTEX_ROBUST to avoid deadlock in the client https://fedorahosted.org/sssd/ticket/1460 --- Makefile.am | 12 ++++++- configure.ac | 15 +++++++- src/sss_client/common.c | 96 +++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 115 insertions(+), 8 deletions(-) diff --git a/Makefile.am b/Makefile.am index 571ea55ca..b553db2a1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -455,6 +455,10 @@ if BUILD_SUDO SSSD_DOCS += libsss_sudo_doc endif +if HAVE_PTHREAD +CLIENT_LIBS = -lpthread +endif + ##################### # Utility libraries # ##################### @@ -741,6 +745,7 @@ sss_sudo_cli_SOURCES = \ src/sss_client/common.c \ src/sss_client/sudo_testcli/sudo_testcli.c sss_sudo_cli_CFLAGS = $(AM_CFLAGS) +sss_sudo_cli_LDFLAGS = $(CLIENT_LIBS) sss_sudo_cli_LDADD = \ libsss_sudo.la endif @@ -1124,7 +1129,7 @@ autofs_test_client_SOURCES = src/sss_client/autofs/autofs_test_client.c \ src/sss_client/autofs/sss_autofs.c \ src/sss_client/common.c autofs_test_client_CFLAGS = $(AM_CFLAGS) -autofs_test_client_LDFLAGS = -lpopt +autofs_test_client_LDFLAGS = -lpopt $(CLIENT_LIBS) endif #################### @@ -1146,6 +1151,7 @@ libnss_sss_la_SOURCES = \ src/sss_client/nss_mc_group.c \ src/sss_client/nss_mc.h libnss_sss_la_LDFLAGS = \ + $(CLIENT_LIBS) \ -module \ -version-info 2:0:0 \ -Wl,--version-script,$(srcdir)/src/sss_client/sss_nss.exports @@ -1159,6 +1165,7 @@ pam_sss_la_SOURCES = \ src/sss_client/sss_pam_macros.h pam_sss_la_LDFLAGS = \ + $(CLIENT_LIBS) \ -lpam \ -module \ -avoid-version \ @@ -1174,6 +1181,7 @@ libsss_sudo_la_SOURCES = \ src/sss_client/sudo/sss_sudo.h \ src/sss_client/sudo/sss_sudo_private.h libsss_sudo_la_LDFLAGS = \ + $(CLIENT_LIBS) \ -Wl,--version-script,$(srcdir)/src/sss_client/sss_sudo.exports \ -version-info 2:0:1 @@ -1193,6 +1201,7 @@ libsss_autofs_la_SOURCES = \ src/sss_client/autofs/sss_autofs_private.h libsss_autofs_la_LDFLAGS = \ + $(CLIENT_LIBS) \ -module \ -avoid-version \ -Wl,--version-script,$(srcdir)/src/sss_client/autofs/sss_autofs.exports @@ -1512,6 +1521,7 @@ sssd_pac_plugin_la_CFLAGS = \ $(AM_CFLAGS) \ $(KRB5_CFLAGS) sssd_pac_plugin_la_LDFLAGS = \ + $(CLIENT_LIBS) \ -lkrb5 \ -avoid-version \ -module diff --git a/configure.ac b/configure.ac index 5bb82a77d..5cd8c723f 100644 --- a/configure.ac +++ b/configure.ac @@ -47,9 +47,22 @@ BUILD_WITH_SHARED_BUILD_DIR AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;]])], - [AC_DEFINE([HAVE_PTHREAD], [1], [Pthread mutexes available.])], + [AC_DEFINE([HAVE_PTHREAD], [1], [Pthread mutexes available.]) + HAVE_PTHREAD=1 + ], [AC_MSG_WARN([Pthread library not found! Clients will not be thread safe...])]) + +AM_CONDITIONAL([HAVE_PTHREAD], [test x"$HAVE_PTHREAD" != "x"]) + +SAVE_LIBS=$LIBS +LIBS="$LIBS -lpthread" +AC_CHECK_FUNCS([ pthread_mutexattr_setrobust \ + pthread_mutex_consistent \ + pthread_mutexattr_setrobust_np \ + pthread_mutex_consistent_np ]) +LIBS=$SAVE_LIBS + #Check for PAM headers AC_CHECK_HEADERS([security/pam_appl.h security/pam_misc.h security/pam_modules.h], [AC_CHECK_LIB(pam, pam_get_item, [ PAM_LIBS="-lpam" ], [AC_MSG_ERROR([PAM must support pam_get_item])])], diff --git a/src/sss_client/common.c b/src/sss_client/common.c index 59eae3b1f..5b1751593 100644 --- a/src/sss_client/common.c +++ b/src/sss_client/common.c @@ -976,24 +976,108 @@ errno_t sss_strnlen(const char *str, size_t maxlen, size_t *len) } #if HAVE_PTHREAD -static pthread_mutex_t sss_nss_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t sss_pam_mutex = PTHREAD_MUTEX_INITIALIZER; +typedef void (*sss_mutex_init)(void); +struct sss_mutex { + pthread_mutex_t mtx; + + pthread_once_t once; + sss_mutex_init init; +}; + +static void sss_nss_mt_init(void); +static void sss_pam_mt_init(void); + +static struct sss_mutex sss_nss_mtx = { .mtx = PTHREAD_MUTEX_INITIALIZER, + .once = PTHREAD_ONCE_INIT, + .init = sss_nss_mt_init }; + +static struct sss_mutex sss_pam_mtx = { .mtx = PTHREAD_MUTEX_INITIALIZER, + .once = PTHREAD_ONCE_INIT, + .init = sss_pam_mt_init }; + + +/* Wrappers for robust mutex support */ +static int sss_mutexattr_setrobust (pthread_mutexattr_t *attr) +{ +#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST + return pthread_mutexattr_setrobust(attr, PTHREAD_MUTEX_ROBUST); +#elif HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP + return pthread_mutexattr_setrobust_np(attr, PTHREAD_MUTEX_ROBUST_NP); +#else +#warning Robust mutexes are not supported on this platform. + return 0; +#endif +} + +static int sss_mutex_consistent(pthread_mutex_t *mtx) +{ +#ifdef HAVE_PTHREAD_MUTEX_CONSISTENT + return pthread_mutex_consistent(mtx); +#elif HAVE_PTHREAD_MUTEX_CONSISTENT_NP + return pthread_mutex_consistent_np(mtx); +#else +#warning Robust mutexes are not supported on this platform. + return 0; +#endif +} + +/* Generic mutex init, lock, unlock functions */ +static void sss_mt_init(struct sss_mutex *m) +{ + pthread_mutexattr_t attr; + + if (pthread_mutexattr_init(&attr) != 0) { + return; + } + if (sss_mutexattr_setrobust(&attr) != 0) { + return; + } + + pthread_mutex_init(&m->mtx, &attr); + pthread_mutexattr_destroy(&attr); +} + +static void sss_mt_lock(struct sss_mutex *m) +{ + pthread_once(&m->once, m->init); + if (pthread_mutex_lock(&m->mtx) == EOWNERDEAD) { + sss_cli_close_socket(); + sss_mutex_consistent(&m->mtx); + } +} + +static void sss_mt_unlock(struct sss_mutex *m) +{ + pthread_mutex_unlock(&m->mtx); +} + +/* NSS mutex wrappers */ +static void sss_nss_mt_init(void) +{ + sss_mt_init(&sss_nss_mtx); +} void sss_nss_lock(void) { - pthread_mutex_lock(&sss_nss_mutex); + sss_mt_lock(&sss_nss_mtx); } void sss_nss_unlock(void) { - pthread_mutex_unlock(&sss_nss_mutex); + sss_mt_unlock(&sss_nss_mtx); +} + +/* NSS mutex wrappers */ +static void sss_pam_mt_init(void) +{ + sss_mt_init(&sss_pam_mtx); } void sss_pam_lock(void) { - pthread_mutex_lock(&sss_pam_mutex); + sss_mt_lock(&sss_pam_mtx); } void sss_pam_unlock(void) { - pthread_mutex_unlock(&sss_pam_mutex); + sss_mt_unlock(&sss_pam_mtx); } #else -- cgit