summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavi@endora.local <>2007-11-01 17:29:20 -0200
committerdavi@endora.local <>2007-11-01 17:29:20 -0200
commit968af721502f47b061e716f955716293e9f2597e (patch)
treee2439b0b42b30ea2e2147c6621485bbd2149cdb1
parent7ec50bd4836a43da0b87a8fd84b356c1a95fc635 (diff)
downloadmariadb-git-968af721502f47b061e716f955716293e9f2597e.tar.gz
Bug#31850 Test crashes in "embedded" server
The mysql_change_user command fails to properly update the database pointer when no database is selected, leading to "use after free" errors. The same happens on the user privilege pointer in the thread security context. The solution is to properly reset and update the database name. Also update the user_priv pointer so that it doesn't point to freed memory.
-rw-r--r--sql/sql_connect.cc23
-rw-r--r--sql/sql_parse.cc5
2 files changed, 12 insertions, 16 deletions
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 8a817e5993a..adf0b9e01ed 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -316,17 +316,20 @@ int check_user(THD *thd, enum enum_server_command command,
{
DBUG_ENTER("check_user");
LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 };
-
+
+ /*
+ Clear thd->db as it points to something, that will be freed when
+ connection is closed. We don't want to accidentally free a wrong
+ pointer if connect failed. Also in case of 'CHANGE USER' failure,
+ current database will be switched to 'no database selected'.
+ */
+ thd->reset_db(NULL, 0);
+
#ifdef NO_EMBEDDED_ACCESS_CHECKS
thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights
/* Change database if necessary */
if (db && db[0])
{
- /*
- thd->db is saved in caller and needs to be freed by caller if this
- function returns 0
- */
- thd->reset_db(NULL, 0);
if (mysql_change_db(thd, &db_str, FALSE))
{
/* Send the error to the client */
@@ -358,14 +361,6 @@ int check_user(THD *thd, enum enum_server_command command,
passwd_len != SCRAMBLE_LENGTH_323)
DBUG_RETURN(ER_HANDSHAKE_ERROR);
- /*
- Clear thd->db as it points to something, that will be freed when
- connection is closed. We don't want to accidentally free a wrong pointer
- if connect failed. Also in case of 'CHANGE USER' failure, current
- database will be switched to 'no database selected'.
- */
- thd->reset_db(NULL, 0);
-
USER_RESOURCES ur;
int res= acl_getroot(thd, &ur, passwd, passwd_len);
#ifndef EMBEDDED_LIBRARY
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 85457fea41b..b2f2e74999b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -911,6 +911,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* Clear variables that are allocated */
thd->user_connect= 0;
+ thd->security_ctx->priv_user= thd->security_ctx->user;
res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE);
if (res)
@@ -933,8 +934,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (save_user_connect)
decrease_user_connections(save_user_connect);
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
- x_free((uchar*) save_db);
- x_free((uchar*) save_security_ctx.user);
+ x_free(save_db);
+ x_free(save_security_ctx.user);
if (cs_number)
{