From b7aafca7b708b40cdfbeeff3798e2074722ece7e Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Mon, 26 Feb 2018 15:55:16 +0530 Subject: [PATCH 1/8] Raise version number after cloning 5.5.60 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 44f719ca097..23e938e60e1 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=60 +MYSQL_VERSION_PATCH=61 MYSQL_VERSION_EXTRA= From d982e717aba67227ec40761a21a4211db91aa0e2 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Mon, 9 Apr 2018 11:18:12 +0530 Subject: [PATCH 2/8] Bug#27510150: MYSQLDUMP FAILS FOR SPECIFIC --WHERE CLAUSES Description: Mysqldump utility fails for specific clauses used with the option, 'where'. Analysis:- Method, "fix_identifier_with_newline()" that prefixes all occurrences of newline char ('\n') in incoming buffer does not verify the size of the buffer. The buffer in which the incoming buffer is copied is limited to 2048 bytes and the method does not try to allocate additional memory for larger incoming buffers. Fix:- Method, "fix_identifier_with_newline()" is modified to fix this issue. --- client/mysqldump.c | 182 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 142 insertions(+), 40 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 2775769fe52..34037337091 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -549,7 +549,8 @@ static int dump_tablespaces_for_databases(char** databases); static int dump_tablespaces(char* ts_where); static void print_comment(FILE *sql_file, my_bool is_error, const char *format, ...); -static const char* fix_identifier_with_newline(char*); +static char const* fix_identifier_with_newline(char const* object_name, + my_bool* freemem); /* @@ -644,13 +645,19 @@ static void write_header(FILE *sql_file, char *db_name) } else if (!opt_compact) { + my_bool freemem= FALSE; + char const* text= fix_identifier_with_newline(db_name, &freemem); + print_comment(sql_file, 0, "-- MySQL dump %s Distrib %s, for %s (%s)\n--\n", DUMP_VERSION, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); print_comment(sql_file, 0, "-- Host: %s Database: %s\n", current_host ? current_host : "localhost", - db_name ? fix_identifier_with_newline(db_name) : ""); + text); + if (freemem) + my_free((void*)text); + print_comment(sql_file, 0, "-- ------------------------------------------------------\n" ); @@ -1982,31 +1989,84 @@ static void print_comment(FILE *sql_file, my_bool is_error, const char *format, print_xml_comment(sql_file, strlen(comment_buff), comment_buff); } -/* - This function accepts object names and prefixes -- wherever \n - character is found. - @param[in] object_name +/** + @brief Accepts object names and prefixes them with "-- " wherever + end-of-line character ('\n') is found. - @return - @retval fixed object name. + @param[in] object_name object name list (concatenated string) + @param[out] freemem should buffer be released after usage + + @return + @retval pointer to a string with prefixed objects */ - -static const char* fix_identifier_with_newline(char* object_name) +static char const* fix_identifier_with_newline(char const* object_name, my_bool* freemem) { - static char buff[COMMENT_LENGTH]= {0}; - char *ptr= buff; - memset(buff, 0, 255); - while(*object_name) + const size_t PREFIX_LENGTH= 3; // strlen ("-- ") + + // static buffer for replacement procedure + static char storage[NAME_LEN + 1]; + static char* buffer= storage; + static size_t buffer_size= sizeof(storage) - 1; + size_t index= 0; + size_t required_size= 0; + + // we presume memory allocation won't be needed + *freemem= FALSE; + + // traverse and reformat objects + while (object_name && *object_name) { - *ptr++ = *object_name; + ++required_size; if (*object_name == '\n') - ptr= strmov(ptr, "-- "); - object_name++; + required_size+= PREFIX_LENGTH; + + // do we need dynamic (re)allocation + if (required_size > buffer_size) + { + // new alloc size increased in COMMENT_LENGTH multiple + buffer_size= COMMENT_LENGTH * (1 + required_size/COMMENT_LENGTH); + + // is our buffer already dynamically allocated + if (*freemem) + { + // just realloc + buffer= (char*)my_realloc(buffer, buffer_size + 1, MYF(MY_WME)); + if (!buffer) + exit(1); + } + else + { + // dynamic allocation + copy from static buffer + buffer= (char*)my_malloc(buffer_size + 1, MYF(MY_WME)); + if (!buffer) + exit(1); + + strncpy(buffer, storage, index); + *freemem= TRUE; + } + } + + // copy a character + buffer[index]= *object_name; + ++index; + + // prefix new lines with double dash + if (*object_name == '\n') + { + strcpy(buffer + index, "-- "); + index += PREFIX_LENGTH; + } + + ++object_name; } - return buff; + + // don't forget null termination + buffer[index]= '\0'; + return buffer; } + /* create_delimiter Generate a new (null-terminated) string that does not exist in query @@ -2066,6 +2126,8 @@ static uint dump_events_for_db(char *db) char db_cl_name[MY_CS_NAME_SIZE]; int db_cl_altered= FALSE; + my_bool freemem= FALSE; + char const *text= fix_identifier_with_newline(db, &freemem); DBUG_ENTER("dump_events_for_db"); DBUG_PRINT("enter", ("db: '%s'", db)); @@ -2075,7 +2137,9 @@ static uint dump_events_for_db(char *db) /* nice comments */ print_comment(sql_file, 0, "\n--\n-- Dumping events for database '%s'\n--\n", - fix_identifier_with_newline(db)); + text); + if (freemem) + my_free((void*)text); /* not using "mysql_query_with_error_report" because we may have not @@ -2284,6 +2348,8 @@ static uint dump_routines_for_db(char *db) char db_cl_name[MY_CS_NAME_SIZE]; int db_cl_altered= FALSE; + my_bool freemem= FALSE; + char const *text= fix_identifier_with_newline(db, &freemem); DBUG_ENTER("dump_routines_for_db"); DBUG_PRINT("enter", ("db: '%s'", db)); @@ -2292,8 +2358,10 @@ static uint dump_routines_for_db(char *db) /* nice comments */ print_comment(sql_file, 0, - "\n--\n-- Dumping routines for database '%s'\n--\n", - fix_identifier_with_newline(db)); + "\n--\n-- Dumping routines for database '%s'\n--\n", text); + + if (freemem) + my_free((void*)text); /* not using "mysql_query_with_error_report" because we may have not @@ -2348,11 +2416,17 @@ static uint dump_routines_for_db(char *db) row[2] ? strlen(row[2]) : 0)); if (row[2] == NULL) { + my_bool freemem= FALSE; + char const* text= fix_identifier_with_newline(current_user, &freemem); + print_comment(sql_file, 1, "\n-- insufficient privileges to %s\n", query_buff); print_comment(sql_file, 1, "-- does %s have permissions on mysql.proc?\n\n", - fix_identifier_with_newline(current_user)); + text); + if (freemem) + my_free((void*)text); + maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", current_user, query_buff); } else if (strlen(row[2])) @@ -2547,6 +2621,8 @@ static uint get_table_structure(char *table, char *db, char *table_type, /* Make an sql-file, if path was given iow. option -T was given */ char buff[20+FN_REFLEN]; MYSQL_FIELD *field; + my_bool freemem= FALSE; + char const *text; my_snprintf(buff, sizeof(buff), "show create table %s", result_table); @@ -2563,14 +2639,17 @@ static uint get_table_structure(char *table, char *db, char *table_type, write_header(sql_file, db); } + text= fix_identifier_with_newline(result_table, &freemem); if (strcmp (table_type, "VIEW") == 0) /* view */ print_comment(sql_file, 0, "\n--\n-- Temporary table structure for view %s\n--\n\n", - fix_identifier_with_newline(result_table)); + text); else print_comment(sql_file, 0, - "\n--\n-- Table structure for table %s\n--\n\n", - fix_identifier_with_newline(result_table)); + "\n--\n-- Table structure for table %s\n--\n\n", text); + + if (freemem) + my_free((void*)text); if (opt_drop) { @@ -2803,6 +2882,9 @@ static uint get_table_structure(char *table, char *db, char *table_type, /* Make an sql-file, if path was given iow. option -T was given */ if (!opt_no_create_info) { + my_bool freemem= FALSE; + char const *text; + if (path) { if (!(sql_file= open_sql_file_for_table(table, O_WRONLY))) @@ -2810,9 +2892,13 @@ static uint get_table_structure(char *table, char *db, char *table_type, write_header(sql_file, db); } + text= fix_identifier_with_newline(result_table, &freemem); print_comment(sql_file, 0, "\n--\n-- Table structure for table %s\n--\n\n", - fix_identifier_with_newline(result_table)); + text); + if (freemem) + my_free((void*)text); + if (opt_drop) fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table); if (!opt_xml) @@ -3515,25 +3601,34 @@ static void dump_table(char *table, char *db) } else { - print_comment(md_result_file, 0, - "\n--\n-- Dumping data for table %s\n--\n", - fix_identifier_with_newline(result_table)); - + my_bool freemem= FALSE; + char const* text= fix_identifier_with_newline(result_table, &freemem); + print_comment(md_result_file, 0, "\n--\n-- Dumping data for table %s\n--\n", + text); + if (freemem) + my_free((void*)text); + dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM "); dynstr_append_checked(&query_string, result_table); if (where) { - print_comment(md_result_file, 0, "-- WHERE: %s\n", - fix_identifier_with_newline(where)); + freemem= FALSE; + text= fix_identifier_with_newline(where, &freemem); + print_comment(md_result_file, 0, "-- WHERE: %s\n", text); + if (freemem) + my_free((void*)text); dynstr_append_checked(&query_string, " WHERE "); dynstr_append_checked(&query_string, where); } if (order_by) { - print_comment(md_result_file, 0, "-- ORDER BY: %s\n", - fix_identifier_with_newline(order_by)); + freemem= FALSE; + text= fix_identifier_with_newline(order_by, &freemem); + print_comment(md_result_file, 0, "-- ORDER BY: %s\n", text); + if (freemem) + my_free((void*)text); dynstr_append_checked(&query_string, " ORDER BY "); dynstr_append_checked(&query_string, order_by); @@ -4302,10 +4397,13 @@ static int init_dumping(char *database, int init_func(char*)) */ char quoted_database_buf[NAME_LEN*2+3]; char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted); + my_bool freemem= FALSE; + char const* text= fix_identifier_with_newline(qdatabase, &freemem); - print_comment(md_result_file, 0, - "\n--\n-- Current Database: %s\n--\n", - fix_identifier_with_newline(qdatabase)); + print_comment(md_result_file, 0, "\n--\n-- Current Database: %s\n--\n", + text); + if (freemem) + my_free((void*)text); /* Call the view or table specific function */ init_func(qdatabase); @@ -5265,6 +5363,8 @@ static my_bool get_view_structure(char *table, char* db) char table_buff2[NAME_LEN*2+3]; char query[QUERY_LENGTH]; FILE *sql_file= md_result_file; + my_bool freemem= FALSE; + char const *text; DBUG_ENTER("get_view_structure"); if (opt_no_create_info) /* Don't write table creation info */ @@ -5309,9 +5409,11 @@ static my_bool get_view_structure(char *table, char* db) write_header(sql_file, db); } + text= fix_identifier_with_newline(result_table, &freemem); print_comment(sql_file, 0, - "\n--\n-- Final view structure for view %s\n--\n\n", - fix_identifier_with_newline(result_table)); + "\n--\n-- Final view structure for view %s\n--\n\n", text); + if (freemem) + my_free((void*)text); /* Table might not exist if this view was dumped with --tab. */ fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n", opt_quoted_table); From 940b88b686bcf037a36f6e81be4017a07fcf782a Mon Sep 17 00:00:00 2001 From: Ajo Robert Date: Tue, 10 Apr 2018 00:30:59 +0530 Subject: [PATCH 3/8] Bug#27197235 USER VARIABLE + UINON + DECIMAL COLUMN RETURNS WRONG VALUES User variables will have the default session collation associated with it. And a select which uses it as part of a union may infer the collation while type merging. This leads to problems when the result is of DECIMAL type. Setting the appropriate collation of DECIMAL result type is missing in 5.7 code base. Added code to set appropriate collation when the result is of DECIMAL type during Item_type_holder::join_types(). --- mysql-test/r/union.result | 16 ++++++++++++++++ mysql-test/t/union.test | 14 ++++++++++++++ sql/item.cc | 3 ++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 97c1a8b4d49..c0b364d0fde 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1860,3 +1860,19 @@ DROP TABLE t17059925, t2, t3; SET @@long_query_time= @old_long_query_time; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; +# +# Bug#27197235 USER VARIABLE + UINON + DECIMAL COLUMN RETURNS +# WRONG VALUES +# +SET NAMES utf8; +SET @advertAcctId = 1000003; +select @advertAcctId as a from dual union all select 1.0 from dual; +a +1000003.0 +1.0 +SET NAMES latin1; +SET @advertAcctId = 1000003; +select @advertAcctId as a from dual union all select 1.0 from dual; +a +1000003.0 +1.0 diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 147c1d3834b..d7e362558e3 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -1256,3 +1256,17 @@ SET @@long_query_time= @old_long_query_time; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; +--echo # +--echo # Bug#27197235 USER VARIABLE + UINON + DECIMAL COLUMN RETURNS +--echo # WRONG VALUES +--echo # + +let $old_charset= `SELECT @@character_set_client`; + +SET NAMES utf8; +SET @advertAcctId = 1000003; +select @advertAcctId as a from dual union all select 1.0 from dual; + +eval SET NAMES $old_charset; +SET @advertAcctId = 1000003; +select @advertAcctId as a from dual union all select 1.0 from dual; diff --git a/sql/item.cc b/sql/item.cc index a37a61453e8..07d64881eeb 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -8266,6 +8266,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) } if (Field::result_merge_type(fld_type) == DECIMAL_RESULT) { + collation.set_numeric(); decimals= min(max(decimals, item->decimals), DECIMAL_MAX_SCALE); int item_int_part= item->decimal_int_part(); int item_prec = max(prev_decimal_int_part, item_int_part) + decimals; From a08508abf83d953f11e4823798398d9229ba0237 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Tue, 24 Apr 2018 10:02:04 +0530 Subject: [PATCH 4/8] Bug#27407480: AUTOMATIC_SP_PRIVILEGES REQUIRES NEED THE INSERT PRIVILEGES FOR MYSQL.USER TABLE Description:- Incorrect granting of EXECUTE and ALTER ROUTINE privileges when the 'automatic_sp_privileges' variable is set. Fix:- EXECUTE and ALTER ROUTINE privileges are correctly granted to the creator of the procedure when the 'automatic_sp_privileges' is SET. --- mysql-test/r/grant.result | 3 +-- sql/sql_acl.cc | 15 ++++----------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 7603e4b1b1c..e524bb5cac2 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1780,8 +1780,6 @@ BEGIN SET @x = 0; REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; END ;|| -Warnings: -Warning 1404 Failed to grant EXECUTE and ALTER ROUTINE privileges SHOW GRANTS FOR 'user1'@'localhost'; Grants for user1@localhost GRANT USAGE ON *.* TO 'user1'@'localhost' @@ -1791,6 +1789,7 @@ SHOW GRANTS FOR 'user2'; Grants for user2@% GRANT USAGE ON *.* TO 'user2'@'%' GRANT CREATE, CREATE ROUTINE ON `db1`.* TO 'user2'@'%' +GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `db1`.`proc2` TO 'user2'@'%' DROP PROCEDURE db1.proc1; DROP PROCEDURE db1.proc2; REVOKE ALL ON db1.* FROM 'user1'@'localhost'; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 385484f2b01..705b4792a37 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -7670,19 +7670,12 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, if (!(combo=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) DBUG_RETURN(TRUE); - combo->user.str= sctx->user; + combo->user.str= (char *) sctx->priv_user; mysql_mutex_lock(&acl_cache->lock); - if ((au= find_acl_user(combo->host.str=(char*)sctx->host_or_ip,combo->user.str,FALSE))) - goto found_acl; - if ((au= find_acl_user(combo->host.str=(char*)sctx->get_host()->ptr(), - combo->user.str,FALSE))) - goto found_acl; - if ((au= find_acl_user(combo->host.str=(char*)sctx->get_ip()->ptr(), - combo->user.str,FALSE))) - goto found_acl; - if((au= find_acl_user(combo->host.str=(char*)"%", combo->user.str, FALSE))) + if ((au= find_acl_user(combo->host.str= (char *) sctx->priv_host, + combo->user.str, FALSE))) goto found_acl; mysql_mutex_unlock(&acl_cache->lock); From 6d570d729682039edd6c490187a0434e7d75d486 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Thu, 10 May 2018 10:14:30 +0530 Subject: [PATCH 5/8] Bug#27230925: HANDLE_FATAL_SIGNAL (SIG=11) IN SHOW_ROUTINE_GRANTS Description :- Server crashes in show_routine_grants(). Analysis :- When "grant_reload_procs_priv" encounters an error, the grant structures (structures with column, function and procedure privileges) are freed. Server crashes when trying to access these structures later. Fix :- Grant structures are retained even when "grant_reload_procs_priv()" encounters an error while reloading column, function and procedure privileges. --- mysql-test/r/grant.result | 1 + mysql-test/t/grant.test | 3 ++ sql/sql_acl.cc | 92 ++++++++++++++++++++++++++------------- 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index e524bb5cac2..d151b58e9ce 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1692,6 +1692,7 @@ revoke create, insert on mysqltest.t6 from mysqltest@localhost; drop user mysqltest@localhost; drop database mysqltest; use test; +call mtr.add_suppression("Can't open and lock privilege tables"); FLUSH PRIVILEGES without procs_priv table. RENAME TABLE mysql.procs_priv TO mysql.procs_gone; FLUSH PRIVILEGES; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 1e1cb6c24dc..2a1a8e34efb 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -1667,6 +1667,9 @@ use test; # # Bug#16470 crash on grant if old grant tables # + +call mtr.add_suppression("Can't open and lock privilege tables"); + --echo FLUSH PRIVILEGES without procs_priv table. RENAME TABLE mysql.procs_priv TO mysql.procs_gone; --error ER_NO_SUCH_TABLE diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 705b4792a37..64888f7308a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -4871,6 +4871,7 @@ end_index_init: exists. @param thd A pointer to the thread handler object. + @param table A pointer to the table list. @see grant_reload @@ -4879,31 +4880,22 @@ end_index_init: @retval TRUE An error has occurred. */ -static my_bool grant_reload_procs_priv(THD *thd) +static my_bool grant_reload_procs_priv(THD *thd, TABLE_LIST *table) { HASH old_proc_priv_hash, old_func_priv_hash; - TABLE_LIST table; my_bool return_val= FALSE; DBUG_ENTER("grant_reload_procs_priv"); - table.init_one_table("mysql", 5, "procs_priv", - strlen("procs_priv"), "procs_priv", - TL_READ); - table.open_type= OT_BASE_ONLY; - - if (open_and_lock_tables(thd, &table, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT)) - DBUG_RETURN(TRUE); - - mysql_rwlock_wrlock(&LOCK_grant); /* Save a copy of the current hash if we need to undo the grant load */ old_proc_priv_hash= proc_priv_hash; old_func_priv_hash= func_priv_hash; - if ((return_val= grant_load_procs_priv(table.table))) + if ((return_val= grant_load_procs_priv(table->table))) { /* Error; Reverting to old hash */ DBUG_PRINT("error",("Reverting to old privileges")); - grant_free(); + my_hash_free(&proc_priv_hash); + my_hash_free(&func_priv_hash); proc_priv_hash= old_proc_priv_hash; func_priv_hash= old_func_priv_hash; } @@ -4912,9 +4904,7 @@ static my_bool grant_reload_procs_priv(THD *thd) my_hash_free(&old_proc_priv_hash); my_hash_free(&old_func_priv_hash); } - mysql_rwlock_unlock(&LOCK_grant); - close_mysql_tables(thd); DBUG_RETURN(return_val); } @@ -4936,7 +4926,7 @@ static my_bool grant_reload_procs_priv(THD *thd) my_bool grant_reload(THD *thd) { - TABLE_LIST tables[2]; + TABLE_LIST tables[3]; HASH old_column_priv_hash; MEM_ROOT old_mem; my_bool return_val= 1; @@ -4952,15 +4942,57 @@ my_bool grant_reload(THD *thd) tables[1].init_one_table(C_STRING_WITH_LEN("mysql"), C_STRING_WITH_LEN("columns_priv"), "columns_priv", TL_READ); + tables[2].init_one_table(C_STRING_WITH_LEN("mysql"), + C_STRING_WITH_LEN("procs_priv"), + "procs_priv", TL_READ); + tables[0].next_local= tables[0].next_global= tables+1; - tables[0].open_type= tables[1].open_type= OT_BASE_ONLY; + tables[1].next_local= tables[1].next_global= tables+2; + tables[0].open_type= tables[1].open_type= tables[2].open_type= OT_BASE_ONLY; + + /* + Reload will work in the following manner:- + + proc_priv_hash structure + / \ + not initialized initialized + / \ | + mysql.procs_priv table Server Startup | + is missing \ | + | open_and_lock_tables() + Assume we are working on /success \failure + pre 4.1 system tables. Normal Scenario. An error is thrown. + A warning is printed Reload column privilege. Retain the old hash. + and continue with Reload function and + reloading the column procedure privileges, + privileges. if available. + */ + + if (!(my_hash_inited(&proc_priv_hash))) + tables[2].open_strategy= TABLE_LIST::OPEN_IF_EXISTS; /* To avoid deadlocks we should obtain table locks before obtaining LOCK_grant rwlock. */ if (open_and_lock_tables(thd, tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT)) + { + if (thd->stmt_da->is_error()) + { + sql_print_error("Fatal error: Can't open and lock privilege tables: %s", + thd->stmt_da->message()); + } goto end; + } + + if (tables[2].table == NULL) + { + sql_print_warning("Table 'mysql.procs_priv' does not exist. " + "Please run mysql_upgrade."); + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NO_SUCH_TABLE, + ER(ER_NO_SUCH_TABLE), tables[2].db, + tables[2].table_name); + } mysql_rwlock_wrlock(&LOCK_grant); old_column_priv_hash= column_priv_hash; @@ -4972,10 +5004,18 @@ my_bool grant_reload(THD *thd) old_mem= memex; init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0); - if ((return_val= grant_load(thd, tables))) + /* + tables[2].table i.e. procs_priv can be null if we are working with + pre 4.1 privilage tables + */ + if ((return_val= (grant_load(thd, tables) || + (tables[2].table != NULL && + grant_reload_procs_priv(thd, &tables[2]))) + )) { // Error. Revert to old hash DBUG_PRINT("error",("Reverting to old privileges")); - grant_free(); /* purecov: deadcode */ + my_hash_free(&column_priv_hash); + free_root(&memex,MYF(0)); column_priv_hash= old_column_priv_hash; /* purecov: deadcode */ memex= old_mem; /* purecov: deadcode */ } @@ -4983,22 +5023,12 @@ my_bool grant_reload(THD *thd) { my_hash_free(&old_column_priv_hash); free_root(&old_mem,MYF(0)); + grant_version++; } mysql_rwlock_unlock(&LOCK_grant); - close_mysql_tables(thd); - - /* - It is OK failing to load procs_priv table because we may be - working with 4.1 privilege tables. - */ - if (grant_reload_procs_priv(thd)) - return_val= 1; - - mysql_rwlock_wrlock(&LOCK_grant); - grant_version++; - mysql_rwlock_unlock(&LOCK_grant); end: + close_mysql_tables(thd); DBUG_RETURN(return_val); } From bbc2e37fe4e0ca3a7cfa1437a763dc43829e98e2 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Mon, 14 May 2018 11:28:13 +0530 Subject: [PATCH 6/8] Bug#27759871: BACKRONYM ISSUE IS STILL IN MYSQL 5.7 Description:- Client applications establishes connection to server, which does not support SSL, via TCP even when SSL is enforced via MYSQL_OPT_SSL_MODE or MYSQL_OPT_SSL_ENFORCE or MYSQL_OPT_SSL_VERIFY_SERVER_CERT. Analysis:- There exist no error handling for catching client applications which enforces SSL connection to connect to a server which does not support SSL. Fix:- Error handling is done to catch above mentioned scenarios. --- include/sql_common.h | 5 ++++- libmysqld/libmysqld.c | 5 ++++- sql-common/client.c | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/include/sql_common.h b/include/sql_common.h index 45e90d438fb..9571dff9778 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -1,7 +1,7 @@ #ifndef SQL_COMMON_INCLUDED #define SQL_COMMON_INCLUDED -/* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -96,6 +96,9 @@ void set_stmt_error(MYSQL_STMT *stmt, int errcode, const char *sqlstate, void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate); void set_mysql_extended_error(MYSQL *mysql, int errcode, const char *sqlstate, const char *format, ...); +#ifdef EMBEDDED_LIBRARY +int embedded_ssl_check(MYSQL *mysql); +#endif /* client side of the pluggable authentication */ struct st_plugin_vio_info; diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index 6de1e3383d2..85ca0cf4bd8 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -173,6 +173,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (db) client_flag|=CLIENT_CONNECT_WITH_DB; + if (embedded_ssl_check(mysql)) + goto error; + mysql->info_buffer= my_malloc(MYSQL_ERRMSG_SIZE, MYF(0)); mysql->thd= create_embedded_thd(client_flag); diff --git a/sql-common/client.c b/sql-common/client.c index 9972ca741f2..3247fd8e339 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -2020,6 +2020,34 @@ error: #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ +/** + Checks if any SSL option is set for libmysqld embedded server. + + @param mysql the connection handle + @retval 0 success + @retval 1 failure +*/ +#ifdef EMBEDDED_LIBRARY +int embedded_ssl_check(MYSQL *mysql) +{ + if (mysql->options.ssl_key || mysql->options.ssl_cert || + mysql->options.ssl_ca || mysql->options.ssl_capath || + mysql->options.ssl_cipher || + mysql->options.client_flag & CLIENT_SSL_VERIFY_SERVER_CERT || + (mysql->options.extension && + mysql->options.extension->ssl_mode == SSL_MODE_REQUIRED)) + { + set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate, + ER(CR_SSL_CONNECTION_ERROR), + "Embedded server libmysqld library doesn't support " + "SSL connections"); + return 1; + } + return 0; +} +#endif + + /* Note that the mysql argument must be initialized with mysql_init() before calling mysql_real_connect ! @@ -3592,6 +3620,11 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, mysql->client_flag= client_flag; +#ifdef EMBEDDED_LIBRARY + if (embedded_ssl_check(mysql)) + goto error; +#endif + /* Part 2: invoke the plugin to send the authentication data to the server */ @@ -4271,10 +4304,14 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) mysql->reconnect= *(my_bool *) arg; break; case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) if (*(my_bool*) arg) mysql->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT; else mysql->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT; +#elif defined(EMBEDDED_LIBRARY) + DBUG_RETURN(1); +#endif break; case MYSQL_PLUGIN_DIR: EXTENSION_SET_STRING(&mysql->options, plugin_dir, arg); @@ -4288,11 +4325,15 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) (*(my_bool*) arg) ? TRUE : FALSE; break; case MYSQL_OPT_SSL_MODE: +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) if (*(uint *) arg == SSL_MODE_REQUIRED) { ENSURE_EXTENSIONS_PRESENT(&mysql->options); mysql->options.extension->ssl_mode= SSL_MODE_REQUIRED; } +#elif defined(EMBEDDED_LIBRARY) + DBUG_RETURN(1); +#endif break; default: DBUG_RETURN(1); From bd5ca6acece65858591c2bf54f86ff34aeea2821 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Mon, 21 May 2018 08:42:45 +0530 Subject: [PATCH 7/8] Bug#25541037: MYSQL BUG ON DELETE Description:- MyISAM table gets corrupted with concurrent executions of INSERT, DELETE statements in a particular sequence. Analysis:- Due to the inappropriate manipulation of w_lock and r_lock associated with a MyISAM table, there arises a scenario where the table's state information becomes invalid. Fix:- A lock is introduced to resolve this issue. --- storage/myisam/ha_myisam.cc | 6 +++++- storage/myisam/mi_check.c | 6 +++++- storage/myisam/mi_locking.c | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 21cbef32188..6eed1be1ba9 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1172,10 +1172,14 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize) if (file->s->base.auto_key) update_auto_increment_key(¶m, file, 1); if (optimize_done) + { + mysql_mutex_lock(&share->intern_lock); error = update_state_info(¶m, file, UPDATE_TIME | UPDATE_OPEN_COUNT | (local_testflag & T_STATISTICS ? UPDATE_STAT : 0)); + mysql_mutex_unlock(&share->intern_lock); + } info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE | HA_STATUS_CONST); if (rows != file->state->records && ! (param.testflag & T_VERY_SILENT)) diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index fe0d4c9c30b..7134cfc265a 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -4474,6 +4474,10 @@ int update_state_info(MI_CHECK *param, MI_INFO *info,uint update) int error; uint r_locks=share->r_locks,w_locks=share->w_locks; share->r_locks= share->w_locks= share->tot_locks= 0; + + DBUG_EXECUTE_IF("simulate_incorrect_share_wlock_value", + DEBUG_SYNC_C("after_share_wlock_set_to_0");); + error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK); share->r_locks=r_locks; share->w_locks=w_locks; diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index 4a33e838fb9..dcfeaca5b8c 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -229,6 +229,10 @@ int mi_lock_database(MI_INFO *info, int lock_type) info->invalidator=info->s->invalidator; share->w_locks++; share->tot_locks++; + + DBUG_EXECUTE_IF("simulate_incorrect_share_wlock_value", + DEBUG_SYNC_C("after_share_wlock_increment");); + info->s->in_use= list_add(info->s->in_use, &info->in_use); break; default: From e48d775c6f066add457fa8cfb2ebc4d5ff0c7613 Mon Sep 17 00:00:00 2001 From: Ivo Roylev Date: Thu, 14 Jun 2018 17:27:54 +0300 Subject: [PATCH 8/8] Bug#27980823: HEAP OVERFLOW VULNERABILITIES IN MYSQL CLIENT LIBRARY (cherry picked from commit b5b986b2cbd9a7848dc3f48e5c42b6d4e1e5fb22) --- sql-common/client.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql-common/client.c b/sql-common/client.c index 3247fd8e339..7938403db59 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1505,7 +1505,8 @@ unpack_fields(MYSQL *mysql, MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, { uchar *pos; /* fields count may be wrong */ - DBUG_ASSERT((uint) (field - result) < fields); + if (field < result || (uint) (field - result) >= fields) + DBUG_RETURN(NULL); cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7); field->catalog= strmake_root(alloc,(char*) row->data[0], lengths[0]); field->db= strmake_root(alloc,(char*) row->data[1], lengths[1]); @@ -1612,6 +1613,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, if ((pkt_len= cli_safe_read(mysql)) == packet_error) DBUG_RETURN(0); + if (pkt_len == 0) DBUG_RETURN(0); if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), MYF(MY_WME | MY_ZEROFILL)))) {