diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2015-06-03 15:00:57 +0100 |
---|---|---|
committer | Stef Walter <stefw@redhat.com> | 2015-06-29 13:49:13 +0200 |
commit | c73edd002462ca1185de1e9e72d9f68f01c93f32 (patch) | |
tree | c421d15df0c17f828b2c225449c24628a3dc0ca8 /p11-kit | |
parent | ec8a291efb87f1751a18c7e023a67232c15a4ef2 (diff) |
Add test case for bug 90289 (deadlock on C_Initialize() in child after fork)
Reviewed-by: Stef Walter <stefw@redhat.com>
Diffstat (limited to 'p11-kit')
-rw-r--r-- | p11-kit/test-proxy.c | 57 |
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"); |