mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 11:01:52 +01:00
branches/5.1:
Fix Bug#34053: * In CREATE TABLE and DROP TABLE check whether the table in question is one of the magic innodb_monitor tables and whether the user has enough rights to mess with it before doing anything else. * Implement a mysql-test testcase. Approved by: Heikki
This commit is contained in:
parent
89fdcd3b18
commit
613bcee7ca
5 changed files with 129 additions and 20 deletions
|
@ -44,6 +44,10 @@ have disabled the InnoDB inlining in this file. */
|
|||
/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t
|
||||
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
|
||||
extern pthread_mutex_t LOCK_thread_count;
|
||||
|
||||
/* this is defined in mysql_priv.h inside #ifdef MYSQL_SERVER
|
||||
but we need it here */
|
||||
bool check_global_access(THD *thd, ulong want_access);
|
||||
#endif /* MYSQL_SERVER */
|
||||
|
||||
/** to protect innobase_open_files */
|
||||
|
@ -4645,6 +4649,12 @@ innodb_check_for_record_too_big_error(
|
|||
}
|
||||
}
|
||||
|
||||
/* limit innodb monitor access to users with PROCESS privilege.
|
||||
See http://bugs.mysql.com/32710 for expl. why we choose PROCESS. */
|
||||
#define IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(table_name, thd) \
|
||||
(row_is_magic_monitor_table(table_name) \
|
||||
&& check_global_access(thd, PROCESS_ACL))
|
||||
|
||||
/*********************************************************************
|
||||
Creates a table definition to an InnoDB database. */
|
||||
static
|
||||
|
@ -4681,6 +4691,12 @@ create_table_def(
|
|||
DBUG_ENTER("create_table_def");
|
||||
DBUG_PRINT("enter", ("table_name: %s", table_name));
|
||||
|
||||
ut_a(trx->mysql_thd != NULL);
|
||||
if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(table_name,
|
||||
(THD*) trx->mysql_thd)) {
|
||||
DBUG_RETURN(HA_ERR_GENERIC);
|
||||
}
|
||||
|
||||
n_cols = form->s->fields;
|
||||
|
||||
/* We pass 0 as the space id, and determine at a lower level the space
|
||||
|
@ -5221,6 +5237,14 @@ ha_innobase::delete_table(
|
|||
|
||||
DBUG_ENTER("ha_innobase::delete_table");
|
||||
|
||||
/* Strangely, MySQL passes the table name without the '.frm'
|
||||
extension, in contrast to ::create */
|
||||
normalize_table_name(norm_name, name);
|
||||
|
||||
if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(norm_name, thd)) {
|
||||
DBUG_RETURN(HA_ERR_GENERIC);
|
||||
}
|
||||
|
||||
/* Get the transaction associated with the current thd, or create one
|
||||
if not yet created */
|
||||
|
||||
|
@ -5254,11 +5278,6 @@ ha_innobase::delete_table(
|
|||
|
||||
assert(name_len < 1000);
|
||||
|
||||
/* Strangely, MySQL passes the table name without the '.frm'
|
||||
extension, in contrast to ::create */
|
||||
|
||||
normalize_table_name(norm_name, name);
|
||||
|
||||
/* Drop the table in InnoDB */
|
||||
|
||||
error = row_drop_table_for_mysql(norm_name, trx,
|
||||
|
|
|
@ -464,6 +464,16 @@ row_check_table_for_mysql(
|
|||
row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
|
||||
handle */
|
||||
|
||||
/*************************************************************************
|
||||
Determines if a table is a magic monitor table. */
|
||||
|
||||
ibool
|
||||
row_is_magic_monitor_table(
|
||||
/*=======================*/
|
||||
/* out: TRUE if monitor table */
|
||||
const char* table_name); /* in: name of the table, in the
|
||||
form database/table_name */
|
||||
|
||||
/* A struct describing a place for an individual column in the MySQL
|
||||
row format which is presented to the table handler in ha_innobase.
|
||||
This template struct is used to speed up row transformations between
|
||||
|
|
1
mysql-test/innodb_bug34053.result
Normal file
1
mysql-test/innodb_bug34053.result
Normal file
|
@ -0,0 +1 @@
|
|||
SET storage_engine=InnoDB;
|
49
mysql-test/innodb_bug34053.test
Normal file
49
mysql-test/innodb_bug34053.test
Normal file
|
@ -0,0 +1,49 @@
|
|||
#
|
||||
# Make sure http://bugs.mysql.com/34053 remains fixed.
|
||||
#
|
||||
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
SET storage_engine=InnoDB;
|
||||
|
||||
# we do not really care about what gets printed, we are only
|
||||
# interested in getting success or failure according to our
|
||||
# expectations
|
||||
-- disable_query_log
|
||||
-- disable_result_log
|
||||
|
||||
GRANT USAGE ON *.* TO 'shane'@'localhost' IDENTIFIED BY '12345';
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
-- connect (con1,localhost,shane,12345,)
|
||||
|
||||
-- connection con1
|
||||
-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;
|
||||
-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
CREATE TABLE innodb_mem_validate (a INT) ENGINE=INNODB;
|
||||
CREATE TABLE innodb_monitorx (a INT) ENGINE=INNODB;
|
||||
DROP TABLE innodb_monitorx;
|
||||
CREATE TABLE innodb_monito (a INT) ENGINE=INNODB;
|
||||
DROP TABLE innodb_monito;
|
||||
CREATE TABLE xinnodb_monitor (a INT) ENGINE=INNODB;
|
||||
DROP TABLE xinnodb_monitor;
|
||||
CREATE TABLE nnodb_monitor (a INT) ENGINE=INNODB;
|
||||
DROP TABLE nnodb_monitor;
|
||||
|
||||
-- connection default
|
||||
CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;
|
||||
CREATE TABLE innodb_mem_validate (a INT) ENGINE=INNODB;
|
||||
|
||||
-- connection con1
|
||||
-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
DROP TABLE innodb_monitor;
|
||||
-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
DROP TABLE innodb_mem_validate;
|
||||
|
||||
-- connection default
|
||||
DROP TABLE innodb_monitor;
|
||||
DROP TABLE innodb_mem_validate;
|
||||
DROP USER 'shane'@'localhost';
|
||||
|
||||
-- disconnect con1
|
|
@ -57,6 +57,12 @@ static const char S_innodb_tablespace_monitor[] = "innodb_tablespace_monitor";
|
|||
static const char S_innodb_table_monitor[] = "innodb_table_monitor";
|
||||
static const char S_innodb_mem_validate[] = "innodb_mem_validate";
|
||||
|
||||
/* Evaluates to true if str1 equals str2_onstack, used for comparing
|
||||
the above strings. */
|
||||
#define STR_EQ(str1, str1_len, str2_onstack) \
|
||||
((str1_len) == sizeof(str2_onstack) \
|
||||
&& memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
|
||||
|
||||
/***********************************************************************
|
||||
Determine if the given name is a name reserved for MySQL system tables. */
|
||||
static
|
||||
|
@ -1809,9 +1815,7 @@ row_create_table_for_mysql(
|
|||
table_name++;
|
||||
table_name_len = strlen(table_name) + 1;
|
||||
|
||||
if (table_name_len == sizeof S_innodb_monitor
|
||||
&& !memcmp(table_name, S_innodb_monitor,
|
||||
sizeof S_innodb_monitor)) {
|
||||
if (STR_EQ(table_name, table_name_len, S_innodb_monitor)) {
|
||||
|
||||
/* Table equals "innodb_monitor":
|
||||
start monitor prints */
|
||||
|
@ -1822,28 +1826,24 @@ row_create_table_for_mysql(
|
|||
of InnoDB monitor prints */
|
||||
|
||||
os_event_set(srv_lock_timeout_thread_event);
|
||||
} else if (table_name_len == sizeof S_innodb_lock_monitor
|
||||
&& !memcmp(table_name, S_innodb_lock_monitor,
|
||||
sizeof S_innodb_lock_monitor)) {
|
||||
} else if (STR_EQ(table_name, table_name_len,
|
||||
S_innodb_lock_monitor)) {
|
||||
|
||||
srv_print_innodb_monitor = TRUE;
|
||||
srv_print_innodb_lock_monitor = TRUE;
|
||||
os_event_set(srv_lock_timeout_thread_event);
|
||||
} else if (table_name_len == sizeof S_innodb_tablespace_monitor
|
||||
&& !memcmp(table_name, S_innodb_tablespace_monitor,
|
||||
sizeof S_innodb_tablespace_monitor)) {
|
||||
} else if (STR_EQ(table_name, table_name_len,
|
||||
S_innodb_tablespace_monitor)) {
|
||||
|
||||
srv_print_innodb_tablespace_monitor = TRUE;
|
||||
os_event_set(srv_lock_timeout_thread_event);
|
||||
} else if (table_name_len == sizeof S_innodb_table_monitor
|
||||
&& !memcmp(table_name, S_innodb_table_monitor,
|
||||
sizeof S_innodb_table_monitor)) {
|
||||
} else if (STR_EQ(table_name, table_name_len,
|
||||
S_innodb_table_monitor)) {
|
||||
|
||||
srv_print_innodb_table_monitor = TRUE;
|
||||
os_event_set(srv_lock_timeout_thread_event);
|
||||
} else if (table_name_len == sizeof S_innodb_mem_validate
|
||||
&& !memcmp(table_name, S_innodb_mem_validate,
|
||||
sizeof S_innodb_mem_validate)) {
|
||||
} else if (STR_EQ(table_name, table_name_len,
|
||||
S_innodb_mem_validate)) {
|
||||
/* We define here a debugging feature intended for
|
||||
developers */
|
||||
|
||||
|
@ -4130,3 +4130,33 @@ row_check_table_for_mysql(
|
|||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Determines if a table is a magic monitor table. */
|
||||
|
||||
ibool
|
||||
row_is_magic_monitor_table(
|
||||
/*=======================*/
|
||||
/* out: TRUE if monitor table */
|
||||
const char* table_name) /* in: name of the table, in the
|
||||
form database/table_name */
|
||||
{
|
||||
const char* name; /* table_name without database/ */
|
||||
ulint len;
|
||||
|
||||
name = strchr(table_name, '/');
|
||||
ut_a(name != NULL);
|
||||
name++;
|
||||
len = strlen(name) + 1;
|
||||
|
||||
if (STR_EQ(name, len, S_innodb_monitor)
|
||||
|| STR_EQ(name, len, S_innodb_lock_monitor)
|
||||
|| STR_EQ(name, len, S_innodb_tablespace_monitor)
|
||||
|| STR_EQ(name, len, S_innodb_table_monitor)
|
||||
|| STR_EQ(name, len, S_innodb_mem_validate)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue