Commit dfda7855 authored by thek@adventure.(none)'s avatar thek@adventure.(none)

Merge adventure.(none):/home/thek/Development/cpp/bug27440/my51-bug27440

into  adventure.(none):/home/thek/Development/cpp/mysql-5.1-runtime
parents aa5786eb 049ea314
......@@ -97,3 +97,36 @@ Note 1051 Unknown table 'ttt'
set global read_only=0;
drop table t1,t2;
drop user test@localhost;
#
# Bug #27440 read_only allows create and drop database
#
set global read_only= 1;
drop database if exists mysqltest_db1;
drop database if exists mysqltest_db2;
delete from mysql.user where User like 'mysqltest_%';
delete from mysql.db where User like 'mysqltest_%';
delete from mysql.tables_priv where User like 'mysqltest_%';
delete from mysql.columns_priv where User like 'mysqltest_%';
flush privileges;
grant all on mysqltest_db2.* to `mysqltest_u1`@`%`;
create database mysqltest_db1;
grant all on mysqltest_db1.* to `mysqltest_u1`@`%`;
flush privileges;
show grants for current_user();
Grants for mysqltest_u1@%
GRANT USAGE ON *.* TO 'mysqltest_u1'@'%'
GRANT ALL PRIVILEGES ON `mysqltest_db2`.* TO 'mysqltest_u1'@'%'
GRANT ALL PRIVILEGES ON `mysqltest_db1`.* TO 'mysqltest_u1'@'%'
create database mysqltest_db2;
ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement
show databases like '%mysqltest_db2%';
Database (%mysqltest_db2%)
drop database mysqltest_db1;
ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement
delete from mysql.user where User like 'mysqltest_%';
delete from mysql.db where User like 'mysqltest_%';
delete from mysql.tables_priv where User like 'mysqltest_%';
delete from mysql.columns_priv where User like 'mysqltest_%';
flush privileges;
drop database mysqltest_db1;
set global read_only=0;
......@@ -225,3 +225,39 @@ connection default;
set global read_only=0;
drop table t1,t2;
drop user test@localhost;
--echo #
--echo # Bug #27440 read_only allows create and drop database
--echo #
set global read_only= 1;
--disable_warnings
drop database if exists mysqltest_db1;
drop database if exists mysqltest_db2;
--enable_warnings
delete from mysql.user where User like 'mysqltest_%';
delete from mysql.db where User like 'mysqltest_%';
delete from mysql.tables_priv where User like 'mysqltest_%';
delete from mysql.columns_priv where User like 'mysqltest_%';
flush privileges;
grant all on mysqltest_db2.* to `mysqltest_u1`@`%`;
create database mysqltest_db1;
grant all on mysqltest_db1.* to `mysqltest_u1`@`%`;
flush privileges;
connect (con_bug27440,127.0.0.1,mysqltest_u1,,test,$MASTER_MYPORT,);
connection con_bug27440;
show grants for current_user();
--error ER_OPTION_PREVENTS_STATEMENT
create database mysqltest_db2;
show databases like '%mysqltest_db2%';
--error ER_OPTION_PREVENTS_STATEMENT
drop database mysqltest_db1;
disconnect con_bug27440;
connection default;
delete from mysql.user where User like 'mysqltest_%';
delete from mysql.db where User like 'mysqltest_%';
delete from mysql.tables_priv where User like 'mysqltest_%';
delete from mysql.columns_priv where User like 'mysqltest_%';
flush privileges;
drop database mysqltest_db1;
set global read_only=0;
......@@ -767,6 +767,74 @@ bool do_command(THD *thd)
#endif /* EMBEDDED_LIBRARY */
/**
@brief Determine if an attempt to update a non-temporary table while the
read-only option was enabled has been made.
This is a helper function to mysql_execute_command.
@note SQLCOM_MULTI_UPDATE is an exception and delt with elsewhere.
@see mysql_execute_command
@returns Status code
@retval TRUE The statement should be denied.
@retval FALSE The statement isn't updating any relevant tables.
*/
static my_bool deny_updates_if_read_only_option(THD *thd,
TABLE_LIST *all_tables)
{
DBUG_ENTER("deny_updates_if_read_only_option");
if (!opt_readonly)
DBUG_RETURN(FALSE);
LEX *lex= thd->lex;
const my_bool user_is_super=
((ulong)(thd->security_ctx->master_access & SUPER_ACL) ==
(ulong)SUPER_ACL);
if (user_is_super)
DBUG_RETURN(FALSE);
if (!(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA))
DBUG_RETURN(FALSE);
/* Multi update is an exception and is dealt with later. */
if (lex->sql_command == SQLCOM_UPDATE_MULTI)
DBUG_RETURN(FALSE);
const my_bool create_temp_tables=
(lex->sql_command == SQLCOM_CREATE_TABLE) &&
(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE);
const my_bool drop_temp_tables=
(lex->sql_command == SQLCOM_DROP_TABLE) &&
lex->drop_temporary;
const my_bool update_real_tables=
some_non_temp_table_to_be_updated(thd, all_tables) &&
!(create_temp_tables || drop_temp_tables);
const my_bool create_or_drop_databases=
(lex->sql_command == SQLCOM_CREATE_DB) ||
(lex->sql_command == SQLCOM_DROP_DB);
if (update_real_tables || create_or_drop_databases)
{
/*
An attempt was made to modify one or more non-temporary tables.
*/
DBUG_RETURN(TRUE);
}
/* Assuming that only temporary tables are modified. */
DBUG_RETURN(FALSE);
}
/*
Perform one connection-level (COM_XXXX) command.
......@@ -1869,14 +1937,7 @@ mysql_execute_command(THD *thd)
When option readonly is set deny operations which change non-temporary
tables. Except for the replication thread and the 'super' users.
*/
if (opt_readonly &&
!(thd->security_ctx->master_access & SUPER_ACL) &&
(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) &&
!((lex->sql_command == SQLCOM_CREATE_TABLE) &&
(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) &&
!((lex->sql_command == SQLCOM_DROP_TABLE) && lex->drop_temporary) &&
((lex->sql_command != SQLCOM_UPDATE_MULTI) &&
some_non_temp_table_to_be_updated(thd, all_tables)))
if (deny_updates_if_read_only_option(thd, all_tables))
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
DBUG_RETURN(-1);
......
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