From 499e854f734ddd1e82c617f19bc925b3ca52da6c Mon Sep 17 00:00:00 2001
From: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Wed, 2 Oct 2019 12:39:10 +0200
Subject: [PATCH] COMMON: A cross-process lock should also lock against threads

The cross-process locks use an flock to lock against other processes.
However, this does not protect against other threads within the same
process. Add a pthread recursive mutex to also protect against threads.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
 usr/lib/api/apiutil.c         | 24 ++++++++++++++++++----
 usr/lib/common/h_extern.h     |  4 +++-
 usr/lib/common/host_defs.h    |  2 ++
 usr/lib/common/new_host.c     |  6 +++++-
 usr/lib/common/utility.c      | 47 ++++++++++++++++++++++++++++++++++++++++++-
 usr/lib/ep11_stdll/new_host.c |  6 +++++-
 usr/lib/icsf_stdll/new_host.c |  6 +++++-
 7 files changed, 86 insertions(+), 9 deletions(-)

diff --git a/usr/lib/api/apiutil.c b/usr/lib/api/apiutil.c
index 3de9ec92..af78ed67 100644
--- a/usr/lib/api/apiutil.c
+++ b/usr/lib/api/apiutil.c
@@ -23,6 +23,7 @@
 #include <dlfcn.h>
 #include <errno.h>
 #include <sys/syslog.h>
+#include <pthread.h>
 
 #include <sys/ipc.h>
 
@@ -38,6 +39,7 @@
 #include <sys/file.h>
 
 static int xplfd = -1;
+pthread_rwlock_t xplfd_rwlock = PTHREAD_RWLOCK_INITIALIZER;
 
 #include <libgen.h>
 
@@ -69,20 +71,34 @@ CK_RV CreateProcLock(void)
 
 CK_RV ProcLock(void)
 {
-    if (xplfd != -1)
+    if (pthread_rwlock_wrlock(&xplfd_rwlock)) {
+        TRACE_ERROR("Lock failed.\n");
+        return CKR_CANT_LOCK;
+    }
+
+    if (xplfd != -1) {
         flock(xplfd, LOCK_EX);
-    else
+    } else {
         TRACE_DEVEL("No file descriptor to lock with.\n");
+        return CKR_CANT_LOCK;
+    }
 
     return CKR_OK;
 }
 
 CK_RV ProcUnLock(void)
 {
-    if (xplfd != -1)
+    if (xplfd != -1) {
         flock(xplfd, LOCK_UN);
-    else
+    } else {
         TRACE_DEVEL("No file descriptor to unlock with.\n");
+        return CKR_CANT_LOCK;
+    }
+
+    if (pthread_rwlock_unlock(&xplfd_rwlock)) {
+        TRACE_ERROR("Unlock failed.\n");
+        return CKR_CANT_LOCK;
+    }
 
     return CKR_OK;
 }
diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
index fbe2b131..119ff7ed 100644
--- a/usr/lib/common/h_extern.h
+++ b/usr/lib/common/h_extern.h
@@ -1793,8 +1793,10 @@ CK_RV check_user_and_group();
 //lock and unlock routines
 CK_RV XProcLock(STDLL_TokData_t *tokdata);
 CK_RV XProcUnLock(STDLL_TokData_t *tokdata);
+CK_RV XThreadLock(STDLL_TokData_t *tokdata);
+CK_RV XThreadUnLock(STDLL_TokData_t *tokdata);
 CK_RV CreateXProcLock(char *tokname, STDLL_TokData_t *tokdata);
-void XProcLock_Init(STDLL_TokData_t *tokdata);
+CK_RV XProcLock_Init(STDLL_TokData_t *tokdata);
 void CloseXProcLock(STDLL_TokData_t *tokdata);
 
 //list mechanisms
diff --git a/usr/lib/common/host_defs.h b/usr/lib/common/host_defs.h
index d4521f39..2b119d16 100644
--- a/usr/lib/common/host_defs.h
+++ b/usr/lib/common/host_defs.h
@@ -17,6 +17,7 @@
 
 #include "pkcs32.h"
 #include <stdint.h>
+#include <pthread.h>
 
 #include "local_types.h"
 
