SSL: Avoid magic allocation of SSL backend specific data

Originally, my idea was to allocate the two structures (or more
precisely, the connectdata structure and the four SSL backend-specific
strucutres required for ssl[0..1] and proxy_ssl[0..1]) in one go, so
that they all could be free()d together.

However, getting the alignment right is tricky. Too tricky.

So let's just bite the bullet and allocate the SSL backend-specific
data separately.

As a consequence, we now have to be very careful to release the memory
allocated for the SSL backend-specific data whenever we release any
connectdata.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

Closes #2119
This commit is contained in:
Johannes Schindelin 2017-11-28 01:21:59 +01:00 committed by Daniel Stenberg
parent 744ee58386
commit 9194a9959b
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 27 additions and 25 deletions

View File

@ -716,6 +716,10 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->unix_domain_socket); Curl_safefree(conn->unix_domain_socket);
#endif #endif
#ifdef USE_SSL
Curl_safefree(conn->ssl_extra);
#endif
free(conn); /* free all the connection oriented data */ free(conn); /* free all the connection oriented data */
} }
@ -1793,38 +1797,27 @@ static void llist_dtor(void *user, void *element)
*/ */
static struct connectdata *allocate_conn(struct Curl_easy *data) static struct connectdata *allocate_conn(struct Curl_easy *data)
{ {
struct connectdata *conn; struct connectdata *conn = calloc(1, sizeof(struct connectdata));
size_t connsize = sizeof(struct connectdata);
#ifdef USE_SSL
/* SSLBK_MAX_ALIGN: The max byte alignment a CPU would use */
#define SSLBK_MAX_ALIGN 32
/* The SSL backend-specific data (ssl_backend_data) objects are allocated as
part of connectdata at the end. To ensure suitable alignment we will
assume a maximum of SSLBK_MAX_ALIGN for alignment. Since calloc returns a
pointer suitably aligned for any variable this will ensure the
ssl_backend_data array has proper alignment, even if that alignment turns
out to be less than SSLBK_MAX_ALIGN. */
size_t paddingsize = sizeof(struct connectdata) % SSLBK_MAX_ALIGN;
size_t alignsize = paddingsize ? (SSLBK_MAX_ALIGN - paddingsize) : 0;
size_t sslbksize = Curl_ssl->sizeof_ssl_backend_data;
connsize += alignsize + (4 * sslbksize);
#endif
conn = calloc(1, connsize);
if(!conn) if(!conn)
return NULL; return NULL;
#ifdef USE_SSL #ifdef USE_SSL
/* Point to the ssl_backend_data objects at the end of connectdata. /* The SSL backend-specific data (ssl_backend_data) objects are allocated as
a separate array to ensure suitable alignment.
Note that these backend pointers can be swapped by vtls (eg ssl backend Note that these backend pointers can be swapped by vtls (eg ssl backend
data becomes proxy backend data). */ data becomes proxy backend data). */
{ {
char *end = (char *)conn + connsize; size_t sslsize = Curl_ssl->sizeof_ssl_backend_data;
conn->ssl[0].backend = ((void *)(end - (4 * sslbksize))); char *ssl = calloc(4, sslsize);
conn->ssl[1].backend = ((void *)(end - (3 * sslbksize))); if(!ssl) {
conn->proxy_ssl[0].backend = ((void *)(end - (2 * sslbksize))); free(conn);
conn->proxy_ssl[1].backend = ((void *)(end - (1 * sslbksize))); return NULL;
}
conn->ssl_extra = ssl;
conn->ssl[0].backend = (void *)ssl;
conn->ssl[1].backend = (void *)(ssl + sslsize);
conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize);
conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize);
} }
#endif #endif
@ -1953,6 +1946,9 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
free(conn->master_buffer); free(conn->master_buffer);
free(conn->localdev); free(conn->localdev);
#ifdef USE_SSL
free(conn->ssl_extra);
#endif
free(conn); free(conn);
return NULL; return NULL;
} }
@ -4438,6 +4434,9 @@ static CURLcode create_conn(struct Curl_easy *data,
conn_temp->inuse = TRUE; /* mark this as being in use so that no other conn_temp->inuse = TRUE; /* mark this as being in use so that no other
handle in a multi stack may nick it */ handle in a multi stack may nick it */
reuse_conn(conn, conn_temp); reuse_conn(conn, conn_temp);
#ifdef USE_SSL
free(conn->ssl_extra);
#endif
free(conn); /* we don't need this anymore */ free(conn); /* we don't need this anymore */
conn = conn_temp; conn = conn_temp;
*in_connect = conn; *in_connect = conn;

View File

@ -860,6 +860,9 @@ struct connectdata {
#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ #endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */ struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */ struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */
#ifdef USE_SSL
void *ssl_extra; /* separately allocated backend-specific data */
#endif
struct ssl_primary_config ssl_config; struct ssl_primary_config ssl_config;
struct ssl_primary_config proxy_ssl_config; struct ssl_primary_config proxy_ssl_config;
bool tls_upgraded; bool tls_upgraded;