mirror of
https://github.com/openssl/openssl.git
synced 2024-12-14 20:43:46 +08:00
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:
parent
1a0de4c1ee
commit
629b408c12
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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. */
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user