Skip to content

Commit befb557

Browse files
author
Nisha Gopalakrishnan
committed
BUG#16373054 - CRASH WHEN MYSQL.PROC HAS NO AVAILABLE PK
Analysis -------- 'mysqld' crashes when: a) The primary key for the system table 'proc' is dropped and b) A stored procedure is invoked. Ideally it is expected that system tables are not tampered. When we access these tables for performing some operation, we do not check if a valid key information is available. Since the primary key is dropped, the mysqld crashes while trying to access the key information. This behavior is observed with other system tables(user, columns_priv, event and plugin) as well when it's primary key is dropped. This issue is addressed with this patch. Fix: --- Make sure that key information is available when the operations accessing the system tables are invoked. In such a case, we now report an error instead of a crash. Note: We do not validate complete key information as it could impact performance. Once MySQL roles is introduced, such checks would become unnecessary.
1 parent 76453a0 commit befb557

5 files changed

Lines changed: 71 additions & 3 deletions

File tree

sql/event_db_repository.cc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
2+
Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -549,6 +549,14 @@ Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *i_s_table,
549549
if (open_system_tables_for_read(thd, &event_table, &open_tables_backup))
550550
DBUG_RETURN(TRUE);
551551

552+
if (!event_table.table->key_info)
553+
{
554+
close_system_tables(thd, &open_tables_backup);
555+
my_error(ER_TABLE_CORRUPT, MYF(0), event_table.table->s->db.str,
556+
event_table.table->s->table_name.str);
557+
DBUG_RETURN(TRUE);
558+
}
559+
552560
if (table_intact.check(event_table.table, &event_table_def))
553561
{
554562
close_system_tables(thd, &open_tables_backup);
@@ -955,6 +963,13 @@ Event_db_repository::find_named_event(LEX_STRING db, LEX_STRING name,
955963
if (db.length > table->field[ET_FIELD_DB]->field_length ||
956964
name.length > table->field[ET_FIELD_NAME]->field_length)
957965
DBUG_RETURN(TRUE);
966+
967+
if (!table->key_info)
968+
{
969+
my_error(ER_TABLE_CORRUPT, MYF(0), table->s->db.str,
970+
table->s->table_name.str);
971+
DBUG_RETURN(TRUE);
972+
}
958973

959974
table->field[ET_FIELD_DB]->store(db.str, db.length, &my_charset_bin);
960975
table->field[ET_FIELD_NAME]->store(name.str, name.length, &my_charset_bin);

sql/share/errmsg-utf8.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7082,6 +7082,9 @@ ER_STOP_SLAVE_SQL_THREAD_TIMEOUT
70827082
ER_STOP_SLAVE_IO_THREAD_TIMEOUT
70837083
eng "STOP SLAVE command execution is incomplete: Slave IO thread got the stop signal, thread is busy, IO thread will stop once the current task is complete."
70847084

7085+
ER_TABLE_CORRUPT
7086+
eng "Operation cannot be performed. The table '%-.64s.%-.64s' is missing, corrupt or contains bad data."
7087+
70857088
#
70867089
# End of 5.6 error messages.
70877090
#

sql/sp.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,12 +414,19 @@ TABLE *open_proc_table_for_read(THD *thd, Open_tables_backup *backup)
414414

415415
if (open_system_tables_for_read(thd, &table, backup))
416416
DBUG_RETURN(NULL);
417+
418+
if (!table.table->key_info)
419+
{
420+
my_error(ER_TABLE_CORRUPT, MYF(0), table.table->s->db.str,
421+
table.table->s->table_name.str);
422+
goto err;
423+
}
417424

418425
if (!proc_table_intact.check(table.table, &proc_table_def))
419426
DBUG_RETURN(table.table);
420427

428+
err:
421429
close_system_tables(thd, backup);
422-
423430
DBUG_RETURN(NULL);
424431
}
425432

sql/sql_acl.cc

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2384,6 +2384,13 @@ bool change_password(THD *thd, const char *host, const char *user,
23842384
if (!(table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
23852385
DBUG_RETURN(1);
23862386

2387+
if (!table->key_info)
2388+
{
2389+
my_error(ER_TABLE_CORRUPT, MYF(0), table->s->db.str,
2390+
table->s->table_name.str);
2391+
DBUG_RETURN(1);
2392+
}
2393+
23872394
/*
23882395
This statement will be replicated as a statement, even when using
23892396
row-based replication. The flag will be reset at the end of the
@@ -2924,6 +2931,13 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER *combo,
29242931
DBUG_ENTER("replace_user_table");
29252932

29262933
mysql_mutex_assert_owner(&acl_cache->lock);
2934+
2935+
if (!table->key_info)
2936+
{
2937+
my_error(ER_TABLE_CORRUPT, MYF(0), table->s->db.str,
2938+
table->s->table_name.str);
2939+
goto end;
2940+
}
29272941

29282942
table->use_all_columns();
29292943
DBUG_ASSERT(combo->host.str != '\0');
@@ -3986,9 +4000,17 @@ static int replace_column_table(GRANT_TABLE *g_t,
39864000
int result=0;
39874001
uchar key[MAX_KEY_LENGTH];
39884002
uint key_prefix_length;
3989-
KEY_PART_INFO *key_part= table->key_info->key_part;
39904003
DBUG_ENTER("replace_column_table");
39914004

4005+
if (!table->key_info)
4006+
{
4007+
my_error(ER_TABLE_CORRUPT, MYF(0), table->s->db.str,
4008+
table->s->table_name.str);
4009+
DBUG_RETURN(-1);
4010+
}
4011+
4012+
KEY_PART_INFO *key_part= table->key_info->key_part;
4013+
39924014
table->use_all_columns();
39934015
table->field[0]->store(combo.host.str,combo.host.length,
39944016
system_charset_info);
@@ -7029,6 +7051,13 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop,
70297051
host_field->store(host_str, user_from->host.length, system_charset_info);
70307052
user_field->store(user_str, user_from->user.length, system_charset_info);
70317053

7054+
if (!table->key_info)
7055+
{
7056+
my_error(ER_TABLE_CORRUPT, MYF(0), table->s->db.str,
7057+
table->s->table_name.str);
7058+
DBUG_RETURN(-1);
7059+
}
7060+
70327061
key_prefix_length= (table->key_info->key_part[0].store_length +
70337062
table->key_info->key_part[1].store_length);
70347063
key_copy(user_key, table->record[0], table->key_info, key_prefix_length);
@@ -8012,6 +8041,13 @@ bool mysql_user_password_expire(THD *thd, List <LEX_USER> &list)
80128041
if (!(table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
80138042
DBUG_RETURN(true);
80148043

8044+
if (!table->key_info)
8045+
{
8046+
my_error(ER_TABLE_CORRUPT, MYF(0), table->s->db.str,
8047+
table->s->table_name.str);
8048+
DBUG_RETURN(true);
8049+
}
8050+
80158051
/*
80168052
This statement will be replicated as a statement, even when using
80178053
row-based replication. The flag will be reset at the end of the

sql/sql_plugin.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,13 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
19421942
if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
19431943
DBUG_RETURN(TRUE);
19441944

1945+
if (!table->key_info)
1946+
{
1947+
my_error(ER_TABLE_CORRUPT, MYF(0), table->s->db.str,
1948+
table->s->table_name.str);
1949+
DBUG_RETURN(TRUE);
1950+
}
1951+
19451952
/*
19461953
Pre-acquire audit plugins for events that may potentially occur
19471954
during [UN]INSTALL PLUGIN.

0 commit comments

Comments
 (0)