QUIC: Fix bugs where threading is disabled

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20856)
This commit is contained in:
Hugo Landau 2023-05-17 13:15:01 +01:00
parent 1a0de4c1ee
commit 629b408c12
13 changed files with 113 additions and 3 deletions

View File

@ -148,6 +148,13 @@ int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
return 1;
}
int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock)
{
*ret = *val;
return 1;
}
int openssl_init_fork_handlers(void)
{
return 0;

View File

@ -270,6 +270,30 @@ int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
return 1;
}
int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock)
{
# if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) && !defined(BROKEN_CLANG_ATOMICS)
if (__atomic_is_lock_free(sizeof(*val), val)) {
__atomic_load(val, ret, __ATOMIC_ACQUIRE);
return 1;
}
# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
/* This will work for all future Solaris versions. */
if (ret != NULL) {
*ret = (int *)atomic_or_uint_nv((unsigned int *)val, 0);
return 1;
}
# endif
if (lock == NULL || !CRYPTO_THREAD_read_lock(lock))
return 0;
*ret = *val;
if (!CRYPTO_THREAD_unlock(lock))
return 0;
return 1;
}
# ifndef FIPS_MODULE
int openssl_init_fork_handlers(void)
{

View File

@ -251,6 +251,22 @@ int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
#endif
}
int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock)
{
#if (defined(NO_INTERLOCKEDOR64))
if (lock == NULL || !CRYPTO_THREAD_read_lock(lock))
return 0;
*ret = *val;
if (!CRYPTO_THREAD_unlock(lock))
return 0;
return 1;
#else
*ret = (int)InterlockedOr((LONG volatile *)val, 0);
return 1;
#endif
}
int openssl_init_fork_handlers(void)
{
return 0;

View File

@ -6,6 +6,7 @@ CRYPTO_THREAD_run_once,
CRYPTO_THREAD_lock_new, CRYPTO_THREAD_read_lock, CRYPTO_THREAD_write_lock,
CRYPTO_THREAD_unlock, CRYPTO_THREAD_lock_free,
CRYPTO_atomic_add, CRYPTO_atomic_or, CRYPTO_atomic_load,
CRYPTO_atomic_load_int,
OSSL_set_max_threads, OSSL_get_max_threads,
OSSL_get_thread_support_flags - OpenSSL thread support
@ -26,6 +27,7 @@ OSSL_get_thread_support_flags - OpenSSL thread support
int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
CRYPTO_RWLOCK *lock);
int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock);
int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock);
int OSSL_set_max_threads(OSSL_LIB_CTX *ctx, uint64_t max_threads);
uint64_t OSSL_get_max_threads(OSSL_LIB_CTX *ctx);
@ -106,6 +108,11 @@ NULL, then the function will fail.
=item *
CRYPTO_atomic_load_int() works identically to CRYPTO_atomic_load() but operates
on an I<int> value instead of a I<uint64_t> value.
=item *
OSSL_set_max_threads() sets the maximum number of threads to be used by the
thread pool. If the argument is 0, thread pooling is disabled. OpenSSL will
not create any threads and existing threads in the thread pool will be torn

View File

@ -159,4 +159,5 @@ char *ossl_ipaddr_to_asc(unsigned char *p, int len);
char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep);
unsigned char *ossl_hexstr2buf_sep(const char *str, long *buflen,
const char sep);
#endif

View File

@ -197,7 +197,7 @@ typedef int CRYPTO_REF_COUNT;
# define CRYPTO_UP_REF(val, ret, lock) CRYPTO_atomic_add(val, 1, ret, lock)
# define CRYPTO_DOWN_REF(val, ret, lock) CRYPTO_atomic_add(val, -1, ret, lock)
# define CRYPTO_GET_REF(val, ret, lock) CRYPTO_atomic_load(val, ret, lock)
# define CRYPTO_GET_REF(val, ret, lock) CRYPTO_atomic_load_int(val, ret, lock)
# endif

View File

@ -89,6 +89,7 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock);
int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
CRYPTO_RWLOCK *lock);
int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock);
int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock);
/* No longer needed, so this is a no-op */
#define OPENSSL_malloc_init() while(0) continue

View File

