return ctx->sessions;
}
+static int ssl_tsan_load(SSL_CTX *ctx, TSAN_QUALIFIER int *stat)
+{
+ int res = 0;
+
+ if (ssl_tsan_lock(ctx)) {
+ res = tsan_load(stat);
+ ssl_tsan_unlock(ctx);
+ }
+ return res;
+}
+
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
{
long l;
case SSL_CTRL_SESS_NUMBER:
return lh_SSL_SESSION_num_items(ctx->sessions);
case SSL_CTRL_SESS_CONNECT:
- return tsan_load(&ctx->stats.sess_connect);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_connect);
case SSL_CTRL_SESS_CONNECT_GOOD:
- return tsan_load(&ctx->stats.sess_connect_good);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_connect_good);
case SSL_CTRL_SESS_CONNECT_RENEGOTIATE:
- return tsan_load(&ctx->stats.sess_connect_renegotiate);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_connect_renegotiate);
case SSL_CTRL_SESS_ACCEPT:
- return tsan_load(&ctx->stats.sess_accept);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_accept);
case SSL_CTRL_SESS_ACCEPT_GOOD:
- return tsan_load(&ctx->stats.sess_accept_good);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_accept_good);
case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE:
- return tsan_load(&ctx->stats.sess_accept_renegotiate);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_accept_renegotiate);
case SSL_CTRL_SESS_HIT:
- return tsan_load(&ctx->stats.sess_hit);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_hit);
case SSL_CTRL_SESS_CB_HIT:
- return tsan_load(&ctx->stats.sess_cb_hit);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_cb_hit);
case SSL_CTRL_SESS_MISSES:
- return tsan_load(&ctx->stats.sess_miss);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_miss);
case SSL_CTRL_SESS_TIMEOUTS:
- return tsan_load(&ctx->stats.sess_timeout);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_timeout);
case SSL_CTRL_SESS_CACHE_FULL:
- return tsan_load(&ctx->stats.sess_cache_full);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_cache_full);
case SSL_CTRL_MODE:
return (ctx->mode |= larg);
case SSL_CTRL_CLEAR_MODE:
return NULL;
}
+#ifdef TSAN_REQUIRES_LOCKING
+ ret->tsan_lock = CRYPTO_THREAD_lock_new();
+ if (ret->tsan_lock == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+#endif
+
ret->libctx = libctx;
if (propq != NULL) {
ret->propq = OPENSSL_strdup(propq);
OPENSSL_free(a->sigalg_lookup_cache);
CRYPTO_THREAD_lock_free(a->lock);
+#ifdef TSAN_REQUIRES_LOCKING
+ CRYPTO_THREAD_lock_free(a->tsan_lock);
+#endif
OPENSSL_free(a->propq);
/* auto flush every 255 connections */
if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) {
TSAN_QUALIFIER int *stat;
+
if (mode & SSL_SESS_CACHE_CLIENT)
stat = &s->session_ctx->stats.sess_connect_good;
else
stat = &s->session_ctx->stats.sess_accept_good;
- if ((tsan_load(stat) & 0xff) == 0xff)
+ if ((ssl_tsan_load(s->session_ctx, stat) & 0xff) == 0xff)
SSL_CTX_flush_sessions(s->session_ctx, (unsigned long)time(NULL));
}
}
* other processes - spooky
* :-) */
} stats;
+#ifdef TSAN_REQUIRES_LOCKING
+ CRYPTO_RWLOCK *tsan_lock;
+#endif
CRYPTO_REF_COUNT references;
# define ssl3_setup_buffers SSL_test_functions()->p_ssl3_setup_buffers
# endif
+
+/* Some helper routines to support TSAN operations safely */
+static ossl_unused ossl_inline int ssl_tsan_lock(const SSL_CTX *ctx)
+{
+#ifdef TSAN_REQUIRES_LOCKING
+ if (!CRYPTO_THREAD_write_lock(ctx->tsan_lock))
+ return 0;
+#endif
+ return 1;
+}
+
+static ossl_unused ossl_inline void ssl_tsan_unlock(const SSL_CTX *ctx)
+{
+#ifdef TSAN_REQUIRES_LOCKING
+ CRYPTO_THREAD_unlock(ctx->tsan_lock);
+#endif
+}
+
+static ossl_unused ossl_inline void ssl_tsan_counter(const SSL_CTX *ctx,
+ TSAN_QUALIFIER int *stat)
+{
+ if (ssl_tsan_lock(ctx)) {
+ tsan_counter(stat);
+ ssl_tsan_unlock(ctx);
+ }
+}
+
#endif
}
CRYPTO_THREAD_unlock(s->session_ctx->lock);
if (ret == NULL)
- tsan_counter(&s->session_ctx->stats.sess_miss);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_miss);
}
if (ret == NULL && s->session_ctx->get_session_cb != NULL) {
ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, ©);
if (ret != NULL) {
- tsan_counter(&s->session_ctx->stats.sess_cb_hit);
+ ssl_tsan_counter(s->session_ctx,
+ &s->session_ctx->stats.sess_cb_hit);
/*
* Increment reference count now if the session callback asks us
}
if (sess_timedout(time(NULL), ret)) {
- tsan_counter(&s->session_ctx->stats.sess_timeout);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_timeout);
if (try_session_cache) {
/* session was from the cache, so remove it */
SSL_CTX_remove_session(s->session_ctx, ret);
s->session = ret;
}
- tsan_counter(&s->session_ctx->stats.sess_hit);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_hit);
s->verify_result = s->session->verify_result;
return 1;
if (!remove_session_lock(ctx, ctx->session_cache_tail, 0))
break;
else
- tsan_counter(&ctx->stats.sess_cache_full);
+ ssl_tsan_counter(ctx, &ctx->stats.sess_cache_full);
}
}
}
return 1;
}
+static ossl_inline void ssl_tsan_decr(const SSL_CTX *ctx,
+ TSAN_QUALIFIER int *stat)
+{
+ if (ssl_tsan_lock(ctx)) {
+ tsan_decr(stat);
+ ssl_tsan_unlock(ctx);
+ }
+}
+
static int init_server_name(SSL *s, unsigned int context)
{
if (s->server) {
*/
if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx
&& s->hello_retry_request == SSL_HRR_NONE) {
- tsan_counter(&s->ctx->stats.sess_accept);
- tsan_decr(&s->session_ctx->stats.sess_accept);
+ ssl_tsan_counter(s->ctx, &s->ctx->stats.sess_accept);
+ ssl_tsan_decr(s->session_ctx, &s->session_ctx->stats.sess_accept);
}
/*
* overwritten if the server refuses resumption.
*/
if (s->session->session_id_length > 0) {
- tsan_counter(&s->session_ctx->stats.sess_miss);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_miss);
if (!ssl_get_new_session(s, 0)) {
/* SSLfatal() already called */
goto err;
}
if (SSL_IS_FIRST_HANDSHAKE(s)) {
/* N.B. s->session_ctx == s->ctx here */
- tsan_counter(&s->session_ctx->stats.sess_accept);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_accept);
} else {
/* N.B. s->ctx may not equal s->session_ctx */
- tsan_counter(&s->ctx->stats.sess_accept_renegotiate);
+ ssl_tsan_counter(s->ctx, &s->ctx->stats.sess_accept_renegotiate);
s->s3.tmp.cert_request = 0;
}
} else {
if (SSL_IS_FIRST_HANDSHAKE(s))
- tsan_counter(&s->session_ctx->stats.sess_connect);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_connect);
else
- tsan_counter(&s->session_ctx->stats.sess_connect_renegotiate);
+ ssl_tsan_counter(s->session_ctx,
+ &s->session_ctx->stats.sess_connect_renegotiate);
/* mark client_random uninitialized */
memset(s->s3.client_random, 0, sizeof(s->s3.client_random));
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
/* N.B. s->ctx may not equal s->session_ctx */
- tsan_counter(&s->ctx->stats.sess_accept_good);
+ ssl_tsan_counter(s->ctx, &s->ctx->stats.sess_accept_good);
s->handshake_func = ossl_statem_accept;
} else {
if (SSL_IS_TLS13(s)) {
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
}
if (s->hit)
- tsan_counter(&s->session_ctx->stats.sess_hit);
+ ssl_tsan_counter(s->session_ctx,
+ &s->session_ctx->stats.sess_hit);
s->handshake_func = ossl_statem_connect;
- tsan_counter(&s->session_ctx->stats.sess_connect_good);
+ ssl_tsan_counter(s->session_ctx,
+ &s->session_ctx->stats.sess_connect_good);
}
if (SSL_IS_DTLS(s)) {