← Back to team overview

maria-developers team mailing list archive

MDEV-260 auditing table accesses

 

Hi, Monty,

Here's a patch for MDEV-260 (auditing table accesses).
Please review and see whether it's safe for 5.5.

Regards,
Sergei
------------------------------------------------------------
revno: 3728
fixes bug: https://mariadb.atlassian.net/browse/MDEV-260
committer: Sergei Golubchik <sergii@xxxxxxxxx>
branch nick: 5.5
timestamp: Wed 2013-04-17 09:31:24 +0200
message:
  MDEV-260 auditing table accesses
modified:
  include/mysql/plugin_audit.h
  include/mysql/plugin_audit.h.pp
  mysql-test/suite/plugins/r/audit_null.result
  mysql-test/suite/plugins/t/audit_null.test
  plugin/audit_null/audit_null.c
  sql/handler.cc
  sql/handler.h
  sql/sql_audit.cc
  sql/sql_audit.h
  sql/sql_table.cc
diff:
=== modified file 'include/mysql/plugin_audit.h'
--- include/mysql/plugin_audit.h	2011-07-05 23:13:50 +0000
+++ include/mysql/plugin_audit.h	2013-04-17 07:31:24 +0000
@@ -25,7 +25,7 @@
 
 #define MYSQL_AUDIT_CLASS_MASK_SIZE 1
 
-#define MYSQL_AUDIT_INTERFACE_VERSION 0x0300
+#define MYSQL_AUDIT_INTERFACE_VERSION 0x0301
 
 
 /*************************************************************************
@@ -97,6 +97,50 @@ struct mysql_event_connection
   unsigned int database_length;
 };
 
+/*
+  AUDIT CLASS : TABLE
+  
+  LOCK occurs when a connection "locks" (this does not necessarily mean a table
+  lock and also happens for row-locking engines) the table at the beginning of
+  a statement. This event is generated at the beginning of every statement for
+  every affected table, unless there's a LOCK TABLES statement in effect (in
+  which case it is generated once for LOCK TABLES and then is suppressed until
+  the tables are unlocked).
+
+  CREATE/DROP/RENAME occur when a table is created, dropped, or renamed.
+*/
+
+#define MYSQL_AUDIT_TABLE_CLASS 15
+#define MYSQL_AUDIT_TABLE_CLASSMASK (1 << MYSQL_AUDIT_TABLE_CLASS)
+#define MYSQL_AUDIT_TABLE_LOCK   0
+#define MYSQL_AUDIT_TABLE_CREATE 1
+#define MYSQL_AUDIT_TABLE_DROP   2
+#define MYSQL_AUDIT_TABLE_RENAME 3
+#define MYSQL_AUDIT_TABLE_ALTER  4
+
+struct mysql_event_table
+{
+  unsigned int event_subclass;
+  unsigned long thread_id;
+  const char *user;
+  const char *priv_user;
+  const char *priv_host;
+  const char *external_user;
+  const char *proxy_user;
+  const char *host;
+  const char *ip;
+  const char *database;
+  unsigned int database_length;
+  const char *table;
+  unsigned int table_length;
+  /* for MYSQL_AUDIT_TABLE_LOCK, true if read-only, false if read/write */
+  int read_only;
+  /* for MYSQL_AUDIT_TABLE_RENAME */
+  const char *new_database;
+  unsigned int new_database_length;
+  const char *new_table;
+  unsigned int new_table_length;
+};
 
 /*************************************************************************
   Here we define the descriptor structure, that is referred from
=== modified file 'include/mysql/plugin_audit.h.pp'
--- include/mysql/plugin_audit.h.pp	2013-01-18 18:04:23 +0000
+++ include/mysql/plugin_audit.h.pp	2013-04-17 07:31:24 +0000
@@ -279,6 +279,27 @@ struct mysql_event_connection
   const char *database;
   unsigned int database_length;
 };
+struct mysql_event_table
+{
+  unsigned int event_subclass;
+  unsigned long thread_id;
+  const char *user;
+  const char *priv_user;
+  const char *priv_host;
+  const char *external_user;
+  const char *proxy_user;
+  const char *host;
+  const char *ip;
+  const char *database;
+  unsigned int database_length;
+  const char *table;
+  unsigned int table_length;
+  int read_only;
+  const char *new_database;
+  unsigned int new_database_length;
+  const char *new_table;
+  unsigned int new_table_length;
+};
 struct st_mysql_audit
 {
   int interface_version;
=== modified file 'mysql-test/suite/plugins/r/audit_null.result'
--- mysql-test/suite/plugins/r/audit_null.result	2012-11-08 15:49:07 +0000
+++ mysql-test/suite/plugins/r/audit_null.result	2013-04-17 07:31:24 +0000
@@ -1,5 +1,6 @@
 set @old_global_general_log=@@global.general_log;
 set global general_log=OFF;
+grant select on *.* to testuser@localhost;
 install plugin audit_null soname 'adt_null';
 select 1;
 1
@@ -18,12 +19,82 @@ concat("test1", x)
 test1-12
 show status like 'audit_null%';
 Variable_name	Value
-Audit_null_called	19
+Audit_null_called	21
 Audit_null_general_error	1
 Audit_null_general_log	7
 Audit_null_general_result	5
+create table t1 (a int);
+insert t1 values (1), (2);
+select * from t1;
+a
+1
+2
+rename table t1 to t2;
+alter table t2 add column b int;
+create definer=testuser@localhost view v1 as select t2.a+1, t2_copy.a+2 from t2, t2 as t2_copy;
+select * from v1;
+t2.a+1	t2_copy.a+2
+2	3
+3	3
+2	4
+3	4
+drop view v1;
+create temporary table t2 (a date);
+insert t2 values ('2020-10-09');
+select * from t2;
+a
+2020-10-09
+drop table t2;
+explain select distinct * from t2;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	Using temporary
+select distinct * from t2;
+a	b
+1	NULL
+2	NULL
+drop table t2;
 uninstall plugin audit_null;
 Warnings:
 Warning	1620	Plugin is busy and will be uninstalled on shutdown
 drop procedure au1;
+drop user testuser@localhost;
 set global general_log=@old_global_general_log;
+root[root] @ localhost []	>> select 1
+root[root] @ localhost []	>> select foobar
+root[root] @ localhost []	>> show status like 'audit_null%'
+root[root] @ localhost []	>> create procedure au1(x char(16)) select concat("test1", x)
+root[root] @ localhost []	mysql.proc : write
+root[root] @ localhost []	>> call au1("-12")
+root[root] @ localhost []	mysql.proc : read
+root[root] @ localhost []	>> select concat("test1",  NAME_CONST('x',_latin1'-12' COLLATE 'latin1_swedish_ci'))
+root[root] @ localhost []	>> show status like 'audit_null%'
+root[root] @ localhost []	>> create table t1 (a int)
+root[root] @ localhost []	test.t1 : create
+root[root] @ localhost []	>> insert t1 values (1), (2)
+root[root] @ localhost []	test.t1 : write
+root[root] @ localhost []	>> select * from t1
+root[root] @ localhost []	test.t1 : read
+root[root] @ localhost []	>> rename table t1 to t2
+root[root] @ localhost []	test.t1 : rename to test.t2
+root[root] @ localhost []	>> alter table t2 add column b int
+root[root] @ localhost []	test.t2 : alter
+root[root] @ localhost []	test.t2 : read
+root[root] @ localhost []	>> create definer=testuser@localhost view v1 as select t2.a+1, t2_copy.a+2 from t2, t2 as t2_copy
+root[root] @ localhost []	test.t2 : read
+root[root] @ localhost []	test.t2 : read
+root[root] @ localhost []	>> select * from v1
+root[root] @ localhost []	test.t2 : read
+root[root] @ localhost []	test.t2 : read
+root[root] @ localhost []	>> drop view v1
+root[root] @ localhost []	>> create temporary table t2 (a date)
+root[root] @ localhost []	>> insert t2 values ('2020-10-09')
+root[root] @ localhost []	>> select * from t2
+root[root] @ localhost []	>> drop table t2
+root[root] @ localhost []	>> explain select distinct * from t2
+root[root] @ localhost []	test.t2 : read
+root[root] @ localhost []	>> select distinct * from t2
+root[root] @ localhost []	test.t2 : read
+root[root] @ localhost []	>> drop table t2
+root[root] @ localhost []	test.t2 : drop
+root[root] @ localhost []	>> uninstall plugin audit_null
+root[root] @ localhost []	mysql.plugin : write
=== modified file 'mysql-test/suite/plugins/t/audit_null.test'
--- mysql-test/suite/plugins/t/audit_null.test	2012-11-22 09:19:31 +0000
+++ mysql-test/suite/plugins/t/audit_null.test	2013-04-17 07:31:24 +0000
@@ -8,6 +8,8 @@ if (!$ADT_NULL_SO) {
 set @old_global_general_log=@@global.general_log;
 set global general_log=OFF;
 
+grant select on *.* to testuser@localhost;
+
 --disable_ps_protocol
 install plugin audit_null soname 'adt_null';
 
@@ -22,9 +24,36 @@ call au1("-12");
 
 show status like 'audit_null%';
 
+create table t1 (a int);
+insert t1 values (1), (2);
+select * from t1;
+rename table t1 to t2;
+alter table t2 add column b int;
+
+create definer=testuser@localhost view v1 as select t2.a+1, t2_copy.a+2 from t2, t2 as t2_copy;
+select * from v1;
+drop view v1;
+
+# temp table generates no audit events
+create temporary table t2 (a date);
+insert t2 values ('2020-10-09');
+select * from t2;
+drop table t2;
+
+# internal temp table generates no audit events
+explain select distinct * from t2;
+select distinct * from t2;
+
+drop table t2;
+
 uninstall plugin audit_null;
 --enable_ps_protocol
 
 drop procedure au1;
+drop user testuser@localhost;
 set global general_log=@old_global_general_log;
 
+let $MYSQLD_DATADIR= `SELECT @@datadir`;
+--replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ /#sql2-[-0-9a-f_]*/#sql2-temporary/
+cat_file $MYSQLD_DATADIR/audit_null_tables.log;
+
=== modified file 'plugin/audit_null/audit_null.c'
--- plugin/audit_null/audit_null.c	2012-11-07 18:07:47 +0000
+++ plugin/audit_null/audit_null.c	2013-04-17 07:31:24 +0000
@@ -22,11 +22,12 @@
 #define __attribute__(A)
 #endif
 
-static volatile int number_of_calls; /* for SHOW STATUS, see below */
-static volatile int number_of_calls_general_log;
-static volatile int number_of_calls_general_error;
-static volatile int number_of_calls_general_result;
+static volatile int ncalls; /* for SHOW STATUS, see below */
+static volatile int ncalls_general_log;
+static volatile int ncalls_general_error;
+static volatile int ncalls_general_result;
 
+FILE *f;
 
 /*
   Initialize the plugin at server start or plugin installation.
@@ -44,11 +45,16 @@ static volatile int number_of_calls_gene
 
 static int audit_null_plugin_init(void *arg __attribute__((unused)))
 {
-  number_of_calls= 0;
-  number_of_calls_general_log= 0;
-  number_of_calls_general_error= 0;
-  number_of_calls_general_result= 0;
-  return(0);
+  ncalls= 0;
+  ncalls_general_log= 0;
+  ncalls_general_error= 0;
+  ncalls_general_result= 0;
+
+  f = fopen("audit_null_tables.log", "w");
+  if (!f)
+    return 1;
+
+  return 0;
 }
 
 
@@ -67,7 +73,8 @@ static int audit_null_plugin_init(void *
 
 static int audit_null_plugin_deinit(void *arg __attribute__((unused)))
 {
-  return(0);
+  fclose(f);
+  return 0;
 }
 
 
@@ -86,7 +93,7 @@ static void audit_null_notify(MYSQL_THD
                               const void *event)
 {
   /* prone to races, oh well */
