List:Commits« Previous MessageNext Message »
From:Marc Alff Date:November 25 2009 9:57am
Subject:bzr commit into mysql-trunk-perfschema branch (marc.alff:2968) WL#2360
View as plain text  
#At file:///home/malff/BZR_TREE/mysql-trunk-perfschema/ based on revid:marc.alff@stripped

 2968 Marc Alff	2009-11-25
      WL#2360 Performance schema
      
      Implemented code review comments related to sql_acl

    added:
      mysql-test/suite/perfschema/r/column_privilege.result
      mysql-test/suite/perfschema/t/column_privilege.test
    modified:
      sql/sql_acl.cc
      sql/sql_parse.cc
      sql/sql_show.cc
=== added file 'mysql-test/suite/perfschema/r/column_privilege.result'
--- a/mysql-test/suite/perfschema/r/column_privilege.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/perfschema/r/column_privilege.result	2009-11-25 09:57:05 +0000
@@ -0,0 +1,32 @@
+show grants;
+Grants for root@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
+grant usage on *.* to 'pfs_user_5'@localhost with GRANT OPTION;
+grant SELECT(thread_id, event_id) on performance_schema.EVENTS_WAITS_CURRENT
+to 'pfs_user_5'@localhost;
+grant UPDATE(enabled) on performance_schema.SETUP_INSTRUMENTS
+to 'pfs_user_5'@localhost;
+flush privileges;
+show grants;
+Grants for pfs_user_5@localhost
+GRANT USAGE ON *.* TO 'pfs_user_5'@'localhost' WITH GRANT OPTION
+GRANT UPDATE (enabled) ON `performance_schema`.`SETUP_INSTRUMENTS` TO 'pfs_user_5'@'localhost'
+GRANT SELECT (thread_id, event_id) ON `performance_schema`.`EVENTS_WAITS_CURRENT` TO 'pfs_user_5'@'localhost'
+select thread_id from performance_schema.EVENTS_WAITS_CURRENT;
+select thread_id, event_id from performance_schema.EVENTS_WAITS_CURRENT;
+update performance_schema.SETUP_INSTRUMENTS set enabled='YES';
+select event_name from performance_schema.EVENTS_WAITS_CURRENT;
+ERROR 42000: SELECT command denied to user 'pfs_user_5'@'localhost' for column 'event_name' in table 'EVENTS_WAITS_CURRENT'
+select thread_id, event_id, event_name
+from performance_schema.EVENTS_WAITS_CURRENT;
+ERROR 42000: SELECT command denied to user 'pfs_user_5'@'localhost' for column 'event_name' in table 'EVENTS_WAITS_CURRENT'
+update performance_schema.SETUP_INSTRUMENTS set name='illegal';
+ERROR 42000: UPDATE command denied to user 'pfs_user_5'@'localhost' for column 'name' in table 'SETUP_INSTRUMENTS'
+update performance_schema.SETUP_INSTRUMENTS set timed='NO';
+ERROR 42000: UPDATE command denied to user 'pfs_user_5'@'localhost' for column 'timed' in table 'SETUP_INSTRUMENTS'
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'pfs_user_5'@localhost;
+DROP USER 'pfs_user_5'@localhost;
+flush privileges;
+UPDATE performance_schema.SETUP_INSTRUMENTS SET enabled = 'YES', timed = 'YES';
+UPDATE performance_schema.SETUP_CONSUMERS SET enabled = 'YES';
+UPDATE performance_schema.SETUP_TIMERS SET timer_name = 'CYCLE';

