Print this page
1667 pkcs11 may deadlock when multi-threaded consumers fork

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libcryptoutil/common/random.c
          +++ new/usr/src/lib/libcryptoutil/common/random.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
       24 + * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  24   25   */
  25   26  
  26   27  #include <stdio.h>
  27   28  #include <unistd.h>
  28   29  #include <errno.h>
  29   30  #include <string.h>
  30   31  #include <fcntl.h>
  31   32  #include <locale.h>
  32   33  #include <stdarg.h>
  33   34  #include <cryptoutil.h>
  34   35  #include <pthread.h>
  35   36  
       37 +#pragma init(pkcs11_random_init)
  36   38  
  37   39  static pthread_mutex_t  random_mutex = PTHREAD_MUTEX_INITIALIZER;
  38   40  static pthread_mutex_t  urandom_mutex = PTHREAD_MUTEX_INITIALIZER;
  39   41  
  40   42  static pthread_mutex_t  random_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
  41   43  static pthread_mutex_t  urandom_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
  42   44  
  43   45  #define RANDOM_DEVICE           "/dev/random"   /* random device name */
  44   46  #define URANDOM_DEVICE          "/dev/urandom"  /* urandom device name */
  45   47  
↓ open down ↓ 128 lines elided ↑ open up ↑
 174  176   */
 175  177  static void
 176  178  pkcs11_close_common(int *fd, pthread_mutex_t *mtx)
 177  179  {
 178  180          (void) pthread_mutex_lock(mtx);
 179  181          (void) close(*fd);
 180  182          *fd = -1;
 181  183          (void) pthread_mutex_unlock(mtx);
 182  184  }
 183  185  
 184      -void
      186 +static void
 185  187  pkcs11_close_random(void)
 186  188  {
 187  189          pkcs11_close_common(&random_fd, &random_mutex);
 188  190  }
 189  191  
 190      -void
      192 +static void
 191  193  pkcs11_close_urandom(void)
 192  194  {
 193  195          pkcs11_close_common(&urandom_fd, &urandom_mutex);
 194  196  }
 195  197  
 196  198  static void
 197  199  pkcs11_close_random_seed(void)
 198  200  {
 199  201          pkcs11_close_common(&random_seed_fd, &random_seed_mutex);
 200  202  }
 201  203  
 202      -void
      204 +static void
 203  205  pkcs11_close_urandom_seed(void)
 204  206  {
 205  207          pkcs11_close_common(&urandom_seed_fd, &urandom_seed_mutex);
 206  208  }
 207  209  
 208  210  /*
 209  211   * Read from the random number generator devices.
 210  212   */
 211  213  static size_t
 212  214  pkcs11_read_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen)
↓ open down ↓ 156 lines elided ↑ open up ↑
 369  371                  if (bytesleft == 0) {
 370  372                          bytesleft = sizeof (extrarand);
 371  373                          if (pkcs11_get_urandom(extrarand, bytesleft) < 0)
 372  374                                  return (-1);
 373  375                  }
 374  376                  bytesleft--;
 375  377  
 376  378                  ((char *)dbuf)[i] = extrarand[bytesleft];
 377  379          }
 378  380          return (0);
      381 +}
      382 +
      383 +static void
      384 +pkcs11_random_prepare(void)
      385 +{
      386 +        /*
      387 +         * NOTE - None of these are acquired more than one at a time.
      388 +         * I can therefore acquire all four without fear of deadlock.
      389 +         */
      390 +        (void) pthread_mutex_lock(&random_mutex);
      391 +        (void) pthread_mutex_lock(&urandom_mutex);
      392 +        (void) pthread_mutex_lock(&random_seed_mutex);
      393 +        (void) pthread_mutex_lock(&urandom_seed_mutex);
      394 +}
      395 +
      396 +static void
      397 +pkcs11_random_parent_post(void)
      398 +{
      399 +        /* Drop the mutexes and get back to work! */
      400 +        (void) pthread_mutex_unlock(&urandom_seed_mutex);
      401 +        (void) pthread_mutex_unlock(&random_seed_mutex);
      402 +        (void) pthread_mutex_unlock(&urandom_mutex);
      403 +        (void) pthread_mutex_unlock(&random_mutex);
      404 +}
      405 +
      406 +static void
      407 +pkcs11_random_child_post(void)
      408 +{
      409 +        pkcs11_random_parent_post();
      410 +
      411 +        /* Also, close the FDs, just in case. */
      412 +        pkcs11_close_random();
      413 +        pkcs11_close_urandom();
      414 +        pkcs11_close_random_seed();
      415 +        pkcs11_close_urandom_seed();
      416 +}
      417 +
      418 +static void
      419 +pkcs11_random_init(void)
      420 +{
      421 +        (void) pthread_atfork(pkcs11_random_prepare, pkcs11_random_parent_post,
      422 +            pkcs11_random_child_post);
 379  423  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX