CVE-2017-15365: Insufficient Information (NVD-CWE-noinfo)
value: sql/event_data_objects.cc in MariaDB before 10.1.30 and 10.2.x before 10.2.10 and Percona XtraDB Cluster before 5.6.37-26.21-3 and 5.7.x before 5.7.19-29.22-3 allows remote authenticated users with SQL access to bypass intended access restrictions and replicate data definition language (DDL) statements to cluster nodes by leveraging incorrect ordering of DDL replication and ACL checking.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 8.8
Published: 2018-01-25T16:29Z
Repository: https://github.com/MariaDB/server
Language: C++
Files changed: sql/event_data_objects.cc
Commit date: 2017-10-10 08:37:44 +0300
Commit message: MW-416 DDL replication moved after acl checking

galera_events test shows a regression with the original fix for MW-416
Reason was that Events::drop_event() can be called also from inside event
execution, and there we have a speacial treatment for event, which executes
"DROP EVENT" statement, and runs TOI replication inside the event processing body.
This resulted in executing WSREP_TO_ISOLATION two times for such DROP EVENT statement.
Fix is to call WSREP_TO_ISOLATION_BEGIN only in Events::drop_event()

Diff: diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index e494b4a429b..90e839debb5 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -1470,23 +1470,37 @@ Event_job_data::execute(THD *thd, bool drop)
       saved_master_access= thd->security_ctx->master_access;
       thd->security_ctx->master_access |= SUPER_ACL;
       bool save_tx_read_only= thd->tx_read_only;
       thd->tx_read_only= false;
 
-      if (WSREP(thd))
-      {
+      /*
+         This code is processing event execution and does not have client
+         connection. Here, event execution will now execute a prepared
+         DROP EVENT statement, but thd->lex->sql_command is set to
+         SQLCOM_CREATE_PROCEDURE
+         DROP EVENT will be logged in binlog, and we have to
+         replicate it to make all nodes have consistent event definitions
+         Wsrep DDL replication is triggered inside Events::drop_event(),
+         and here we need to prepare the THD so that DDL replication is
+         possible, essentially it requires setting sql_command to
+         SQLCOMM_DROP_EVENT, we will switch sql_command for the duration
+         of DDL replication only.
+      */
+      const enum_sql_command sql_command_save= thd->lex->sql_command;
+      const bool sql_command_set= WSREP(thd);
+
+      if (sql_command_set)
         thd->lex->sql_command = SQLCOM_DROP_EVENT;
-        WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
-      }
 
       ret= Events::drop_event(thd, dbname, name, FALSE);
 
-      WSREP_TO_ISOLATION_END;
+      if (sql_command_set)
+      {
+        WSREP_TO_ISOLATION_END;
+        thd->lex->sql_command = sql_command_save;
+      }
 
-#ifdef WITH_WSREP
-  error:
-#endif
       thd->tx_read_only= save_tx_read_only;
       thd->security_ctx->master_access= saved_master_access;
     }
   }
 #ifndef NO_EMBEDDED_ACCESS_CHECKS

Vulnerable code:       if (WSREP(thd))
      {
        WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
      }
      WSREP_TO_ISOLATION_END;
#ifdef WITH_WSREP
  error:
#endif
Fixed code:       /*
         This code is processing event execution and does not have client
         connection. Here, event execution will now execute a prepared
         DROP EVENT statement, but thd->lex->sql_command is set to
         SQLCOM_CREATE_PROCEDURE
         DROP EVENT will be logged in binlog, and we have to
         replicate it to make all nodes have consistent event definitions
         Wsrep DDL replication is triggered inside Events::drop_event(),
         and here we need to prepare the THD so that DDL replication is
         possible, essentially it requires setting sql_command to
         SQLCOMM_DROP_EVENT, we will switch sql_command for the duration
         of DDL replication only.
      */
      const enum_sql_command sql_command_save= thd->lex->sql_command;
      const bool sql_command_set= WSREP(thd);

      if (sql_command_set)
      if (sql_command_set)
      {
        WSREP_TO_ISOLATION_END;
        thd->lex->sql_command = sql_command_save;
      }