Blob Blame History Raw
commit c79e899d77a5724635a9d4451a34a240e2c7e891
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date:   Fri Apr 16 13:41:41 2021 +0200

    Fix potential deadlock situation with double read-locks
    
    Do not get and read-lock an object twice within the same thread via
    function object_mgr_find_in_map1(), as this would read-lock the object
    twice.
    
    This could cause a deadlock situation, when in-between the first
    and the second call to object_mgr_find_in_map1() the token object is
    modified by another process. The second object_mgr_find_in_map1() would
    detect that the object has been modified (object_mgr_check_shm()), and
    would try to re-load the object from the disk. For re-loading, the
    object is unlocked once, and a write-lock is acquired instead.
    However, if the current thread has read-locked the object twice, but
    releases only one read-lock, then it will never get the write lock,
    because it still owns the read lock itself.
    
    To avoid this situation, release the read-lock before calling another
    function that also acquires the read lock of the object. That way, only
    one read-lock is held by the current thread, and re-loading the object
    will not cause a deadlock.
    
    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>

diff --git a/usr/lib/common/decr_mgr.c b/usr/lib/common/decr_mgr.c
index 317ef995..9842302b 100644
--- a/usr/lib/common/decr_mgr.c
+++ b/usr/lib/common/decr_mgr.c
@@ -540,6 +540,10 @@ CK_RV decr_mgr_init(STDLL_TokData_t *tokdata,
         }
         memset(ctx->context, 0x0, sizeof(AES_GCM_CONTEXT));
 
