Following the changes introduced by "9290bfcc - Use pointer as session handler in API layer" and "38fc2310 - Use pointer as session handler in common library layer", but for object handlers.
This avoids interating through a list of objects attached to some particular process every time the object is needed. Again, potential segfaults are handled by sigaction()/sigsetjmp() and siglongjmp(). Signed-off-by: Klaus Heinrich Kiwi <[email protected]> --- usr/lib/pkcs11/common/globals.c | 2 +- usr/lib/pkcs11/common/h_extern.h | 3 +- usr/lib/pkcs11/common/host_defs.h | 2 + usr/lib/pkcs11/common/new_host.c | 2 +- usr/lib/pkcs11/common/obj_mgr.c | 174 +++++++++++++++++++++++++++++-------- 5 files changed, 144 insertions(+), 39 deletions(-) diff --git a/usr/lib/pkcs11/common/globals.c b/usr/lib/pkcs11/common/globals.c index 47b1b7f..104fc16 100755 --- a/usr/lib/pkcs11/common/globals.c +++ b/usr/lib/pkcs11/common/globals.c @@ -336,7 +336,7 @@ CK_STATE global_login_state = CKS_RO_PUBLIC_SESSION; LW_SHM_TYPE *global_shm; //CK_ULONG next_session_handle = 1; -CK_ULONG next_object_handle = 1; +//CK_ULONG next_object_handle = 1; TOKEN_DATA *nv_token_data = NULL; diff --git a/usr/lib/pkcs11/common/h_extern.h b/usr/lib/pkcs11/common/h_extern.h index 63bd197..5d7db25 100755 --- a/usr/lib/pkcs11/common/h_extern.h +++ b/usr/lib/pkcs11/common/h_extern.h @@ -357,9 +357,10 @@ extern LW_SHM_TYPE *global_shm; extern TOKEN_DATA *nv_token_data; extern CK_SLOT_INFO slot_info; +// extern CK_ULONG next_object_handle; // extern CK_ULONG next_session_handle; + extern CK_ULONG ro_session_count; -extern CK_ULONG next_object_handle; extern CK_STATE global_login_state; diff --git a/usr/lib/pkcs11/common/host_defs.h b/usr/lib/pkcs11/common/host_defs.h index 432df30..a137066 100755 --- a/usr/lib/pkcs11/common/host_defs.h +++ b/usr/lib/pkcs11/common/host_defs.h @@ -549,6 +549,8 @@ typedef struct _OBJECT_MAP OBJECT * ptr; } OBJECT_MAP; +/* FIXME: Compile-time check that sizeof(CK_OBJECT_HANDLE) == sizeof(DL_NODE *) */ + typedef struct _ATTRIBUTE_PARSE_LIST { diff --git a/usr/lib/pkcs11/common/new_host.c b/usr/lib/pkcs11/common/new_host.c index 70e1f6e..96153f1 100755 --- a/usr/lib/pkcs11/common/new_host.c +++ b/usr/lib/pkcs11/common/new_host.c @@ -418,7 +418,7 @@ Fork_Initializer(void) session_mgr_close_all_sessions(); //next_session_handle = 1; // Make is so sessions start with 1 - next_object_handle = 1; + //next_object_handle = 1; // Clean out the global login state variable // When implemented... Although logout_all should clear this up. diff --git a/usr/lib/pkcs11/common/obj_mgr.c b/usr/lib/pkcs11/common/obj_mgr.c index 64eda19..f8492dc 100755 --- a/usr/lib/pkcs11/common/obj_mgr.c +++ b/usr/lib/pkcs11/common/obj_mgr.c @@ -299,6 +299,8 @@ #include <stdio.h> #include <string.h> // for memcmp() et al #include <strings.h> +#include <setjmp.h> +#include <signal.h> #include "pkcs11types.h" #include "defs.h" @@ -310,6 +312,13 @@ pthread_rwlock_t obj_list_rw_mutex = PTHREAD_RWLOCK_INITIALIZER; +static jmp_buf objsigbuf; + +void objsegvhandler(int signum, siginfo_t *info, void *ptr) +{ + siglongjmp(objsigbuf, 1); +} + CK_RV object_mgr_add( SESSION * sess, CK_ATTRIBUTE * pTemplate, @@ -536,7 +545,6 @@ object_mgr_add_to_map( SESSION * sess, st_err_log(0, __FILE__, __LINE__); return CKR_HOST_MEMORY; } - map_node->handle = next_object_handle++; map_node->session = sess; map_node->ptr = obj; @@ -551,6 +559,10 @@ object_mgr_add_to_map( SESSION * sess, return CKR_FUNCTION_FAILED; } object_map = dlist_add_as_first( object_map, map_node ); + map_node->handle = (CK_SESSION_HANDLE) object_map; // handle is the DL_NODE pointer and + // dlist_add_as_first() will return + // this newly added DL_NODE as it is the + // new head of the list pthread_rwlock_unlock(&obj_list_rw_mutex); *handle = map_node->handle; @@ -1176,13 +1188,23 @@ CK_RV object_mgr_find_in_map_nocache( CK_OBJECT_HANDLE handle, OBJECT ** ptr ) { - DL_NODE * node = NULL; - OBJECT * obj = NULL; + DL_NODE * node = NULL; + OBJECT_MAP * map = NULL; + OBJECT * obj = NULL; + CK_RV result = CKR_OK; + + struct sigaction segvact, oldact; if (!ptr){ st_err_log(4, __FILE__, __LINE__, __FUNCTION__); return CKR_FUNCTION_FAILED; } + + if (!handle) { + st_err_log(30, __FILE__, __LINE__); + return CKR_OBJECT_HANDLE_INVALID; + } + // // no mutex here. the calling function should have locked the mutex // @@ -1191,20 +1213,52 @@ object_mgr_find_in_map_nocache( CK_OBJECT_HANDLE handle, st_err_log(4, __FILE__, __LINE__, __FUNCTION__); return CKR_FUNCTION_FAILED; } - node = object_map; - while (node) { - OBJECT_MAP *map = (OBJECT_MAP *)node->data; + node = (DL_NODE *) handle; + + if (sigsetjmp(objsigbuf, 1) == 0) { + memset(&segvact, 0, sizeof(segvact)); + segvact.sa_sigaction = objsegvhandler; + segvact.sa_flags = SA_SIGINFO | SA_RESETHAND; - if (map->handle == handle) { + // Register Segfault signal handler, so we can derefence 'node' + // safely (or sort of) + if (sigaction(SIGSEGV, &segvact, &oldact) != 0) { + st_err_log(4, __FILE__, __LINE__, __FUNCTION__); + result = CKR_FUNCTION_FAILED; + goto out; + } + + // Try dereferencing it, and check if we have the right handle + map = (OBJECT_MAP *) node->data; + if ( map->handle == handle ){ obj = map->ptr; - break; } - node = node->next; + // restore the old signal handler + if (sigaction(SIGSEGV, &oldact, NULL) != 0) { + // Even if we *have* the right handle & could recover, failing to + // restore the handler might indicate problems. + st_err_log(4, __FILE__, __LINE__, __FUNCTION__); + result = CKR_FUNCTION_FAILED; + goto out; + } + } + else { + // If we are here, means that a segfault was caught and we somehow recovered + // result: the object handle was invalid + result = CKR_OK; + obj = NULL; } + + +out: pthread_rwlock_unlock(&obj_list_rw_mutex); + + if (result != CKR_OK) { + return result; + } - if (obj == NULL || node == NULL) { + if (obj == NULL) { st_err_log(30, __FILE__, __LINE__); return CKR_OBJECT_HANDLE_INVALID; } @@ -1232,13 +1286,22 @@ CK_RV object_mgr_find_in_map1( CK_OBJECT_HANDLE handle, OBJECT ** ptr ) { - DL_NODE * node = NULL; - OBJECT * obj = NULL; + DL_NODE * node = NULL; + OBJECT_MAP * map = NULL; + OBJECT * obj = NULL; + CK_RV result = CKR_OK; + + struct sigaction segvact, oldact; if (!ptr){ st_err_log(4, __FILE__, __LINE__, __FUNCTION__); return CKR_FUNCTION_FAILED; } + + if (!handle){ + st_err_log(30, __FILE__, __LINE__); + return CKR_OBJECT_HANDLE_INVALID; + } // // no mutex here. the calling function should have locked the mutex // @@ -1247,20 +1310,54 @@ object_mgr_find_in_map1( CK_OBJECT_HANDLE handle, st_err_log(4, __FILE__, __LINE__, __FUNCTION__); return CKR_FUNCTION_FAILED; } - node = object_map; - while (node) { - OBJECT_MAP *map = (OBJECT_MAP *)node->data; - - if (map->handle == handle) { + node = (DL_NODE *) handle; + + // FIXME: the below will segfault when the app gives us an invalid + // handle + if (sigsetjmp(objsigbuf, 1) == 0) { + memset(&segvact, 0, sizeof(segvact)); + segvact.sa_sigaction = objsegvhandler; + segvact.sa_flags = SA_SIGINFO | SA_RESETHAND; + + // Register Segfault signal handler, so we can derefence 'node' + // safely (or sort of) + if (sigaction(SIGSEGV, &segvact, &oldact) != 0) { + st_err_log(4, __FILE__, __LINE__, __FUNCTION__); + result = CKR_FUNCTION_FAILED; + goto out; + } + + // Try dereferencing it, and check if we have the right handle + map = (OBJECT_MAP *) node->data; + if ( handle == map->handle ){ obj = map->ptr; - break; } - node = node->next; + // restore the old signal handler + if (sigaction(SIGSEGV, &oldact, NULL) != 0) { + // Even if we *have* the right handle & could recover, failing to + // restore the handler might indicate problems. + st_err_log(4, __FILE__, __LINE__, __FUNCTION__); + result = CKR_FUNCTION_FAILED; + goto out; + } + } + else { + // If we are here, means that a segfault was caught and we somehow recovered + // result: the object handle was invalid + result = CKR_OK; + obj = NULL; } + +out: pthread_rwlock_unlock(&obj_list_rw_mutex); - if (obj == NULL || node == NULL) { + if (result != CKR_OK) { + return result; + } + + + if (obj == NULL) { st_err_log(30, __FILE__, __LINE__); return CKR_OBJECT_HANDLE_INVALID; } @@ -1646,34 +1743,39 @@ done: CK_BBOOL object_mgr_invalidate_handle1( CK_OBJECT_HANDLE handle ) { - DL_NODE *node = NULL; + DL_NODE *node = NULL; + OBJECT_MAP *map = NULL; + CK_BBOOL result; // // no mutex stuff here. the calling routine should have locked the mutex // + if (!handle){ + return FALSE; + } + if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { st_err_log(4, __FILE__, __LINE__, __FUNCTION__); - return CKR_FUNCTION_FAILED; + return FALSE; // FIXME: Proper error messages } - node = object_map; - - while (node) { - OBJECT_MAP *map = (OBJECT_MAP *)node->data; - // I think we can do this because even token objects exist in RAM - // - if (map->handle == handle) { - object_map = dlist_remove_node( object_map, node ); - free( map ); - pthread_rwlock_unlock(&obj_list_rw_mutex); - return TRUE; - } + node = (DL_NODE *)handle; + // FIXME: The below will segfault whenever the caller uses an invalid + // handle + map = (OBJECT_MAP *)node->data; - node = node->next; + if ( handle == map->handle ) { + object_map = dlist_remove_node( object_map, node ); + free( map ); + result = TRUE; } + else { + result = FALSE; + } + pthread_rwlock_unlock(&obj_list_rw_mutex); - return FALSE; + return result; } -- 1.6.6.1 ------------------------------------------------------------------------------ ThinkGeek and WIRED's GeekDad team up for the Ultimate GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the lucky parental unit. See the prize list and enter to win: http://p.sf.net/sfu/thinkgeek-promo _______________________________________________ Opencryptoki-tech mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/opencryptoki-tech
