Hi
There are several issues in SoftHSM when using threads and
C_CloseAllSessions.
I'm not a C++ programmer, but I believe the issue is that
C_CloseAllSessions 'delete's sessions although the sessions can be in
use in another thread - causing segmentation faults in the other thread.
The attached patch to the test suite easily demonstrates the problem on
my system. Ubuntu 12.04, SoftHSM rev 6958.
$ gdb --args ./checks -o
...
Program received signal SIGSEGV, Segmentation fault.
0x000000000040cc54 in C_GenerateRandom (hSession=<optimized out>,
pRandomData=0x7fffffffe0b0 "<snip>",
ulRandomLen=40) at ../../../src/lib/main.cpp:2756
2756 session->rng->randomize(pRandomData, ulRandomLen);
(gdb) list
2751 if(pRandomData == NULL_PTR) {
2752 DEBUG_MSG("C_GenerateRandom", "pRandomData must not be a
NULL_PTR");
2753 return CKR_ARGUMENTS_BAD;
2754 }
2755
2756 session->rng->randomize(pRandomData, ulRandomLen);
2757
2758 DEBUG_MSG("C_GenerateRandom", "OK");
2759 return CKR_OK;
2760 }
(gdb)
So session->rng is now an invalid reference since C_CloseAllSessions did
'delete' on the session from another thread.
I've seen this problem in C_GenerateKeyPair (also due to session->rng)
and in unknown place(s) crashing out in sqlite as well.
/Fredrik
Index: checks/checks.h
===================================================================
--- checks/checks.h (revision 6958)
+++ checks/checks.h (working copy)
@@ -41,3 +41,4 @@
void runEncryptCheck(unsigned int counter);
void runDecryptCheck(unsigned int counter);
void runSignVerifyCheck();
+void runThreadsCheck(unsigned int counter);
Index: checks/checks.c
===================================================================
--- checks/checks.c (revision 6958)
+++ checks/checks.c (working copy)
@@ -36,6 +36,8 @@
#include <assert.h>
#include <string.h>
+#include <pthread.h>
+
CK_UTF8CHAR userPIN[] = {"123456"};
CK_UTF8CHAR soPIN[] = {"12345678"};
@@ -61,6 +63,7 @@
printf("-l\t\tTest encrypt functions\n");
printf("-m\t\tTest decrypt functions\n");
printf("-n\t\tTest all sign and verify mechanisms\n");
+ printf("-o\t\tTest with pthreads\n");
printf("\n-z\t\tRun all tests\n");
}
@@ -80,7 +83,7 @@
/* Init token */
inittoken();
- while ((c = getopt(argc, argv, "abcdefghijklmnz")) != -1) {
+ while ((c = getopt(argc, argv, "abcdefghijklmnoz")) != -1) {
switch(c) {
case 'a':
runInitCheck(5);
@@ -124,6 +127,9 @@
case 'n':
runSignVerifyCheck();
break;
+ case 'o':
+ runThreadsCheck(5);
+ break;
case 'z':
runInitCheck(5);
runInfoCheck(5);
@@ -138,6 +144,7 @@
runEncryptCheck(5);
runDecryptCheck(5);
runSignVerifyCheck();
+ runThreadsCheck(5);
break;
default:
usage();
@@ -1781,3 +1788,67 @@
printf("OK\n");
}
+
+static void *run_closeAll_thread()
+{
+ int i = 0;
+ CK_RV rv;
+
+ while (i++ < 10000) {
+ rv = C_CloseAllSessions(slotWithToken);
+ assert(rv == CKR_OK);
+ }
+
+ return NULL;
+}
+
+void runThreadsCheck(unsigned int counter) {
+ unsigned int i;
+
+ printf("Checking C_CloseAllSessions and C_GenerateRandom with pthreads: ");
+
+ for(i = 0; i < counter; i++) {
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession[10];
+ CK_BYTE seed[] = {"Some random data"};
+ CK_BYTE randomData[40];
+ pthread_t closeAll_thread;
+ CK_C_INITIALIZE_ARGS init_args;
+ int res;
+
+ memset(&init_args, 0, sizeof(init_args));
+ init_args.flags = CKF_OS_LOCKING_OK;
+
+ rv = C_Initialize(&init_args);
+ assert(rv == CKR_OK);
+
+ rv = C_OpenSession(slotWithToken, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession[0]);
+ assert(rv == CKR_OK);
+
+ rv = C_SeedRandom(hSession[0], seed, sizeof(seed));
+ assert(rv == CKR_OK);
+
+ /* Create a thread to run C_CloseAllSessions repeatedly */
+ res = pthread_create(&closeAll_thread, NULL,
+ run_closeAll_thread, NULL);
+ assert(res == 0);
+
+ /* C_GenerateRandom while sessions are being closed */
+
+ for (i = 0; i < 100; i++) {
+ rv = C_GenerateRandom(hSession[0], randomData, 40);
+ assert(rv == CKR_OK);
+ }
+
+ pthread_cancel(closeAll_thread);
+
+ res = pthread_join(closeAll_thread, NULL);
+ assert(res == 0);
+
+ rv = C_Finalize(NULL_PTR);
+ assert(rv == CKR_OK);
+
+ }
+
+ printf("OK\n");
+}
_______________________________________________
Opendnssec-user mailing list
[email protected]
https://lists.opendnssec.org/mailman/listinfo/opendnssec-user