+        /* Release obj lock, token specific aes-gcm may re-acquire the lock */
+        object_put(tokdata, key_obj, TRUE);
+        key_obj = NULL;
+
         rc = aes_gcm_init(tokdata, sess, ctx, mech, key_handle, 0);
         if (rc) {
             TRACE_ERROR("Could not initialize AES_GCM parms.\n");
diff --git a/usr/lib/common/encr_mgr.c b/usr/lib/common/encr_mgr.c
index d3ecdeee..3e85ceab 100644
--- a/usr/lib/common/encr_mgr.c
+++ b/usr/lib/common/encr_mgr.c
@@ -537,6 +537,10 @@ CK_RV encr_mgr_init(STDLL_TokData_t *tokdata,
         }
         memset(ctx->context, 0x0, sizeof(AES_GCM_CONTEXT));
 
+        /* Release obj lock, token specific aes-gcm may re-acquire the lock */
+        object_put(tokdata, key_obj, TRUE);
+        key_obj = NULL;
+
         rc = aes_gcm_init(tokdata, sess, ctx, mech, key_handle, 1);
         if (rc != CKR_OK) {
             TRACE_ERROR("Could not initialize AES_GCM parms.\n");
diff --git a/usr/lib/common/mech_rsa.c b/usr/lib/common/mech_rsa.c
index 1652f90a..e35b383c 100644
--- a/usr/lib/common/mech_rsa.c
+++ b/usr/lib/common/mech_rsa.c
@@ -602,6 +602,10 @@ CK_RV rsa_oaep_crypt(STDLL_TokData_t *tokdata, SESSION *sess,
             goto done;
         }
 
+        /* Release obj lock, token specific rsa-oaep may re-acquire the lock */
+        object_put(tokdata, key_obj, TRUE);
+        key_obj = NULL;
+
         rc = token_specific.t_rsa_oaep_encrypt(tokdata, ctx, in_data,
                                                in_data_len, out_data,
                                                out_data_len, hash, hlen);
@@ -625,6 +629,10 @@ CK_RV rsa_oaep_crypt(STDLL_TokData_t *tokdata, SESSION *sess,
             goto done;
         }
 
+        /* Release obj lock, token specific rsa-oaep may re-acquire the lock */
+        object_put(tokdata, key_obj, TRUE);
+        key_obj = NULL;
+
         rc = token_specific.t_rsa_oaep_decrypt(tokdata, ctx, in_data,
                                                in_data_len, out_data,
                                                out_data_len, hash, hlen);
@@ -1331,6 +1339,10 @@ CK_RV rsa_pss_sign(STDLL_TokData_t *tokdata, SESSION *sess,
         goto done;
     }
 
+    /* Release obj lock, token specific rsa_pss may re-acquire the lock */
+    object_put(tokdata, key_obj, TRUE);
+    key_obj = NULL;
+
     rc = token_specific.t_rsa_pss_sign(tokdata, sess, ctx, in_data, in_data_len,
                                        out_data, out_data_len);
     if (rc != CKR_OK)
@@ -1389,6 +1401,10 @@ CK_RV rsa_pss_verify(STDLL_TokData_t *tokdata, SESSION *sess,
         goto done;
     }
 
+    /* Release obj lock, token specific rsa_pss may re-acquire the lock */
+    object_put(tokdata, key_obj, TRUE);
+    key_obj = NULL;
+
     rc = token_specific.t_rsa_pss_verify(tokdata, sess, ctx, in_data,
                                          in_data_len, signature, sig_len);
     if (rc != CKR_OK)
diff --git a/usr/lib/common/sign_mgr.c b/usr/lib/common/sign_mgr.c
index 937a371a..c7268e01 100644
--- a/usr/lib/common/sign_mgr.c
+++ b/usr/lib/common/sign_mgr.c
@@ -424,6 +424,10 @@ CK_RV sign_mgr_init(STDLL_TokData_t *tokdata,
         ctx->context_len = 0;
         ctx->context = NULL;
 
+        /* Release obj lock, token specific hmac-sign may re-acquire the lock */
+        object_put(tokdata, key_obj, TRUE);
+        key_obj = NULL;
+
         rc = hmac_sign_init(tokdata, sess, mech, key);
         if (rc != CKR_OK) {
             TRACE_ERROR("Failed to initialize hmac.\n");
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
index 3ac3768a..52f95d7a 100644
--- a/usr/lib/ep11_stdll/ep11_specific.c
+++ b/usr/lib/ep11_stdll/ep11_specific.c
@@ -6948,6 +6948,13 @@ CK_RV ep11tok_sign_init(STDLL_TokData_t * tokdata, SESSION * session,
     rc = ep11tok_pkey_check(tokdata, session, key_obj, mech);
     switch (rc) {
     case CKR_OK:
+        /*
+         * Release obj lock, sign_mgr_init or ep11tok_sign_verify_init_ibm_ed
+         * may re-acquire the lock
+         */
+        object_put(tokdata, key_obj, TRUE);
+        key_obj = NULL;
+
         /* Note that Edwards curves in general are not yet supported in
          * opencryptoki. These two special IBM specific ED mechs are only
          * supported by the ep11token, so let's keep them local here. */
@@ -7029,11 +7036,16 @@ CK_RV ep11tok_sign(STDLL_TokData_t * tokdata, SESSION * session,
          * opencryptoki. These two special IBM specific ED mechs are only
          * supported by the ep11token, so let's keep them local here. */
         if (ctx->mech.mechanism == CKM_IBM_ED25519_SHA512 ||
-            ctx->mech.mechanism == CKM_IBM_ED448_SHA3)
+            ctx->mech.mechanism == CKM_IBM_ED448_SHA3) {
             rc = pkey_ibm_ed_sign(key_obj, in_data, in_data_len, signature, sig_len);
-        else
+        } else {
+            /* Release obj lock, sign_mgr_sign may re-acquire the lock */
+            object_put(tokdata, key_obj, TRUE);
+            key_obj = NULL;
+
             rc = sign_mgr_sign(tokdata, session, length_only, ctx, in_data,
                                in_data_len, signature, sig_len);
+        }
         goto done; /* no ep11 fallback possible */
     }
 
@@ -7071,6 +7083,11 @@ CK_RV ep11tok_sign_update(STDLL_TokData_t * tokdata, SESSION * session,
     if (!in_data || !in_data_len)
         return CKR_OK;
 
+    if (ctx->pkey_active) {
+        rc = sign_mgr_sign_update(tokdata, session, ctx, in_data, in_data_len);
+        goto done; /* no ep11 fallback possible */
+    }
+
     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
                           READ_LOCK);
     if (rc != CKR_OK) {
@@ -7078,11 +7095,6 @@ CK_RV ep11tok_sign_update(STDLL_TokData_t * tokdata, SESSION * session,
         return rc;
     }
 
-    if (ctx->pkey_active) {
-        rc = sign_mgr_sign_update(tokdata, session, ctx, in_data, in_data_len);
-        goto done; /* no ep11 fallback possible */
-    }
-
     RETRY_START
         rc = dll_m_SignUpdate(ctx->context, ctx->context_len, in_data,
                               in_data_len, ep11_data->target);
@@ -7115,6 +7127,11 @@ CK_RV ep11tok_sign_final(STDLL_TokData_t * tokdata, SESSION * session,
     CK_BYTE *keyblob;
     OBJECT *key_obj = NULL;
 
+    if (ctx->pkey_active) {
+        rc = sign_mgr_sign_final(tokdata, session, length_only, ctx, signature, sig_len);
+        goto done; /* no ep11 fallback possible */
+    }
+
     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
                           READ_LOCK);
     if (rc != CKR_OK) {
@@ -7122,11 +7139,6 @@ CK_RV ep11tok_sign_final(STDLL_TokData_t * tokdata, SESSION * session,
         return rc;
     }
 
-    if (ctx->pkey_active) {
-        rc = sign_mgr_sign_final(tokdata, session, length_only, ctx, signature, sig_len);
-        goto done; /* no ep11 fallback possible */
-    }
-
     RETRY_START
         rc = dll_m_SignFinal(ctx->context, ctx->context_len, signature, sig_len,
                              ep11_data->target);
@@ -7241,6 +7253,13 @@ CK_RV ep11tok_verify_init(STDLL_TokData_t * tokdata, SESSION * session,
     rc = ep11tok_pkey_check(tokdata, session, key_obj, mech);
     switch (rc) {
     case CKR_OK:
+        /*
+         * Release obj lock, verify_mgr_init or ep11tok_sign_verify_init_ibm_ed
+         * may re-acquire the lock
+         */
+        object_put(tokdata, key_obj, TRUE);
+        key_obj = NULL;
+
         /* Note that Edwards curves in general are not yet supported in
          * opencryptoki. These two special IBM specific ED mechs are only
          * supported by the ep11token, so let's keep them local here. */
@@ -7320,12 +7339,17 @@ CK_RV ep11tok_verify(STDLL_TokData_t * tokdata, SESSION * session,
          * opencryptoki. These two special IBM specific ED mechs are only
          * supported by the ep11token, so let's keep them local here. */
         if (ctx->mech.mechanism == CKM_IBM_ED25519_SHA512 ||
-            ctx->mech.mechanism == CKM_IBM_ED448_SHA3)
+            ctx->mech.mechanism == CKM_IBM_ED448_SHA3) {
             rc = pkey_ibm_ed_verify(key_obj, in_data, in_data_len,
                                     signature, sig_len);
-        else
+        } else {
+            /* Release obj lock, verify_mgr_verify may re-acquire the lock */
+            object_put(tokdata, key_obj, TRUE);
+            key_obj = NULL;
+
             rc = verify_mgr_verify(tokdata, session, ctx, in_data,
                                    in_data_len, signature, sig_len);
+        }
         goto done; /* no ep11 fallback possible */
     }
 
@@ -7363,6 +7387,11 @@ CK_RV ep11tok_verify_update(STDLL_TokData_t * tokdata, SESSION * session,
     if (!in_data || !in_data_len)
         return CKR_OK;
 
+    if (ctx->pkey_active) {
+        rc = verify_mgr_verify_update(tokdata, session, ctx, in_data, in_data_len);
+        goto done; /* no ep11 fallback possible */
+    }
+
     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
                          READ_LOCK);
     if (rc != CKR_OK) {
@@ -7370,11 +7399,6 @@ CK_RV ep11tok_verify_update(STDLL_TokData_t * tokdata, SESSION * session,
         return rc;
     }
 
-    if (ctx->pkey_active) {
-        rc = verify_mgr_verify_update(tokdata, session, ctx, in_data, in_data_len);
-        goto done; /* no ep11 fallback possible */
-    }
-
     RETRY_START
         rc = dll_m_VerifyUpdate(ctx->context, ctx->context_len, in_data,
                                 in_data_len, ep11_data->target);
@@ -7406,6 +7430,11 @@ CK_RV ep11tok_verify_final(STDLL_TokData_t * tokdata, SESSION * session,
     CK_BYTE *keyblob;
     OBJECT *key_obj = NULL;
 
+    if (ctx->pkey_active) {
+        rc = verify_mgr_verify_final(tokdata, session, ctx, signature, sig_len);
+        goto done; /* no ep11 fallback possible */
+    }
+
     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
                          READ_LOCK);
     if (rc != CKR_OK) {
@@ -7413,11 +7442,6 @@ CK_RV ep11tok_verify_final(STDLL_TokData_t * tokdata, SESSION * session,
         return rc;
     }
 
-    if (ctx->pkey_active) {
-        rc = verify_mgr_verify_final(tokdata, session, ctx, signature, sig_len);
-        goto done; /* no ep11 fallback possible */
-    }
-
     RETRY_START
         rc = dll_m_VerifyFinal(ctx->context, ctx->context_len, signature,
                                sig_len, ep11_data->target);
@@ -7501,6 +7525,12 @@ CK_RV ep11tok_decrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
     CK_BYTE *keyblob;
     OBJECT *key_obj = NULL;
 
+    if (ctx->pkey_active) {
+        rc = decr_mgr_decrypt_final(tokdata, session, length_only,
+                                    ctx, output_part, p_output_part_len);
+        goto done; /* no ep11 fallback possible */
+    }
+
     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
                          READ_LOCK);
     if (rc != CKR_OK) {
@@ -7508,12 +7538,6 @@ CK_RV ep11tok_decrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
         return rc;
     }
 
-    if (ctx->pkey_active) {
-        rc = decr_mgr_decrypt_final(tokdata, session, length_only,
-                                    ctx, output_part, p_output_part_len);
-        goto done; /* no ep11 fallback possible */
-    }
-
     RETRY_START
         rc = dll_m_DecryptFinal(ctx->context, ctx->context_len,
                                 output_part, p_output_part_len,
@@ -7548,13 +7572,6 @@ CK_RV ep11tok_decrypt(STDLL_TokData_t * tokdata, SESSION * session,
     CK_BYTE *keyblob;
     OBJECT *key_obj = NULL;
 
-    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-                         READ_LOCK);
-    if (rc != CKR_OK) {
-        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
-        return rc;
-    }
-
     if (ctx->pkey_active) {
         rc = decr_mgr_decrypt(tokdata, session, length_only, ctx,
                               input_data, input_data_len, output_data,
@@ -7562,6 +7579,13 @@ CK_RV ep11tok_decrypt(STDLL_TokData_t * tokdata, SESSION * session,
         goto done; /* no ep11 fallback possible */
     }
 
+    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
+                         READ_LOCK);
+    if (rc != CKR_OK) {
+        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
+        return rc;
+    }
+
     RETRY_START
         rc = dll_m_Decrypt(ctx->context, ctx->context_len, input_data,
                            input_data_len, output_data, p_output_data_len,
@@ -7602,13 +7626,6 @@ CK_RV ep11tok_decrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
         return CKR_OK;          /* nothing to update, keep context */
     }
 
-    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-                         READ_LOCK);
-    if (rc != CKR_OK) {
-        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
-        return rc;
-    }
-
     if (ctx->pkey_active) {
         rc = decr_mgr_decrypt_update(tokdata, session, length_only,
                                      ctx, input_part, input_part_len,
@@ -7616,6 +7633,13 @@ CK_RV ep11tok_decrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
         goto done; /* no ep11 fallback possible */
     }
 
+    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
+                         READ_LOCK);
+    if (rc != CKR_OK) {
+        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
+        return rc;
+    }
+
     RETRY_START
         rc = dll_m_DecryptUpdate(ctx->context, ctx->context_len,
                                  input_part, input_part_len, output_part,
@@ -7695,6 +7719,12 @@ CK_RV ep11tok_encrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
     CK_BYTE *keyblob;
     OBJECT *key_obj = NULL;
 
+    if (ctx->pkey_active) {
+        rc = encr_mgr_encrypt_final(tokdata, session, length_only,
+                                    ctx, output_part, p_output_part_len);
+        goto done; /* no ep11 fallback possible */
+    }
+
     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
                          READ_LOCK);
     if (rc != CKR_OK) {
@@ -7702,12 +7732,6 @@ CK_RV ep11tok_encrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
         return rc;
     }
 
-    if (ctx->pkey_active) {
-        rc = encr_mgr_encrypt_final(tokdata, session, length_only,
-                                    ctx, output_part, p_output_part_len);
-        goto done; /* no ep11 fallback possible */
-    }
-
     RETRY_START
         rc = dll_m_EncryptFinal(ctx->context, ctx->context_len,
                                 output_part, p_output_part_len,
@@ -7742,13 +7766,6 @@ CK_RV ep11tok_encrypt(STDLL_TokData_t * tokdata, SESSION * session,
     CK_BYTE *keyblob;
     OBJECT *key_obj = NULL;
 
-    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-                         READ_LOCK);
-    if (rc != CKR_OK) {
-        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
-        return rc;
-    }
-
     if (ctx->pkey_active) {
         rc = encr_mgr_encrypt(tokdata, session, length_only, ctx,
                               input_data, input_data_len, output_data,
@@ -7756,6 +7773,13 @@ CK_RV ep11tok_encrypt(STDLL_TokData_t * tokdata, SESSION * session,
         goto done; /* no ep11 fallback possible */
     }
 
+    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
+                         READ_LOCK);
+    if (rc != CKR_OK) {
+        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
+        return rc;
+    }
+
     RETRY_START
         rc = dll_m_Encrypt(ctx->context, ctx->context_len, input_data,
                            input_data_len, output_data, p_output_data_len,
@@ -7796,13 +7820,6 @@ CK_RV ep11tok_encrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
         return CKR_OK;          /* nothing to update, keep context */
     }
 
-    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-                         READ_LOCK);
-    if (rc != CKR_OK) {
-        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
-        return rc;
-    }
-
     if (ctx->pkey_active) {
         rc = encr_mgr_encrypt_update(tokdata, session, length_only, ctx,
                                      input_part, input_part_len, output_part,
@@ -7810,6 +7827,13 @@ CK_RV ep11tok_encrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
         goto done; /* no ep11 fallback possible */
     }
 
+    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
+                         READ_LOCK);
+    if (rc != CKR_OK) {
+        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
+        return rc;
+    }
+
     RETRY_START
         rc = dll_m_EncryptUpdate(ctx->context, ctx->context_len,
                                  input_part, input_part_len, output_part,
@@ -7921,6 +7945,10 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
     rc = ep11tok_pkey_check(tokdata, session, key_obj, mech);
     switch (rc) {
     case CKR_OK:
+        /* Release obj lock, encr/decr_mgr_init may re-acquire the lock */
+        object_put(tokdata, key_obj, TRUE);
+        key_obj = NULL;
+
         if (op == DECRYPT) {
             rc = decr_mgr_init(tokdata, session, &session->decr_ctx,
                                OP_DECRYPT_INIT, mech, key);