Print this page
1667 pkcs11 may deadlock when multi-threaded consumers 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 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.

  24  */
  25 
  26 #include <stdio.h>
  27 #include <unistd.h>
  28 #include <errno.h>
  29 #include <string.h>
  30 #include <fcntl.h>
  31 #include <locale.h>
  32 #include <stdarg.h>
  33 #include <cryptoutil.h>
  34 #include <pthread.h>
  35 

  36 
  37 static pthread_mutex_t  random_mutex = PTHREAD_MUTEX_INITIALIZER;
  38 static pthread_mutex_t  urandom_mutex = PTHREAD_MUTEX_INITIALIZER;
  39 
  40 static pthread_mutex_t  random_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
  41 static pthread_mutex_t  urandom_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
  42 
  43 #define RANDOM_DEVICE           "/dev/random"   /* random device name */
  44 #define URANDOM_DEVICE          "/dev/urandom"  /* urandom device name */
  45 
  46 static int      random_fd = -1;
  47 static int      urandom_fd = -1;
  48 
  49 static int      random_seed_fd = -1;
  50 static int      urandom_seed_fd = -1;
  51 
  52 
  53 /*
  54  * Equivalent of open(2) insulated from EINTR.
  55  * Also sets close-on-exec.


 164 
 165 static int
 166 pkcs11_open_urandom_seed(void)
 167 {
 168         return (pkcs11_open_common(&urandom_seed_fd, &urandom_seed_mutex,
 169             URANDOM_DEVICE, O_WRONLY));
 170 }
 171 
 172 /*
 173  * Close the random number generator devices if already open.
 174  */
 175 static void
 176 pkcs11_close_common(int *fd, pthread_mutex_t *mtx)
 177 {
 178         (void) pthread_mutex_lock(mtx);
 179         (void) close(*fd);
 180         *fd = -1;
 181         (void) pthread_mutex_unlock(mtx);
 182 }
 183 
 184 void
 185 pkcs11_close_random(void)
 186 {
 187         pkcs11_close_common(&random_fd, &random_mutex);
 188 }
 189 
 190 void
 191 pkcs11_close_urandom(void)
 192 {
 193         pkcs11_close_common(&urandom_fd, &urandom_mutex);
 194 }
 195 
 196 static void
 197 pkcs11_close_random_seed(void)
 198 {
 199         pkcs11_close_common(&random_seed_fd, &random_seed_mutex);
 200 }
 201 
 202 void
 203 pkcs11_close_urandom_seed(void)
 204 {
 205         pkcs11_close_common(&urandom_seed_fd, &urandom_seed_mutex);
 206 }
 207 
 208 /*
 209  * Read from the random number generator devices.
 210  */
 211 static size_t
 212 pkcs11_read_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen)
 213 {
 214         size_t  n;
 215 
 216         (void) pthread_mutex_lock(mtx);
 217         n = readn_nointr(*fd, dbuf, dlen);
 218         (void) pthread_mutex_unlock(mtx);
 219 
 220         return (n);
 221 }
 222 


 359         if (pkcs11_get_urandom(dbuf, dlen) < 0)
 360                 return (-1);
 361 
 362         /* Walk through data replacing any 0 bytes with more random data */
 363         while (i < dlen) {
 364                 if (((char *)dbuf)[i] != 0) {
 365                         i++;
 366                         continue;
 367                 }
 368 
 369                 if (bytesleft == 0) {
 370                         bytesleft = sizeof (extrarand);
 371                         if (pkcs11_get_urandom(extrarand, bytesleft) < 0)
 372                                 return (-1);
 373                 }
 374                 bytesleft--;
 375 
 376                 ((char *)dbuf)[i] = extrarand[bytesleft];
 377         }
 378         return (0);










































 379 }


   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 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  25  */
  26 
  27 #include <stdio.h>
  28 #include <unistd.h>
  29 #include <errno.h>
  30 #include <string.h>
  31 #include <fcntl.h>
  32 #include <locale.h>
  33 #include <stdarg.h>
  34 #include <cryptoutil.h>
  35 #include <pthread.h>
  36 
  37 #pragma init(pkcs11_random_init)
  38 
  39 static pthread_mutex_t  random_mutex = PTHREAD_MUTEX_INITIALIZER;
  40 static pthread_mutex_t  urandom_mutex = PTHREAD_MUTEX_INITIALIZER;
  41 
  42 static pthread_mutex_t  random_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
  43 static pthread_mutex_t  urandom_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
  44 
  45 #define RANDOM_DEVICE           "/dev/random"   /* random device name */
  46 #define URANDOM_DEVICE          "/dev/urandom"  /* urandom device name */
  47 
  48 static int      random_fd = -1;
  49 static int      urandom_fd = -1;
  50 
  51 static int      random_seed_fd = -1;
  52 static int      urandom_seed_fd = -1;
  53 
  54 
  55 /*
  56  * Equivalent of open(2) insulated from EINTR.
  57  * Also sets close-on-exec.


 166 
 167 static int
 168 pkcs11_open_urandom_seed(void)
 169 {
 170         return (pkcs11_open_common(&urandom_seed_fd, &urandom_seed_mutex,
 171             URANDOM_DEVICE, O_WRONLY));
 172 }
 173 
 174 /*
 175  * Close the random number generator devices if already open.
 176  */
 177 static void
 178 pkcs11_close_common(int *fd, pthread_mutex_t *mtx)
 179 {
 180         (void) pthread_mutex_lock(mtx);
 181         (void) close(*fd);
 182         *fd = -1;
 183         (void) pthread_mutex_unlock(mtx);
 184 }
 185 
 186 static void
 187 pkcs11_close_random(void)
 188 {
 189         pkcs11_close_common(&random_fd, &random_mutex);
 190 }
 191 
 192 static void
 193 pkcs11_close_urandom(void)
 194 {
 195         pkcs11_close_common(&urandom_fd, &urandom_mutex);
 196 }
 197 
 198 static void
 199 pkcs11_close_random_seed(void)
 200 {
 201         pkcs11_close_common(&random_seed_fd, &random_seed_mutex);
 202 }
 203 
 204 static void
 205 pkcs11_close_urandom_seed(void)
 206 {
 207         pkcs11_close_common(&urandom_seed_fd, &urandom_seed_mutex);
 208 }
 209 
 210 /*
 211  * Read from the random number generator devices.
 212  */
 213 static size_t
 214 pkcs11_read_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen)
 215 {
 216         size_t  n;
 217 
 218         (void) pthread_mutex_lock(mtx);
 219         n = readn_nointr(*fd, dbuf, dlen);
 220         (void) pthread_mutex_unlock(mtx);
 221 
 222         return (n);
 223 }
 224 


 361         if (pkcs11_get_urandom(dbuf, dlen) < 0)
 362                 return (-1);
 363 
 364         /* Walk through data replacing any 0 bytes with more random data */
 365         while (i < dlen) {
 366                 if (((char *)dbuf)[i] != 0) {
 367                         i++;
 368                         continue;
 369                 }
 370 
 371                 if (bytesleft == 0) {
 372                         bytesleft = sizeof (extrarand);
 373                         if (pkcs11_get_urandom(extrarand, bytesleft) < 0)
 374                                 return (-1);
 375                 }
 376                 bytesleft--;
 377 
 378                 ((char *)dbuf)[i] = extrarand[bytesleft];
 379         }
 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);
 423 }