It is expected that SSL_CTX objects are shared across threads,
and as such we are responsible for ensuring coherent data accesses.
Aligned integer accesses ought to be atomic already on all supported
architectures, but we can be formally correct.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/4549)
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
{
long l;
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
{
long l;
/* For some cases with ctx == NULL perform syntax checks */
if (ctx == NULL) {
switch (cmd) {
/* For some cases with ctx == NULL perform syntax checks */
if (ctx == NULL) {
switch (cmd) {
case SSL_CTRL_SESS_NUMBER:
return lh_SSL_SESSION_num_items(ctx->sessions);
case SSL_CTRL_SESS_CONNECT:
case SSL_CTRL_SESS_NUMBER:
return lh_SSL_SESSION_num_items(ctx->sessions);
case SSL_CTRL_SESS_CONNECT:
- return ctx->stats.sess_connect;
+ return CRYPTO_atomic_read(&ctx->stats.sess_connect, &i, ctx->lock)
+ ? i : 0;
case SSL_CTRL_SESS_CONNECT_GOOD:
case SSL_CTRL_SESS_CONNECT_GOOD:
- return ctx->stats.sess_connect_good;
+ return CRYPTO_atomic_read(&ctx->stats.sess_connect_good, &i, ctx->lock)
+ ? i : 0;
case SSL_CTRL_SESS_CONNECT_RENEGOTIATE:
case SSL_CTRL_SESS_CONNECT_RENEGOTIATE:
- return ctx->stats.sess_connect_renegotiate;
+ return CRYPTO_atomic_read(&ctx->stats.sess_connect_renegotiate, &i,
+ ctx->lock)
+ ? i : 0;
case SSL_CTRL_SESS_ACCEPT:
case SSL_CTRL_SESS_ACCEPT:
- return ctx->stats.sess_accept;
+ return CRYPTO_atomic_read(&ctx->stats.sess_accept, &i, ctx->lock)
+ ? i : 0;
case SSL_CTRL_SESS_ACCEPT_GOOD:
case SSL_CTRL_SESS_ACCEPT_GOOD:
- return ctx->stats.sess_accept_good;
+ return CRYPTO_atomic_read(&ctx->stats.sess_accept_good, &i, ctx->lock)
+ ? i : 0;
case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE:
case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE:
- return ctx->stats.sess_accept_renegotiate;
+ return CRYPTO_atomic_read(&ctx->stats.sess_accept_renegotiate, &i,
+ ctx->lock)
+ ? i : 0;
- return ctx->stats.sess_hit;
+ return CRYPTO_atomic_read(&ctx->stats.sess_hit, &i, ctx->lock)
+ ? i : 0;
case SSL_CTRL_SESS_CB_HIT:
case SSL_CTRL_SESS_CB_HIT:
- return ctx->stats.sess_cb_hit;
+ return CRYPTO_atomic_read(&ctx->stats.sess_cb_hit, &i, ctx->lock)
+ ? i : 0;
case SSL_CTRL_SESS_MISSES:
case SSL_CTRL_SESS_MISSES:
- return ctx->stats.sess_miss;
+ return CRYPTO_atomic_read(&ctx->stats.sess_miss, &i, ctx->lock)
+ ? i : 0;
case SSL_CTRL_SESS_TIMEOUTS:
case SSL_CTRL_SESS_TIMEOUTS:
- return ctx->stats.sess_timeout;
+ return CRYPTO_atomic_read(&ctx->stats.sess_timeout, &i, ctx->lock)
+ ? i : 0;
case SSL_CTRL_SESS_CACHE_FULL:
case SSL_CTRL_SESS_CACHE_FULL:
- return ctx->stats.sess_cache_full;
+ return CRYPTO_atomic_read(&ctx->stats.sess_cache_full, &i, ctx->lock)
+ ? i : 0;
case SSL_CTRL_MODE:
return (ctx->mode |= larg);
case SSL_CTRL_CLEAR_MODE:
case SSL_CTRL_MODE:
return (ctx->mode |= larg);
case SSL_CTRL_CLEAR_MODE:
/* auto flush every 255 connections */
if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) {
/* auto flush every 255 connections */
if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) {
- if ((((mode & SSL_SESS_CACHE_CLIENT)
- ? s->session_ctx->stats.sess_connect_good
- : s->session_ctx->stats.sess_accept_good) & 0xff) == 0xff) {
+ int *stat, val;
+ if (mode & SSL_SESS_CACHE_CLIENT)
+ stat = &s->session_ctx->stats.sess_connect_good;
+ else
+ stat = &s->session_ctx->stats.sess_accept_good;
+ if (CRYPTO_atomic_read(stat, &val, s->session_ctx->lock)
+ && (val & 0xff) == 0xff)
SSL_CTX_flush_sessions(s->session_ctx, (unsigned long)time(NULL));
SSL_CTX_flush_sessions(s->session_ctx, (unsigned long)time(NULL));
/* This is used only by servers. */
SSL_SESSION *ret = NULL;
/* This is used only by servers. */
SSL_SESSION *ret = NULL;
+ int fatal = 0, discard;
int try_session_cache = 0;
TICKET_RETURN r;
int try_session_cache = 0;
TICKET_RETURN r;
}
CRYPTO_THREAD_unlock(s->session_ctx->lock);
if (ret == NULL)
}
CRYPTO_THREAD_unlock(s->session_ctx->lock);
if (ret == NULL)
- s->session_ctx->stats.sess_miss++;
+ CRYPTO_atomic_add(&s->session_ctx->stats.sess_miss, 1, &discard,
+ s->session_ctx->lock);
}
if (try_session_cache &&
}
if (try_session_cache &&
©);
if (ret != NULL) {
©);
if (ret != NULL) {
- s->session_ctx->stats.sess_cb_hit++;
+ CRYPTO_atomic_add(&s->session_ctx->stats.sess_cb_hit, 1, &discard,
+ s->session_ctx->lock);
/*
* Increment reference count now if the session callback asks us
/*
* Increment reference count now if the session callback asks us
}
if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */
}
if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */
- s->session_ctx->stats.sess_timeout++;
+ CRYPTO_atomic_add(&s->session_ctx->stats.sess_timeout, 1, &discard,
+ s->session_ctx->lock);
if (try_session_cache) {
/* session was from the cache, so remove it */
SSL_CTX_remove_session(s->session_ctx, ret);
if (try_session_cache) {
/* session was from the cache, so remove it */
SSL_CTX_remove_session(s->session_ctx, ret);
- s->session_ctx->stats.sess_hit++;
+ CRYPTO_atomic_add(&s->session_ctx->stats.sess_hit, 1, &discard,
+ s->session_ctx->lock);
s->verify_result = s->session->verify_result;
return 1;
s->verify_result = s->session->verify_result;
return 1;
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
{
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
{
if (!remove_session_lock(ctx, ctx->session_cache_tail, 0))
break;
else
if (!remove_session_lock(ctx, ctx->session_cache_tail, 0))
break;
else
- ctx->stats.sess_cache_full++;
+ CRYPTO_atomic_add(&ctx->stats.sess_cache_full, 1, &discard,
+ ctx->lock);
unsigned int compression;
unsigned int sversion;
unsigned int context;
unsigned int compression;
unsigned int sversion;
unsigned int context;
RAW_EXTENSION *extensions = NULL;
#ifndef OPENSSL_NO_COMP
SSL_COMP *comp;
RAW_EXTENSION *extensions = NULL;
#ifndef OPENSSL_NO_COMP
SSL_COMP *comp;
|| (SSL_IS_TLS13(s)
&& s->session->ext.tick_identity
!= TLSEXT_PSK_BAD_IDENTITY)) {
|| (SSL_IS_TLS13(s)
&& s->session->ext.tick_identity
!= TLSEXT_PSK_BAD_IDENTITY)) {
- s->ctx->stats.sess_miss++;
+ CRYPTO_atomic_add(&s->ctx->stats.sess_miss, 1, &discard,
+ s->ctx->lock);
if (!ssl_get_new_session(s, 0)) {
goto f_err;
}
if (!ssl_get_new_session(s, 0)) {
goto f_err;
}
return 0;
}
if (SSL_IS_FIRST_HANDSHAKE(s)) {
return 0;
}
if (SSL_IS_FIRST_HANDSHAKE(s)) {
- s->ctx->stats.sess_accept++;
+ CRYPTO_atomic_add(&s->ctx->stats.sess_accept, 1, &i, s->ctx->lock);
} else if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
/* Renegotiation is disabled */
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
} else if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
/* Renegotiation is disabled */
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
return 0;
} else {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
return 0;
} else {
- s->ctx->stats.sess_accept_renegotiate++;
+ CRYPTO_atomic_add(&s->ctx->stats.sess_accept_renegotiate, 1, &i,
+ s->ctx->lock);
s->s3->tmp.cert_request = 0;
}
} else {
s->s3->tmp.cert_request = 0;
}
} else {
if (SSL_IS_FIRST_HANDSHAKE(s))
if (SSL_IS_FIRST_HANDSHAKE(s))
- s->ctx->stats.sess_connect++;
+ CRYPTO_atomic_add(&s->ctx->stats.sess_connect, 1, &discard,
+ s->ctx->lock);
- s->ctx->stats.sess_connect_renegotiate++;
+ CRYPTO_atomic_add(&s->ctx->stats.sess_connect_renegotiate, 1,
+ &discard, s->ctx->lock);
/* mark client_random uninitialized */
memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
/* mark client_random uninitialized */
memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
*/
WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
{
*/
WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
{
void (*cb) (const SSL *ssl, int type, int val) = NULL;
#ifndef OPENSSL_NO_SCTP
void (*cb) (const SSL *ssl, int type, int val) = NULL;
#ifndef OPENSSL_NO_SCTP
if (s->server) {
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
if (s->server) {
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
- s->ctx->stats.sess_accept_good++;
+ CRYPTO_atomic_add(&s->ctx->stats.sess_accept_good, 1, &discard,
+ s->ctx->lock);
s->handshake_func = ossl_statem_accept;
} else {
/*
s->handshake_func = ossl_statem_accept;
} else {
/*
if (!SSL_IS_TLS13(s))
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
if (s->hit)
if (!SSL_IS_TLS13(s))
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
if (s->hit)
- s->ctx->stats.sess_hit++;
+ CRYPTO_atomic_add(&s->ctx->stats.sess_hit, 1, &discard,
+ s->ctx->lock);
s->handshake_func = ossl_statem_connect;
s->handshake_func = ossl_statem_connect;
- s->ctx->stats.sess_connect_good++;
+ CRYPTO_atomic_add(&s->ctx->stats.sess_connect_good, 1, &discard,
+ s->ctx->lock);
}
if (s->info_callback != NULL)
}
if (s->info_callback != NULL)