]> granicus.if.org Git - p11-kit/commitdiff
proxy: Reuse the existing slot ID mapping after fork
authorDaiki Ueno <dueno@redhat.com>
Tue, 16 Jan 2018 15:17:22 +0000 (16:17 +0100)
committerDaiki Ueno <ueno@gnu.org>
Mon, 29 Jan 2018 16:09:27 +0000 (17:09 +0100)
While the proxy module reassigns slot IDs in C_Initialize(), some
applications assume that valid slot IDs should never change across
multiple calls to C_Initialize().  This patch mitigates this by
preserving the slot IDs, if they are known to the proxy module.

p11-kit/Makefile.am
p11-kit/fixtures/package-modules/six.module [new file with mode: 0644]
p11-kit/mock-module-ep4.c [new file with mode: 0644]
p11-kit/proxy.c
p11-kit/test-proxy.c

index 955719a775acf31d39d2c9447fc8465ebbe67322..434c257e320aa503785b5f48e0fd1a5fade80f94 100644 (file)
@@ -307,6 +307,13 @@ mock_five_la_SOURCES = p11-kit/mock-module-ep3.c
 mock_five_la_LDFLAGS = $(mock_one_la_LDFLAGS)
 mock_five_la_LIBADD = $(mock_one_la_LIBADD)
 
+if !OS_WIN32
+noinst_LTLIBRARIES += mock-six.la
+mock_six_la_SOURCES = p11-kit/mock-module-ep4.c
+mock_six_la_LDFLAGS = $(mock_one_la_LDFLAGS)
+mock_six_la_LIBADD = $(mock_one_la_LIBADD)
+endif
+
 EXTRA_DIST += \
        p11-kit/fixtures \
        p11-kit/test-mock.c \
diff --git a/p11-kit/fixtures/package-modules/six.module b/p11-kit/fixtures/package-modules/six.module
new file mode 100644 (file)
index 0000000..bad9379
--- /dev/null
@@ -0,0 +1,7 @@
+
+module: mock-six.so
+
+enable-in: test-proxy
+
+# the highest priority among others loaded by test-proxy
+priority: 100
diff --git a/p11-kit/mock-module-ep4.c b/p11-kit/mock-module-ep4.c
new file mode 100644 (file)
index 0000000..5170b6b
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012 Stefan Walter
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *     * Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the
+ *       following disclaimer.
+ *     * Redistributions in binary form must reproduce the
+ *       above copyright notice, this list of conditions and
+ *       the following disclaimer in the documentation and/or
+ *       other materials provided with the distribution.
+ *     * The names of contributors to this software may not be
+ *       used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stef@thewalter.net>
+ */
+
+#include "config.h"
+
+#define CRYPTOKI_EXPORTS 1
+#include "pkcs11.h"
+
+#include "mock.h"
+#include "test.h"
+
+#include <unistd.h>
+
+static pid_t init_pid;
+
+static CK_RV
+override_initialize (CK_VOID_PTR init_args)
+{
+       if (init_pid != getpid ())
+               return CKR_GENERAL_ERROR;
+       return mock_C_Initialize (init_args);
+}
+
+#ifdef OS_WIN32
+__declspec(dllexport)
+#endif
+CK_RV
+C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+       mock_module_init ();
+       mock_module.C_GetFunctionList = C_GetFunctionList;
+       if (list == NULL)
+               return CKR_ARGUMENTS_BAD;
+       init_pid = getpid ();
+       mock_module.C_Initialize = override_initialize;
+       *list = &mock_module;
+       return CKR_OK;
+}
index 8c437a0f9837a0483dd8d7c73a44f7ef24780d1e..6f5aedd1e3e0d0011a057d28d7640d490d0f2be0 100644 (file)
@@ -248,12 +248,13 @@ modules_dup (CK_FUNCTION_LIST **modules)
 }
 
 static CK_RV
