[CONC-276] Crash after reconnecting to server using TLS Created: 2017-08-24  Updated: 2017-08-24  Resolved: 2017-08-24

Status: Closed
Project: MariaDB Connector/C
Component/s: None
Affects Version/s: 3.0.2
Fix Version/s: 3.0.3

Type: Bug Priority: Major
Reporter: Scott Thomas Assignee: Georg Richter
Resolution: Fixed Votes: 0
Labels: None
Environment:

Tested on Windows client with Linux server configured for TLS



 Description   

Hi

I'm seeing a crash within the MariaDB connector client when connecting to a server via TLS after a server reconnect (eg, internet, restart, etc).

After doing some digging, it appears that the mysql pointer within the security context is not set to the new structure after a disconnect and reconnect, thus when doing a read or write the connector then tries to access freed memory. The crashes tend to happen deep inside ma_schannel_read_decrypt or ma_schannel_write_encrypt but can be traced back to ma_tls_read/write, (schannel.c, Ln 394 + Ln 408) where the sctx->mysql pointer refers to the pre-reconnect structure.

Adding a hack to set sctx->mysql to ctls->pvio->mysql (or amending the following line to pvio = ctls->pvio) works however this is obviously not the correct location to update that pointer.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
#ifdef LINUX
#include <unistd.h>
#endif
#ifdef WINDOWS
#include <windows.h>
#endif
 
void mySleep(int sleepMs)
{
#ifdef LINUX
    usleep(sleepMs * 1000);   // usleep takes sleep time in us (1 millionth of a second)
#endif
#ifdef WINDOWS
    Sleep(sleepMs);
#endif
}
 
#include "mysql.h"
 
const char* host = "127.0.0.1";
const char* user = "root";
const char* pass = "";
 
int main(int argc, char** arvg) {
  MYSQL *mysql = new MYSQL;
  mysql_init(mysql);
  my_bool yes = 1;
  mysql_options(mysql, MYSQL_OPT_RECONNECT, &yes);
  //mysql_options(mysql, MYSQL_OPT_COMPRESS, NULL);
  mysql_ssl_set(mysql, 0, 0, 0, 0, 0);
 
  if (!mysql_real_connect(mysql, host, user, pass, "mysql", 3306, NULL, CLIENT_SSL)) {
    printf("Can't connect\n");
    return 0;
  }
 
  while (mysql_ping(mysql) == 0) {
    printf("Connected, please stop server. Sleeping\n");
    mySleep(5000); 
  }
 
  while (mysql_ping(mysql) != 0) {
    printf("Server gone, please start it\n");
    mySleep(5000);
  }
 
  printf("Recovered, exiting");
 
  mysql_close(mysql);
}



 Comments   
Comment by Georg Richter [ 2017-08-24 ]

Thank you for reporting this bug which has been fixed now.

One note about your test case: Since C/C 3.0 it's not mandatory to restart the server for emulating reconnect scenario - instead of you can use

mariadb_reconnect()

API function to force a reconnect.

commit a2b0bcda07c310aea63d90a17ea594c3c28ee93e

Generated at Thu Feb 08 03:04:09 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.