summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@thewalter.net>2014-07-03 10:26:16 +0200
committerStef Walter <stef@thewalter.net>2014-07-04 14:23:15 +0200
commit25e8999fd11d0b2c156f3bdd8597142dedd042cb (patch)
treea4b76d584756f8ede20d9d29766e9eea6defb0c9
parenta2bd1a8c5ba3c611899f7dfc27d553010899eeec (diff)
downloadp11-kit-25e8999fd11d0b2c156f3bdd8597142dedd042cb.tar.gz
p11-kit: Handle managed modules correctly when forking
Correctly allow reinitialization when a process forks. We don't yet implement checks on all entry points of a managed module, but this allows callers to call C_Initialize again after forking, as outlined by the PKCS#11 v2 spec.
-rw-r--r--p11-kit/modules.c14
-rw-r--r--p11-kit/tests/test-managed.c47
2 files changed, 56 insertions, 5 deletions
diff --git a/p11-kit/modules.c b/p11-kit/modules.c
index 2988f31..bddc823 100644
--- a/p11-kit/modules.c
+++ b/p11-kit/modules.c
@@ -1384,7 +1384,7 @@ cleanup:
typedef struct {
p11_virtual virt;
Module *mod;
- bool initialized;
+ pid_t initialized;
p11_dict *sessions;
} Managed;
@@ -1394,12 +1394,14 @@ managed_C_Initialize (CK_X_FUNCTION_LIST *self,
{
Managed *managed = ((Managed *)self);
p11_dict *sessions;
+ pid_t pid;
CK_RV rv;
p11_debug ("in");
p11_lock ();
- if (managed->initialized) {
+ pid = getpid ();
+ if (managed->initialized == pid) {
rv = CKR_CRYPTOKI_ALREADY_INITIALIZED;
} else {
@@ -1412,7 +1414,7 @@ managed_C_Initialize (CK_X_FUNCTION_LIST *self,
rv = initialize_module_inlock_reentrant (managed->mod);
if (rv == CKR_OK) {
managed->sessions = sessions;
- managed->initialized = true;
+ managed->initialized = pid;
} else {
p11_dict_free (sessions);
}
@@ -1513,13 +1515,15 @@ managed_C_Finalize (CK_X_FUNCTION_LIST *self,
{
Managed *managed = ((Managed *)self);
CK_SESSION_HANDLE *sessions;
+ pid_t pid;
int count;
CK_RV rv;
p11_debug ("in");
p11_lock ();
- if (!managed->initialized) {
+ pid = getpid ();
+ if (managed->initialized != pid) {
rv = CKR_CRYPTOKI_NOT_INITIALIZED;
} else {
@@ -1538,7 +1542,7 @@ managed_C_Finalize (CK_X_FUNCTION_LIST *self,
rv = finalize_module_inlock_reentrant (managed->mod);
if (rv == CKR_OK) {
- managed->initialized = false;
+ managed->initialized = 0;
p11_dict_free (managed->sessions);
managed->sessions = NULL;
}
diff --git a/p11-kit/tests/test-managed.c b/p11-kit/tests/test-managed.c
index 9fc9ffb..c4ccd9a 100644
--- a/p11-kit/tests/test-managed.c
+++ b/p11-kit/tests/test-managed.c
@@ -42,6 +42,8 @@
#include "p11-kit.h"
#include "virtual.h"
+#include <sys/types.h>
+#include <sys/wait.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
@@ -194,6 +196,49 @@ test_separate_close_all_sessions (void)
teardown_mock_module (second);
}
+static void
+test_fork_and_reinitialize (void)
+{
+ CK_FUNCTION_LIST *module;
+ CK_INFO info;
+ int status;
+ CK_RV rv;
+ pid_t pid;
+ int i;
+
+ module = setup_mock_module (NULL);
+ assert_ptr_not_null (module);
+
+ pid = fork ();
+ assert_num_cmp (pid, >=, 0);
+
+ /* The child */
+ if (pid == 0) {
+ rv = (module->C_Initialize) (NULL);
+ assert_num_eq (CKR_OK, rv);
+
+ for (i = 0; i < 32; i++) {
+ rv = (module->C_GetInfo) (&info);
+ assert_num_eq (CKR_OK, rv);
+ }
+
+ rv = (module->C_Finalize) (NULL);
+ assert_num_eq (CKR_OK, rv);
+
+ _exit (66);
+ }
+
+ for (i = 0; i < 128; i++) {
+ rv = (module->C_GetInfo) (&info);
+ assert_num_eq (CKR_OK, rv);
+ }
+
+ assert_num_eq (waitpid (pid, &status, 0), pid);
+ assert_num_eq (WEXITSTATUS (status), 66);
+
+ teardown_mock_module (module);
+}
+
/* Bring in all the mock module tests */
#include "test-mock.c"
@@ -207,6 +252,8 @@ main (int argc,
p11_test (test_initialize_finalize, "/managed/test_initialize_finalize");
p11_test (test_initialize_fail, "/managed/test_initialize_fail");
p11_test (test_separate_close_all_sessions, "/managed/test_separate_close_all_sessions");
+ p11_test (test_fork_and_reinitialize, "/managed/fork-and-reinitialize");
+
test_mock_add_tests ("/managed");
p11_kit_be_quiet ();