Fix to bugs #665, and #664. Potentially to #649.

http://bugs.skysql.com/show_bug.cgi?id=665
http://bugs.skysql.com/show_bug.cgi?id=664
http://bugs.skysql.com/show_bug.cgi?id=649

dcb.c:dcb_final_free: (665):set dcb->session->client pointer to NULL so that it won't be read anymore and other threads won't try to close it.
	dcb_final_free:(664):don't free dcb->data, it is either freed in session_alloc if session creation fails or in session_free only.
session.c:if session creation fails, free dcb->data and remove links between client DCB and session.
mysql_backend.c:(665):gw_backend_close:check that session->client isn't NULL and that client DCB's state is still polling before calling dcb_close for it.
mysql_client.c:gw_mysql_do_authentication:if anything fails, and session_alloc won't be called, free dcb->data.
mysql_common.c:gw_send_authentication_to_backend:if session is already closing then return with error.
This commit is contained in:
VilhoRaatikka
2014-12-29 20:19:01 +02:00
parent beacd524da
commit 635fcf708f
8 changed files with 97 additions and 29 deletions

View File

@ -377,15 +377,18 @@ MySQLSendHandshake(DCB* dcb)
*
* Performs the MySQL protocol 4.1 authentication, using data in GWBUF *queue
*
* The useful data: user, db, client_sha1 are copied into the MYSQL_session * dcb->session->data
* (MYSQL_session*)client_data including: user, db, client_sha1 are copied into
* the dcb->data and later to dcb->session->data.
*
* client_capabilitiesa are copied into the dcb->protocol
*
* @param dcb Descriptor Control Block of the client
* @param queue The GWBUF with data from client
* @return 0 If succeed, otherwise non-zero value
*
* @note in case of failure, dcb->data is freed before returning. If succeed,
* dcb->data is freed in session.c:session_free.
*/
static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
MySQLProtocol *protocol = NULL;
/* int compress = -1; */
@ -405,6 +408,13 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
protocol = DCB_PROTOCOL(dcb, MySQLProtocol);
CHK_PROTOCOL(protocol);
client_data = (MYSQL_session *)calloc(1, sizeof(MYSQL_session));
#if defined(SS_DEBUG)
client_data->myses_chk_top = CHK_NUM_MYSQLSES;
client_data->myses_chk_tail = CHK_NUM_MYSQLSES;
#endif
/**
* Assign authentication structure with client DCB.
*/
dcb->data = client_data;
stage1_hash = client_data->client_sha1;
@ -425,7 +435,10 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
*/
/* Detect now if there are enough bytes to continue */
if (client_auth_packet_size < (4 + 4 + 4 + 1 + 23)) {
if (client_auth_packet_size < (4 + 4 + 4 + 1 + 23))
{
free(dcb->data);
dcb->data = NULL;
return 1;
}
@ -444,6 +457,8 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
if (username == NULL)
{
free(dcb->data);
dcb->data = NULL;
return 1;
}
@ -512,6 +527,11 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
if (auth_ret == 0) {
dcb->user = strdup(client_data->user);
}
else
{
free(dcb->data);
dcb->data = NULL;
}
/* let's free the auth_token now */
if (auth_token) {
@ -618,7 +638,7 @@ int gw_read_client_event(
* Now there should be at least one complete mysql packet in read_buffer.
*/
switch (protocol->protocol_auth_state) {
case MYSQL_AUTH_SENT:
{
int auth_val;