summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/show_explain.result45
-rw-r--r--mysql-test/t/show_explain.test67
-rw-r--r--sql/my_apc.cc2
-rw-r--r--sql/my_apc.h2
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_parse.cc5
-rw-r--r--sql/sql_show.cc25
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