1281
1281
if (!table->prelocking_placeholder &&
1282
1282
(old_lex->sql_command == SQLCOM_SELECT && old_lex->describe))
1284
if (check_table_access(thd, SELECT_ACL, view_tables, FALSE,
1286
check_table_access(thd, SHOW_VIEW_ACL, table, FALSE, UINT_MAX, TRUE))
1285
The user we run EXPLAIN as (either the connected user who issued
1286
the EXPLAIN statement, or the definer of a SUID stored routine
1287
which contains the EXPLAIN) should have both SHOW_VIEW_ACL and
1288
SELECT_ACL on the view being opened as well as on all underlying
1289
views since EXPLAIN will disclose their structure. This user also
1290
should have SELECT_ACL on all underlying tables of the view since
1291
this EXPLAIN will disclose information about the number of rows in it.
1293
To perform this privilege check we create auxiliary TABLE_LIST object
1294
for the view in order a) to avoid trashing "table->grant" member for
1295
original table list element, which contents can be important at later
1296
stage for column-level privilege checking b) get TABLE_LIST object
1297
with "security_ctx" member set to 0, i.e. forcing check_table_access()
1298
to use active user's security context.
1300
There is no need for creating similar copies of TABLE_LIST elements
1301
for underlying tables since they just have been constructed and thus
1302
have TABLE_LIST::security_ctx == 0 and fresh TABLE_LIST::grant member.
1304
Finally at this point making sure we have SHOW_VIEW_ACL on the views
1305
will suffice as we implicitly require SELECT_ACL anyway.
1308
TABLE_LIST view_no_suid;
1309
bzero(static_cast<void *>(&view_no_suid), sizeof(TABLE_LIST));
1310
view_no_suid.db= table->db;
1311
view_no_suid.table_name= table->table_name;
1313
DBUG_ASSERT(view_tables == NULL || view_tables->security_ctx == NULL);
1315
if (check_table_access(thd, SELECT_ACL, view_tables,
1316
FALSE, UINT_MAX, TRUE) ||
1317
check_table_access(thd, SHOW_VIEW_ACL, &view_no_suid,
1318
FALSE, UINT_MAX, TRUE))
1288
1320
my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0));