-  number_of_calls++;
+  ncalls++;
   if (event_class == MYSQL_AUDIT_GENERAL_CLASS)
   {
     const struct mysql_event_general *event_general=
@@ -94,18 +101,56 @@ static void audit_null_notify(MYSQL_THD
     switch (event_general->event_subclass)
     {
     case MYSQL_AUDIT_GENERAL_LOG:
-      number_of_calls_general_log++;
+      ncalls_general_log++;
+      fprintf(f, "%s\t>> %s\n", event_general->general_user,
+              event_general->general_query);
       break;
     case MYSQL_AUDIT_GENERAL_ERROR:
-      number_of_calls_general_error++;
+      ncalls_general_error++;
       break;
     case MYSQL_AUDIT_GENERAL_RESULT:
-      number_of_calls_general_result++;
+      ncalls_general_result++;
       break;
     default:
       break;
     }
   }
+  else
+  if (event_class == MYSQL_AUDIT_TABLE_CLASS)
+  {
+    const struct mysql_event_table *event_table=
+      (const struct mysql_event_table *) event;
+    const char *ip= event_table->ip ? event_table->ip : "";
+    const char *op= 0;
+    char buf[1024];
+
+    switch (event_table->event_subclass)
+    {
+    case MYSQL_AUDIT_TABLE_LOCK:
+      op= event_table->read_only ? "read" : "write";
+      break;
+    case MYSQL_AUDIT_TABLE_CREATE:
+      op= "create";
+      break;
+    case MYSQL_AUDIT_TABLE_DROP:
+      op= "drop";
+      break;
+    case MYSQL_AUDIT_TABLE_ALTER:
+      op= "alter";
+      break;
+    case MYSQL_AUDIT_TABLE_RENAME:
+      snprintf(buf, sizeof(buf), "rename to %s.%s",
+               event_table->new_database, event_table->new_table);
+      buf[sizeof(buf)-1]= 0;
+      op= buf;
+      break;
+    }
+
+    fprintf(f, "%s[%s] @ %s [%s]\t%s.%s : %s\n",
+            event_table->priv_user, event_table->user,
+            event_table->host, ip,
+            event_table->database, event_table->table, op);
+  }
 }
 
 
@@ -127,12 +170,10 @@ static struct st_mysql_audit audit_null_
 
 static struct st_mysql_show_var simple_status[]=
 {
-  { "Audit_null_called", (char *) &number_of_calls, SHOW_INT },
-  { "Audit_null_general_log", (char *) &number_of_calls_general_log, SHOW_INT },
-  { "Audit_null_general_error", (char *) &number_of_calls_general_error,
-    SHOW_INT },
-  { "Audit_null_general_result", (char *) &number_of_calls_general_result,
-    SHOW_INT },
+  { "Audit_null_called", (char *) &ncalls, SHOW_INT },
+  { "Audit_null_general_log", (char *) &ncalls_general_log, SHOW_INT },
+  { "Audit_null_general_error", (char *) &ncalls_general_error, SHOW_INT },
+  { "Audit_null_general_result", (char *) &ncalls_general_result, SHOW_INT },
   { 0, 0, 0}
 };
 
=== modified file 'sql/handler.cc'
--- sql/handler.cc	2013-01-18 18:04:23 +0000
+++ sql/handler.cc	2013-04-17 07:31:24 +0000
@@ -43,6 +43,7 @@
 #include "myisam.h"
 #include "probes_mysql.h"
 #include "debug_sync.h"         // DEBUG_SYNC
+#include "sql_audit.h"
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
 #include "ha_partition.h"
@@ -3722,8 +3722,11 @@ int
 handler::ha_create(const char *name, TABLE *form, HA_CREATE_INFO *info)
 {
   mark_trx_read_write();
-
-  return create(name, form, info);
+  int error= create(name, form, info);
+  if (!error &&
+      !(info->options & (HA_LEX_CREATE_TMP_TABLE | HA_CREATE_TMP_ALTER)))
+    mysql_audit_create_table(form);
+  return error;
 }
 
 