-proxy_create (Proxy **res)
+proxy_create (Proxy **res, Mapping *mappings, unsigned int n_mappings)
 {
        CK_FUNCTION_LIST_PTR *f;
        CK_FUNCTION_LIST_PTR funcs;
        CK_SLOT_ID_PTR slots;
        CK_ULONG i, count;
+       unsigned int j;
        CK_RV rv = CKR_OK;
        Proxy *py;
 
@@ -293,8 +294,14 @@ proxy_create (Proxy **res)
 
                                /* And now add a mapping for each of those slots */
                                for (i = 0; i < count; ++i) {
+                                       /* Reuse the existing mapping if any */
+                                       for (j = 0; j < n_mappings; ++j) {
+                                               if (mappings[j].funcs == funcs &&
+                                                   mappings[j].real_slot == slots[i])
+                                                       break;
+                                       }
                                        py->mappings[py->n_mappings].funcs = funcs;
-                                       py->mappings[py->n_mappings].wrap_slot = py->n_mappings + MAPPING_OFFSET;
+                                       py->mappings[py->n_mappings].wrap_slot = j == n_mappings ? py->n_mappings + MAPPING_OFFSET : mappings[j].wrap_slot;
                                        py->mappings[py->n_mappings].real_slot = slots[i];
                                        ++py->n_mappings;
                                }
@@ -323,6 +330,8 @@ proxy_C_Initialize (CK_X_FUNCTION_LIST *self,
 {
        State *state = (State *)self;
        bool initialize = false;
+       Mapping *mappings = NULL;
+       unsigned int n_mappings = 0;
        Proxy *py;
        CK_RV rv;
 
@@ -338,8 +347,15 @@ proxy_C_Initialize (CK_X_FUNCTION_LIST *self,
                        unsigned call_finalize = 1;
 
                        initialize = true;
-                       if (PROXY_FORKED(state->px))
+                       if (PROXY_FORKED(state->px)) {
                                call_finalize = 0;
+                               if (state->px->mappings) {
+                                       mappings = state->px->mappings;
+                                       n_mappings = state->px->n_mappings;
+                                       state->px->mappings = NULL;
+                                       state->px->n_mappings = 0;
+                               }
+                       }
                        proxy_free (state->px, call_finalize);
 
                        state->px = NULL;
@@ -354,7 +370,8 @@ proxy_C_Initialize (CK_X_FUNCTION_LIST *self,
                return CKR_OK;
        }
 
-       rv = proxy_create (&py);
+       rv = proxy_create (&py, mappings, n_mappings);
+       free (mappings);
        if (rv != CKR_OK) {
                p11_debug ("out: %lu", rv);
                return rv;
index 9d894bf61f35f0a13afe502f00bc090016bfed2a..3229002337af1b752da35dcb461a533c94c5f490 100644 (file)
@@ -121,6 +121,8 @@ test_initialize_child (void)
        CK_RV rv;
        pid_t pid;
        int st;
+       CK_SLOT_ID slots[32], last_slot;
+       CK_ULONG count, last_count;
 
        rv = C_GetFunctionList (&proxy);
        assert (rv == CKR_OK);
@@ -130,6 +132,11 @@ test_initialize_child (void)
        rv = proxy->C_Initialize(NULL);
        assert_num_eq (rv, CKR_OK);
 
+       rv = proxy->C_GetSlotList (CK_FALSE, slots, &count);
+       assert_num_cmp (count, >=, 2);
+       last_slot = slots[count - 1];
+       last_count = count;
+
        pid = fork ();
        if (!pid) {
                /* The PKCS#11 Usage Guide (v2.40) advocates in ยง2.5.2 that
@@ -149,6 +156,17 @@ test_initialize_child (void)
                rv = proxy->C_Initialize(NULL);
                assert_num_eq (rv, CKR_OK);
 
+               rv = proxy->C_GetSlotList (CK_FALSE, slots, &count);
+               assert_num_eq (rv, CKR_OK);
+               assert_num_cmp (count, >=, 2);
+
+               /* One of the module initializations should fail after
+                * fork (see mock-module-ep4.c) and the total number
+                * of slots should be less than last_count. */
+               assert_num_cmp (count, <, last_count);
+               /* Check if the last valid slot ID is preserved */
+               assert_num_eq (slots[count - 1], last_slot);
+
                rv = proxy->C_Finalize (NULL);
                assert_num_eq (rv, CKR_OK);