]> granicus.if.org Git - p11-kit/commitdiff
p11-kit: Handle managed modules correctly when forking
authorStef Walter <stef@thewalter.net>
Thu, 3 Jul 2014 08:26:16 +0000 (10:26 +0200)
committerStef Walter <stef@thewalter.net>
Fri, 4 Jul 2014 12:23:15 +0000 (14:23 +0200)
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.

p11-kit/modules.c
p11-kit/tests/test-managed.c

index 2988f31430bdad6489d763c1f47f86cd3efaf224..bddc823e3de98882983dd82d365313f9c7086a43 100644 (file)
@@ -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;
                }
index 9fc9ffba6190752857da21ebd1e0424ff5042298..c4ccd9a3c5b11cbf851c765753cf8f7f4297f725 100644 (file)
@@ -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 ();