Commit dd9a0770 authored by evgen@sunlight.local's avatar evgen@sunlight.local

Fixed bug#21261: Wrong access rights was required for an insert into a view

SELECT right instead of INSERT right was required for an insert into to a view.
This wrong behaviour appeared after the fix for bug #20989. Its intention was
to ask only SELECT right for all tables except the very first for a complex
INSERT query. But that patch has done it in a wrong way and lead to asking 
a wrong access right for an insert into a view.

The setup_tables_and_check_access() function now accepts two want_access
parameters. One will be used for the first table and the second for other
tables.
parent 5f3d231f
...@@ -2850,3 +2850,22 @@ Tables_in_test ...@@ -2850,3 +2850,22 @@ Tables_in_test
t1 t1
DROP TABLE t1; DROP TABLE t1;
DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1;
CREATE DATABASE bug21261DB;
CREATE TABLE t1 (x INT);
CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT x FROM t1;
GRANT INSERT, UPDATE ON v1 TO 'user21261'@'localhost';
GRANT INSERT, UPDATE ON t1 TO 'user21261'@'localhost';
CREATE TABLE t2 (y INT);
GRANT SELECT ON t2 TO 'user21261'@'localhost';
INSERT INTO v1 (x) VALUES (5);
UPDATE v1 SET x=1;
GRANT SELECT ON v1 TO 'user21261'@'localhost';
UPDATE v1,t2 SET x=1 WHERE x=y;
SELECT * FROM t1;
x
1
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user21261'@'localhost';
DROP USER 'user21261'@'localhost';
DROP VIEW v1;
DROP TABLE t1;
DROP DATABASE bug21261DB;
...@@ -2718,3 +2718,33 @@ DROP TABLE t1; ...@@ -2718,3 +2718,33 @@ DROP TABLE t1;
--disable_warnings --disable_warnings
DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1;
--enable_warnings --enable_warnings
#
# Bug #21261: Wrong access rights was required for an insert to a view
#
CREATE DATABASE bug21261DB;
CONNECT (root,localhost,root,,bug21261DB);
CONNECTION root;
CREATE TABLE t1 (x INT);
CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT x FROM t1;
GRANT INSERT, UPDATE ON v1 TO 'user21261'@'localhost';
GRANT INSERT, UPDATE ON t1 TO 'user21261'@'localhost';
CREATE TABLE t2 (y INT);
GRANT SELECT ON t2 TO 'user21261'@'localhost';
CONNECT (user21261, localhost, user21261,, bug21261DB);
CONNECTION user21261;
INSERT INTO v1 (x) VALUES (5);
UPDATE v1 SET x=1;
CONNECTION root;
GRANT SELECT ON v1 TO 'user21261'@'localhost';
CONNECTION user21261;
UPDATE v1,t2 SET x=1 WHERE x=y;
CONNECTION root;
SELECT * FROM t1;
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user21261'@'localhost';
DROP USER 'user21261'@'localhost';
DROP VIEW v1;
DROP TABLE t1;
DROP DATABASE bug21261DB;
...@@ -974,6 +974,7 @@ bool setup_tables_and_check_access (THD *thd, ...@@ -974,6 +974,7 @@ bool setup_tables_and_check_access (THD *thd,
TABLE_LIST *tables, Item **conds, TABLE_LIST *tables, Item **conds,
TABLE_LIST **leaves, TABLE_LIST **leaves,
bool select_insert, bool select_insert,
ulong want_access_first,
ulong want_access); ulong want_access);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num); List<Item> *sum_func_list, uint wild_num);
......
...@@ -4563,9 +4563,11 @@ bool setup_tables_and_check_access(THD *thd, ...@@ -4563,9 +4563,11 @@ bool setup_tables_and_check_access(THD *thd,
TABLE_LIST *tables, TABLE_LIST *tables,
Item **conds, TABLE_LIST **leaves, Item **conds, TABLE_LIST **leaves,
bool select_insert, bool select_insert,
ulong want_access_first,
ulong want_access) ulong want_access)
{ {
TABLE_LIST *leaves_tmp = NULL; TABLE_LIST *leaves_tmp = NULL;
bool first_table= true;
if (setup_tables (thd, context, from_clause, tables, conds, if (setup_tables (thd, context, from_clause, tables, conds,
&leaves_tmp, select_insert)) &leaves_tmp, select_insert))
...@@ -4575,13 +4577,16 @@ bool setup_tables_and_check_access(THD *thd, ...@@ -4575,13 +4577,16 @@ bool setup_tables_and_check_access(THD *thd,
*leaves = leaves_tmp; *leaves = leaves_tmp;
for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf) for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf)
{
if (leaves_tmp->belong_to_view && if (leaves_tmp->belong_to_view &&
check_single_table_access(thd, want_access, leaves_tmp)) check_single_table_access(thd, first_table ? want_access_first :
want_access, leaves_tmp))
{ {
tables->hide_view_error(thd); tables->hide_view_error(thd);
return TRUE; return TRUE;
} }
first_table= false;
}
return FALSE; return FALSE;
} }
......
...@@ -350,7 +350,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) ...@@ -350,7 +350,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
&thd->lex->select_lex.top_join_list, &thd->lex->select_lex.top_join_list,
table_list, conds, table_list, conds,
&select_lex->leaf_tables, FALSE, &select_lex->leaf_tables, FALSE,
DELETE_ACL) || DELETE_ACL, SELECT_ACL) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
setup_ftfuncs(select_lex)) setup_ftfuncs(select_lex))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -413,7 +413,7 @@ bool mysql_multi_delete_prepare(THD *thd) ...@@ -413,7 +413,7 @@ bool mysql_multi_delete_prepare(THD *thd)
&thd->lex->select_lex.top_join_list, &thd->lex->select_lex.top_join_list,
lex->query_tables, &lex->select_lex.where, lex->query_tables, &lex->select_lex.where,
&lex->select_lex.leaf_tables, FALSE, &lex->select_lex.leaf_tables, FALSE,
DELETE_ACL)) DELETE_ACL, SELECT_ACL))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
......
...@@ -847,7 +847,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, ...@@ -847,7 +847,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
&thd->lex->select_lex.top_join_list, &thd->lex->select_lex.top_join_list,
table_list, where, table_list, where,
&thd->lex->select_lex.leaf_tables, &thd->lex->select_lex.leaf_tables,
select_insert, SELECT_ACL)) select_insert, INSERT_ACL, SELECT_ACL))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (insert_into_view && !fields.elements) if (insert_into_view && !fields.elements)
......
...@@ -157,6 +157,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -157,6 +157,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
&thd->lex->select_lex.top_join_list, &thd->lex->select_lex.top_join_list,
table_list, &unused_conds, table_list, &unused_conds,
&thd->lex->select_lex.leaf_tables, FALSE, &thd->lex->select_lex.leaf_tables, FALSE,
INSERT_ACL | UPDATE_ACL,
INSERT_ACL | UPDATE_ACL)) INSERT_ACL | UPDATE_ACL))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (!table_list->table || // do not suport join view if (!table_list->table || // do not suport join view
......
...@@ -344,7 +344,7 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -344,7 +344,7 @@ JOIN::prepare(Item ***rref_pointer_array,
setup_tables_and_check_access(thd, &select_lex->context, join_list, setup_tables_and_check_access(thd, &select_lex->context, join_list,
tables_list, &conds, tables_list, &conds,
&select_lex->leaf_tables, FALSE, &select_lex->leaf_tables, FALSE,
SELECT_ACL)) || SELECT_ACL, SELECT_ACL)) ||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
select_lex->setup_ref_array(thd, og_num) || select_lex->setup_ref_array(thd, og_num) ||
setup_fields(thd, (*rref_pointer_array), fields_list, 1, setup_fields(thd, (*rref_pointer_array), fields_list, 1,
......
...@@ -627,7 +627,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, ...@@ -627,7 +627,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
&select_lex->top_join_list, &select_lex->top_join_list,
table_list, conds, table_list, conds,
&select_lex->leaf_tables, &select_lex->leaf_tables,
FALSE, UPDATE_ACL) || FALSE, UPDATE_ACL, SELECT_ACL) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
select_lex->setup_ref_array(thd, order_num) || select_lex->setup_ref_array(thd, order_num) ||
setup_order(thd, select_lex->ref_pointer_array, setup_order(thd, select_lex->ref_pointer_array,
...@@ -722,7 +722,7 @@ reopen_tables: ...@@ -722,7 +722,7 @@ reopen_tables:
&lex->select_lex.top_join_list, &lex->select_lex.top_join_list,
table_list, &lex->select_lex.where, table_list, &lex->select_lex.where,
&lex->select_lex.leaf_tables, FALSE, &lex->select_lex.leaf_tables, FALSE,
UPDATE_ACL)) UPDATE_ACL, SELECT_ACL))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0)) if (setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0))
......
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