summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@thewalter.net>2014-02-13 09:52:34 +0100
committerStef Walter <stef@thewalter.net>2014-02-13 10:00:07 +0100
commit98292d6bbc21168b517cdfca2635d35f2b47740d (patch)
tree43f798f816c876b8a29af4a57d20119a74763ba6
parentdeca4955a6cce1dd77bbd45b9524b0f7b0825169 (diff)
downloadp11-kit-98292d6bbc21168b517cdfca2635d35f2b47740d.tar.gz
proxy: Fix cases where modules are unloaded while in use
The proxy module would unload the PKCS#11 modules it was proxying when C_Finalize() was called. However if a caller in another thread was inside of a PKCS#11 function at the time, this would cause a crash. Change things around so that underlying modules are finalized during the proxy C_Finalize() but not released/unloaded until the proxy module itself is unloaded. https://bugs.freedesktop.org/show_bug.cgi?id=74919
-rw-r--r--p11-kit/proxy.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/p11-kit/proxy.c b/p11-kit/proxy.c
index 4e599c7..4e1c61e 100644
--- a/p11-kit/proxy.c
+++ b/p11-kit/proxy.c
@@ -81,7 +81,7 @@ typedef struct {
Mapping *mappings;
unsigned int n_mappings;
p11_dict *sessions;
- CK_FUNCTION_LIST **modules;
+ p11_array *inited;
} Proxy;
typedef struct _State {
@@ -92,6 +92,7 @@ typedef struct _State {
Proxy *px;
} State;
+static CK_FUNCTION_LIST **all_modules = NULL;
static State *all_instances = NULL;
static State global = { { { { -1, -1 }, NULL, }, }, NULL, NULL, FIRST_HANDLE, NULL };
@@ -186,7 +187,7 @@ static void
proxy_free (Proxy *py)
{
if (py) {
- p11_kit_modules_finalize_and_release (py->modules);
+ p11_array_free (py->inited);
p11_dict_free (py->sessions);
free (py->mappings);
free (py);
@@ -274,28 +275,19 @@ proxy_create (Proxy **res)
py = calloc (1, sizeof (Proxy));
return_val_if_fail (py != NULL, CKR_HOST_MEMORY);
- p11_lock ();
-
- /* WARNING: Reentrancy can occur here */
- rv = p11_modules_load_inlock_reentrant (0, &py->modules);
+ py->inited = p11_array_new ((p11_destroyer)p11_kit_module_finalize);
+ return_val_if_fail (py->inited != NULL, CKR_HOST_MEMORY);
- p11_unlock ();
-
- if (rv != CKR_OK) {
- proxy_free (py);
- free (py);
- return rv;
- }
+ for (f = all_modules; *f; ++f) {
+ funcs = *f;
- rv = p11_kit_modules_initialize (py->modules, (p11_destroyer)p11_kit_module_release);
- if (rv != CKR_OK) {
- p11_kit_modules_release (py->modules);
- free (py);
- return rv;
- }
+ rv = p11_kit_module_initialize (funcs);
+ if (rv != CKR_OK)
+ break;
- for (f = py->modules; *f; ++f) {
- funcs = *f;
+ /* Make note of everything we've initialized */
+ if (!p11_array_push (py->inited, funcs))
+ return_val_if_reached (CKR_HOST_MEMORY);
assert (funcs != NULL);
slots = NULL;
@@ -2364,13 +2356,25 @@ CK_RV
C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
{
CK_FUNCTION_LIST_PTR module = NULL;
+ CK_FUNCTION_LIST **loaded;
State *state;
CK_RV rv = CKR_OK;
p11_library_init_once ();
p11_lock ();
- if (p11_virtual_can_wrap ()) {
+ if (all_modules == NULL) {
+ /* WARNING: Reentrancy can occur here */
+ rv = p11_modules_load_inlock_reentrant (0, &loaded);
+ if (rv == CKR_OK) {
+ if (all_modules == NULL)
+ all_modules = loaded;
+ else
+ p11_modules_release_inlock_reentrant (loaded);
+ }
+ }
+
+ if (rv == CKR_OK && p11_virtual_can_wrap ()) {
state = calloc (1, sizeof (State));
if (!state) {
rv = CKR_HOST_MEMORY;
@@ -2417,6 +2421,11 @@ p11_proxy_module_cleanup (void)
next = state->next;
p11_virtual_unwrap (state->wrapped);
}
+
+ if (all_modules) {
+ p11_kit_modules_release (all_modules);
+ all_modules = NULL;
+ }
}
bool