Avoid iterating through the common library layer's session list
by assigning the session's own pointer as the handler.

This is similar to "9290bfcc - Use pointer as session handler
in API layer", but for the common library/token specific layer.

Again, avoid segfaults by hooking into SIGSEGV and trying to recover
with sigsetjmp()/siglongjmp()

Signed-off-by: Klaus Heinrich Kiwi <[email protected]>
---
 usr/lib/pkcs11/common/globals.c   |    2 +-
 usr/lib/pkcs11/common/h_extern.h  |    2 +-
 usr/lib/pkcs11/common/host_defs.h |    4 ++
 usr/lib/pkcs11/common/new_host.c  |    4 +-
 usr/lib/pkcs11/common/sess_mgr.c  |   69 +++++++++++++++++++++++++++++--------
 5 files changed, 62 insertions(+), 19 deletions(-)

diff --git a/usr/lib/pkcs11/common/globals.c b/usr/lib/pkcs11/common/globals.c
index 7b1432f..47b1b7f 100755
--- a/usr/lib/pkcs11/common/globals.c
+++ b/usr/lib/pkcs11/common/globals.c
@@ -335,7 +335,7 @@ CK_STATE  global_login_state = CKS_RO_PUBLIC_SESSION;
 
 LW_SHM_TYPE *global_shm;
 
-CK_ULONG next_session_handle = 1;
+//CK_ULONG next_session_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 4368902..63bd197 100755
--- a/usr/lib/pkcs11/common/h_extern.h
+++ b/usr/lib/pkcs11/common/h_extern.h
@@ -357,9 +357,9 @@ extern LW_SHM_TYPE *global_shm;
 extern TOKEN_DATA        *nv_token_data;
 extern CK_SLOT_INFO       slot_info;
 
+// extern CK_ULONG next_session_handle;
 extern CK_ULONG  ro_session_count;
 extern CK_ULONG next_object_handle;
-extern CK_ULONG next_session_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 3dddcda..432df30 100755
--- a/usr/lib/pkcs11/common/host_defs.h
+++ b/usr/lib/pkcs11/common/host_defs.h
@@ -462,6 +462,10 @@ typedef struct _SESSION
    SIGN_VERIFY_CONTEXT  verify_ctx;
 } SESSION;
 
+/* TODO:
+ * Add compile-time checking that sizeof(SESSION *) == 
sizeof(CK_SESSION_HANDLE)
+ * */
+
 
 typedef struct _DES_CONTEXT
 {
diff --git a/usr/lib/pkcs11/common/new_host.c b/usr/lib/pkcs11/common/new_host.c
index 394203f..70e1f6e 100755
--- a/usr/lib/pkcs11/common/new_host.c
+++ b/usr/lib/pkcs11/common/new_host.c
@@ -417,7 +417,7 @@ Fork_Initializer(void)
        // This should clear the entire session list out
        session_mgr_close_all_sessions();
 
-       next_session_handle = 1; // Make is so sessions start with 1
+       //next_session_handle = 1; // Make is so sessions start with 1
        next_object_handle = 1;
 
        // Clean out the global login state variable
@@ -1382,7 +1382,7 @@ CK_RV SC_OpenSession(CK_SLOT_ID             sid,
                st_err_log(152, __FILE__, __LINE__); 
                goto done;
        }
-       *phSession = sess->handle;
+       *phSession = (CK_SESSION_HANDLE_PTR) sess;
        // Set the correct slot ID here. Was hard coded to 1. - KEY
        sess->session_info.slotID = sid;
  done:
diff --git a/usr/lib/pkcs11/common/sess_mgr.c b/usr/lib/pkcs11/common/sess_mgr.c
index d6d5aa8..45aedc1 100755
--- a/usr/lib/pkcs11/common/sess_mgr.c
+++ b/usr/lib/pkcs11/common/sess_mgr.c
@@ -297,6 +297,8 @@
 #include <pthread.h>
 #include <stdlib.h>
 #include <string.h>  // for memcmp() et al
+#include <setjmp.h>
+#include <signal.h>
 
 #include "pkcs11types.h"
 #include "defs.h"
@@ -304,11 +306,19 @@
 #include "h_extern.h"
 #include "tok_spec_struct.h"
 
+static jmp_buf sesssigbuf;
+   
+void sesssegvhandler(int signum, siginfo_t *info, void *ptr)
+{  
+     siglongjmp(sesssigbuf, 1);
+}
+
+
 
 // session_mgr_find()
 //
 // search for the specified session.  returning a pointer to the session
-// is dangerous
+// might be dangerous, but performs well
 //
 // Returns:  SESSION * or NULL
 //
@@ -318,25 +328,55 @@ session_mgr_find( CK_SESSION_HANDLE handle )
    DL_NODE  * node   = NULL;
    SESSION  * result = NULL;
    CK_RV      rc;
+   struct sigaction segvact, oldact;
+
+   if (!handle) {
+      return NULL;
+   }
 
    rc = MY_LockMutex( &sess_list_mutex );
    if (rc != CKR_OK){
       st_err_log(146, __FILE__, __LINE__); 
       return NULL;
    }
-   node = sess_list;
 
-   while (node) {
-      SESSION *s = (SESSION *)node->data;
+   result = (SESSION *) handle;
 
-      if (s->handle == handle) {
-         result = s;
-         break;
+   if (sigsetjmp(sesssigbuf, 1) == 0) {
+      memset(&segvact, 0, sizeof(segvact));
+      segvact.sa_sigaction = sesssegvhandler;
+      segvact.sa_flags = SA_SIGINFO | SA_RESETHAND;
+
+      // Register Segfault signal handler, so we can derefence 'result'
+      // safely (or sort of)
+      if (sigaction(SIGSEGV, &segvact, &oldact) != 0) {
+         st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+         result = NULL;
+         goto out;
+      }
+      
+      // Try dereferencing it, and check if we have the right handle
+      if ( result->handle != handle ) {
+         result = NULL;
       }
 
-      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 = NULL;
+         goto out;
+      }
+   }
+   else {
+      // If we are here, means that a segfault was caught and we somehow 
recovered
+      // result: the session handle was invalid
+      result = NULL;
    }
 
+out:
+
    MY_UnlockMutex( &sess_list_mutex );
    return result;
 }
@@ -385,13 +425,7 @@ session_mgr_new( CK_ULONG flags, SESSION **sess )
    }
    pkcs_locked = TRUE;
 
-   do {
-      s = session_mgr_find( next_session_handle );
-      if (s != NULL)
-         next_session_handle++;
-      else
-         new_session->handle = next_session_handle++;
-   } while (s != NULL);
+   new_session->handle = (CK_SESSION_HANDLE) new_session;
 
    MY_UnlockMutex( &pkcs_mutex );
    pkcs_locked = FALSE;
@@ -596,6 +630,9 @@ session_mgr_close_session( SESSION *sess )
       ro_session_count--;
    }
 
+   // Make sure this address is now invalid
+   sess->handle = CK_INVALID_HANDLE;
+
    if (sess->find_list)
       free( sess->find_list );
 
@@ -680,6 +717,8 @@ session_mgr_close_all_sessions( void )
 
       object_mgr_purge_session_objects( sess, ALL );
 
+      sess->handle = CK_INVALID_HANDLE;
+
       if (sess->find_list)
          free( sess->find_list );
 
-- 
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

Reply via email to