=== added file 'mysql-test/suite/perfschema/t/column_privilege.test'
--- a/mysql-test/suite/perfschema/t/column_privilege.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/perfschema/t/column_privilege.test	2009-11-25 09:57:05 +0000
@@ -0,0 +1,80 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+#
+# 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
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# Tests for PERFORMANCE_SCHEMA
+# Test how columns privileges can be used on performance schema tables,
+# for very fine control.
+
+--source include/not_embedded.inc
+
+show grants;
+
+grant usage on *.* to 'pfs_user_5'@localhost with GRANT OPTION;
+
+# Test per column privileges on performance_schema
+
+grant SELECT(thread_id, event_id) on performance_schema.EVENTS_WAITS_CURRENT
+  to 'pfs_user_5'@localhost;
+
+grant UPDATE(enabled) on performance_schema.SETUP_INSTRUMENTS
+  to 'pfs_user_5'@localhost;
+
+flush privileges;
+
+connect (con1, localhost, pfs_user_5, , );
+
+show grants;
+
+# For statements that works, we do not look at the output
+--disable_result_log
+
+select thread_id from performance_schema.EVENTS_WAITS_CURRENT;
+
+select thread_id, event_id from performance_schema.EVENTS_WAITS_CURRENT;
+
+update performance_schema.SETUP_INSTRUMENTS set enabled='YES';
+
+--enable_result_log
+
+# For statements that are denied, check the error number and error text.
+
+--replace_result '\'events_waits_current' '\'EVENTS_WAITS_CURRENT'
+--error ER_COLUMNACCESS_DENIED_ERROR
+select event_name from performance_schema.EVENTS_WAITS_CURRENT;
+
+--replace_result '\'events_waits_current' '\'EVENTS_WAITS_CURRENT'
+--error ER_COLUMNACCESS_DENIED_ERROR
+select thread_id, event_id, event_name
+  from performance_schema.EVENTS_WAITS_CURRENT;
+
+--replace_result '\'setup_instruments' '\'SETUP_INSTRUMENTS'
+--error ER_COLUMNACCESS_DENIED_ERROR
+update performance_schema.SETUP_INSTRUMENTS set name='illegal';
+
+--replace_result '\'setup_instruments' '\'SETUP_INSTRUMENTS'
+--error ER_COLUMNACCESS_DENIED_ERROR
+update performance_schema.SETUP_INSTRUMENTS set timed='NO';
+
+# Cleanup
+
+--connection default
+--disconnect con1
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'pfs_user_5'@localhost;
+DROP USER 'pfs_user_5'@localhost;
+flush privileges;
+UPDATE performance_schema.SETUP_INSTRUMENTS SET enabled = 'YES', timed = 'YES';
+UPDATE performance_schema.SETUP_CONSUMERS SET enabled = 'YES';
+UPDATE performance_schema.SETUP_TIMERS SET timer_name = 'CYCLE';
+

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2009-11-24 06:30:37 +0000
+++ b/sql/sql_acl.cc	2009-11-25 09:57:05 +0000
@@ -3934,7 +3934,7 @@ bool check_grant(THD *thd, ulong want_ac
       table->security_ctx : thd->security_ctx;
 
     const ACL_internal_table_access *access;
-    access= get_cached_table_access(& table->grant.m_internal,
+    access= get_cached_table_access(&table->grant.m_internal,
                                     table->get_db_name(),
                                     table->get_table_name());
 
@@ -3952,7 +3952,17 @@ bool check_grant(THD *thd, ulong want_ac
           so this branch is not used.
         */
         DBUG_ASSERT(0);
-        continue;
+        /*
+          When this branch is used, consider adjusting the code below:
+            want_access= orig_want_access;
+            want_access&= ~sctx->master_access;
+          to:
+            want_access= orig_want_access;
+            want_access&= ~sctx->master_access;
+            want_access&= ~table->grant.privilege;
+          to account for access granted internally.
+        */
+        break;
       case ACL_INTERNAL_ACCESS_DENIED:
         goto err;
       case ACL_INTERNAL_ACCESS_CHECK_GRANT:
@@ -3965,8 +3975,17 @@ bool check_grant(THD *thd, ulong want_ac
     if (!want_access)
       continue;                                 // ok
 
+    /*
+      If the table is an INFORMATION_SCHEMA table,
+      privileges should have been checked and resolved already,
+      for every code path leading here,
+      so the assert below enforces that there are no special cases left.
+    */
+    DBUG_ASSERT(!table->schema_table ||
+                ((~table->grant.privilege & want_access) == 0));
+
     if (!(~table->grant.privilege & want_access) ||
-        table->is_anonymous_derived_table() || table->schema_table)
+        table->is_anonymous_derived_table())
     {
       /*
         It is subquery in the FROM clause. VIEW set table->derived after
@@ -3976,8 +3995,7 @@ bool check_grant(THD *thd, ulong want_ac
       {
         /*
           If it's a temporary table created for a subquery in the FROM
-          clause, or an INFORMATION_SCHEMA table, drop the request for
-          a privilege.
+          clause, drop the request for a privilege.
         */
         table->grant.want_privilege= 0;
       }

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2009-11-24 06:30:37 +0000
+++ b/sql/sql_parse.cc	2009-11-25 09:57:05 +0000
@@ -5285,7 +5285,10 @@ check_access(THD *thd, ulong want_access
   if (save_priv)
     *save_priv=0;
   else
+  {
     save_priv= &dummy;
+    dummy= 0;
+  }
 
   thd_proc_info(thd, "checking permissions");
   if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
@@ -5306,7 +5309,20 @@ check_access(THD *thd, ulong want_access
       switch (access->check(want_access, save_priv))
       {
       case ACL_INTERNAL_ACCESS_GRANTED:
-        DBUG_RETURN(FALSE);
+        want_access&= ~(*save_priv);
+        if (!want_access)
+        {
+          /*
+            All the privileges requested have been granted internally.
+            [out] *save_privileges= Internal privileges.
+          */
+          DBUG_RETURN(FALSE);
+        }
+        /*
+          Only some of the privilege requested have been granted internally,
+          proceed with the remaining bits of the request (want_access).
+        */
+        break;
       case ACL_INTERNAL_ACCESS_DENIED:
         if (! no_errors)
         {
@@ -5340,12 +5356,13 @@ check_access(THD *thd, ulong want_access
       }
       /*
         The effective privileges are the union of the global privileges
-        and the intersection of db- and host-privileges.
+        and the intersection of db- and host-privileges,
+        plus the internal privileges.
       */
-      *save_priv=sctx->master_access | db_access;
+      *save_priv|= sctx->master_access | db_access;
     }
     else
-      *save_priv=sctx->master_access;
+      *save_priv|= sctx->master_access;
     DBUG_RETURN(FALSE);
   }
   if (((want_access & ~sctx->master_access) & ~DB_ACLS) ||
@@ -5381,10 +5398,10 @@ check_access(THD *thd, ulong want_access
 
   /*
     Save the union of User-table and the intersection between Db-table and
-    Host-table privileges.
+    Host-table privileges, with the already saved internal privileges.
   */
   db_access= (db_access | sctx->master_access);
-  *save_priv= db_access;
+  *save_priv|= db_access;
 
   /*
     We need to investigate column- and table access if all requested privileges
@@ -5405,14 +5422,14 @@ check_access(THD *thd, ulong want_access
   {
     /*
        Ok; but need to check table- and column privileges.
-       [out] *save_privileges is (User-priv | (Db-priv & Host-priv))
+       [out] *save_privileges is (User-priv | (Db-priv & Host-priv) | Internal-priv)
     */
     DBUG_RETURN(FALSE);
   }
 
   /*
     Access is denied;
-    [out] *save_privileges is (User-priv | (Db-priv & Host-priv))
+    [out] *save_privileges is (User-priv | (Db-priv & Host-priv) | Internal-priv)
   */
   DBUG_PRINT("error",("Access denied"));
   if (!no_errors)
@@ -5428,6 +5445,18 @@ check_access(THD *thd, ulong want_access
 
 static bool check_show_access(THD *thd, TABLE_LIST *table)
 {
+  /*
+    This is a SHOW command using an INFORMATION_SCHEMA table.
+    check_access() has not been called for 'table',
+    and SELECT is currently always granted on the I_S, so we automatically
+    grant SELECT on table here, to bypass a call to check_access().
+    Note that not calling check_access(table) is an optimization,
+    which needs to be revisited if the INFORMATION_SCHEMA does
+    not always automatically grant SELECT but use the grant tables.
+    See Bug#38837 need a way to disable information_schema for security
+  */
+  table->grant.privilege= SELECT_ACL;
+
   switch (get_schema_table_idx(table->schema_table)) {
   case SCH_SCHEMATA:
     return (specialflag & SPECIAL_SKIP_SHOW_DB) &&

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	2009-11-23 22:35:45 +0000
+++ b/sql/sql_show.cc	2009-11-25 09:57:05 +0000
@@ -7333,17 +7333,19 @@ ACL_internal_access_result
 IS_internal_schema_access::check(ulong want_access,
                                  ulong *save_priv) const
 {
-  if (unlikely(want_access & ~(SELECT_ACL | FILE_ACL)))
+  want_access &= ~SELECT_ACL;
+
+  /*
+    We don't allow any simple privileges but SELECT_ACL on
+    the information_schema database.
+  */
+  if (unlikely(want_access & DB_ACLS))
     return ACL_INTERNAL_ACCESS_DENIED;
 
-  if ((want_access & ~SELECT_ACL) == 0)
-  {
-    /* Always grant SELECT for the information schema */
-    *save_priv= SELECT_ACL;
-    return ACL_INTERNAL_ACCESS_GRANTED;
-  }
+  /* Always grant SELECT for the information schema. */
+  *save_priv|= SELECT_ACL;
 
-  return ACL_INTERNAL_ACCESS_CHECK_GRANT;
+  return ACL_INTERNAL_ACCESS_GRANTED;
 }
 
 const ACL_internal_table_access *


Attachment: [text/bzr-bundle] bzr/marc.alff@sun.com-20091125095705-o1h2uonnd5bjiizk.bundle
Thread
bzr commit into mysql-trunk-perfschema branch (marc.alff:2968) WL#2360Marc Alff25 Nov