Created attachment 115518 [details]
simple test case
The PKCS#11 Users Guide §2.5.2 at http://docs.oasis-open.org/pkcs11/pkcs11-ug/v2.40/cn02/pkcs11-ug-v2.40-cn02.html#_Toc406759987 advises that the child of a Cryptoki application, after forking, should call C_Initialize() to avoid leaving the module in an undefined state.
p11-kit-trust.so deadlocks when you do this:
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1 0x0000003841a0988d in __GI___pthread_mutex_lock (mutex=0x3860c64840 <p11_library_mutex>) at ../nptl/pthread_mutex_lock.c:80
#2 0x0000003860a1e812 in managed_C_Finalize (self=0x61ee00, reserved=<optimized out>) at p11-kit/modules.c:1546
#3 0x0000003860a396e0 in binding_C_Finalize (cif=<optimized out>, ret=0x7fffffffda60, args=<optimized out>, funcs=<optimized out>) at p11-kit/virtual.c:124
#4 0x0000003844205b9f in ffi_closure_unix64_inner (closure=0x7ffff7ff9048, rvalue=0x7fffffffda60, reg_args=0x7fffffffd9b0, argp=0x7fffffffda80 "PHb") at ../src/x86/ffi64.c:670
#5 0x0000003844205f18 in ffi_closure_unix64 () at ../src/x86/unix64.S:229
#6 0x0000003860a20ba1 in p11_kit_modules_finalize (modules=<optimized out>) at p11-kit/modules.c:2108
#7 0x0000003860a22132 in proxy_free (py=0x624810) at p11-kit/proxy.c:193
#8 0x0000003860a22303 in proxy_C_Initialize (self=0x623920, init_args=<optimized out>) at p11-kit/proxy.c:335
#9 0x0000003860a396c0 in binding_C_Initialize (cif=<optimized out>, ret=0x7fffffffdcc0, args=<optimized out>, funcs=<optimized out>) at p11-kit/virtual.c:114
#10 0x0000003844205b9f in ffi_closure_unix64_inner (closure=0x7ffff7ff96a0, rvalue=0x7fffffffdcc0, reg_args=0x7fffffffdc10, argp=0x7fffffffdce0 "`\t@") at ../src/x86/ffi64.c:670
#11 0x0000003844205f18 in ffi_closure_unix64 () at ../src/x86/unix64.S:229
#12 0x00000000004008e4 in main ()
It calls p11_lock() in proxy_C_Initialize() in frame 8 right before calling proxy_free(). And then when it calls it again in managed_C_Finalize() it deadlocks.
This is seen when attempting to use p11-kit-proxy.so from within OpenVPN (which is sad really, since I recently made OpenVPN do that by default if no other provider was specified...)
I think it's wrong to be calling C_Finalize() on the loaded modules in the child anyway. The behaviour if you do that is undefined. If anything it needs to be calling C_Initialize(), surely?
Fixed by this patch in git master:
Author: Nikos Mavrogiannopoulos <firstname.lastname@example.org>
Date: Wed Jun 24 09:43:57 2015 +0200
In proxy module don't call C_Finalize on a forked process.
This corrects a deadlock on the forked process. The deadlock
happened because the proxy called C_Finalize prior to a C_Initialize
which is wrong according to PKCS #11 (2.40). This patch eliminates
the C_Finalize call in that case.
This resolves #90289