summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2012-08-13 15:30:39 +0200
committerJakub Hrozek <jhrozek@redhat.com>2012-08-27 16:32:01 +0200
commit86b61156743b7ebdc049450a6f88452890fd9a61 (patch)
treeb155c68344e2adda5085047eee3f7dd5e98f6bcc
parentfd2840c15ce480ef017ce880a6ac8b10e22ae9d2 (diff)
downloadsssd-86b61156743b7ebdc049450a6f88452890fd9a61.tar.gz
sssd-86b61156743b7ebdc049450a6f88452890fd9a61.tar.xz
sssd-86b61156743b7ebdc049450a6f88452890fd9a61.zip
Use PTHREAD_MUTEX_ROBUST to avoid deadlock in the client
https://fedorahosted.org/sssd/ticket/1460
-rw-r--r--Makefile.am12
-rw-r--r--configure.ac15
-rw-r--r--src/sss_client/common.c96
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.h>]],
[[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