The pkcs11-helper library installs a pthread_atfork() handler which, in the child, will call the C_Initialize() method on any PKCS#11 provider module which is active in the parent.
I'm going to assume that Alon knows what he's doing and that this is actually the correct thing for pkcs11-helper to be doing. Nevertheless, it does seem to be central to a number of issues. Firstly, OpenVPN is forking to spawn systemd-ask-password from *within* the PIN request callback, which is expressly forbidden and leads directly to a deadlock. Secondly, even if we work around that by disabling systemd support, we find that the OpenSC PKCS#11 module doesn't cope. It ends up confusing pcscd by interacting with it over two separate connections, as described at http://sourceforge.net/p/opensc/mailman/message/34073754/ Third, the p11-kit-proxy.so module also doesn't cope, and suffers an internal deadlock as described at https://www.mail-archive.com/p11-glue@lists.freedesktop.org/msg00126.html Even if this behaviour of calling C_Initialize() in the child is strictly correct, it doesn't seem that we can rely on provider modules to cope with it in the general case. Perhaps it would be safer to not actually reinitialise the modules until later, if they are really going to be accessed again? From the OpenVPN point of view, actually there's a cheap trick which can let us call it Someone Else's Problem... just use vfork() instead of fork(). Because we *know* we're about to call execve() and it doesn't matter, and the atfork handlers don't get called for a vfork(). Signed-off-by: David Woodhouse <david.woodho...@intel.com> Trac #538 diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c index 5627cb9..ec14fbc 100644 --- a/src/openvpn/misc.c +++ b/src/openvpn/misc.c @@ -44,6 +44,10 @@ #include "console.h" #include "win32.h" +#ifdef HAVE_VFORK_H +#include <vfork.h> +#endif + #include "memdbg.h" #ifdef ENABLE_IPROUTE @@ -305,7 +309,11 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i char *const *envp = (char *const *)make_env_array (es, true, &gc); pid_t pid; +#ifdef HAVE_WORKING_VFORK + pid = vfork (); +#else pid = fork (); +#endif if (pid == (pid_t)0) /* child side */ { execve (cmd, argv, envp); -- dwmw2
smime.p7s
Description: S/MIME cryptographic signature