Search
j0ke.net Open Build Service
>
Projects
>
internetx
:
mysql5
>
mysql-5.0.26
> mysql-5.0.26-CVE-2007-2692.patch
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File mysql-5.0.26-CVE-2007-2692.patch of Package mysql-5.0.26
from http://mysql.bkbits.net:8080/mysql-5.0-community/?PAGE=gnupatch&REV=1.2410.5.12 --- mysql-test/r/grant.result | 75 ++++++++++++++++++++ mysql-test/t/grant.test | 144 +++++++++++++++++++++++++++++++++++++++ sql/mysql_priv.h | 2 sql/sql_db.cc | 43 +++++------ sql/sql_parse.cc | 167 +++++++++++++++++++++++++++++++++------------- sql/sql_show.cc | 2 6 files changed, 362 insertions(+), 71 deletions(-) --- mysql-test/r/grant.result.orig +++ mysql-test/r/grant.result @@ -1000,4 +1000,79 @@ f1 f2 DROP DATABASE db27878; use test; DROP TABLE t1; +DROP DATABASE IF EXISTS mysqltest1; +DROP DATABASE IF EXISTS mysqltest2; +CREATE DATABASE mysqltest1; +CREATE DATABASE mysqltest2; +GRANT ALL PRIVILEGES ON mysqltest1.* TO mysqltest_1@localhost; +GRANT SELECT ON mysqltest2.* TO mysqltest_1@localhost; +CREATE PROCEDURE mysqltest1.p1() SQL SECURITY INVOKER +SELECT 1; + +---> connection: bug27337_con1 +CREATE TABLE t1(c INT); +ERROR 42000: CREATE command denied to user 'mysqltest_1'@'localhost' for table 't1' +CALL mysqltest1.p1(); +1 +1 +CREATE TABLE t1(c INT); +ERROR 42000: CREATE command denied to user 'mysqltest_1'@'localhost' for table 't1' + +---> connection: bug27337_con2 +CREATE TABLE t1(c INT); +ERROR 42000: CREATE command denied to user 'mysqltest_1'@'localhost' for table 't1' +SHOW TABLES; +Tables_in_mysqltest2 + +---> connection: default +DROP DATABASE mysqltest1; +DROP DATABASE mysqltest2; +DROP USER mysqltest_1@localhost; +DROP DATABASE IF EXISTS mysqltest1; +DROP DATABASE IF EXISTS mysqltest2; +CREATE DATABASE mysqltest1; +CREATE DATABASE mysqltest2; +CREATE TABLE mysqltest1.t1(c INT); +CREATE TABLE mysqltest2.t2(c INT); +GRANT SELECT ON mysqltest1.t1 TO mysqltest_1@localhost; +GRANT SELECT ON mysqltest2.t2 TO mysqltest_2@localhost; + +---> connection: bug27337_con1 +SHOW TABLES FROM mysqltest1; +Tables_in_mysqltest1 +t1 +PREPARE stmt1 FROM 'SHOW TABLES FROM mysqltest1'; +EXECUTE stmt1; +Tables_in_mysqltest1 +t1 + +---> connection: bug27337_con2 +SHOW COLUMNS FROM mysqltest2.t2; +Field Type Null Key Default Extra +c int(11) YES NULL +PREPARE stmt2 FROM 'SHOW COLUMNS FROM mysqltest2.t2'; +EXECUTE stmt2; +Field Type Null Key Default Extra +c int(11) YES NULL + +---> connection: default +REVOKE SELECT ON mysqltest1.t1 FROM mysqltest_1@localhost; +REVOKE SELECT ON mysqltest2.t2 FROM mysqltest_2@localhost; + +---> connection: bug27337_con1 +SHOW TABLES FROM mysqltest1; +ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysqltest1' +EXECUTE stmt1; +ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysqltest1' + +---> connection: bug27337_con2 +SHOW COLUMNS FROM mysqltest2.t2; +ERROR 42000: SELECT command denied to user 'mysqltest_2'@'localhost' for table 't2' +EXECUTE stmt2; +ERROR 42000: SELECT command denied to user 'mysqltest_2'@'localhost' for table 't2' + +---> connection: default +DROP DATABASE mysqltest1; +DROP DATABASE mysqltest2; +DROP USER mysqltest_1@localhost; End of 5.0 tests --- mysql-test/t/grant.test.orig +++ mysql-test/t/grant.test @@ -911,4 +911,148 @@ DROP DATABASE db27878; use test; DROP TABLE t1; +# +# BUG#27337: Privileges are not restored properly. +# +# Actually, the patch for this bugs fixes two problems. So, here are two test +# cases. + +# Test case 1: privileges are not restored properly after calling a stored +# routine defined with SQL SECURITY INVOKER clause. + +# Prepare. + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest1; +DROP DATABASE IF EXISTS mysqltest2; +--enable_warnings + +CREATE DATABASE mysqltest1; +CREATE DATABASE mysqltest2; + +GRANT ALL PRIVILEGES ON mysqltest1.* TO mysqltest_1@localhost; +GRANT SELECT ON mysqltest2.* TO mysqltest_1@localhost; + +CREATE PROCEDURE mysqltest1.p1() SQL SECURITY INVOKER + SELECT 1; + +# Test. + +--connect (bug27337_con1,localhost,mysqltest_1,,mysqltest2) +--echo +--echo ---> connection: bug27337_con1 + +--error ER_TABLEACCESS_DENIED_ERROR +CREATE TABLE t1(c INT); + +CALL mysqltest1.p1(); + +--error ER_TABLEACCESS_DENIED_ERROR +CREATE TABLE t1(c INT); + +--disconnect bug27337_con1 + +--connect (bug27337_con2,localhost,mysqltest_1,,mysqltest2) +--echo +--echo ---> connection: bug27337_con2 + +--error ER_TABLEACCESS_DENIED_ERROR +CREATE TABLE t1(c INT); + +SHOW TABLES; + +# Cleanup. + +--connection default +--echo +--echo ---> connection: default + +--disconnect bug27337_con2 + +DROP DATABASE mysqltest1; +DROP DATABASE mysqltest2; + +DROP USER mysqltest_1@localhost; + +# Test case 2: priveleges are not checked properly for prepared statements. + +# Prepare. + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest1; +DROP DATABASE IF EXISTS mysqltest2; +--enable_warnings + +CREATE DATABASE mysqltest1; +CREATE DATABASE mysqltest2; + +CREATE TABLE mysqltest1.t1(c INT); +CREATE TABLE mysqltest2.t2(c INT); + +GRANT SELECT ON mysqltest1.t1 TO mysqltest_1@localhost; +GRANT SELECT ON mysqltest2.t2 TO mysqltest_2@localhost; + +# Test. + +--connect (bug27337_con1,localhost,mysqltest_1,,mysqltest1) +--echo +--echo ---> connection: bug27337_con1 + +SHOW TABLES FROM mysqltest1; + +PREPARE stmt1 FROM 'SHOW TABLES FROM mysqltest1'; + +EXECUTE stmt1; + +--connect (bug27337_con2,localhost,mysqltest_2,,mysqltest2) +--echo +--echo ---> connection: bug27337_con2 + +SHOW COLUMNS FROM mysqltest2.t2; + +PREPARE stmt2 FROM 'SHOW COLUMNS FROM mysqltest2.t2'; + +EXECUTE stmt2; + +--connection default +--echo +--echo ---> connection: default + +REVOKE SELECT ON mysqltest1.t1 FROM mysqltest_1@localhost; +REVOKE SELECT ON mysqltest2.t2 FROM mysqltest_2@localhost; + +--connection bug27337_con1 +--echo +--echo ---> connection: bug27337_con1 + +--error ER_DBACCESS_DENIED_ERROR +SHOW TABLES FROM mysqltest1; + +--error ER_DBACCESS_DENIED_ERROR +EXECUTE stmt1; + +--connection bug27337_con2 +--echo +--echo ---> connection: bug27337_con2 + +--error ER_TABLEACCESS_DENIED_ERROR +SHOW COLUMNS FROM mysqltest2.t2; + +--error ER_TABLEACCESS_DENIED_ERROR +EXECUTE stmt2; + +# Cleanup. + +--connection default +--echo +--echo ---> connection: default + +--disconnect bug27337_con2 + +DROP DATABASE mysqltest1; +DROP DATABASE mysqltest2; + +DROP USER mysqltest_1@localhost; + + --echo End of 5.0 tests --- sql/mysql_priv.h.orig +++ sql/mysql_priv.h @@ -908,6 +908,8 @@ int fill_schema_schema_privileges(THD *t int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond); bool get_schema_tables_result(JOIN *join); +enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table); + #define is_schema_db(X) \ !my_strcasecmp(system_charset_info, information_schema_name.str, (X)) --- sql/sql_db.cc.orig +++ sql/sql_db.cc @@ -1304,30 +1304,27 @@ bool mysql_change_db(THD *thd, const LEX DBUG_PRINT("info",("Use database: %s", new_db_file_name.str)); #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (!force_switch) /* FIXME: this is BUG#27337. */ + db_access= + test_all_bits(sctx->master_access, DB_ACLS) ? + DB_ACLS : + acl_get(sctx->host, + sctx->ip, + sctx->priv_user, + new_db_file_name.str, + FALSE) | sctx->master_access; + + if (!force_switch && + !(db_access & DB_ACLS) && + (!grant_option || check_grant_db(thd, new_db_file_name.str))) { - db_access= - test_all_bits(sctx->master_access, DB_ACLS) ? - DB_ACLS : - acl_get(sctx->host, - sctx->ip, - sctx->priv_user, - new_db_file_name.str, - FALSE) | sctx->master_access; - - if (!force_switch && - !(db_access & DB_ACLS) && - (!grant_option || check_grant_db(thd, new_db_file_name.str))) - { - my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - sctx->priv_user, - sctx->priv_host, - new_db_file_name.str); - mysql_log.write(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR), - sctx->priv_user, sctx->priv_host, new_db_file_name.str); - my_free(new_db_file_name.str, MYF(0)); - DBUG_RETURN(TRUE); - } + my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), + sctx->priv_user, + sctx->priv_host, + new_db_file_name.str); + mysql_log.write(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR), + sctx->priv_user, sctx->priv_host, new_db_file_name.str); + my_free(new_db_file_name.str, MYF(0)); + DBUG_RETURN(TRUE); } #endif --- sql/sql_parse.cc.orig +++ sql/sql_parse.cc @@ -2210,7 +2210,8 @@ int prepare_schema_table(THD *thd, LEX * enum enum_schema_tables schema_table_idx) { DBUG_ENTER("prepare_schema_table"); - SELECT_LEX *sel= 0; + SELECT_LEX *schema_select_lex= NULL; + switch (schema_table_idx) { case SCH_SCHEMATA: #if defined(DONT_ALLOW_SHOW_COMMANDS) @@ -2218,11 +2219,9 @@ int prepare_schema_table(THD *thd, LEX * ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */ DBUG_RETURN(1); #else - if ((specialflag & SPECIAL_SKIP_SHOW_DB) && - check_global_access(thd, SHOW_DB_ACL)) - DBUG_RETURN(1); break; #endif + case SCH_TABLE_NAMES: case SCH_TABLES: case SCH_VIEWS: @@ -2232,32 +2231,25 @@ int prepare_schema_table(THD *thd, LEX * ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */ DBUG_RETURN(1); #else + if (lex->select_lex.db == NULL && + thd->copy_db_to(&lex->select_lex.db, NULL)) { - char *db; - if (lex->select_lex.db == NULL && - thd->copy_db_to(&lex->select_lex.db, 0)) - { - DBUG_RETURN(1); - } - db= lex->select_lex.db; - remove_escape(db); // Fix escaped '_' - if (check_db_name(db)) - { - my_error(ER_WRONG_DB_NAME, MYF(0), db); - DBUG_RETURN(1); - } - if (check_access(thd, SELECT_ACL, db, &thd->col_access, 0, 0, - is_schema_db(db))) - DBUG_RETURN(1); /* purecov: inspected */ - if (!thd->col_access && check_grant_db(thd,db)) - { - my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - thd->security_ctx->priv_user, thd->security_ctx->priv_host, - db); - DBUG_RETURN(1); - } - break; + DBUG_RETURN(1); + } + + schema_select_lex= new SELECT_LEX(); + schema_select_lex->db= lex->select_lex.db; + schema_select_lex->table_list.first= NULL; + remove_escape(schema_select_lex->db); // Fix escaped '_' + + if (check_db_name(schema_select_lex->db)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), schema_select_lex->db); + DBUG_RETURN(1); } + + + break; #endif case SCH_COLUMNS: case SCH_STATISTICS: @@ -2266,28 +2258,23 @@ int prepare_schema_table(THD *thd, LEX * ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */ DBUG_RETURN(1); #else - if (table_ident) { + DBUG_ASSERT(table_ident); + TABLE_LIST **query_tables_last= lex->query_tables_last; - sel= new SELECT_LEX(); + schema_select_lex= new SELECT_LEX(); /* 'parent_lex' is used in init_query() so it must be before it. */ - sel->parent_lex= lex; - sel->init_query(); - if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ, - (List<String> *) 0, (List<String> *) 0)) + schema_select_lex->parent_lex= lex; + schema_select_lex->init_query(); + if (!schema_select_lex->add_table_to_list(thd, table_ident, 0, 0, TL_READ, + (List<String> *) 0, (List<String> *) 0)) DBUG_RETURN(1); lex->query_tables_last= query_tables_last; - TABLE_LIST *table_list= (TABLE_LIST*) sel->table_list.first; - char *db= table_list->db; - remove_escape(db); // Fix escaped '_' - remove_escape(table_list->table_name); - if (check_access(thd,SELECT_ACL | EXTRA_ACL,db, - &table_list->grant.privilege, 0, 0, - test(table_list->schema_table))) - DBUG_RETURN(1); /* purecov: inspected */ - if (grant_option && check_grant(thd, SELECT_ACL, table_list, 2, - UINT_MAX, 0)) - DBUG_RETURN(1); + + TABLE_LIST *dst_table= (TABLE_LIST*) schema_select_lex->table_list.first; + remove_escape(dst_table->db); // Fix escaped '_' + remove_escape(dst_table->table_name); + break; } #endif @@ -2314,7 +2301,7 @@ int prepare_schema_table(THD *thd, LEX * DBUG_RETURN(1); } TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first; - table_list->schema_select_lex= sel; + table_list->schema_select_lex= schema_select_lex; table_list->schema_table_reformed= 1; statistic_increment(thd->status_var.com_stat[lex->orig_sql_command], &LOCK_status); @@ -5318,6 +5305,83 @@ bool check_global_access(THD *thd, ulong } +static bool check_show_access(THD *thd, TABLE_LIST *table) +{ + switch (get_schema_table_idx(table->schema_table)) + { + case SCH_SCHEMATA: + return (specialflag & SPECIAL_SKIP_SHOW_DB) && + check_global_access(thd, SHOW_DB_ACL); + + case SCH_TABLE_NAMES: + case SCH_TABLES: + case SCH_VIEWS: + case SCH_TRIGGERS: + { + const char *dst_db_name= table->schema_select_lex->db; + + DBUG_ASSERT(dst_db_name); + + if (check_access(thd, SELECT_ACL, dst_db_name, + &thd->col_access, FALSE, FALSE, + is_schema_db(dst_db_name))) + { + return TRUE; + } + + if (!thd->col_access && check_grant_db(thd, dst_db_name)) + { + my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), + thd->security_ctx->priv_user, + thd->security_ctx->priv_host, + dst_db_name); + return TRUE; + } + + return FALSE; + } + + case SCH_COLUMNS: + case SCH_STATISTICS: + { + TABLE_LIST *dst_table= + (TABLE_LIST *) table->schema_select_lex->table_list.first; + + DBUG_ASSERT(dst_table); + + if (check_access(thd, SELECT_ACL | EXTRA_ACL, + dst_table->db, + &dst_table->grant.privilege, + FALSE, FALSE, + test(dst_table->schema_table))) + { + return FALSE; + } + + return grant_option && + check_grant(thd, SELECT_ACL, dst_table, 2, UINT_MAX, FALSE); + } + + case SCH_OPEN_TABLES: + case SCH_VARIABLES: + case SCH_STATUS: + case SCH_PROCEDURES: + case SCH_CHARSETS: + case SCH_COLLATIONS: + case SCH_COLLATION_CHARACTER_SET_APPLICABILITY: + case SCH_USER_PRIVILEGES: + case SCH_SCHEMA_PRIVILEGES: + case SCH_TABLE_PRIVILEGES: + case SCH_COLUMN_PRIVILEGES: + case SCH_TABLE_CONSTRAINTS: + case SCH_KEY_COLUMN_USAGE: + break; + } + + return FALSE; +} + + /* Check the privilege for all used tables. @@ -5376,7 +5440,16 @@ check_table_access(THD *thd, ulong want_ Remove SHOW_VIEW_ACL, because it will be checked during making view */ tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); - if (tables->derived || tables->schema_table || + + if (tables->schema_table_reformed) + { + if (check_show_access(thd, tables)) + goto deny; + + continue; + } + + if (tables->derived || (tables->table && (int)tables->table->s->tmp_table) || my_tz_check_n_skip_implicit_tables(&tables, thd->lex->time_zone_tables_used)) --- sql/sql_show.cc.orig +++ sql/sql_show.cc @@ -2140,7 +2140,7 @@ int get_all_tables(THD *thd, TABLE_LIST */ thd->reset_n_backup_open_tables_state(&open_tables_state_backup); - if (lsel) + if (lsel && lsel->table_list.first) { TABLE_LIST *show_table_list= (TABLE_LIST*) lsel->table_list.first; bool res;