From 689366b6b790fc0e21358efa95672a7ee26b12ba Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Tue, 8 Nov 2016 09:24:00 +0200 Subject: [PATCH] Fix possible writes to closed DCBs When persistent connections were used, it was possible that the injection of COM_CHANGE_USER statements caused a crash when a DCB in the wrong state was accessed. For MySQL protocol modules, the `data` member of the client DCB points to the shared session data, a MYSQL_session struct, but for sessions in the persistent pool, it points to NULL. The boolean, `was_persistent`, tells whether a DCB was just taken from the pool or it has been in use. The `was_persistent` status wasn't properly reset for connections that were put into the pool which caused a COM_CHANGE_USER statement to be injected for stale connections in the pool which caused a crash when the NULL `data` member was accessed. --- server/core/dcb.c | 1 + server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/server/core/dcb.c b/server/core/dcb.c index 939fe6a2b..2cc65eeb3 100644 --- a/server/core/dcb.c +++ b/server/core/dcb.c @@ -1827,6 +1827,7 @@ dcb_maybe_add_persistent(DCB *dcb) MXS_DEBUG("%lu [dcb_maybe_add_persistent] Adding DCB to persistent pool, user %s.\n", pthread_self(), dcb->user); + dcb->was_persistent = false; dcb->dcb_is_zombie = false; dcb->persistentstart = time(NULL); if (dcb->session) diff --git a/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c b/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c index 4253b1c45..fe48791b6 100644 --- a/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c +++ b/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c @@ -947,8 +947,9 @@ static int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue) CHK_DCB(dcb); spinlock_acquire(&dcb->authlock); - if (dcb->was_persistent) + if (dcb->was_persistent && dcb->state == DCB_STATE_POLLING) { + ss_dassert(dcb->persistentstart == 0); /** * This is a DCB that was just taken out of the persistent connection pool. * We need to sent a COM_CHANGE_USER query to the backend to reset the