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); }