diff --git a/.gitignore b/.gitignore
index 9a5cfaf..0df1015 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/p11-kit-0.18.7.tar.gz
+SOURCES/p11-kit-0.20.7.tar.gz
diff --git a/.p11-kit.metadata b/.p11-kit.metadata
index 7695c95..2d7d667 100644
--- a/.p11-kit.metadata
+++ b/.p11-kit.metadata
@@ -1 +1 @@
-c4be252d13d045cb403fe32db4de286f241d49ff SOURCES/p11-kit-0.18.7.tar.gz
+7b486d570fddfe91ff33c49e0672a4338bab4643 SOURCES/p11-kit-0.20.7.tar.gz
diff --git a/SOURCES/p11-kit-extract-trust b/SOURCES/p11-kit-extract-trust
deleted file mode 100755
index fe9c991..0000000
--- a/SOURCES/p11-kit-extract-trust
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/bash
-
-set -e
-
-if test "$UID" != "0"; then
-	echo "p11-kit: the 'extract-trust' command must be run as root" >&2
-	exit 2
-fi
-
-if test $# -gt 1; then
-	echo "p11-kit: no additional arguments are supported for this command" >&2
-	exit 2
-fi
-
-exec /usr/bin/update-ca-trust
-
diff --git a/SOURCES/pthread-atfork-fix-deadlock.patch b/SOURCES/pthread-atfork-fix-deadlock.patch
new file mode 100644
index 0000000..f6f7f15
--- /dev/null
+++ b/SOURCES/pthread-atfork-fix-deadlock.patch
@@ -0,0 +1,421 @@
+From 0ecc141f372b375ddd2087a8ca406797976f03bf Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw@redhat.com>
+Date: Fri, 3 Oct 2014 09:42:27 +0200
+Subject: [PATCH] p11-kit: Use pthread_atfork() in a safe manner
+
+Instead of trying to perform actions in pthread_atfork() which
+are not async-signal-safe, just increment a counter so we can
+later tell if the process has forked.
+
+Note this does not make it safe to mix threads and forking without
+immediately execing. This is a far broader problem that p11-kit,
+however we now do the right thing when fork+exec is used from a
+thread.
+
+https://bugs.freedesktop.org/show_bug.cgi?id=84567
+---
+ common/library.c           | 11 ++++++++
+ common/library.h           |  2 ++
+ common/mock.c              |  1 +
+ p11-kit/modules.c          | 55 +++++++++-------------------------------
+ p11-kit/proxy.c            | 62 ++++++++++++++--------------------------------
+ p11-kit/proxy.h            |  2 --
+ p11-kit/tests/test-proxy.c |  2 +-
+ 7 files changed, 46 insertions(+), 89 deletions(-)
+
+diff --git a/common/library.c b/common/library.c
+index b7d6923..502ea98 100644
+--- a/common/library.c
++++ b/common/library.c
+@@ -63,6 +63,8 @@ p11_mutex_t p11_library_mutex;
+ pthread_once_t p11_library_once = PTHREAD_ONCE_INIT;
+ #endif
+ 
++unsigned int p11_forkid = 1;
++
+ static char *
+ thread_local_message (void)
+ {
+@@ -103,6 +105,13 @@ _p11_library_get_thread_local (void)
+ 	return local;
+ }
+ 
++static void
++count_forks (void)
++{
++	/* Thread safe, executed in child, one thread exists */
++	p11_forkid++;
++}
++
+ void
+ p11_library_init_impl (void)
+ {
+@@ -111,6 +120,8 @@ p11_library_init_impl (void)
+ 	p11_mutex_init (&p11_library_mutex);
+ 	pthread_key_create (&thread_local, free);
+ 	p11_message_storage = thread_local_message;
++
++	pthread_atfork (NULL, NULL, count_forks);
+ }
+ 
+ void
+diff --git a/common/library.h b/common/library.h
+index 33a33fb..f87494d 100644
+--- a/common/library.h
++++ b/common/library.h
+@@ -44,6 +44,8 @@
+ 
+ extern p11_mutex_t p11_library_mutex;
+ 
++extern unsigned int p11_forkid;
++
+ #define       p11_lock()                   p11_mutex_lock (&p11_library_mutex);
+ 
+ #define       p11_unlock()                 p11_mutex_unlock (&p11_library_mutex);
+diff --git a/common/mock.c b/common/mock.c
+index 51b32b6..ed2fad6 100644
+--- a/common/mock.c
++++ b/common/mock.c
+@@ -46,6 +46,7 @@
+ #include "debug.h"
+ #include "dict.h"
+ #include "array.h"
++#include "library.h"
+ 
+ #include <assert.h>
+ #include <ctype.h>
+diff --git a/p11-kit/modules.c b/p11-kit/modules.c
+index 1d9fe61..4a84803 100644
+--- a/p11-kit/modules.c
++++ b/p11-kit/modules.c
+@@ -157,7 +157,7 @@ typedef struct _Module {
+ 
+ 	/* Initialization, mutex must be held */
+ 	p11_mutex_t initialize_mutex;
+-	bool initialize_called;
++	unsigned int initialize_called;
+ 	p11_thread_id_t initialize_thread;
+ } Module;
+ 
+@@ -239,7 +239,6 @@ free_module_unlocked (void *data)
+ 		p11_debug_precond ("module unloaded without C_Finalize having been "
+ 		                   "called for each C_Initialize");
+ 	} else {
+-		assert (!mod->initialize_called);
+ 		assert (mod->initialize_thread == 0);
+ 	}
+ 
+@@ -580,7 +579,7 @@ initialize_module_inlock_reentrant (Module *mod)
+ 	p11_unlock ();
+ 	p11_mutex_lock (&mod->initialize_mutex);
+ 
+-	if (!mod->initialize_called) {
++	if (mod->initialize_called != p11_forkid) {
+ 		p11_debug ("C_Initialize: calling");
+ 
+ 		rv = mod->virt.funcs.C_Initialize (&mod->virt.funcs,
+@@ -590,10 +589,12 @@ initialize_module_inlock_reentrant (Module *mod)
+ 
+ 		/* Module was initialized and C_Finalize should be called */
+ 		if (rv == CKR_OK)
+-			mod->initialize_called = true;
++			mod->initialize_called = p11_forkid;
++		else
++			mod->initialize_called = 0;
+ 
+ 		/* Module was already initialized, we don't call C_Finalize */
+-		else if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED)
++		if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED)
+ 			rv = CKR_OK;
+ 	}
+ 
+@@ -612,31 +613,6 @@ initialize_module_inlock_reentrant (Module *mod)
+ 	return rv;
+ }
+ 
+-#ifdef OS_UNIX
+-
+-static void
+-reinitialize_after_fork (void)
+-{
+-	p11_dictiter iter;
+-	Module *mod;
+-
+-	p11_debug ("forked");
+-
+-	p11_lock ();
+-
+-		if (gl.modules) {
+-			p11_dict_iterate (gl.modules, &iter);
+-			while (p11_dict_next (&iter, (void **)&mod, NULL))
+-				mod->initialize_called = false;
+-		}
+-
+-	p11_unlock ();
+-
+-	p11_proxy_after_fork ();
+-}
+-
+-#endif /* OS_UNIX */
+-
+ static CK_RV
+ init_globals_unlocked (void)
+ {
+@@ -666,9 +642,6 @@ init_globals_unlocked (void)
+ 	if (once)
+ 		return CKR_OK;
+ 
+-#ifdef OS_UNIX
+-	pthread_atfork (NULL, NULL, reinitialize_after_fork);
+-#endif
+ 	once = true;
+ 
+ 	return CKR_OK;
+@@ -724,9 +697,9 @@ finalize_module_inlock_reentrant (Module *mod)
+ 	p11_unlock ();
+ 	p11_mutex_lock (&mod->initialize_mutex);
+ 
+-	if (mod->initialize_called) {
++	if (mod->initialize_called == p11_forkid) {
+ 		mod->virt.funcs.C_Finalize (&mod->virt.funcs, NULL);
+-		mod->initialize_called = false;
++		mod->initialize_called = 0;
+ 	}
+ 
+ 	p11_mutex_unlock (&mod->initialize_mutex);
+@@ -1384,7 +1357,7 @@ cleanup:
+ typedef struct {
+ 	p11_virtual virt;
+ 	Module *mod;
+-	pid_t initialized;
++	unsigned int initialized;
+ 	p11_dict *sessions;
+ } Managed;
+ 
+@@ -1394,14 +1367,12 @@ managed_C_Initialize (CK_X_FUNCTION_LIST *self,
+ {
+ 	Managed *managed = ((Managed *)self);
+ 	p11_dict *sessions;
+-	pid_t pid;
+ 	CK_RV rv;
+ 
+ 	p11_debug ("in");
+ 	p11_lock ();
+ 
+-	pid = getpid ();
+-	if (managed->initialized == pid) {
++	if (managed->initialized == p11_forkid) {
+ 		rv = CKR_CRYPTOKI_ALREADY_INITIALIZED;
+ 
+ 	} else {
+@@ -1414,7 +1385,7 @@ managed_C_Initialize (CK_X_FUNCTION_LIST *self,
+ 			rv = initialize_module_inlock_reentrant (managed->mod);
+ 		if (rv == CKR_OK) {
+ 			managed->sessions = sessions;
+-			managed->initialized = pid;
++			managed->initialized = p11_forkid;
+ 		} else {
+ 			p11_dict_free (sessions);
+ 		}
+@@ -1515,18 +1486,16 @@ managed_C_Finalize (CK_X_FUNCTION_LIST *self,
+ {
+ 	Managed *managed = ((Managed *)self);
+ 	CK_SESSION_HANDLE *sessions;
+-	pid_t pid;
+ 	int count;
+ 	CK_RV rv;
+ 
+ 	p11_debug ("in");
+ 	p11_lock ();
+ 
+-	pid = getpid ();
+ 	if (managed->initialized == 0) {
+ 		rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ 
+-	} else if (managed->initialized != pid) {
++	} else if (managed->initialized != p11_forkid) {
+ 		/*
+ 		 * In theory we should be returning CKR_CRYPTOKI_NOT_INITIALIZED here
+ 		 * but enough callers are not completely aware of their forking.
+diff --git a/p11-kit/proxy.c b/p11-kit/proxy.c
+index 3e76f15..db2acb8 100644
+--- a/p11-kit/proxy.c
++++ b/p11-kit/proxy.c
+@@ -82,6 +82,7 @@ typedef struct {
+ 	unsigned int n_mappings;
+ 	p11_dict *sessions;
+ 	CK_FUNCTION_LIST **inited;
++	unsigned int forkid;
+ } Proxy;
+ 
+ typedef struct _State {
+@@ -96,6 +97,8 @@ static CK_FUNCTION_LIST **all_modules = NULL;
+ static State *all_instances = NULL;
+ static State global = { { { { -1, -1 }, NULL, }, }, NULL, NULL, FIRST_HANDLE, NULL };
+ 
++#define PROXY_VALID(px) ((px) && (px)->forkid == p11_forkid)
++
+ #define MANUFACTURER_ID         "PKCS#11 Kit                     "
+ #define LIBRARY_DESCRIPTION     "PKCS#11 Kit Proxy Module        "
+ #define LIBRARY_VERSION_MAJOR   1
+@@ -137,7 +140,7 @@ map_slot_to_real (Proxy *px,
+ 
+ 	p11_lock ();
+ 
+-		if (!px)
++		if (!PROXY_VALID (px))
+ 			rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ 		else
+ 			rv = map_slot_unlocked (px, *slot, mapping);
+@@ -163,7 +166,7 @@ map_session_to_real (Proxy *px,
+ 
+ 	p11_lock ();
+ 
+-		if (!px) {
++		if (!PROXY_VALID (px)) {
+ 			rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ 		} else {
+ 			assert (px->sessions);
+@@ -195,40 +198,6 @@ proxy_free (Proxy *py)
+ 	}
+ }
+ 
+-void
+-p11_proxy_after_fork (void)
+-{
+-	p11_array *array;
+-	State *state;
+-	unsigned int i;
+-
+-	/*
+-	 * After a fork the callers are supposed to call C_Initialize and all.
+-	 * In addition the underlying libraries may change their state so free
+-	 * up any mappings and all
+-	 */
+-
+-	array = p11_array_new (NULL);
+-
+-	p11_lock ();
+-
+-		if (global.px)
+-			p11_array_push (array, global.px);
+-		global.px = NULL;
+-
+-		for (state = all_instances; state != NULL; state = state->next) {
+-			if (state->px)
+-				p11_array_push (array, state->px);
+-			state->px = NULL;
+-		}
+-
+-	p11_unlock ();
+-
+-	for (i = 0; i < array->num; i++)
+-		proxy_free (array->elem[i]);
+-	p11_array_free (array);
+-}
+-
+ static CK_RV
+ proxy_C_Finalize (CK_X_FUNCTION_LIST *self,
+                   CK_VOID_PTR reserved)
+@@ -247,8 +216,10 @@ proxy_C_Finalize (CK_X_FUNCTION_LIST *self,
+ 	} else {
+ 		p11_lock ();
+ 
+-			if (!state->px) {
++			if (!PROXY_VALID (state->px)) {
+ 				rv = CKR_CRYPTOKI_NOT_INITIALIZED;
++				py = state->px;
++				state->px = NULL;
+ 			} else if (state->px->refs-- == 1) {
+ 				py = state->px;
+ 				state->px = NULL;
+@@ -287,6 +258,8 @@ proxy_create (Proxy **res)
+ 	py = calloc (1, sizeof (Proxy));
+ 	return_val_if_fail (py != NULL, CKR_HOST_MEMORY);
+ 
++	py->forkid = p11_forkid;
++
+ 	py->inited = modules_dup (all_modules);
+ 	return_val_if_fail (py->inited != NULL, CKR_HOST_MEMORY);
+ 
+@@ -357,10 +330,13 @@ proxy_C_Initialize (CK_X_FUNCTION_LIST *self,
+ 
+ 	p11_lock ();
+ 
+-		if (state->px == NULL)
++		if (!PROXY_VALID (state->px)) {
+ 			initialize = true;
+-		else
++			proxy_free (state->px);
++			state->px = NULL;
++		} else {
+ 			state->px->refs++;
++		}
+ 
+ 	p11_unlock ();
+ 
+@@ -402,7 +378,7 @@ proxy_C_GetInfo (CK_X_FUNCTION_LIST *self,
+ 
+ 	p11_lock ();
+ 
+-		if (!state->px)
++		if (!PROXY_VALID (state->px))
+ 			rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ 
+ 	p11_unlock ();
+@@ -438,7 +414,7 @@ proxy_C_GetSlotList (CK_X_FUNCTION_LIST *self,
+ 
+ 	p11_lock ();
+ 
+-		if (!state->px) {
++		if (!PROXY_VALID (state->px)) {
+ 			rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ 		} else {
+ 			index = 0;
+@@ -586,7 +562,7 @@ proxy_C_OpenSession (CK_X_FUNCTION_LIST *self,
+ 	if (rv == CKR_OK) {
+ 		p11_lock ();
+ 
+-			if (!state->px) {
++			if (!PROXY_VALID (state->px)) {
+ 				/*
+ 				 * The underlying module should have returned an error, so this
+ 				 * code should never be reached with properly behaving modules.
+@@ -650,7 +626,7 @@ proxy_C_CloseAllSessions (CK_X_FUNCTION_LIST *self,
+ 
+ 	p11_lock ();
+ 
+-		if (!state->px) {
++		if (!PROXY_VALID (state->px)) {
+ 			rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ 		} else {
+ 			assert (state->px->sessions != NULL);
+diff --git a/p11-kit/proxy.h b/p11-kit/proxy.h
+index df05be0..f3d56d7 100644
+--- a/p11-kit/proxy.h
++++ b/p11-kit/proxy.h
+@@ -35,8 +35,6 @@
+ #ifndef __P11_PROXY_H__
+ #define __P11_PROXY_H__
+ 
+-void       p11_proxy_after_fork                      (void);
+-
+ bool       p11_proxy_module_check                    (CK_FUNCTION_LIST_PTR module);
+ 
+ void       p11_proxy_module_cleanup                  (void);
+diff --git a/p11-kit/tests/test-proxy.c b/p11-kit/tests/test-proxy.c
+index bf5007d..e4998be 100644
+--- a/p11-kit/tests/test-proxy.c
++++ b/p11-kit/tests/test-proxy.c
+@@ -76,7 +76,7 @@ test_initialize_finalize (void)
+ 	assert (rv == CKR_OK);
+ 
+ 	rv = proxy->C_Finalize (NULL);
+-	assert (rv == CKR_OK);
++	assert_num_eq (rv, CKR_OK);
+ 
+ 	p11_proxy_module_cleanup ();
+ }
+-- 
+1.9.3
+
diff --git a/SOURCES/trust-extract-compat b/SOURCES/trust-extract-compat
new file mode 100755
index 0000000..fe9c991
--- /dev/null
+++ b/SOURCES/trust-extract-compat
@@ -0,0 +1,16 @@
+#!/usr/bin/bash
+
+set -e
+
+if test "$UID" != "0"; then
+	echo "p11-kit: the 'extract-trust' command must be run as root" >&2
+	exit 2
+fi
+
+if test $# -gt 1; then
+	echo "p11-kit: no additional arguments are supported for this command" >&2
+	exit 2
+fi
+
+exec /usr/bin/update-ca-trust
+
diff --git a/SPECS/p11-kit.spec b/SPECS/p11-kit.spec
index 8e302ea..4f517bb 100644
--- a/SPECS/p11-kit.spec
+++ b/SPECS/p11-kit.spec
@@ -1,14 +1,17 @@
 Name:           p11-kit
-Version:        0.18.7
-Release:        4%{?dist}
+Version:        0.20.7
+Release:        3%{?dist}
 Summary:        Library for loading and sharing PKCS#11 modules
 
 License:        BSD
 URL:            http://p11-glue.freedesktop.org/p11-kit.html
 Source0:        http://p11-glue.freedesktop.org/releases/p11-kit-%{version}.tar.gz
-Source1:        p11-kit-extract-trust
+Source1:        trust-extract-compat
+Patch1:         pthread-atfork-fix-deadlock.patch
+
 BuildRequires:  libtasn1-devel >= 2.3
 BuildRequires:  nss-softokn-freebl
+BuildRequires:	libffi-devel
 BuildRequires:	gtk-doc
 
 %description
@@ -45,7 +48,7 @@ contains certificate anchors and black lists.
 
 
 # solution taken from icedtea-web.spec
-%define multilib_arches ppc64 sparc64 x86_64
+%define multilib_arches ppc64 sparc64 x86_64 s390x
 %ifarch %{multilib_arches}
 %define alt_ckbi  libnssckbi.so.%{_arch}
 %else
@@ -55,11 +58,12 @@ contains certificate anchors and black lists.
 
 %prep
 %setup -q
+%patch1 -p1
 
 %build
 # These paths are the source paths that  come from the plan here:
 # https://fedoraproject.org/wiki/Features/SharedSystemCertificates:SubTasks
-%configure --disable-static --enable-doc --with-trust-paths=%{_sysconfdir}/pki/ca-trust/source:%{_datadir}/pki/ca-trust-source --with-hash-impl=freebl
+%configure --disable-static --enable-doc --with-trust-paths=%{_sysconfdir}/pki/ca-trust/source:%{_datadir}/pki/ca-trust-source --with-hash-impl=freebl --disable-silent-rules
 make %{?_smp_mflags} V=1
 
 %install
@@ -79,14 +83,25 @@ make check
 
 %post trust
 %{_sbindir}/update-alternatives --install %{_libdir}/libnssckbi.so \
-        %{alt_ckbi} %{_libdir}/pkcs11/p11-kit-trust.so 30
+	%{alt_ckbi} %{_libdir}/pkcs11/p11-kit-trust.so 30
+
+# Fix bad links from earlier p11-kit packages which didn't include s390x
+%posttrans trust
+%ifarch s390x
+if %{_sbindir}/update-alternatives --display libnssckbi.so | grep -q lib64; then
+    %{_sbindir}/update-alternatives --remove libnssckbi.so %{_libdir}/pkcs11/p11-kit-trust.so
+    if test -e /usr/lib/nss/libnssckbi.so; then
+        %{_sbindir}/update-alternatives --install /usr/lib/libnssckbi.so libnssckbi.so /usr/lib/nss/libnssckbi.so 10
+    fi
+fi
+%endif
 
 %postun -p /sbin/ldconfig
 
 %postun trust
 if [ $1 -eq 0 ] ; then
-        # package removal
-        %{_sbindir}/update-alternatives --remove %{alt_ckbi} %{_libdir}/pkcs11/p11-kit-trust.so
+	# package removal
+	%{_sbindir}/update-alternatives --remove %{alt_ckbi} %{_libdir}/pkcs11/p11-kit-trust.so
 fi
 
 
@@ -113,12 +128,35 @@ fi
 %doc %{_datadir}/gtk-doc/
 
 %files trust
+%{_bindir}/trust
+%{_mandir}/man1/trust.1.gz
 %{_libdir}/pkcs11/p11-kit-trust.so
 %{_datadir}/p11-kit/modules/p11-kit-trust.module
-%{_libdir}/p11-kit/p11-kit-extract-trust
+%{_libdir}/p11-kit/trust-extract-compat
 
 
 %changelog
+* Thu Jan 08 2015 Stef Walter <stefw@redhat.com> - 0.20.7-3
+- Fix incorrect alternative links for s390 and s390x rhbz#1174178
+
+* Sun Oct 05 2014 Stef Walter <stefw@redhat.com> - 0.20.7-2
+- Fix deadlock related to forking and pthread_atfork rhbz#1148774
+
+* Thu Sep 18 2014 Stef Walter <stefw@redhat.com> - 0.20.7-1
+- Update to upstream stable 0.20.7 release
+- Expose pkcs11x.h header and defines for attached extensions rhbz#1142305
+
+* Tue Sep 09 2014 Stef Walter <stefw@redhat.com> - 0.20.6-1
+- Update to upstream stable 0.20.6 release
+- Respect critical = no in p11-kit-proxy.so rhbz#1128615
+
+* Fri Sep 05 2014 Stef Walter <stefw@redhat.com> - 0.20.5-1
+- Update to upstream version 0.20.5
+- Fixes several issues highlighted at rhbz#1128218
+
+* Thu Aug 07 2014 Stef Walter <stefw@redhat.com> - 0.20.4-1
+- Rebase to upstream version 0.20.x (#1122528)
+
 * Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 0.18.7-4
 - Mass rebuild 2014-01-24