Commit 1588c116 authored by Evgeny Potemkin's avatar Evgeny Potemkin

Bug#37908: Skipped access right check caused server crash.

      
The check_table_access function initializes per-table grant info and performs
access rights check. It wasn't called for SHOW STATUS statement thus left
grants info uninitialized. In some cases this led to server crash. In other
cases it allowed a user to check for presence/absence of arbitrary values in
any tables.
      
Now the check_table_access function is called prior to the statement
processing.


mysql-test/r/status.result:
  Added a test case for the bug#37908.
mysql-test/t/status.test:
  Added a test case for the bug#37908.
sql/sql_parse.cc:
  Bug#37908: Skipped access right check caused server crash.
  Now the check_table_access function is called when the SHOW STATUS statement
  uses any table except information.STATUS.
sql/sql_yacc.yy:
  Bug#37908: Skipped access right check caused server crash.
  For the SHOW PROCEDURE/FUNCTION STATUS the 'mysql.proc' table isn't added
  to the table list anymore as there is no need.
parent dbbb48c3
...@@ -180,3 +180,21 @@ Variable_name Value ...@@ -180,3 +180,21 @@ Variable_name Value
Com_alter_function 0 Com_alter_function 0
Com_create_function 1 Com_create_function 1
Com_drop_function 1 Com_drop_function 1
create database db37908;
create table db37908.t1(f1 int);
insert into db37908.t1 values(1);
grant usage,execute on test.* to mysqltest_1@localhost;
create procedure proc37908() begin select 1; end |
create function func37908() returns int sql security invoker
return (select * from db37908.t1 limit 1)|
select * from db37908.t1;
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
show status where variable_name ='uptime' and 2 in (select * from db37908.t1);
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
show procedure status where name ='proc37908' and 1 in (select f1 from db37908.t1);
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
show function status where name ='func37908' and 1 in (select func37908());
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
drop database db37908;
drop procedure proc37908;
drop function func37908;
...@@ -261,4 +261,37 @@ drop function f1; ...@@ -261,4 +261,37 @@ drop function f1;
show status like 'Com%function'; show status like 'Com%function';
#
# Bug#37908: Skipped access right check caused server crash.
#
connect (root, localhost, root,,test);
connection root;
--disable_warnings
create database db37908;
--enable_warnings
create table db37908.t1(f1 int);
insert into db37908.t1 values(1);
grant usage,execute on test.* to mysqltest_1@localhost;
delimiter |;
create procedure proc37908() begin select 1; end |
create function func37908() returns int sql security invoker
return (select * from db37908.t1 limit 1)|
delimiter ;|
connect (user1,localhost,mysqltest_1,,test);
connection user1;
--error 1142
select * from db37908.t1;
--error 1142
show status where variable_name ='uptime' and 2 in (select * from db37908.t1);
--error 1142
show procedure status where name ='proc37908' and 1 in (select f1 from db37908.t1);
--error 1142
show function status where name ='func37908' and 1 in (select func37908());
connection root;
drop database db37908;
drop procedure proc37908;
drop function func37908;
# End of 5.1 tests # End of 5.1 tests
...@@ -2083,13 +2083,15 @@ mysql_execute_command(THD *thd) ...@@ -2083,13 +2083,15 @@ mysql_execute_command(THD *thd)
#endif #endif
case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC: case SQLCOM_SHOW_STATUS_FUNC:
res= execute_sqlcom_select(thd, all_tables); if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
res= execute_sqlcom_select(thd, all_tables);
break; break;
case SQLCOM_SHOW_STATUS: case SQLCOM_SHOW_STATUS:
{ {
system_status_var old_status_var= thd->status_var; system_status_var old_status_var= thd->status_var;
thd->initial_status_var= &old_status_var; thd->initial_status_var= &old_status_var;
res= execute_sqlcom_select(thd, all_tables); if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
res= execute_sqlcom_select(thd, all_tables);
/* Don't log SHOW STATUS commands to slow query log */ /* Don't log SHOW STATUS commands to slow query log */
thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
SERVER_QUERY_NO_GOOD_INDEX_USED); SERVER_QUERY_NO_GOOD_INDEX_USED);
......
...@@ -10105,8 +10105,6 @@ show_param: ...@@ -10105,8 +10105,6 @@ show_param:
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_STATUS_PROC; lex->sql_command= SQLCOM_SHOW_STATUS_PROC;
if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
MYSQL_YYABORT;
if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES)) if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -10114,8 +10112,6 @@ show_param: ...@@ -10114,8 +10112,6 @@ show_param:
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_STATUS_FUNC; lex->sql_command= SQLCOM_SHOW_STATUS_FUNC;
if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
MYSQL_YYABORT;
if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES)) if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
......
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