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

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to