]> granicus.if.org Git - p11-kit/commitdiff
trust: Fix reinitialization of trust module
authorStef Walter <stefw@gnome.org>
Wed, 5 Jun 2013 08:41:19 +0000 (10:41 +0200)
committerStef Walter <stefw@gnome.org>
Wed, 5 Jun 2013 11:18:50 +0000 (13:18 +0200)
Track number of C_Initialize calls, and require similar number
of C_Finalize calls to finalize.

This fixes leaks/disappearing sessions in the trust module.

https://bugs.freedesktop.org/show_bug.cgi?id=65401

trust/module.c
trust/tests/frob-multi-init.c [new file with mode: 0644]
trust/tests/test-module.c

index 7595ba1d6d860d9cd0f6c5534c128b6c1226e476..15a4890db188b01afbd31a976cde590c6acdfac7 100644 (file)
 #define BASE_SLOT_ID   18UL
 
 static struct _Shared {
+       int initialized;
        p11_dict *sessions;
        p11_array *tokens;
        char *paths;
-} gl = { NULL, NULL };
+} gl = { 0, NULL, NULL, NULL };
 
 /* Used during FindObjects */
 typedef struct _FindObjects {
@@ -354,10 +355,13 @@ sys_C_Finalize (CK_VOID_PTR reserved)
        } else {
                p11_lock ();
 
-                       if (!gl.sessions) {
+                       if (gl.initialized == 0) {
+                               p11_debug ("trust module is not initialized");
                                rv = CKR_CRYPTOKI_NOT_INITIALIZED;
 
-                       } else {
+                       } else if (gl.initialized == 1) {
+                               p11_debug ("doing finalization");
+
                                free (gl.paths);
                                gl.paths = NULL;
 
@@ -368,6 +372,11 @@ sys_C_Finalize (CK_VOID_PTR reserved)
                                gl.tokens = NULL;
 
                                rv = CKR_OK;
+                               gl.initialized = 0;
+
+                       } else {
+                               gl.initialized--;
+                               p11_debug ("trust module still initialized %d times", gl.initialized);
                        }
 
                p11_unlock ();
@@ -416,11 +425,17 @@ sys_C_Initialize (CK_VOID_PTR init_args)
                        rv = CKR_CANT_LOCK;
                }
 
+               if (rv == CKR_OK && gl.initialized != 0) {
+                       p11_debug ("trust module already initialized %d times",
+                                  gl.initialized);
+
                /*
                 * We support setting the socket path and other arguments from from the
                 * pReserved pointer, similar to how NSS PKCS#11 components are initialized.
                 */
-               if (rv == CKR_OK) {
+               } else if (rv == CKR_OK) {
+                       p11_debug ("doing initialization");
+
                        if (args->pReserved)
                                parse_arguments ((const char*)args->pReserved);
 
@@ -438,6 +453,8 @@ sys_C_Initialize (CK_VOID_PTR init_args)
                        }
                }
 
+               gl.initialized++;
+
        p11_unlock ();
 
        if (rv != CKR_OK)
diff --git a/trust/tests/frob-multi-init.c b/trust/tests/frob-multi-init.c
new file mode 100644 (file)
index 0000000..d966540
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * gcc -Wall -o frob-multi-init $(pkg-config p11-kit-1 --cflags --libs) -ldl frob-multi-init.c
+ */
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+
+#include <p11-kit/p11-kit.h>
+
+#define TRUST_SO "/usr/lib64/pkcs11/p11-kit-trust.so"
+
+int
+main (void)
+{
+       CK_C_INITIALIZE_ARGS args =
+               { NULL, NULL, NULL, NULL, CKF_OS_LOCKING_OK, NULL, };
+       CK_C_GetFunctionList C_GetFunctionList;
+       CK_SESSION_HANDLE session;
+       CK_FUNCTION_LIST *module;
+       CK_SLOT_ID slots[8];
+       CK_SESSION_INFO info;
+       CK_ULONG count;
+       CK_RV rv;
+       void *dl;
+
+       dl = dlopen (TRUST_SO, RTLD_LOCAL | RTLD_NOW);
+       if (dl == NULL)
+               fprintf (stderr, "%s\n", dlerror());
+       assert (dl != NULL);
+
+       C_GetFunctionList = dlsym (dl, "C_GetFunctionList");
+       assert (C_GetFunctionList != NULL);
+
+       rv = C_GetFunctionList (&module);
+       assert (rv == CKR_OK);
+       assert (module != NULL);
+
+       rv = module->C_Initialize (&args);
+       assert (rv == CKR_OK);
+
+       count = 8;
+       rv = module->C_GetSlotList (CK_TRUE, slots, &count);
+       assert (rv == CKR_OK);
+       assert (count > 1);
+
+       rv = module->C_OpenSession (slots[0], CKF_SERIAL_SESSION, NULL, NULL, &session);
+       assert (rv == CKR_OK);
+
+       rv = module->C_GetSessionInfo (session, &info);
+       assert (rv == CKR_OK);
+
+       rv = p11_kit_initialize_registered ();
+       assert (rv == CKR_OK);
+
+       rv = module->C_GetSessionInfo (session, &info);
+       if (rv == CKR_OK) {
+               printf ("no reinitialization bug\n");
+               return 0;
+
+       } else if (rv == CKR_SESSION_HANDLE_INVALID) {
+               printf ("reinitialization bug present\n");
+               return 1;
+
+       } else {
+               printf ("another error: %lu\n", rv);
+               return 1;
+       }
+}
index 16d8037c2121173a8ff24b9572fd65425bae2657..7f0b1a5db0214f3941fc846e8d915f1792756099 100644 (file)
@@ -143,6 +143,54 @@ test_get_slot_list (CuTest *cu)
        teardown (cu);
 }
 
