Print this page
1667 pkcs11 may deadlock when multi-threaded consumers fork
*** 19,28 ****
--- 19,29 ----
* CDDL HEADER END
*/
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
*** 31,40 ****
--- 32,42 ----
#include <locale.h>
#include <stdarg.h>
#include <cryptoutil.h>
#include <pthread.h>
+ #pragma init(pkcs11_random_init)
static pthread_mutex_t random_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t urandom_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t random_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
*** 179,195 ****
(void) close(*fd);
*fd = -1;
(void) pthread_mutex_unlock(mtx);
}
! void
pkcs11_close_random(void)
{
pkcs11_close_common(&random_fd, &random_mutex);
}
! void
pkcs11_close_urandom(void)
{
pkcs11_close_common(&urandom_fd, &urandom_mutex);
}
--- 181,197 ----
(void) close(*fd);
*fd = -1;
(void) pthread_mutex_unlock(mtx);
}
! static void
pkcs11_close_random(void)
{
pkcs11_close_common(&random_fd, &random_mutex);
}
! static void
pkcs11_close_urandom(void)
{
pkcs11_close_common(&urandom_fd, &urandom_mutex);
}
*** 197,207 ****
pkcs11_close_random_seed(void)
{
pkcs11_close_common(&random_seed_fd, &random_seed_mutex);
}
! void
pkcs11_close_urandom_seed(void)
{
pkcs11_close_common(&urandom_seed_fd, &urandom_seed_mutex);
}
--- 199,209 ----
pkcs11_close_random_seed(void)
{
pkcs11_close_common(&random_seed_fd, &random_seed_mutex);
}
! static void
pkcs11_close_urandom_seed(void)
{
pkcs11_close_common(&urandom_seed_fd, &urandom_seed_mutex);
}
*** 374,379 ****
--- 376,423 ----
bytesleft--;
((char *)dbuf)[i] = extrarand[bytesleft];
}
return (0);
+ }
+
+ static void
+ pkcs11_random_prepare(void)
+ {
+ /*
+ * NOTE - None of these are acquired more than one at a time.
+ * I can therefore acquire all four without fear of deadlock.
+ */
+ (void) pthread_mutex_lock(&random_mutex);
+ (void) pthread_mutex_lock(&urandom_mutex);
+ (void) pthread_mutex_lock(&random_seed_mutex);
+ (void) pthread_mutex_lock(&urandom_seed_mutex);
+ }
+
+ static void
+ pkcs11_random_parent_post(void)
+ {
+ /* Drop the mutexes and get back to work! */
+ (void) pthread_mutex_unlock(&urandom_seed_mutex);
+ (void) pthread_mutex_unlock(&random_seed_mutex);
+ (void) pthread_mutex_unlock(&urandom_mutex);
+ (void) pthread_mutex_unlock(&random_mutex);
+ }
+
+ static void
+ pkcs11_random_child_post(void)
+ {
+ pkcs11_random_parent_post();
+
+ /* Also, close the FDs, just in case. */
+ pkcs11_close_random();
+ pkcs11_close_urandom();
+ pkcs11_close_random_seed();
+ pkcs11_close_urandom_seed();
+ }
+
+ static void
+ pkcs11_random_init(void)
+ {
+ (void) pthread_atfork(pkcs11_random_prepare, pkcs11_random_parent_post,
+ pkcs11_random_child_post);
}