@@ -5099,7 +5102,11 @@ int handler::ha_external_lock(THD *thd,
   int error= external_lock(thd, lock_type);
 
   if (error == 0)
+  {
     cached_table_flags= table_flags();
+    if (table_share->tmp_table == NO_TMP_TABLE)
+      mysql_audit_external_lock(thd, table_share, lock_type);
+  }
 
   if (MYSQL_HANDLER_RDLOCK_DONE_ENABLED() ||
       MYSQL_HANDLER_WRLOCK_DONE_ENABLED() ||
=== modified file 'sql/handler.h'
--- sql/handler.h	2013-01-18 18:04:23 +0000
+++ sql/handler.h	2013-04-17 07:31:24 +0000
@@ -318,6 +318,7 @@
 #define HA_LEX_CREATE_TMP_TABLE	1
 #define HA_LEX_CREATE_IF_NOT_EXISTS 2
 #define HA_LEX_CREATE_TABLE_LIKE 4
+#define HA_CREATE_TMP_ALTER    8
 #define HA_MAX_REC_LENGTH	65535
 
 /* Table caching type */
=== modified file 'sql/sql_audit.cc'
--- sql/sql_audit.cc	2013-01-15 18:16:29 +0000
+++ sql/sql_audit.cc	2013-04-17 07:31:24 +0000
@@ -111,9 +110,36 @@ static void connection_class_handler(THD
 }
 
 
+static void table_class_handler(THD *thd, uint event_subclass, va_list ap)
+{
+  mysql_event_table event;
+  event.event_subclass= event_subclass;
+  event.read_only= va_arg(ap, int);
+  event.thread_id= va_arg(ap, unsigned long);
+  event.user= va_arg(ap, const char *);
+  event.priv_user= va_arg(ap, const char *);
+  event.priv_host= va_arg(ap, const char *);
+  event.external_user= va_arg(ap, const char *);
+  event.proxy_user= va_arg(ap, const char *);
+  event.host= va_arg(ap, const char *);
+  event.ip= va_arg(ap, const char *);
+  event.database= va_arg(ap, const char *);
+  event.database_length= va_arg(ap, unsigned int);
+  event.table= va_arg(ap, const char *);
+  event.table_length= va_arg(ap, unsigned int);
+  event.new_database= va_arg(ap, const char *);
+  event.new_database_length= va_arg(ap, unsigned int);
+  event.new_table= va_arg(ap, const char *);
+  event.new_table_length= va_arg(ap, unsigned int);
+  event_class_dispatch(thd, MYSQL_AUDIT_TABLE_CLASS, &event);
+}
+
+
 static audit_handler_t audit_handlers[] =
 {
-  general_class_handler, connection_class_handler
+  general_class_handler, connection_class_handler,
+  0,0,0,0,0,0,0,0,0,0,0,0,0, /* placeholders */
+  table_class_handler
 };
 
 static const uint audit_handlers_count=
=== modified file 'sql/sql_audit.h'
--- sql/sql_audit.h	2013-01-15 18:16:29 +0000
+++ sql/sql_audit.h	2013-04-17 07:31:24 +0000
@@ -43,17 +43,23 @@ static inline bool mysql_audit_general_e
   return mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK;
 }
 
+static inline bool mysql_audit_table_enabled()
+{
+  return mysql_global_audit_mask[0] & MYSQL_AUDIT_TABLE_CLASSMASK;
+}
+
 #else
 static inline void mysql_audit_notify(THD *thd, uint event_class,
                                       uint event_subtype, ...) { }
 #define mysql_audit_general_enabled() 0
+#define mysql_audit_table_enabled() 0
 #endif
 extern void mysql_audit_release(THD *thd);
 
 #define MAX_USER_HOST_SIZE 512
 static inline uint make_user_name(THD *thd, char *buf)
 {
-  Security_context *sctx= thd->security_ctx;
+  const Security_context *sctx= thd->security_ctx;
   return strxnmov(buf, MAX_USER_HOST_SIZE,
                   sctx->priv_user[0] ? sctx->priv_user : "", "[",
                   sctx->user ? sctx->user : "", "] @ ",
@@ -174,4 +180,87 @@ void mysql_audit_general(THD *thd, uint
   (thd)->security_ctx->ip ? strlen((thd)->security_ctx->ip) : 0,\
   (thd)->db, (thd)->db ? strlen((thd)->db) : 0)
 
+static inline
+void mysql_audit_external_lock(THD *thd, TABLE_SHARE *share, int lock)
+{
+  if (lock != F_UNLCK && mysql_audit_table_enabled())
+  {
+    const Security_context *sctx= thd->security_ctx;
+    mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, MYSQL_AUDIT_TABLE_LOCK,
+                       (int)(lock == F_RDLCK), (ulong)thd->thread_id,
+                       sctx->user, sctx->priv_user, sctx->priv_host,
+                       sctx->external_user, sctx->proxy_user, sctx->host,
+                       sctx->ip, share->db.str, (uint)share->db.length,
+                       share->table_name.str, (uint)share->table_name.length,
+                       0,0,0,0);
+  }
+}
+
+static inline
+void mysql_audit_create_table(TABLE *table)
+{
+  if (mysql_audit_table_enabled())
+  {
+    THD *thd= table->in_use;
+    const TABLE_SHARE *share= table->s;
+    const Security_context *sctx= thd->security_ctx;
+    mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, MYSQL_AUDIT_TABLE_CREATE,
+                       0, (ulong)thd->thread_id,
+                       sctx->user, sctx->priv_user, sctx->priv_host,
+                       sctx->external_user, sctx->proxy_user, sctx->host,
+                       sctx->ip, share->db.str, (uint)share->db.length,
+                       share->table_name.str, (uint)share->table_name.length,
+                       0,0,0,0);
+  }
+}
+
+static inline
+void mysql_audit_drop_table(THD *thd, TABLE_LIST *table)
+{
+  if (mysql_audit_table_enabled())
+  {
+    const Security_context *sctx= thd->security_ctx;
+    mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, MYSQL_AUDIT_TABLE_DROP,
+                       0, (ulong)thd->thread_id,
+                       sctx->user, sctx->priv_user, sctx->priv_host,
+                       sctx->external_user, sctx->proxy_user, sctx->host,
+                       sctx->ip, table->db, (uint)table->db_length,
+                       table->table_name, (uint)table->table_name_length,
+                       0,0,0,0);
+  }
+}
+
+static inline
+void mysql_audit_rename_table(THD *thd, const char *old_db, const char *old_tb,
+                              const char *new_db, const char *new_tb)
+{
+  if (mysql_audit_table_enabled())
+  {
+    const Security_context *sctx= thd->security_ctx;
+    mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, MYSQL_AUDIT_TABLE_RENAME,
+                       0, (ulong)thd->thread_id,
+                       sctx->user, sctx->priv_user, sctx->priv_host,
+                       sctx->external_user, sctx->proxy_user, sctx->host,
+                       sctx->ip,
+                       old_db, (uint)strlen(old_db), old_tb, (uint)strlen(old_tb),
+                       new_db, (uint)strlen(new_db), new_tb, (uint)strlen(new_tb));
+  }
+}
+
+static inline
+void mysql_audit_alter_table(THD *thd, TABLE_LIST *table)
+{
+  if (mysql_audit_table_enabled())
+  {
+    const Security_context *sctx= thd->security_ctx;
+    mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, MYSQL_AUDIT_TABLE_ALTER,
+                       0, (ulong)thd->thread_id,
+                       sctx->user, sctx->priv_user, sctx->priv_host,
+                       sctx->external_user, sctx->proxy_user, sctx->host,
+                       sctx->ip, table->db, (uint)table->db_length,
+                       table->table_name, (uint)table->table_name_length,
+                       0,0,0,0);
+  }
+}
+
 #endif /* SQL_AUDIT_INCLUDED */