@@ -280,6 +281,7 @@ struct _LW_SHM_TYPE {
 struct _STDLL_TokData_t {
     CK_SLOT_INFO slot_info;
     int spinxplfd;              // token specific lock
+    pthread_mutex_t spinxplfd_mutex; // token specific pthread lock
     char data_store[256];       // path information of the token directory
     CK_BYTE user_pin_md5[MD5_HASH_SIZE];
     CK_BYTE so_pin_md5[MD5_HASH_SIZE];
diff --git a/usr/lib/common/new_host.c b/usr/lib/common/new_host.c
index a68e38b4..da049eac 100644
--- a/usr/lib/common/new_host.c
+++ b/usr/lib/common/new_host.c
@@ -164,7 +164,11 @@ CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber,
     }
 
     /* Initialize Lock */
-    XProcLock_Init(sltp->TokData);
+    if (XProcLock_Init(sltp->TokData) != CKR_OK) {
+        TRACE_ERROR("Thread lock failed.\n");
+        rc = CKR_FUNCTION_FAILED;
+        goto done;
+    }
 
     /* Create lockfile */
     if (CreateXProcLock(sinfp->tokname, sltp->TokData) != CKR_OK) {
diff --git a/usr/lib/common/utility.c b/usr/lib/common/utility.c
index 794d7e89..8f927c8a 100644
--- a/usr/lib/common/utility.c
+++ b/usr/lib/common/utility.c
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <pwd.h>
 #include <grp.h>
+#include <pthread.h>
 
 #include "pkcs11types.h"
 #include "defs.h"
@@ -388,10 +389,34 @@ void CloseXProcLock(STDLL_TokData_t *tokdata)
 {
     if (tokdata->spinxplfd != -1)
         close(tokdata->spinxplfd);
+    pthread_mutex_destroy(&tokdata->spinxplfd_mutex);
+}
+
+CK_RV XThreadLock(STDLL_TokData_t *tokdata)
+{
+    if (pthread_mutex_lock(&tokdata->spinxplfd_mutex)) {
+        TRACE_ERROR("Lock failed.\n");
+        return CKR_CANT_LOCK;
+    }
+
+    return CKR_OK;
+}
+
+CK_RV XThreadUnLock(STDLL_TokData_t *tokdata)
+{
+    if (pthread_mutex_unlock(&tokdata->spinxplfd_mutex)) {
+        TRACE_ERROR("Unlock failed.\n");
+        return CKR_CANT_LOCK;
+    }
+
+    return CKR_OK;
 }
 
 CK_RV XProcLock(STDLL_TokData_t *tokdata)
 {
+    if (XThreadLock(tokdata) != CKR_OK)
+        return CKR_CANT_LOCK;
+
     if (tokdata->spinxplfd != -1) {
         flock(tokdata->spinxplfd, LOCK_EX);
     } else {
@@ -411,12 +436,32 @@ CK_RV XProcUnLock(STDLL_TokData_t *tokdata)
         return CKR_CANT_LOCK;
     }
 
+    if (XThreadUnLock(tokdata) != CKR_OK)
+        return CKR_CANT_LOCK;
+
     return CKR_OK;
 }
 
-void XProcLock_Init(STDLL_TokData_t *tokdata)
+CK_RV XProcLock_Init(STDLL_TokData_t *tokdata)
 {
+    pthread_mutexattr_t attr;
+
     tokdata->spinxplfd = -1;
+
+    if (pthread_mutexattr_init(&attr)) {
+        TRACE_ERROR("Mutex attribute init failed.\n");
+        return CKR_CANT_LOCK;
+    }
+    if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) {
+        TRACE_ERROR("Mutex attribute set failed.\n");
+        return CKR_CANT_LOCK;
+    }
+    if (pthread_mutex_init(&tokdata->spinxplfd_mutex, &attr)) {
+        TRACE_ERROR("Mutex init failed.\n");
+        return CKR_CANT_LOCK;
+    }
+
+    return CKR_OK;
 }
 
 //
diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
index 875d6d30..2311a560 100644
--- a/usr/lib/ep11_stdll/new_host.c
+++ b/usr/lib/ep11_stdll/new_host.c
@@ -156,7 +156,11 @@ CK_RV ST_Initialize(API_Slot_t * sltp, CK_SLOT_ID SlotNumber,
     }
 
     /* Initialize lock */
-    XProcLock_Init(sltp->TokData);
+    if (XProcLock_Init(sltp->TokData) != CKR_OK) {
+        TRACE_ERROR("Thread lock failed.\n");
+        rc = CKR_FUNCTION_FAILED;
+        goto done;
+    }
 
     /* Create lockfile */
     if (CreateXProcLock(sinfp->tokname, sltp->TokData) != CKR_OK) {
diff --git a/usr/lib/icsf_stdll/new_host.c b/usr/lib/icsf_stdll/new_host.c
index f01475be..ffdc4dca 100644
--- a/usr/lib/icsf_stdll/new_host.c
+++ b/usr/lib/icsf_stdll/new_host.c
@@ -156,7 +156,11 @@ CK_RV ST_Initialize(API_Slot_t * sltp, CK_SLOT_ID SlotNumber,
     }
 
     /* Initialize lock */
-    XProcLock_Init(sltp->TokData);
+    if (XProcLock_Init(sltp->TokData) != CKR_OK) {
+        TRACE_ERROR("Thread lock failed.\n");
+        rc = CKR_FUNCTION_FAILED;
+        goto done;
+    }
 
     /* Create lockfile */
     if (CreateXProcLock(sinfp->tokname, sltp->TokData) != CKR_OK) {
-- 
2.13.7