@ -258,14 +258,18 @@ static int ossl_unused expect_quic_conn_only(const SSL *s, QCTX *ctx)
*/
static void quic_lock(QUIC_CONNECTION *qc)
{
#if defined(OPENSSL_THREADS)
ossl_crypto_mutex_lock(qc->mutex);
#endif
}
/* Precondition: Channel mutex is held (unchecked) */
QUIC_NEEDS_LOCK
static void quic_unlock(QUIC_CONNECTION *qc)
{
#if defined(OPENSSL_THREADS)
ossl_crypto_mutex_unlock(qc->mutex);
#endif
}
@ -304,11 +308,15 @@ SSL *ossl_quic_new(SSL_CTX *ctx)
if (qc->tls == NULL || (sc = SSL_CONNECTION_FROM_SSL(qc->tls)) == NULL)
goto err;
#if defined(OPENSSL_THREADS)
if ((qc->mutex = ossl_crypto_mutex_new()) == NULL)
goto err;
#endif
#if !defined(OPENSSL_NO_QUIC_THREAD_ASSIST)
qc->is_thread_assisted
= (ssl_base->method == OSSL_QUIC_client_thread_method());
#endif
qc->as_server = 0; /* TODO(QUIC): server support */
qc->as_server_state = qc->as_server;
@ -338,6 +346,9 @@ SSL *ossl_quic_new(SSL_CTX *ctx)
err:
if (qc != NULL) {
#if defined(OPENSSL_THREADS)
ossl_crypto_mutex_free(qc->mutex);
#endif
ossl_quic_channel_free(qc->ch);
SSL_free(qc->tls);
}
@ -418,10 +429,12 @@ void ossl_quic_free(SSL *s)
/* Ensure we have no remaining XSOs. */
assert(ctx.qc->num_xso == 0);
#if !defined(OPENSSL_NO_QUIC_THREAD_ASSIST)
if (ctx.qc->is_thread_assisted && ctx.qc->started) {
ossl_quic_thread_assist_wait_stopped(&ctx.qc->thread_assist);
ossl_quic_thread_assist_cleanup(&ctx.qc->thread_assist);
}
#endif
ossl_quic_channel_free(ctx.qc->ch);
@ -431,7 +444,9 @@ void ossl_quic_free(SSL *s)
/* Note: SSL_free calls OPENSSL_free(qc) for us */
SSL_free(ctx.qc->tls);
#if defined(OPENSSL_THREADS)
ossl_crypto_mutex_free(&ctx.qc->mutex); /* freed while still locked */
#endif
}
/* SSL method init */
@ -491,8 +506,10 @@ void ossl_quic_conn_force_assist_thread_wake(SSL *s)
if (!expect_quic(s, &ctx))
return;
#if !defined(OPENSSL_NO_QUIC_THREAD_ASSIST)
if (ctx.qc->is_thread_assisted && ctx.qc->started)
ossl_quic_thread_assist_notify_deadline_changed(&ctx.qc->thread_assist);
#endif
}
QUIC_NEEDS_LOCK
@ -1121,9 +1138,11 @@ static int ensure_channel_started(QUIC_CONNECTION *qc)
|| !ossl_quic_channel_start(qc->ch))
goto err;
#if !defined(OPENSSL_NO_QUIC_THREAD_ASSIST)
if (qc->is_thread_assisted)
if (!ossl_quic_thread_assist_init_start(&qc->thread_assist, qc->ch))
goto err;
#endif
}
qc->started = 1;

View File

