diff options
-rw-r--r-- | mysql-test/r/show_explain.result | 45 | ||||
-rw-r--r-- | mysql-test/t/show_explain.test | 67 | ||||
-rw-r--r-- | sql/my_apc.cc | 2 | ||||
-rw-r--r-- | sql/my_apc.h | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 5 | ||||
-rw-r--r-- | sql/sql_show.cc | 25 |
7 files changed, 138 insertions, 10 deletions
diff --git a/mysql-test/r/show_explain.result b/mysql-test/r/show_explain.result index 07bcb29a7ea..a4097b9d65e 100644 --- a/mysql-test/r/show_explain.result +++ b/mysql-test/r/show_explain.result @@ -728,4 +728,49 @@ a 2 set debug_dbug=''; drop table t1,t3,t4; +# +# ---------- SHOW EXPLAIN and permissions ----------------- +# +grant ALL on test.* to test2@localhost; +# +# First, make sure that user 'test2' cannot do SHOW EXPLAIN on us +# +set debug_dbug='d,show_explain_probe_join_exec_start'; +select * from t0 where a < 3; +show explain for $thr2; +ERROR 42000: Access denied; you need (at least one of) the PROCESSLIST privilege(s) for this operation +show explain for $thr2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where +Warnings: +Note 1003 select * from t0 where a < 3 +a +0 +1 +2 +set debug_dbug=''; +# +# Unfortunately, our test setup doesn't allow to check that test2 +# can do SHOW EXPLAIN on his own queries. This is because SET debug_dbug +# requires SUPER privilege. Giving SUPER to test2 will make the test +# meaningless +# +# +# Now, grant test2 a PROCESSLIST permission, and see that he's able to observe us +# +grant process on *.* to test2@localhost; +set debug_dbug='d,show_explain_probe_join_exec_start'; +select * from t0 where a < 3; +show explain for $thr2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where +Warnings: +Note 1003 select * from t0 where a < 3 +a +0 +1 +2 +set debug_dbug=''; +revoke all privileges on test.* from test2@localhost; +drop user test2@localhost; drop table t0; diff --git a/mysql-test/t/show_explain.test b/mysql-test/t/show_explain.test index ffd2c25dfd9..5db6b96d93b 100644 --- a/mysql-test/t/show_explain.test +++ b/mysql-test/t/show_explain.test @@ -727,10 +727,71 @@ reap; set debug_dbug=''; drop table t1,t3,t4; + +--echo # +--echo # ---------- SHOW EXPLAIN and permissions ----------------- +--echo # +grant ALL on test.* to test2@localhost; + +connect (con2, localhost, test2,,); +connection con1; + +--echo # +--echo # First, make sure that user 'test2' cannot do SHOW EXPLAIN on us +--echo # +set debug_dbug='d,show_explain_probe_join_exec_start'; +send +select * from t0 where a < 3; + +connection default; +--source include/wait_condition.inc + +connection con2; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +evalp show explain for $thr2; + +connection default; +evalp show explain for $thr2; + +connection con1; +reap; +set debug_dbug=''; + +--echo # +--echo # Unfortunately, our test setup doesn't allow to check that test2 +--echo # can do SHOW EXPLAIN on his own queries. This is because SET debug_dbug +--echo # requires SUPER privilege. Giving SUPER to test2 will make the test +--echo # meaningless +--echo # + +--echo # +--echo # Now, grant test2 a PROCESSLIST permission, and see that he's able to observe us +--echo # +disconnect con2; +grant process on *.* to test2@localhost; +connect (con2, localhost, test2,,); +connection con1; + +set debug_dbug='d,show_explain_probe_join_exec_start'; +send +select * from t0 where a < 3; + +connection default; +--source include/wait_condition.inc + +connection con2; +evalp show explain for $thr2; + +connection con1; +reap; +set debug_dbug=''; + + + +revoke all privileges on test.* from test2@localhost; +drop user test2@localhost; + ## TODO: Test this: have several SHOW EXPLAIN requests be queued up for a ## thread and served together. -## TODO: SHOW EXPLAIN while the primary query is running EXPLAIN EXTENDED/PARTITIONS -## - drop table t0; diff --git a/sql/my_apc.cc b/sql/my_apc.cc index 48d539aed78..b5f2300c17f 100644 --- a/sql/my_apc.cc +++ b/sql/my_apc.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2009, 2011, Monty Program Ab + Copyright (c) 2011 - 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/my_apc.h b/sql/my_apc.h index 99861ca3194..88df8145186 100644 --- a/sql/my_apc.h +++ b/sql/my_apc.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2009, 2011, Monty Program Ab + Copyright (c) 2011 - 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_class.h b/sql/sql_class.h index 73123151738..d1183225a83 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1552,7 +1552,7 @@ public: }; class THD; -void mysqld_show_explain(THD *thd, ulong thread_id); +void mysqld_show_explain(THD *thd, const char *calling_user, ulong thread_id); #ifndef DBUG_OFF void dbug_serve_apcs(THD *thd, int n_calls); #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 18db712d6cb..9ebb1b3f36e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3130,6 +3130,7 @@ end_with_restore_list: break; case SQLCOM_SHOW_EXPLAIN: { + const char *effective_user; /* Same security as SHOW PROCESSLIST (TODO check this) */ if (!thd->security_ctx->priv_user[0] && check_global_access(thd,PROCESS_ACL)) @@ -3150,8 +3151,10 @@ end_with_restore_list: MYF(0)); goto error; } + effective_user=(thd->security_ctx->master_access & PROCESS_ACL ? NullS : + thd->security_ctx->priv_user); - mysqld_show_explain(thd, (ulong)it->val_int()); + mysqld_show_explain(thd, effective_user, (ulong)it->val_int()); break; } case SQLCOM_SHOW_AUTHORS: diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 145f4fbebcc..d26c8f18340 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2002,8 +2002,11 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) /* SHOW EXPLAIN FOR command handler - @param thd Current thread's thd - @param thread_id Thread whose explain we need + @param thd Current thread's thd + @param calling_user User that invoked SHOW EXPLAIN, or NULL if the user + has SUPER or PROCESS privileges, and so is allowed + to run SHOW EXPLAIN on anybody. + @param thread_id Thread whose explain we need @notes - Attempt to do "SHOW EXPLAIN FOR <myself>" will properly produce "target not @@ -2011,7 +2014,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) - todo: check how all this can/will work when using thread pools */ -void mysqld_show_explain(THD *thd, ulong thread_id) +void mysqld_show_explain(THD *thd, const char *calling_user, ulong thread_id) { THD *tmp; Protocol *protocol= thd->protocol; @@ -2043,6 +2046,22 @@ void mysqld_show_explain(THD *thd, ulong thread_id) if (tmp) { + Security_context *tmp_sctx= tmp->security_ctx; + /* + If calling_user==NULL, calling thread has SUPER or PROCESS + privilege, and so can do SHOW EXPLAIN on any user. + + if calling_user!=NULL, he's only allowed to view SHOW EXPLAIN on + his own threads. + */ + if (calling_user && (!tmp_sctx->user || strcmp(calling_user, + tmp_sctx->user))) + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "PROCESSLIST"); + mysql_mutex_unlock(&tmp->LOCK_thd_data); + DBUG_VOID_RETURN; + } + bool bres; /* Ok we've found the thread of interest and it won't go away because |