+static void
+test_multi_initialize (CuTest *cu)
+{
+       static CK_C_INITIALIZE_ARGS args =
+               { NULL, NULL, NULL, NULL, CKF_OS_LOCKING_OK, NULL, };
+       CK_FUNCTION_LIST *module;
+       CK_SESSION_HANDLE session;
+       CK_SLOT_ID slots[8];
+       CK_SESSION_INFO info;
+       CK_ULONG count;
+       CK_RV rv;
+
+       /* This is the entry point of the trust module, linked to this test */
+       rv = C_GetFunctionList (&module);
+       CuAssertTrue (cu, rv == CKR_OK);
+
+       rv = module->C_Initialize (&args);
+       CuAssertTrue (cu, rv == CKR_OK);
+
+       count = 8;
+       rv = module->C_GetSlotList (CK_TRUE, slots, &count);
+       CuAssertTrue (cu, rv == CKR_OK);
+       CuAssertTrue (cu, count > 0);
+
+       rv = module->C_OpenSession (slots[0], CKF_SERIAL_SESSION, NULL, NULL, &session);
+       CuAssertTrue (cu, rv == CKR_OK);
+
+       rv = module->C_GetSessionInfo (session, &info);
+       CuAssertTrue (cu, rv == CKR_OK);
+       CuAssertTrue (cu, info.slotID == slots[0]);
+
+       rv = module->C_Initialize (&args);
+       CuAssertTrue (cu, rv == CKR_OK);
+
+       rv = module->C_GetSessionInfo (session, &info);
+       CuAssertTrue (cu, rv == CKR_OK);
+       CuAssertTrue (cu, info.slotID == slots[0]);
+
+       rv = module->C_Finalize (NULL);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+
+       rv = module->C_Finalize (NULL);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+
+       rv = module->C_Finalize (NULL);
+       CuAssertIntEquals (cu, CKR_CRYPTOKI_NOT_INITIALIZED, rv);
+}
+
 static void
 test_get_slot_info (CuTest *cu)
 {
@@ -1009,6 +1057,7 @@ main (void)
        putenv ("P11_KIT_STRICT=1");
        p11_library_init ();
 
+       SUITE_ADD_TEST (suite, test_multi_initialize);
        SUITE_ADD_TEST (suite, test_get_slot_list);
        SUITE_ADD_TEST (suite, test_get_slot_info);
        SUITE_ADD_TEST (suite, test_get_token_info);