Skip to content

Commit

Permalink
proxy: Reuse the existing slot ID mapping after fork
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ueno committed Jan 17, 2018
1 parent 50b752e commit 8f75b97
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 9 deletions.
9 changes: 8 additions & 1 deletion p11-kit/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,8 @@ noinst_LTLIBRARIES += \
mock-two.la \
mock-three.la \
mock-four.la \
mock-five.la
mock-five.la \
mock-six.la

mock_one_la_SOURCES = p11-kit/mock-module-ep.c
mock_one_la_LIBADD = libp11-test.la libp11-common.la
Expand All @@ -307,6 +308,12 @@ 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
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) libp11-library.la
endif

EXTRA_DIST += \
p11-kit/fixtures \
p11-kit/test-mock.c \
Expand Down
7 changes: 7 additions & 0 deletions p11-kit/fixtures/package-modules/six.module
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

module: mock-six.so

enable-in: test-proxy

# the highest priority among others loaded by test-proxy
priority: 100
69 changes: 69 additions & 0 deletions p11-kit/mock-module-ep4.c
Original file line number Diff line number Diff line change
@@ -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;
}
32 changes: 24 additions & 8 deletions p11-kit/proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ proxy_free (Proxy *py, unsigned finalize)
free (py->inited);
p11_dict_free (py->sessions);
free (py->mappings);
free (py);
}
free (py);
}

static CK_RV
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -288,13 +289,18 @@ proxy_create (Proxy **res)
return_val_if_fail (count == 0 || slots != NULL, CKR_GENERAL_ERROR);

if (count > 0) {
py->mappings = realloc (py->mappings, sizeof (Mapping) * (py->n_mappings + count));
return_val_if_fail (py->mappings != NULL, CKR_HOST_MEMORY);

/* 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 = realloc (py->mappings, sizeof (Mapping) * (py->n_mappings + 1));
return_val_if_fail (py->mappings != NULL, CKR_HOST_MEMORY);
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;
}
Expand Down Expand Up @@ -323,6 +329,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;

Expand All @@ -338,8 +346,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;
Expand All @@ -354,7 +369,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;
Expand Down
18 changes: 18 additions & 0 deletions p11-kit/test-proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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);

Expand Down

0 comments on commit 8f75b97

Please sign in to comment.