=== modified file 'sql/sql_table.cc'
--- sql/sql_table.cc	2013-03-05 18:15:36 +0000
+++ sql/sql_table.cc	2013-04-17 07:31:24 +0000
@@ -54,6 +54,7 @@
 #include "sql_show.h"
 #include "transaction.h"
 #include "datadict.h"  // dd_frm_type()
+#include "sql_audit.h"
 
 #ifdef __WIN__
 #include <io.h>
@@ -2344,6 +2345,10 @@ int mysql_rm_table_no_locks(THD *thd, TA
 	wrong_tables.append(',');
       wrong_tables.append(String(table->table_name,system_charset_info));
     }
+    else
+    {
+      mysql_audit_drop_table(thd, table);
+    }
     DBUG_PRINT("table", ("table: 0x%lx  s: 0x%lx", (long) table->table,
                          table->table ? (long) table->table->s : (long) -1));
 
@@ -4728,6 +4733,8 @@ mysql_rename_table(handlerton *base, con
     my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
   else if (error)
     my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
+  else if (!(flags & FN_IS_TMP))
+    mysql_audit_rename_table(thd, old_db, old_name, new_db, new_name);
   DBUG_RETURN(error != 0);
 }
 
@@ -6054,6 +6061,8 @@ bool mysql_alter_table(THD *thd,char *ne
 
   mysql_ha_rm_tables(thd, table_list);
 
+  mysql_audit_alter_table(thd, table_list);
+
   /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
   if (alter_info->tablespace_op != NO_TABLESPACE_OP)
     /* Conditionally writes to binlog. */
@@ -6716,6 +6725,7 @@ bool mysql_alter_table(THD *thd,char *ne
                                   HA_OPTION_PACK_RECORD));
   }
   tmp_disable_binlog(thd);
+  create_info->options|=HA_CREATE_TMP_ALTER;
   error= mysql_create_table_no_lock(thd, new_db, tmp_name,
                                     create_info,
                                     alter_info,