Bug #37908 'show procedure/function status' referencing a table in a subquery crashes
Submitted: 6 Jul 2008 17:16 Modified: 17 Oct 2008 17:44
Reporter: Davi Arnaut (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S2 (Serious)
Version:5.0, 5.1, 6.0 OS:Any
Assigned to: Evgeny Potemkin CPU Architecture:Any
Tags: crash, show procedure/function status, subquery, table

[6 Jul 2008 17:16] Davi Arnaut
Description:
Calling SHOW PROCEDURE/FUNCTION STATUS while referencing a table in a subquery in the where condition causes a server crash.

How to repeat:
CREATE TABLE t1 (a INT);
SHOW PROCEDURE STATUS WHERE (1) IN (SELECT * FROM t1);

Suggested fix:
Although the crash happens in check_grant_all_columns, skipping the check for privilege in the used tables is probably what leads to this crash. Its probably better to remove the special check for the two commands and make the privileges checks more robust.

2674│       if (lex->orig_sql_command != SQLCOM_SHOW_STATUS_PROC &&
2675│           lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC)
2676│         res= check_table_access(thd,
2677│                                 lex->exchange ? SELECT_ACL | FILE_ACL :
2678│                                 SELECT_ACL,
2679│                                 all_tables, 0);
[6 Jul 2008 17:34] MySQL Verification Team
Thank you for the bug report.

Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
00000001401F3EA5    mysqld.exe!my_sigabrt_handler()[mysqld.cc:2114]
00000001408F1FB1    mysqld.exe!raise()[winsig.c:597]
00000001408E84E3    mysqld.exe!abort()[abort.c:78]
00000001408DA974    mysqld.exe!_wassert()[assert.c:212]
00000001402BD9AE    mysqld.exe!check_grant_all_columns()[sql_acl.cc:4273]
00000001402E75A6    mysqld.exe!insert_fields()[sql_base.cc:6810]
00000001402E480D    mysqld.exe!setup_wild()[sql_base.cc:6410]
00000001403A9F16    mysqld.exe!JOIN::prepare()[sql_select.cc:527]
0000000140167A63    mysqld.exe!subselect_single_select_engine::prepare()[item_subselect.cc:2081]
00000001401600C4    mysqld.exe!Item_subselect::fix_fields()[item_subselect.cc:174]
0000000140166A4A    mysqld.exe!Item_in_subselect::fix_fields()[item_subselect.cc:1754]
00000001402E7EE7    mysqld.exe!setup_conds()[sql_base.cc:6998]
00000001403F551B    mysqld.exe!setup_without_group()[sql_select.cc:443]
00000001403AA066    mysqld.exe!JOIN::prepare()[sql_select.cc:527]
00000001403B30C1    mysqld.exe!mysql_select()[sql_select.cc:2973]
00000001403A9664    mysqld.exe!handle_select()[sql_select.cc:302]
0000000140364AAB    mysqld.exe!execute_sqlcom_select()[sql_parse.cc:4847]
000000014035AF14    mysqld.exe!mysql_execute_command()[sql_parse.cc:1962]
0000000140367238    mysqld.exe!mysql_parse()[sql_parse.cc:5815]
0000000140358F39    mysqld.exe!dispatch_command()[sql_parse.cc:1053]
00000001403584C3    mysqld.exe!do_command()[sql_parse.cc:724]
0000000140319FD6    mysqld.exe!handle_one_connection()[sql_connect.cc:1153]
00000001405603C5    mysqld.exe!pthread_start()[my_winthread.c:86]
00000001408F2635    mysqld.exe!_callthreadstart()[thread.c:295]
00000001408F2607    mysqld.exe!_threadstart()[thread.c:277]
00000000779FCDCD    kernel32.dll!BaseThreadInitThunk()
0000000077B4C6E1    ntdll.dll!RtlUserThreadStart()
Trying to get some variables.
Some pointers may be invalid and cause the dump to abort...
thd->query at 0000000004272F00=SHOW PROCEDURE STATUS WHERE (1) IN (SELECT * FROM t1)
thd->thread_id=1
thd->killed=NOT_KILLED
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
[9 Jul 2008 13:13] Davi Arnaut
Another similar test case:

SHOW STATUS WHERE (1) IN (SELECT * FROM t1);
[11 Aug 2008 14:09] Evgeny Potemkin
This is also a security breach:
As 'root':

mysql> create user ttt@localhost;
Query OK, 0 rows affected (0.00 sec)

mysql> create database d1;
Query OK, 1 row affected (0.00 sec)

mysql> use d1;
Database changed

mysql> create table t1(f1 int);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into d1.t1 values(1);
Query OK, 1 row affected (0.00 sec)

As 'ttt':

mysql> select f1 from d1.t1;
ERROR 1142 (42000): SELECT command denied to user 'ttt'@'localhost' for table 't1'

mysql> show status where variable_name ='uptime' and 1 in (select f1 from d1.t1);
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Uptime        | 210   | 
+---------------+-------+
1 row in set (0.02 sec)

mysql> show status where variable_name ='uptime' and 2 in (select f1 from d1.t1);
Empty set (0.00 sec)

I.e this way one could bypass access rights check and check for presence/absence of arbitrary values in any tables.
[26 Aug 2008 20:41] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/52607

2583 Evgeny Potemkin	2008-08-27
      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.
[28 Aug 2008 11:48] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/52834

2679 Evgeny Potemkin	2008-08-28
      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.
      The check_table_access function is adjusted to correctly check access to
      system tables for schema tables filling.
[15 Sep 2008 8:32] Bugs System
Pushed into 5.1.29  (revid:epotemkin@mysql.com-20080905104416-y1p4oqlxlqiibhai) (version source revid:kgeorge@mysql.com-20080910094421-1i1kxv3n1bxskiqa) (pib:3)
[15 Sep 2008 18:44] Paul DuBois
Noted in 5.1.29 changelog.

Access checks were skipped for SHOW PROCEDURE STATUS and SHOW
FUNCTION STATUS, which could lead to a server crash or insufficient
access checks in subsequent statements.

Setting report to NDI pending push into 6.0.x.
[1 Oct 2008 16:00] Bugs System
Pushed into 5.1.29  (revid:epotemkin@mysql.com-20080905104416-y1p4oqlxlqiibhai) (version source revid:kgeorge@mysql.com-20080910094421-1i1kxv3n1bxskiqa) (pib:4)
[1 Oct 2008 17:13] Paul DuBois
Setting report to NDI pending push into 6.0.x.
[17 Oct 2008 16:40] Bugs System
Pushed into 6.0.8-alpha  (revid:epotemkin@mysql.com-20080905104416-y1p4oqlxlqiibhai) (version source revid:kpettersson@mysql.com-20080911114255-81pt7q1uvl1fkojq) (pib:5)
[17 Oct 2008 17:44] Paul DuBois
Noted in 6.0.8 changelog.
[28 Oct 2008 21:01] Bugs System
Pushed into 5.1.29-ndb-6.2.17  (revid:epotemkin@mysql.com-20080905104416-y1p4oqlxlqiibhai) (version source revid:tomas.ulin@sun.com-20081028140209-u4emkk1xphi5tkfb) (pib:5)
[28 Oct 2008 22:20] Bugs System
Pushed into 5.1.29-ndb-6.3.19  (revid:epotemkin@mysql.com-20080905104416-y1p4oqlxlqiibhai) (version source revid:tomas.ulin@sun.com-20081028194045-0353yg8cvd2c7dd1) (pib:5)
[1 Nov 2008 9:45] Bugs System
Pushed into 5.1.29-ndb-6.4.0  (revid:epotemkin@mysql.com-20080905104416-y1p4oqlxlqiibhai) (version source revid:jonas@mysql.com-20081101082305-qx5a1bj0z7i8ueys) (pib:5)