Commit 613bcee7 authored by vasil's avatar vasil

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
parent 89fdcd3b
......@@ -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
......
SET storage_engine=InnoDB;
#
# 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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment