From aa74a314e482e801b8a893126989ba53d5c37477 Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Fri, 5 Sep 2008 14:44:16 +0400 Subject: [PATCH] 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 | 18 ++++++++++++++++++ mysql-test/t/status.test | 33 +++++++++++++++++++++++++++++++++ sql/sql_parse.cc | 6 ++++-- sql/sql_yacc.yy | 4 ---- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index b6f855d96cb..97547ff7c47 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -180,3 +180,21 @@ Variable_name Value Com_alter_function 0 Com_create_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; diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index bc629e9c86d..8bd9ee26b26 100644 --- a/mysql-test/t/status.test +++ b/mysql-test/t/status.test @@ -261,4 +261,37 @@ drop function f1; 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 diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index eb643184e1f..1e253b8c662 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2083,13 +2083,15 @@ mysql_execute_command(THD *thd) #endif case SQLCOM_SHOW_STATUS_PROC: 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; case SQLCOM_SHOW_STATUS: { system_status_var old_status_var= thd->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 */ thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index baecf716cdd..04f73cb963b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -10105,8 +10105,6 @@ show_param: { LEX *lex= Lex; 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)) MYSQL_YYABORT; } @@ -10114,8 +10112,6 @@ show_param: { LEX *lex= Lex; 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)) MYSQL_YYABORT; }