diff options
author | Stef Walter <stef@thewalter.net> | 2014-02-13 09:52:34 +0100 |
---|---|---|
committer | Stef Walter <stef@thewalter.net> | 2014-02-13 10:00:07 +0100 |
commit | 98292d6bbc21168b517cdfca2635d35f2b47740d (patch) | |
tree | 43f798f816c876b8a29af4a57d20119a74763ba6 | |
parent | deca4955a6cce1dd77bbd45b9524b0f7b0825169 (diff) |
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.c | 53 |
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 |