@ -175,8 +175,10 @@ static int poll_two_fds(int rfd, int rfd_want_read,
/* Do not block forever; should not happen. */
return 0;
# if defined(OPENSSL_THREADS)
if (mutex != NULL)
ossl_crypto_mutex_unlock(mutex);
# endif
do {
/*
@ -200,8 +202,10 @@ static int poll_two_fds(int rfd, int rfd_want_read,
pres = select(maxfd + 1, &rfd_set, &wfd_set, &efd_set, ptv);
} while (pres == -1 && get_last_socket_error_is_eintr());
# if defined(OPENSSL_THREADS)
if (mutex != NULL)
ossl_crypto_mutex_lock(mutex);
# endif
return pres < 0 ? 0 : 1;
#else
@ -232,8 +236,10 @@ static int poll_two_fds(int rfd, int rfd_want_read,
/* Do not block forever; should not happen. */
return 0;
# if defined(OPENSSL_THREADS)
if (mutex != NULL)
ossl_crypto_mutex_unlock(mutex);
# endif
do {
if (ossl_time_is_infinite(deadline)) {
@ -247,8 +253,10 @@ static int poll_two_fds(int rfd, int rfd_want_read,
pres = poll(pfds, npfd, timeout_ms);
} while (pres == -1 && get_last_socket_error_is_eintr());
# if defined(OPENSSL_THREADS)
if (mutex != NULL)
ossl_crypto_mutex_lock(mutex);
# endif
return pres < 0 ? 0 : 1;
#endif

View File

@ -67,8 +67,10 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,
srv->args = *args;
#if defined(OPENSSL_THREADS)
if ((srv->mutex = ossl_crypto_mutex_new()) == NULL)
goto err;
#endif
srv->ctx = SSL_CTX_new_ex(srv->args.libctx, srv->args.propq, TLS_method());
if (srv->ctx == NULL)
@ -106,7 +108,9 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,
err:
if (srv != NULL) {
ossl_quic_channel_free(srv->ch);
#if defined(OPENSSL_THREADS)
ossl_crypto_mutex_free(&srv->mutex);
#endif
}
OPENSSL_free(srv);
@ -123,7 +127,9 @@ void ossl_quic_tserver_free(QUIC_TSERVER *srv)
BIO_free(srv->args.net_wbio);
SSL_free(srv->tls);
SSL_CTX_free(srv->ctx);
#if defined(OPENSSL_THREADS)
ossl_crypto_mutex_free(&srv->mutex);
#endif
OPENSSL_free(srv);
}

View File

@ -581,7 +581,10 @@ static int run_script_worker(struct helper *h, const struct script_op *script,
size_t offset = 0;
size_t op_idx = 0;
const struct script_op *op = NULL;
int no_advance = 0, first = 1, end_wait_warning = 0;
int no_advance = 0, first = 1;
#if defined(OPENSSL_THREADS)
int end_wait_warning = 0;
#endif
OSSL_TIME op_start_time = ossl_time_zero(), op_deadline = ossl_time_zero();
struct helper_local hl;
#define REPEAT_SLOTS 8
@ -657,6 +660,7 @@ static int run_script_worker(struct helper *h, const struct script_op *script,
if (!TEST_size_t_eq(repeat_stack_len, 0))
goto out;
#if defined(OPENSSL_THREADS)
if (thread_idx < 0) {
int done;
size_t i;
@ -679,6 +683,7 @@ static int run_script_worker(struct helper *h, const struct script_op *script,
}
}
}
#endif
TEST_info("script finished on thread %d", thread_idx);
testresult = 1;
@ -1190,7 +1195,12 @@ static int run_script_worker(struct helper *h, const struct script_op *script,
case OPK_NEW_THREAD:
{
#if !defined(OPENSSL_THREADS)
TEST_error("threading not supported");
/*
* If this test script requires threading and we do not have
* support for it, skip the rest of it.
*/
TEST_skip("threading not supported, skipping");
testresult = 1;
goto out;
#else
size_t i;
@ -1261,8 +1271,10 @@ static int run_script(const struct script_op *script, int free_order)
if (!TEST_true(run_script_worker(&h, script, -1)))
goto out;
#if defined(OPENSSL_THREADS)
if (!TEST_true(join_threads(h.threads, h.num_threads)))
goto out;
#endif
testresult = 1;
out:

View File

@ -12,6 +12,7 @@
#include "internal/common.h"
#include "internal/sockets.h"
#include "internal/quic_tserver.h"
#include "internal/quic_thread_assist.h"
#include "internal/quic_ssl.h"
#include "internal/time.h"
#include "testutil.h"
@ -75,6 +76,13 @@ static int do_test(int use_thread_assist, int use_fake_time, int use_inject)
OSSL_TIME (*now_cb)(void *arg) = use_fake_time ? fake_now : real_now;
size_t limit_ms = 1000;
#if defined(OPENSSL_NO_QUIC_THREAD_ASSIST)
if (use_thread_assist) {
TEST_skip("thread assisted mode not enabled");
return 1;
}
#endif
ina.s_addr = htonl(0x7f000001UL);
/* Setup test server. */

View File

@ -5517,3 +5517,4 @@ EC_GROUP_to_params ? 3_2_0 EXIST::FUNCTION:EC
X509_STORE_CTX_init_rpk ? 3_2_0 EXIST::FUNCTION:
X509_STORE_CTX_get0_rpk ? 3_2_0 EXIST::FUNCTION:
X509_STORE_CTX_set0_rpk ? 3_2_0 EXIST::FUNCTION:
CRYPTO_atomic_load_int ? 3_2_0 EXIST::FUNCTION: