summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2015-06-03 15:00:57 +0100
committerStef Walter <stefw@redhat.com>2015-06-29 13:49:13 +0200
commitc73edd002462ca1185de1e9e72d9f68f01c93f32 (patch)
treec421d15df0c17f828b2c225449c24628a3dc0ca8
parentec8a291efb87f1751a18c7e023a67232c15a4ef2 (diff)
downloadp11-kit-c73edd002462ca1185de1e9e72d9f68f01c93f32.tar.gz
Add test case for bug 90289 (deadlock on C_Initialize() in child after fork)
Reviewed-by: Stef Walter <stefw@redhat.com>
-rw-r--r--p11-kit/test-proxy.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/p11-kit/test-proxy.c b/p11-kit/test-proxy.c
index 96b9ada..0fb270b 100644
--- a/p11-kit/test-proxy.c
+++ b/p11-kit/test-proxy.c
@@ -149,6 +149,62 @@ test_deinit_after_fork (void)
assert_fail("Child failed to C_Initialize() and C_Finalize()", NULL);
}
+
+static void
+test_initialize_child (void)
+{
+ CK_FUNCTION_LIST_PTR proxy;
+ CK_RV rv;
+ pid_t pid;
+ int st;
+
+ rv = C_GetFunctionList (&proxy);
+ assert (rv == CKR_OK);
+
+ assert (p11_proxy_module_check (proxy));
+
+ rv = proxy->C_Initialize(NULL);
+ assert_num_eq (rv, CKR_OK);
+
+ pid = fork ();
+ if (!pid) {
+ /* The PKCS#11 Usage Guide (v2.40) advocates in ยง2.5.2 that
+ * a child should call C_Initialize() after forking, and
+ * then immediately C_Finalize() if it's not going to do
+ * anything more with the PKCS#11 token. In a multi-threaded
+ * program this is a violation of the POSIX standard, which
+ * puts strict limits on what you're allowed to do between
+ * fork and an eventual exec or exit. But some things (like
+ * pkcs11-helper and thus OpenVPN) do it anyway, and we
+ * need to cope... */
+
+ /* https://bugs.freedesktop.org/show_bug.cgi?id=90289 reports
+ * a deadlock when this happens. Catch it with SIGALRM... */
+ alarm(1);
+
+ rv = proxy->C_Initialize(NULL);
+ assert_num_eq (rv, CKR_OK);
+
+ rv = proxy->C_Finalize (NULL);
+ assert_num_eq (rv, CKR_OK);
+
+ exit(0);
+ }
+ assert (pid != -1);
+ waitpid(pid, &st, 0);
+
+ rv = proxy->C_Finalize (NULL);
+ assert_num_eq (rv, CKR_OK);
+
+ p11_proxy_module_cleanup ();
+
+ /* If the assertion fails, p11_kit_failed() doesn't return. So make
+ * sure we do all the cleanup before the (expected) failure, or it
+ * causes all the *later* tests to fail too! */
+ if (!WIFEXITED (st) || WEXITSTATUS(st) != 0)
+ assert_fail("Child failed to C_Initialize() and C_Finalize()", NULL);
+
+}
#endif
static CK_FUNCTION_LIST_PTR
@@ -231,6 +287,7 @@ main (int argc,
p11_test (test_initialize_multiple, "/proxy/initialize-multiple");
#ifndef _WIN32
p11_test (test_deinit_after_fork, "/proxy/deinit-after-fork");
+ p11_test (test_initialize_child, "/proxy/initialize-child");
#endif
test_mock_add_tests ("/proxy");