Print this page
4912 soft_giant_mutex in pkcs11_softtoken stays held after fork


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.


  24  */
  25 
  26 #include <strings.h>
  27 #include <errno.h>
  28 #include <cryptoutil.h>
  29 #include <unistd.h> /* for pid_t */
  30 #include <pthread.h>
  31 #include <security/cryptoki.h>
  32 #include "softGlobal.h"
  33 #include "softSession.h"
  34 #include "softObject.h"
  35 #include "softKeystore.h"
  36 #include "softKeystoreUtil.h"
  37 
  38 #pragma init(softtoken_init)
  39 #pragma fini(softtoken_fini)
  40 
  41 extern soft_session_t token_session; /* for fork handler */
  42 
  43 static struct CK_FUNCTION_LIST functionList = {


 111         C_CancelFunction,
 112         C_WaitForSlotEvent
 113 };
 114 
 115 boolean_t softtoken_initialized = B_FALSE;
 116 
 117 static pid_t softtoken_pid = 0;
 118 
 119 /* This mutex protects soft_session_list, all_sessions_closing */
 120 pthread_mutex_t soft_sessionlist_mutex;
 121 soft_session_t *soft_session_list = NULL;
 122 
 123 int all_sessions_closing = 0;
 124 
 125 slot_t soft_slot;
 126 obj_to_be_freed_list_t obj_delay_freed;
 127 ses_to_be_freed_list_t ses_delay_freed;
 128 
 129 /* protects softtoken_initialized and access to C_Initialize/C_Finalize */
 130 pthread_mutex_t soft_giant_mutex = PTHREAD_MUTEX_INITIALIZER;





 131 
 132 static CK_RV finalize_common(boolean_t force, CK_VOID_PTR pReserved);
 133 static void softtoken_init();
 134 static void softtoken_fini();
 135 static void softtoken_fork_prepare();
 136 static void softtoken_fork_after();

 137 
 138 CK_RV
 139 C_Initialize(CK_VOID_PTR pInitArgs)
 140 {
 141 
 142         int initialize_pid;
 143         boolean_t supplied_ok;
 144         CK_RV rv;
 145 
 146         /*
 147          * Get lock to insure only one thread enters this
 148          * function at a time.
 149          */
 150         (void) pthread_mutex_lock(&soft_giant_mutex);
 151 
 152         initialize_pid = getpid();
 153 
 154         if (softtoken_initialized) {
 155                 if (initialize_pid == softtoken_pid) {
 156                         /*


 394         (void) pthread_mutex_destroy(&ses_delay_freed.ses_to_be_free_mutex);
 395 
 396         return (rv);
 397 }
 398 
 399 static void
 400 softtoken_init()
 401 {
 402         /* Children inherit parent's atfork handlers */
 403         (void) pthread_atfork(softtoken_fork_prepare,
 404             softtoken_fork_after, softtoken_fork_after);
 405 }
 406 
 407 /*
 408  * softtoken_fini() function required to make sure complete cleanup
 409  * is done if softtoken is ever unloaded without a C_Finalize() call.
 410  */
 411 static void
 412 softtoken_fini()
 413 {














 414         (void) pthread_mutex_lock(&soft_giant_mutex);

 415 
 416         /* if we're not initilized, do not attempt to finalize */
 417         if (!softtoken_initialized) {
 418                 (void) pthread_mutex_unlock(&soft_giant_mutex);
 419                 return;







 420         }
 421 
 422         (void) finalize_common(B_TRUE, NULL_PTR);
 423 



 424         (void) pthread_mutex_unlock(&soft_giant_mutex);
 425 }
 426 
 427 CK_RV
 428 C_GetInfo(CK_INFO_PTR pInfo)
 429 {
 430         if (!softtoken_initialized)
 431                 return (CKR_CRYPTOKI_NOT_INITIALIZED);
 432 
 433         if (pInfo == NULL) {
 434                 return (CKR_ARGUMENTS_BAD);
 435         }
 436 
 437         /* Provide general information in the provided buffer */
 438         pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
 439         pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
 440         (void) strncpy((char *)pInfo->manufacturerID,
 441             SOFT_MANUFACTURER_ID, 32);
 442         pInfo->flags = 0;
 443         (void) strncpy((char *)pInfo->libraryDescription,


 479 CK_RV
 480 C_CancelFunction(CK_SESSION_HANDLE hSession)
 481 {
 482         return (CKR_FUNCTION_NOT_PARALLEL);
 483 }
 484 
 485 /*
 486  * Take out all mutexes before fork.
 487  *
 488  * Order:
 489  * 1. soft_giant_mutex
 490  * 2. soft_sessionlist_mutex
 491  * 3. soft_slot.slot_mutex
 492  * 4. soft_slot.keystore_mutex
 493  * 5. token_session mutexes via soft_acquire_all_session_mutexes()
 494  * 6. all soft_session_list mutexes via soft_acquire_all_session_mutexes()
 495  * 7. obj_delay_freed.obj_to_be_free_mutex;
 496  * 8. ses_delay_freed.ses_to_be_free_mutex
 497  */
 498 void
 499 softtoken_fork_prepare()
 500 {
 501         (void) pthread_mutex_lock(&soft_giant_mutex);
 502         if (softtoken_initialized) {
 503                 (void) pthread_mutex_lock(&soft_sessionlist_mutex);
 504                 (void) pthread_mutex_lock(&soft_slot.slot_mutex);
 505                 (void) pthread_mutex_lock(&soft_slot.keystore_mutex);
 506                 soft_acquire_all_session_mutexes(&token_session);
 507                 soft_acquire_all_session_mutexes(soft_session_list);
 508                 (void) pthread_mutex_lock(
 509                     &obj_delay_freed.obj_to_be_free_mutex);
 510                 (void) pthread_mutex_lock(
 511                     &ses_delay_freed.ses_to_be_free_mutex);
 512         }

 513 }
 514 
 515 /*
 516  * Release in opposite order to softtoken_fork_prepare().
 517  * Function is used for parent and child.
 518  */
 519 void
 520 softtoken_fork_after()
 521 {
 522         if (softtoken_initialized) {
 523                 (void) pthread_mutex_unlock(
 524                     &ses_delay_freed.ses_to_be_free_mutex);
 525                 (void) pthread_mutex_unlock(
 526                     &obj_delay_freed.obj_to_be_free_mutex);
 527                 soft_release_all_session_mutexes(soft_session_list);
 528                 soft_release_all_session_mutexes(&token_session);
 529                 (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
 530                 (void) pthread_mutex_unlock(&soft_slot.slot_mutex);
 531                 (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
 532         }











 533         (void) pthread_mutex_unlock(&soft_giant_mutex);
 534 }


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  *
  25  * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  26  */
  27 
  28 #include <strings.h>
  29 #include <errno.h>
  30 #include <cryptoutil.h>
  31 #include <unistd.h> /* for pid_t */
  32 #include <pthread.h>
  33 #include <security/cryptoki.h>
  34 #include "softGlobal.h"
  35 #include "softSession.h"
  36 #include "softObject.h"
  37 #include "softKeystore.h"
  38 #include "softKeystoreUtil.h"
  39 
  40 #pragma init(softtoken_init)
  41 #pragma fini(softtoken_fini)
  42 
  43 extern soft_session_t token_session; /* for fork handler */
  44 
  45 static struct CK_FUNCTION_LIST functionList = {


 113         C_CancelFunction,
 114         C_WaitForSlotEvent
 115 };
 116 
 117 boolean_t softtoken_initialized = B_FALSE;
 118 
 119 static pid_t softtoken_pid = 0;
 120 
 121 /* This mutex protects soft_session_list, all_sessions_closing */
 122 pthread_mutex_t soft_sessionlist_mutex;
 123 soft_session_t *soft_session_list = NULL;
 124 
 125 int all_sessions_closing = 0;
 126 
 127 slot_t soft_slot;
 128 obj_to_be_freed_list_t obj_delay_freed;
 129 ses_to_be_freed_list_t ses_delay_freed;
 130 
 131 /* protects softtoken_initialized and access to C_Initialize/C_Finalize */
 132 pthread_mutex_t soft_giant_mutex = PTHREAD_MUTEX_INITIALIZER;
 133 /*
 134  * ONLY SET TO TRUE BY softtoken_fork_prepare().
 135  * ONLY SET TO FALSE BY softtoken_fork_after().
 136  */
 137 boolean_t fork_prepared = B_FALSE;
 138 
 139 static CK_RV finalize_common(boolean_t force, CK_VOID_PTR pReserved);
 140 static void softtoken_init();
 141 static void softtoken_fini();
 142 static void softtoken_fork_prepare();
 143 static void softtoken_fork_after();
 144 static void softtoken_fork_after_droplocks(void);
 145 
 146 CK_RV
 147 C_Initialize(CK_VOID_PTR pInitArgs)
 148 {
 149 
 150         int initialize_pid;
 151         boolean_t supplied_ok;
 152         CK_RV rv;
 153 
 154         /*
 155          * Get lock to insure only one thread enters this
 156          * function at a time.
 157          */
 158         (void) pthread_mutex_lock(&soft_giant_mutex);
 159 
 160         initialize_pid = getpid();
 161 
 162         if (softtoken_initialized) {
 163                 if (initialize_pid == softtoken_pid) {
 164                         /*


 402         (void) pthread_mutex_destroy(&ses_delay_freed.ses_to_be_free_mutex);
 403 
 404         return (rv);
 405 }
 406 
 407 static void
 408 softtoken_init()
 409 {
 410         /* Children inherit parent's atfork handlers */
 411         (void) pthread_atfork(softtoken_fork_prepare,
 412             softtoken_fork_after, softtoken_fork_after);
 413 }
 414 
 415 /*
 416  * softtoken_fini() function required to make sure complete cleanup
 417  * is done if softtoken is ever unloaded without a C_Finalize() call.
 418  */
 419 static void
 420 softtoken_fini()
 421 {
 422         int rc;
 423 
 424         rc = pthread_mutex_trylock(&soft_giant_mutex);
 425         /*
 426          * Check to see if it was acquired by softtoken_fork_prepare().
 427          */
 428         if (rc == EBUSY && fork_prepared)
 429                 rc = 0;
 430 
 431         if (rc != 0) {
 432                 /*
 433                  * I don't know WHAT just happened, but it's pretty bad.  Grab
 434                  * the lock for real, even if it means deadlocking here.
 435                  */
 436                 (void) pthread_mutex_lock(&soft_giant_mutex);
 437         } /* Else we acquired the lock and life is good. */
 438 
 439         /* Only finalize if we're initialized. */
 440         if (softtoken_initialized) {
 441                 /*
 442                  * We also have to DROP all of the other locks that
 443                  * softtoken_fork_prepare did IF it was prepared, because
 444                  * finalize_common() is going to pick them right back up.
 445                  */
 446                 if (fork_prepared)
 447                         softtoken_fork_after_droplocks();
 448                 (void) finalize_common(B_TRUE, NULL_PTR);
 449                 /* ASSERT(!softtoken_initialized); */
 450         }
 451 
 452         /*
 453          * If we don't want to drop the lock, we assume softtoken_fork_after()
 454          * will get called.
 455          */
 456         if (!fork_prepared)
 457                 (void) pthread_mutex_unlock(&soft_giant_mutex);
 458 }
 459 
 460 CK_RV
 461 C_GetInfo(CK_INFO_PTR pInfo)
 462 {
 463         if (!softtoken_initialized)
 464                 return (CKR_CRYPTOKI_NOT_INITIALIZED);
 465 
 466         if (pInfo == NULL) {
 467                 return (CKR_ARGUMENTS_BAD);
 468         }
 469 
 470         /* Provide general information in the provided buffer */
 471         pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
 472         pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
 473         (void) strncpy((char *)pInfo->manufacturerID,
 474             SOFT_MANUFACTURER_ID, 32);
 475         pInfo->flags = 0;
 476         (void) strncpy((char *)pInfo->libraryDescription,


 512 CK_RV
 513 C_CancelFunction(CK_SESSION_HANDLE hSession)
 514 {
 515         return (CKR_FUNCTION_NOT_PARALLEL);
 516 }
 517 
 518 /*
 519  * Take out all mutexes before fork.
 520  *
 521  * Order:
 522  * 1. soft_giant_mutex
 523  * 2. soft_sessionlist_mutex
 524  * 3. soft_slot.slot_mutex
 525  * 4. soft_slot.keystore_mutex
 526  * 5. token_session mutexes via soft_acquire_all_session_mutexes()
 527  * 6. all soft_session_list mutexes via soft_acquire_all_session_mutexes()
 528  * 7. obj_delay_freed.obj_to_be_free_mutex;
 529  * 8. ses_delay_freed.ses_to_be_free_mutex
 530  */
 531 void
 532 softtoken_fork_prepare(void)
 533 {
 534         (void) pthread_mutex_lock(&soft_giant_mutex);
 535         if (softtoken_initialized) {
 536                 (void) pthread_mutex_lock(&soft_sessionlist_mutex);
 537                 (void) pthread_mutex_lock(&soft_slot.slot_mutex);
 538                 (void) pthread_mutex_lock(&soft_slot.keystore_mutex);
 539                 soft_acquire_all_session_mutexes(&token_session);
 540                 soft_acquire_all_session_mutexes(soft_session_list);
 541                 (void) pthread_mutex_lock(
 542                     &obj_delay_freed.obj_to_be_free_mutex);
 543                 (void) pthread_mutex_lock(
 544                     &ses_delay_freed.ses_to_be_free_mutex);
 545         }
 546         fork_prepared = B_TRUE;
 547 }
 548 
 549 static void
 550 softtoken_fork_after_droplocks(void)




 551 {
 552         /* ASSERT(softtoken_initialized); */
 553         (void) pthread_mutex_unlock(&ses_delay_freed.ses_to_be_free_mutex);
 554         (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);


 555         soft_release_all_session_mutexes(soft_session_list);
 556         soft_release_all_session_mutexes(&token_session);
 557         (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
 558         (void) pthread_mutex_unlock(&soft_slot.slot_mutex);
 559         (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
 560 }
 561 
 562 /*
 563  * Release in opposite order to softtoken_fork_prepare().
 564  * Function is used for parent and child.
 565  */
 566 void
 567 softtoken_fork_after(void)
 568 {
 569         if (softtoken_initialized)
 570                 softtoken_fork_after_droplocks();
 571         fork_prepared = B_FALSE;
 572         (void) pthread_mutex_unlock(&soft_giant_mutex);
 573 }