Reserve ex_data index zero for app_data.
In the ancient times, before ex_data and OpenSSL, SSLeay supported a
single app_data slot in various types. Later app_data begat ex_data, and
app_data was replaced by compatibility macros to ex_data index zero.
Today, app_data is still in use, but ex_data never reserved index zero
for app_data. This causes some danger where, if the first ex_data
registration did not use NULL callbacks, the registration's callbacks
would collide with app_data.
Instead, add an option to the types with app_data to reserve index zero.
Also switch SSL_get_ex_data_X509_STORE_CTX_idx to always return zero
rather than allocate a new one. It used to be that you used
X509_STORE_CTX_get_app_data. I only found one consumer that we probably
don't care about, but, to be safe and since it's easy, go with the
conservative option. (Although SSL_get_ex_data_X509_STORE_CTX_idx wasn't
guaranteed to alias app_data, in practice it always did. No consumer
ever calls X509_STORE_CTX_get_ex_new_index.)
Change-Id: Ie75b279d60aefd003ffef103f99021c5d696a5e9
Reviewed-on: https://boringssl-review.googlesource.com/5313
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
index b272650..f562f17 100644
--- a/crypto/ex_data.c
+++ b/crypto/ex_data.c
@@ -161,7 +161,8 @@
goto err;
}
- *out_index = sk_CRYPTO_EX_DATA_FUNCS_num(ex_data_class->meth) - 1;
+ *out_index = sk_CRYPTO_EX_DATA_FUNCS_num(ex_data_class->meth) - 1 +
+ ex_data_class->num_reserved;
ret = 1;
err:
@@ -244,8 +245,8 @@
CRYPTO_EX_DATA_FUNCS *func_pointer =
sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
if (func_pointer->new_func) {
- func_pointer->new_func(obj, NULL, ad, i, func_pointer->argl,
- func_pointer->argp);
+ func_pointer->new_func(obj, NULL, ad, i + ex_data_class->num_reserved,
+ func_pointer->argl, func_pointer->argp);
}
}
@@ -272,12 +273,12 @@
for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
CRYPTO_EX_DATA_FUNCS *func_pointer =
sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
- void *ptr = CRYPTO_get_ex_data(from, i);
+ void *ptr = CRYPTO_get_ex_data(from, i + ex_data_class->num_reserved);
if (func_pointer->dup_func) {
- func_pointer->dup_func(to, from, &ptr, i, func_pointer->argl,
- func_pointer->argp);
+ func_pointer->dup_func(to, from, &ptr, i + ex_data_class->num_reserved,
+ func_pointer->argl, func_pointer->argp);
}
- CRYPTO_set_ex_data(to, i, ptr);
+ CRYPTO_set_ex_data(to, i + ex_data_class->num_reserved, ptr);
}
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
@@ -298,9 +299,9 @@
CRYPTO_EX_DATA_FUNCS *func_pointer =
sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
if (func_pointer->free_func) {
- void *ptr = CRYPTO_get_ex_data(ad, i);
- func_pointer->free_func(obj, ptr, ad, i, func_pointer->argl,
- func_pointer->argp);
+ void *ptr = CRYPTO_get_ex_data(ad, i + ex_data_class->num_reserved);
+ func_pointer->free_func(obj, ptr, ad, i + ex_data_class->num_reserved,
+ func_pointer->argl, func_pointer->argp);
}
}
diff --git a/crypto/internal.h b/crypto/internal.h
index 59eddd0..a502d20 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -493,9 +493,14 @@
typedef struct {
struct CRYPTO_STATIC_MUTEX lock;
STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth;
+ /* num_reserved is one if the ex_data index zero is reserved for legacy
+ * |TYPE_get_app_data| functions. */
+ uint8_t num_reserved;
} CRYPTO_EX_DATA_CLASS;
-#define CRYPTO_EX_DATA_CLASS_INIT {CRYPTO_STATIC_MUTEX_INIT, NULL}
+#define CRYPTO_EX_DATA_CLASS_INIT {CRYPTO_STATIC_MUTEX_INIT, NULL, 0}
+#define CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA \
+ {CRYPTO_STATIC_MUTEX_INIT, NULL, 1}
/* CRYPTO_get_ex_new_index allocates a new index for |ex_data_class| and writes
* it to |*out_index|. Each class of object should provide a wrapper function
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 46bc1f9..288ddd8 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -72,7 +72,8 @@
#include "../internal.h"
-static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
+static CRYPTO_EX_DATA_CLASS g_ex_data_class =
+ CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
/* CRL score values */
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 6273bcb..7b01968 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -134,18 +134,12 @@
#include "internal.h"
-static CRYPTO_once_t g_x509_store_ex_data_index_once;
-static int g_x509_store_ex_data_index;
-
-static void ssl_x509_store_ex_data_index_init(void) {
- g_x509_store_ex_data_index = X509_STORE_CTX_get_ex_new_index(
- 0, "SSL for verify callback", NULL, NULL, NULL);
-}
-
int SSL_get_ex_data_X509_STORE_CTX_idx(void) {
- CRYPTO_once(&g_x509_store_ex_data_index_once,
- ssl_x509_store_ex_data_index_init);
- return g_x509_store_ex_data_index;
+ /* The ex_data index to go from |X509_STORE_CTX| to |SSL| always uses the
+ * reserved app_data slot. Before ex_data was introduced, app_data was used.
+ * Avoid breaking any software which assumes |X509_STORE_CTX_get_app_data|
+ * works. */
+ return 0;
}
CERT *ssl_cert_new(void) {
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index aa621e1..a7e3b9c 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -164,8 +164,10 @@
/* kMaxHandshakeSize is the maximum size, in bytes, of a handshake message. */
static const size_t kMaxHandshakeSize = (1u << 24) - 1;
-static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl = CRYPTO_EX_DATA_CLASS_INIT;
-static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl_ctx = CRYPTO_EX_DATA_CLASS_INIT;
+static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl =
+ CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
+static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl_ctx =
+ CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
int SSL_clear(SSL *ssl) {
if (ssl->method == NULL) {
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 62b5c72..2c5dfe6 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -151,7 +151,8 @@
* that it needs to asynchronously fetch session information. */
static const char g_pending_session_magic = 0;
-static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
+static CRYPTO_EX_DATA_CLASS g_ex_data_class =
+ CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);