You've already forked mysql-audit
mirror of
https://github.com/trellix-enterprise/mysql-audit.git
synced 2025-12-14 18:14:01 +08:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd928db022 | ||
|
|
622366a459 | ||
|
|
3ec0c137c9 | ||
|
|
a875a835a4 | ||
|
|
2b130c7bd7 | ||
|
|
266447b8b7 | ||
|
|
416e6fa0aa | ||
|
|
edbed38f42 | ||
|
|
72af9c00f4 | ||
|
|
637d30a568 | ||
|
|
a52594c59c | ||
|
|
cb2cbc605c | ||
|
|
52c611cef8 | ||
|
|
6ea0b6bd15 | ||
|
|
2d0a23c73d | ||
|
|
bca3715fb5 | ||
|
|
d9786405af | ||
|
|
286197fe6d | ||
|
|
40dc1e7ff7 | ||
|
|
969d0b481a | ||
|
|
e7d07fc1fe |
@@ -42,7 +42,7 @@ Source code is available at: https://github.com/mcafee/mysql-audit
|
||||
|
||||
License
|
||||
-------------------------------
|
||||
Copyright (C) 2011-2017 McAfee, Inc.
|
||||
Copyright (C) 2011-2021 McAfee, LLC.
|
||||
|
||||
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.
|
||||
|
||||
@@ -52,6 +52,8 @@ first (see www.boost.org). In such a case, use:
|
||||
|
||||
Note: For MariaDB use: cmake . -DBUILD_CONFIG=mysql_release
|
||||
|
||||
Note: For Percona`s MySQL use: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_CONFIG=mysql_release -DWITH_BOOST=boost_1_59_0 .
|
||||
|
||||
Note: to speed things up it is possible to build just the following directories:
|
||||
libservices
|
||||
extra
|
||||
@@ -63,6 +65,8 @@ chmod +x bootstrap.sh
|
||||
CXX='gcc -static-libgcc' CC='gcc -static-libgcc' ./configure --with-mysql=mysql-5.x.x --with-mysql-libservices=mysql-5.x.x/libservices/libmysqlservices.a
|
||||
make
|
||||
|
||||
Note: For Percona`s MySQL define also PERCONA_BUILD=true variable, like "PERCONA_BUILD=true ./configure..."
|
||||
|
||||
==== Compiling with make =====
|
||||
|
||||
Go to top source dir and run:
|
||||
@@ -77,3 +81,20 @@ Some documentation about configure command for mysql:
|
||||
|
||||
http://dev.mysql.com/doc/refman/5.1/en/source-configuration-options.html
|
||||
|
||||
|
||||
==== MariaDB 10.2.10 ======
|
||||
1. Firstly checkout the source code:-
|
||||
- svn co https://beasource3.corp.nai.org/svn/projects/DBSec-MySQL audit_plugin_mysql
|
||||
2. cd audit_plugin_mysql
|
||||
3. unzip zip-sources/mariadb-10.2.10.zip
|
||||
4. cd mariadb-10.2.10
|
||||
5. CC=gcc CXX=g++ cmake . -DBUILD_CONFIG=mysql_release -DGNUTLS_INCLUDE_DIR=./zip-sources/mariadb-10.2.10/gnutls-3.3.24/64b/include -DGNUTLS_LIBRARY=./zip-sources/mariadb-10.2.10/gnutls-3.3.24/64b/lib
|
||||
6. cd mariadb-10.2.10/libservices
|
||||
7. make
|
||||
8. cd ../extra
|
||||
9. make
|
||||
10. cd ../..
|
||||
11. chmod +x bootstrap.sh
|
||||
12. ./bootstrap.sh
|
||||
13. CXX='gcc -static-libgcc' CC='gcc -static-libgcc' MYSQL_AUDIT_PLUGIN_VERSION=1.1.7 MYSQL_AUDIT_PLUGIN_REVISION=`svn info|grep ^Revision|awk -F ": " '{print $2}'` ./configure --enable-debug=no --with-mysql=mariadb-10.2.10 --with-mysql-libservices=mariadb-10.2.10/libservices/libmysqlservices.a
|
||||
14. gmake <======== This will create the plugin "libaudit_plugin.so"
|
||||
|
||||
@@ -33,7 +33,7 @@ dnl
|
||||
dnl table_id.h included from table.h included by mysql_inc.h is
|
||||
dnl in libbinlogevents/include.
|
||||
AC_DEFINE([MYSQL_SRC], [1], [Source directory for MySQL])
|
||||
MYSQL_INC="-I$withval/sql -I$withval/libbinlogevents/export -I$withval/libbinlogevents/include -I$withval/include -I$withval/regex -I$withval"
|
||||
MYSQL_INC="-I$withval/sql -I$withval/libbinlogevents/export -I$withval/libbinlogevents/include -I$withval/include -I$withval/regex -I$withval -I$withval/extra/rapidjson/include"
|
||||
AC_MSG_RESULT(["$withval"])
|
||||
],
|
||||
[
|
||||
|
||||
@@ -96,8 +96,7 @@ AC_PATH_PROG(DIFF, diff, diff)
|
||||
#we can add the following flags for better error catching: -Werror -Wimplicit
|
||||
CPPFLAGS="$CPPFLAGS -Werror -Wall"
|
||||
CFLAGS="$CFLAGS -Wimplicit"
|
||||
# From MySQL: Disable exceptions as they seams to create problems with gcc and threads.
|
||||
CXXFLAGS="-fno-implicit-templates -fno-exceptions -fno-rtti -Wno-reorder -Wno-strict-aliasing"
|
||||
CXXFLAGS="-fno-implicit-templates -fno-strict-aliasing"
|
||||
|
||||
#add pthread libs
|
||||
LIBS="$LIBS -lpthread"
|
||||
@@ -128,6 +127,10 @@ CPPFLAGS="$CPPFLAGS -DMYSQL_AUDIT_PLUGIN_VERSION='\"$MYSQL_AUDIT_PLUGIN_VERSION\
|
||||
CPPFLAGS="$CPPFLAGS -DMYSQL_AUDIT_PLUGIN_REVISION='\"$MYSQL_AUDIT_PLUGIN_REVISION\"'"
|
||||
CPPFLAGS="$CPPFLAGS '-DMYSQL_AUDIT_PLUGIN_SYMBOL_VERSION()=extern const char audit_plugin_version_$MYSQL_AUDIT_PLUGIN_SYMBOL_VERSION'"
|
||||
|
||||
# Percona`s MySQL macro
|
||||
if [[ "$PERCONA_BUILD" = "true" ]]; then
|
||||
CPPFLAGS="$CPPFLAGS -DPERCONA_BUILD" # Percona`s build macro, used to distinguish between MySQL/MariaDB build VS Percona build
|
||||
fi
|
||||
|
||||
#subst the relevant variables
|
||||
AC_SUBST(CPPFLAGS)
|
||||
|
||||
@@ -69,7 +69,7 @@ typedef size_t OFFSET;
|
||||
|
||||
// mysql max identifier is 64 so 2*64 + . and null
|
||||
#define MAX_OBJECT_CHAR_NUMBERS 131
|
||||
#define MAX_USER_CHAR_NUMBERS 20
|
||||
#define MAX_USER_CHAR_NUMBERS 32
|
||||
#define MAX_NUM_OBJECT_ELEM 256
|
||||
#define MAX_NUM_USER_ELEM 256
|
||||
|
||||
@@ -101,6 +101,10 @@ typedef struct ThdOffsets {
|
||||
OFFSET found_rows;
|
||||
OFFSET sent_row_count;
|
||||
OFFSET row_count_func;
|
||||
OFFSET stmt_da;
|
||||
OFFSET da_status;
|
||||
OFFSET da_sql_errno;
|
||||
OFFSET view_tables;
|
||||
} ThdOffsets;
|
||||
|
||||
/*
|
||||
@@ -145,6 +149,9 @@ public:
|
||||
const char *getOsUser() const;
|
||||
const int getPort() const { return m_port; }
|
||||
const StatementSource getStatementSource() const { return m_source; }
|
||||
void storeErrorCode();
|
||||
void setErrorCode(uint code) { m_errorCode = code; m_setErrorCode = true; }
|
||||
bool getErrorCode(uint & code) const { code = m_errorCode; return m_setErrorCode; }
|
||||
/**
|
||||
* Start fetching objects. Return true if there are objects available.
|
||||
*/
|
||||
@@ -178,6 +185,9 @@ private:
|
||||
|
||||
int m_port; // TCP port of remote side
|
||||
|
||||
uint m_errorCode;
|
||||
bool m_setErrorCode;
|
||||
|
||||
protected:
|
||||
ThdSesData(const ThdSesData&);
|
||||
ThdSesData &operator =(const ThdSesData&);
|
||||
@@ -215,7 +225,9 @@ public:
|
||||
virtual ssize_t stop_msg_format(IWriter *writer) { return 0; }
|
||||
|
||||
static const char *retrieve_object_type(TABLE_LIST *pObj);
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
static QueryTableInf *getQueryCacheTableList1(THD *thd);
|
||||
#endif
|
||||
|
||||
// utility functions for fetching thd stuff
|
||||
static int thd_client_port(THD *thd);
|
||||
@@ -278,7 +290,9 @@ public:
|
||||
static inline const char *thd_inst_main_security_ctx_host(THD *thd)
|
||||
{
|
||||
Security_context *sctx = thd_inst_main_security_ctx(thd);
|
||||
if (! Audit_formatter::thd_offsets.sec_ctx_ip) // check ip to understand if set as host is first and may actually be set to 0
|
||||
// check ip to understand if set, as host is first in the struct and may actually be set to 0
|
||||
// we expect to have offsets for both ip and host or for neither of them
|
||||
if (! Audit_formatter::thd_offsets.sec_ctx_ip)
|
||||
{
|
||||
// interface changed in 5.5.34 and 5.6.14 and up host changed to get_host()
|
||||
// see: http://bazaar.launchpad.net/~mysql/mysql-server/5.5/revision/4407.1.1/sql/sql_class.h
|
||||
@@ -337,15 +351,9 @@ public:
|
||||
return sctx->priv_user().str;
|
||||
#endif
|
||||
}
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
// in 5.1.x priv_user is a pointer
|
||||
return *(const char **) (((unsigned char *) sctx)
|
||||
+ Audit_formatter::thd_offsets.sec_ctx_priv_user);
|
||||
#else
|
||||
// in 5.5 and up priv_user is an array (char priv_user[USERNAME_LENGTH])
|
||||
return (const char *) (((unsigned char *) sctx)
|
||||
+ Audit_formatter::thd_offsets.sec_ctx_priv_user);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int thd_inst_command(THD *thd)
|
||||
@@ -389,23 +397,19 @@ public:
|
||||
|
||||
static inline const char * pfs_connect_attrs(void * pfs)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs)
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs || pfs == NULL)
|
||||
{
|
||||
//no offsets - return null
|
||||
return NULL;
|
||||
}
|
||||
const char **pfs_pointer = (const char **) (((unsigned char *) pfs) + Audit_formatter::thd_offsets.pfs_connect_attrs);
|
||||
if (pfs_pointer == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return *pfs_pointer;
|
||||
}
|
||||
|
||||
static inline uint pfs_connect_attrs_length(void * pfs)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs_length)
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs_length || pfs == NULL)
|
||||
{
|
||||
//no offsets - return 0
|
||||
return 0;
|
||||
@@ -415,7 +419,7 @@ public:
|
||||
|
||||
static inline const CHARSET_INFO * pfs_connect_attrs_cs(void * pfs)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs_cs)
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs_cs || pfs == NULL)
|
||||
{
|
||||
//no offsets - return null
|
||||
return NULL;
|
||||
@@ -437,7 +441,7 @@ static inline const CHARSET_INFO * pfs_connect_attrs_cs(void * pfs)
|
||||
// major, minor, patch);
|
||||
}
|
||||
|
||||
if ( ( major == 5 && ( (minor == 6 && patch >= 15) || minor >= 7) ) // MySQL
|
||||
if ( ( major == 5 && ( (minor == 6 && patch >= 15) || minor >= 7) ) || (major == 8) // MySQL
|
||||
|| ( major == 10 && ( (minor == 0 && patch >= 11) || minor >= 1) ) ) // MariaDB
|
||||
{
|
||||
uint cs_number = *(uint *) (((unsigned char *) pfs) + Audit_formatter::thd_offsets.pfs_connect_attrs_cs);
|
||||
@@ -516,6 +520,47 @@ static inline const CHARSET_INFO * pfs_connect_attrs_cs(void * pfs)
|
||||
return *rows;
|
||||
}
|
||||
|
||||
static inline bool thd_error_code(THD *thd, uint & code)
|
||||
{
|
||||
#if MYSQL_VERSION_ID >= 50534
|
||||
|
||||
if ( Audit_formatter::thd_offsets.stmt_da == 0 ||
|
||||
Audit_formatter::thd_offsets.da_status == 0 ||
|
||||
Audit_formatter::thd_offsets.da_sql_errno == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Diagnostics_area **stmt_da = ((Diagnostics_area **) (((unsigned char *) thd)
|
||||
+ Audit_formatter::thd_offsets.stmt_da));
|
||||
|
||||
enum Diagnostics_area::enum_diagnostics_status *status =
|
||||
((enum Diagnostics_area::enum_diagnostics_status *) (((unsigned char *) (*stmt_da))
|
||||
+ Audit_formatter::thd_offsets.da_status));
|
||||
|
||||
uint *sql_errno = ((uint *) (((unsigned char *) (*stmt_da))
|
||||
+ Audit_formatter::thd_offsets.da_sql_errno));
|
||||
|
||||
if (*status == Diagnostics_area::DA_OK ||
|
||||
*status == Diagnostics_area::DA_EOF )
|
||||
{
|
||||
code = 0;
|
||||
return true;
|
||||
}
|
||||
else if (*status == Diagnostics_area::DA_ERROR)
|
||||
{
|
||||
code = *sql_errno;
|
||||
return true;
|
||||
}
|
||||
else // DA_EMPTY, DA_DISABLE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709
|
||||
static inline Sql_cmd_uninstall_plugin* lex_sql_cmd(LEX *lex)
|
||||
{
|
||||
@@ -537,7 +582,10 @@ static inline const CHARSET_INFO * pfs_connect_attrs_cs(void * pfs)
|
||||
|
||||
static inline bool table_is_view(TABLE_LIST *table)
|
||||
{
|
||||
return table->view_tables != 0;
|
||||
if (!Audit_formatter::thd_offsets.view_tables)
|
||||
return table->view_tables != 0;
|
||||
List<TABLE_LIST> **view_tables = (List<TABLE_LIST> **)((char*)table + Audit_formatter::thd_offsets.view_tables);
|
||||
return *view_tables;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -550,14 +598,14 @@ public:
|
||||
static const char *DEF_MSG_DELIMITER;
|
||||
|
||||
Audit_json_formatter()
|
||||
: m_msg_delimiter(NULL),
|
||||
m_write_start_msg(true),
|
||||
: m_write_start_msg(true),
|
||||
m_write_sess_connect_attrs(true),
|
||||
m_write_client_capabilities(false),
|
||||
m_write_socket_creds(true),
|
||||
m_password_mask_regex_preg(NULL),
|
||||
m_perform_password_masking(NULL),
|
||||
m_msg_delimiter(NULL),
|
||||
m_password_mask_regex_compiled(false),
|
||||
m_perform_password_masking(NULL)
|
||||
m_password_mask_regex_preg(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -664,8 +712,12 @@ public:
|
||||
static void stop_all();
|
||||
|
||||
Audit_handler() :
|
||||
m_initialized(false), m_enabled(false), m_print_offset_err(true),
|
||||
m_formatter(NULL), m_failed(false), m_log_io_errors(true)
|
||||
m_formatter()
|
||||
,m_initialized()
|
||||
,m_enabled()
|
||||
,m_failed()
|
||||
,m_log_io_errors(true)
|
||||
,m_print_offset_err(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -831,7 +883,10 @@ class Audit_file_handler: public Audit_io_handler {
|
||||
public:
|
||||
|
||||
Audit_file_handler() :
|
||||
m_sync_period(0), m_log_file(NULL), m_sync_counter(0), m_bufsize(0)
|
||||
m_sync_period(0)
|
||||
, m_bufsize(0)
|
||||
, m_log_file(NULL)
|
||||
, m_sync_counter(0)
|
||||
{
|
||||
m_io_type = "file";
|
||||
}
|
||||
@@ -878,8 +933,10 @@ class Audit_socket_handler: public Audit_io_handler {
|
||||
public:
|
||||
|
||||
Audit_socket_handler() :
|
||||
m_vio(NULL), m_connect_timeout(1), m_write_timeout(0),
|
||||
m_log_with_error_severity(false)
|
||||
m_connect_timeout(1)
|
||||
, m_write_timeout()
|
||||
, m_vio()
|
||||
, m_log_with_error_severity()
|
||||
{
|
||||
m_io_type = "socket";
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Created on: Jan 10, 2011
|
||||
* Author: Guyl
|
||||
*/
|
||||
|
||||
#ifndef HOT_PATCH_H_
|
||||
#define HOT_PATCH_H_
|
||||
|
||||
@@ -14,9 +13,14 @@
|
||||
|
||||
#define GETPAGESIZE() sysconf (_SC_PAGE_SIZE)
|
||||
|
||||
int hot_patch_function(void* targetFunction, void* newFunction, void* trampolineFunction, unsigned int *trampolinesize, unsigned int *usedsize, bool log_info);
|
||||
struct SavedCode {
|
||||
char code [1024];
|
||||
size_t size;
|
||||
};
|
||||
|
||||
void remove_hot_patch_function(void* targetFunction, void* trampolineFunction, unsigned int trampolinesize, bool log_info);
|
||||
int hot_patch_function(void* targetFunction, void* newFunction, void* trampolineFunction, unsigned int *trampolinesize, unsigned int *usedsize, bool log_info, SavedCode* saved_code);
|
||||
|
||||
void remove_hot_patch_function(void* targetFunction, void* trampolineFunction, unsigned int trampolinesize, bool log_info, SavedCode* saved_code);
|
||||
|
||||
//8KB NOP + 16
|
||||
//can be used to define a block of memory to use for trampolines
|
||||
|
||||
@@ -17,12 +17,6 @@
|
||||
#include <my_config.h>
|
||||
#include <mysql_version.h>
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
#include <mysql_priv.h>
|
||||
#else
|
||||
|
||||
// version 5.5.x doesn't contain mysql_priv.h . We need to add the includes provided by it.
|
||||
#if MYSQL_VERSION_ID >= 50505
|
||||
|
||||
// These two are not present in 5.7.9
|
||||
#if MYSQL_VERSION_ID < 50709
|
||||
@@ -39,11 +33,31 @@
|
||||
|
||||
#include <sql_parse.h>
|
||||
#include <sql_class.h>
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80019
|
||||
#include <mysql/components/services/mysql_connection_attributes_iterator.h>
|
||||
#include <mysql/components/my_service.h>
|
||||
#include <mysql/service_plugin_registry.h>
|
||||
#endif
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80000
|
||||
using my_bool = bool;
|
||||
#if MYSQL_VERSION_ID < 80012
|
||||
#define PLUGIN_VAR_NOSYSVAR 0x0400
|
||||
#endif
|
||||
#include <sql/item.h>
|
||||
#include <sql/log.h>
|
||||
#include <sql/log_event.h>
|
||||
#include <sql/mysqld.h>
|
||||
#include <sql/protocol.h>
|
||||
#include <sql/sql_lex.h>
|
||||
#else
|
||||
#include <my_global.h>
|
||||
typedef struct st_mysql_sys_var SYS_VAR;
|
||||
#endif
|
||||
#include <sql_connect.h>
|
||||
#include <sql/sql_base.h>
|
||||
#include <sql/sql_table.h>
|
||||
#include <sql/sql_view.h>
|
||||
#include <sql/sql_error.h>
|
||||
|
||||
// TODO: use mysql mutex instead of pthread
|
||||
/*
|
||||
@@ -53,8 +67,6 @@
|
||||
#define pthread_mutex_destroy mysql_mutex_destroy
|
||||
#define pthread_mutex_t mysql_mutex_t
|
||||
*/
|
||||
#endif /* ! if MYSQL_VERSION_ID >= 50505 */
|
||||
#endif /* ! if MYSQL_VERSION_ID < 50505 */
|
||||
|
||||
#if MYSQL_VERSION_ID >= 50709
|
||||
#include <sql/log.h>
|
||||
@@ -80,10 +92,7 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// MariaDB doesn't have my_getsystime (returns 100 nano seconds) function. They replaced with my_hrtime_t my_hrtime() which returns microseconds
|
||||
#if defined(MARIADB_BASE_VERSION)
|
||||
|
||||
#define my_getsystime() ((my_hrtime()).val * 10)
|
||||
#if defined(MARIADB_BASE_VERSION)
|
||||
// MariaDB has a kill service that overrides thd_killed as a macro. It also has thd_killed function defined for backwards compatibility, so we redefine it.
|
||||
#undef thd_killed
|
||||
extern "C" int thd_killed(const MYSQL_THD thd);
|
||||
@@ -92,7 +101,6 @@ extern "C" int thd_killed(const MYSQL_THD thd);
|
||||
#if MYSQL_VERSION_ID >= 100010
|
||||
extern "C" char *thd_security_context(MYSQL_THD thd, char *buffer, unsigned int length, unsigned int max_query_len);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//Define HAVE_SESS_CONNECT_ATTRS. We define it for mysql 5.6 and above
|
||||
@@ -100,4 +108,80 @@ extern "C" char *thd_security_context(MYSQL_THD thd, char *buffer, unsigned int
|
||||
#define HAVE_SESS_CONNECT_ATTRS 1
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
namespace compat {
|
||||
/*************************/
|
||||
/* my_getsystime */
|
||||
/*************************/
|
||||
#if defined(MARIADB_BASE_VERSION)
|
||||
// MariaDB doesn't have my_getsystime (returns 100 nano seconds) function. They replaced with my_hrtime_t my_hrtime() which returns microseconds
|
||||
static inline unsigned long long int my_getsystime() { return (my_hrtime()).val * 10; }
|
||||
#elif MYSQL_VERSION_ID < 80000
|
||||
static inline unsigned long long int my_getsystime() { return ::my_getsystime(); }
|
||||
#else
|
||||
static inline unsigned long long int my_getsystime() {
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
// Performance regression testing showed this to be preferable
|
||||
struct timespec tp;
|
||||
clock_gettime(CLOCK_REALTIME, &tp);
|
||||
return (static_cast<unsigned long long int>(tp.tv_sec) * 10000000 +
|
||||
static_cast<unsigned long long int>(tp.tv_nsec) / 100);
|
||||
#else
|
||||
return std::chrono::duration_cast<
|
||||
std::chrono::duration<std::int64_t, std::ratio<1, 10000000>>>(
|
||||
UTC_clock::now().time_since_epoch())
|
||||
.count();
|
||||
#endif /* HAVE_CLOCK_GETTIME */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************/
|
||||
/* vio_socket_connect */
|
||||
/*********************************************/
|
||||
#if MYSQL_VERSION_ID >= 50600
|
||||
#ifndef MYSQL_VIO
|
||||
#define MYSQL_VIO Vio*
|
||||
#endif
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
static inline bool vio_socket_connect(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, int timeout)
|
||||
{
|
||||
return ::vio_socket_connect(vio, addr, len, timeout);
|
||||
}
|
||||
#else
|
||||
/*********************************************/
|
||||
/* */
|
||||
/* resolve the symbols manualy to permit */
|
||||
/* loading of the plugin in their absence */
|
||||
/* */
|
||||
/*********************************************/
|
||||
extern bool (*_vio_socket_connect)(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, int timeout);
|
||||
extern bool (*_vio_socket_connect_80016)(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, bool nonblocking, int timeout);
|
||||
extern bool (*_vio_socket_connect_80020)(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, bool nonblocking, int timeout, bool *connect_done);
|
||||
|
||||
static inline bool vio_socket_connect(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, int timeout)
|
||||
{
|
||||
if (_vio_socket_connect) return _vio_socket_connect(vio, addr, len, timeout);
|
||||
if (_vio_socket_connect_80016) return _vio_socket_connect_80016(vio, addr, len, false, timeout);
|
||||
if (_vio_socket_connect_80020) return _vio_socket_connect_80020(vio, addr, len, false, timeout, nullptr);
|
||||
return true;
|
||||
}
|
||||
static inline bool init()
|
||||
{
|
||||
void* handle = dlopen(NULL, RTLD_LAZY);
|
||||
if (!handle)
|
||||
return false;
|
||||
_vio_socket_connect = (decltype(_vio_socket_connect))dlsym(handle, "_Z18vio_socket_connectP3VioP8sockaddrji");
|
||||
_vio_socket_connect_80016 = (decltype(_vio_socket_connect_80016))dlsym(handle, "_Z18vio_socket_connectP3VioP8sockaddrjbi");
|
||||
_vio_socket_connect_80020 = (decltype(_vio_socket_connect_80020))dlsym(handle, "_Z18vio_socket_connectP3VioP8sockaddrjbiPb");
|
||||
dlclose(handle);
|
||||
return _vio_socket_connect || _vio_socket_connect_80016 || _vio_socket_connect_80020;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // MYSQL_INCL_H
|
||||
|
||||
@@ -32,7 +32,7 @@ DB=db
|
||||
CLIENT_CAPS="print_offset THD client_capabilities"
|
||||
|
||||
# In 5.6 command member is named m_command
|
||||
if echo $MYVER | grep -P '^(5\.6|5\.7|10\.)' > /dev/null
|
||||
if echo $MYVER | grep -P '^(5\.6|5\.7|8\.|10\.)' > /dev/null
|
||||
then
|
||||
COMMAND_MEMBER=m_command
|
||||
HAS_CONNECT_ATTRS=yes
|
||||
@@ -40,7 +40,7 @@ fi
|
||||
|
||||
CONNECT_ATTRS_CS=m_session_connect_attrs_cs
|
||||
# In 5.7 thread_id changed to m_thread_id. main_security_ctx changed to m_main_security_ctx
|
||||
if echo $MYVER | grep -P '^(5\.7)' > /dev/null
|
||||
if echo $MYVER | grep -P '^(5\.7|8\.)' > /dev/null
|
||||
then
|
||||
THREAD_ID=m_thread_id
|
||||
SEC_CONTEXT=m_main_security_ctx
|
||||
@@ -59,7 +59,7 @@ fi
|
||||
|
||||
# In 5.6.15 and up, 5.7 and mariabdb 10.0.11 and up, mariadb 10.1
|
||||
# m_session_connect_attrs_cs changed to m_session_connect_attrs_cs_number
|
||||
if echo $MYVER | grep -P '^(5\.7|10\.[1-2]|5\.6\.(1[5-9]|[2-9][0-9])|10.0.(1[1-9]|[2-9][0-9]))' > /dev/null
|
||||
if echo $MYVER | grep -P '^(5\.7|8\.|10\.[1-2]|5\.6\.(1[5-9]|[2-9][0-9])|10.0.(1[1-9]|[2-9][0-9]))' > /dev/null
|
||||
then
|
||||
CONNECT_ATTRS_CS=m_session_connect_attrs_cs_number
|
||||
fi
|
||||
@@ -75,7 +75,7 @@ else
|
||||
CONNECT_ATTRS='printf ", 0, 0, 0"'
|
||||
fi
|
||||
|
||||
if echo $MYVER | grep -P '^5\.7' > /dev/null
|
||||
if echo $MYVER | grep -P '^(5\.7|8\.0)' > /dev/null
|
||||
then
|
||||
if echo $MYVER | grep -P '^5\.7\.8' > /dev/null
|
||||
then
|
||||
@@ -110,6 +110,37 @@ else
|
||||
LEX_SQL='printf ", 0, 0"'
|
||||
fi
|
||||
|
||||
# Exit status info 5.5, 5.6, 5.7
|
||||
DA_STATUS="print_offset Diagnostics_area m_status" # 5.5, 5.6, 5.7, mariadb 10.0, 10.1, 10.2
|
||||
DA_SQL_ERRNO="print_offset Diagnostics_area m_sql_errno" # 5.5, 5.6, mariadb 10.0, 10.1, 10.2
|
||||
STMT_DA="print_offset THD m_stmt_da" # 5.6, 5.7, mariadb 10.0, 10.1, 10.2
|
||||
|
||||
if echo $MYVER | grep -P '^(5\.7|8\.0)' > /dev/null
|
||||
then
|
||||
DA_SQL_ERRNO="print_offset Diagnostics_area m_mysql_errno"
|
||||
elif echo $MYVER | grep -P '^(5\.6|10\.)' > /dev/null
|
||||
then
|
||||
: place holder
|
||||
elif echo $MYVER | grep -P '^(5\.5)' > /dev/null
|
||||
then
|
||||
STMT_DA="print_offset THD stmt_da"
|
||||
else
|
||||
STMT_DA='printf ", 0"'
|
||||
DA_STATUS='printf ", 0"'
|
||||
DA_SQL_ERRNO='printf ", 0"'
|
||||
fi
|
||||
|
||||
LEX_COMMENT=""
|
||||
VIEW_TABLES=""
|
||||
if echo $MYVER | grep -P '^(8\.0)' > /dev/null
|
||||
then
|
||||
LEX_COMMENT='printf ", 0"'
|
||||
VIEW_TABLES="print_offset TABLE_LIST view_tables"
|
||||
else
|
||||
LEX_COMMENT="print_offset LEX comment"
|
||||
VIEW_TABLES='printf ", 0"'
|
||||
fi
|
||||
|
||||
cat <<EOF > offsets.gdb
|
||||
set logging on
|
||||
set width 0
|
||||
@@ -122,7 +153,7 @@ print_offset THD $THREAD_ID
|
||||
print_offset THD $SEC_CONTEXT
|
||||
print_offset THD $COMMAND_MEMBER
|
||||
print_offset THD lex
|
||||
print_offset LEX comment
|
||||
$LEX_COMMENT
|
||||
print_offset Security_context $USER
|
||||
print_offset Security_context $HOST
|
||||
print_offset Security_context $IP
|
||||
@@ -136,6 +167,10 @@ $LEX_SQL
|
||||
$FOUND_ROWS
|
||||
$SENT_ROW_COUNT
|
||||
$ROW_COUNT_FUNC
|
||||
$STMT_DA
|
||||
$DA_STATUS
|
||||
$DA_SQL_ERRNO
|
||||
$VIEW_TABLES
|
||||
printf "}"
|
||||
EOF
|
||||
|
||||
|
||||
0
src/MySQLPlugin.map
Executable file → Normal file
0
src/MySQLPlugin.map
Executable file → Normal file
@@ -508,7 +508,7 @@ int Audit_socket_handler::open(const char *io_dest, bool log_errors)
|
||||
m_connect_timeout))
|
||||
#else
|
||||
// in 5.6 timeout is in ms
|
||||
if (vio_socket_connect((Vio*)m_vio,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
|
||||
if (compat::vio_socket_connect((Vio*)m_vio,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
|
||||
m_connect_timeout * 1000))
|
||||
#endif
|
||||
{
|
||||
@@ -585,7 +585,7 @@ static void yajl_add_uint64(yajl_gen gen, const char *name, uint64 num)
|
||||
{
|
||||
const size_t max_int64_str_len = 21;
|
||||
char buf[max_int64_str_len];
|
||||
snprintf(buf, max_int64_str_len, "%llu", num);
|
||||
snprintf(buf, max_int64_str_len, "%llu", (unsigned long long)num);
|
||||
yajl_add_string_val(gen, name, buf);
|
||||
}
|
||||
|
||||
@@ -622,8 +622,11 @@ static const char *retrieve_user(THD *thd)
|
||||
// starting with MySQL version 5.1.41 thd_query_string is added
|
||||
// And at 5.7 it changed
|
||||
#if ! defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709
|
||||
|
||||
#if MYSQL_VERSION_ID >= 80000
|
||||
extern LEX_CSTRING thd_query_unsafe(MYSQL_THD thd);
|
||||
#else
|
||||
extern "C" LEX_CSTRING thd_query_unsafe(MYSQL_THD thd);
|
||||
#endif
|
||||
|
||||
static const char *thd_query_str(THD *thd, size_t *len)
|
||||
{
|
||||
@@ -694,9 +697,9 @@ ssize_t Audit_json_formatter::start_msg_format(IWriter *writer)
|
||||
yajl_gen gen = yajl_gen_alloc(NULL);
|
||||
yajl_gen_map_open(gen);
|
||||
yajl_add_string_val(gen, "msg-type", "header");
|
||||
uint64 ts = my_getsystime() / (10000);
|
||||
uint64 ts = compat::my_getsystime() / (10000);
|
||||
yajl_add_uint64(gen, "date", ts);
|
||||
yajl_add_string_val(gen, "audit-version", MYSQL_AUDIT_PLUGIN_VERSION"-"MYSQL_AUDIT_PLUGIN_REVISION);
|
||||
yajl_add_string_val(gen, "audit-version", MYSQL_AUDIT_PLUGIN_VERSION "-" MYSQL_AUDIT_PLUGIN_REVISION);
|
||||
yajl_add_string_val(gen, "audit-protocol-version", AUDIT_PROTOCOL_VERSION);
|
||||
yajl_add_string_val(gen, "hostname", glob_hostname);
|
||||
yajl_add_string_val(gen, "mysql-version", server_version);
|
||||
@@ -758,6 +761,7 @@ static const char *replace_in_string(THD *thd,
|
||||
#ifdef HAVE_SESS_CONNECT_ATTRS
|
||||
#include <storage/perfschema/pfs_instr.h>
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
//declare the function: parse_length_encoded_string from: storage/perfschema/table_session_connect.cc
|
||||
bool parse_length_encoded_string(const char **ptr,
|
||||
char *dest, uint dest_size,
|
||||
@@ -767,6 +771,72 @@ bool parse_length_encoded_string(const char **ptr,
|
||||
const CHARSET_INFO *from_cs,
|
||||
uint nchars_max);
|
||||
|
||||
#else
|
||||
// the function is not exported in MySQL 8
|
||||
/**
|
||||
Take a length encoded string
|
||||
|
||||
@arg ptr inout the input string array
|
||||
@arg dest where to store the result
|
||||
@arg dest_size max size of @c dest
|
||||
@arg copied_len the actual length of the data copied
|
||||
@arg start_ptr pointer to the start of input
|
||||
@arg input_length the length of the incoming data
|
||||
@arg from_cs character set in which @c ptr is encoded
|
||||
@arg nchars_max maximum number of characters to read
|
||||
@return status
|
||||
@retval true parsing failed
|
||||
@retval false parsing succeeded
|
||||
*/
|
||||
static bool parse_length_encoded_string(
|
||||
const char **ptr
|
||||
,char *dest
|
||||
,uint dest_size
|
||||
,uint *copied_len
|
||||
,const char *start_ptr
|
||||
,uint input_length
|
||||
,bool /* unused */
|
||||
,const CHARSET_INFO *from_cs
|
||||
,uint nchars_max
|
||||
)
|
||||
{
|
||||
ulong copy_length, data_length;
|
||||
const char *well_formed_error_pos = NULL, *cannot_convert_error_pos = NULL,
|
||||
*from_end_pos = NULL;
|
||||
|
||||
copy_length = data_length = net_field_length((uchar **)ptr);
|
||||
|
||||
/* we don't tolerate NULL as a length */
|
||||
if (data_length == NULL_LENGTH) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (*ptr - start_ptr + data_length > input_length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: Migrate the data itself to UTF8MB4,
|
||||
this is still UTF8MB3 printed in a UTF8MB4 column.
|
||||
*/
|
||||
copy_length = well_formed_copy_nchars(
|
||||
&my_charset_utf8_bin
|
||||
, dest
|
||||
, dest_size
|
||||
, from_cs
|
||||
, *ptr
|
||||
, data_length
|
||||
, nchars_max
|
||||
, &well_formed_error_pos
|
||||
, &cannot_convert_error_pos
|
||||
, &from_end_pos
|
||||
);
|
||||
*copied_len = copy_length;
|
||||
(*ptr) += data_length;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Code based upon read_nth_attribute of storage/perfschema/table_session_connect.cc
|
||||
* Only difference we do once loop and write out the attributes
|
||||
@@ -782,9 +852,10 @@ static void log_session_connect_attrs(yajl_gen gen, THD *thd)
|
||||
const uint max_idx = 32;
|
||||
uint idx;
|
||||
const char *ptr;
|
||||
bool array_start = false;
|
||||
// bool array_start = false;
|
||||
if(!connect_attrs || !connect_attrs_length || !connect_attrs_cs)
|
||||
{
|
||||
sql_print_information("%s Failed to compute offsets connect_attrs. pfs [%p], connect_attrs [%p], connect_attrs_length [%d], connect_attrs_cs [%p]", AUDIT_LOG_PREFIX, pfs, connect_attrs, connect_attrs_length, connect_attrs_cs);
|
||||
//either offsets are wrong or not set
|
||||
return;
|
||||
}
|
||||
@@ -812,6 +883,7 @@ static void log_session_connect_attrs(yajl_gen gen, THD *thd)
|
||||
connect_attrs_cs, MAX_COPY_CHARS_NAME) || !copy_length)
|
||||
{
|
||||
//something went wrong or we are done
|
||||
// sql_print_information("%s something went wrong or we are done 1", AUDIT_LOG_PREFIX);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -825,23 +897,14 @@ static void log_session_connect_attrs(yajl_gen gen, THD *thd)
|
||||
fill_in_attr_value,
|
||||
connect_attrs_cs, MAX_COPY_CHARS_VAL) || !copy_length)
|
||||
{
|
||||
// sql_print_information("%s something went wrong or we are done 2", AUDIT_LOG_PREFIX);
|
||||
break;
|
||||
}
|
||||
attr_value_length= copy_length;
|
||||
if(!array_start)
|
||||
{
|
||||
yajl_add_string(gen, "connect_attrs");
|
||||
yajl_gen_map_open(gen);
|
||||
array_start = true;
|
||||
}
|
||||
yajl_gen_string(gen, (const unsigned char*)attr_name, attr_name_length);
|
||||
yajl_gen_string(gen, (const unsigned char*)attr_value, attr_value_length);
|
||||
|
||||
} //close for loop
|
||||
if(array_start)
|
||||
{
|
||||
yajl_gen_map_close(gen);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -861,7 +924,7 @@ ssize_t Audit_json_formatter::event_format(ThdSesData *pThdData, IWriter *writer
|
||||
// TODO: get the start date from THD (but it is not in millis. Need to think about how we handle this)
|
||||
// for now simply use the current time.
|
||||
// my_getsystime() time since epoc in 100 nanosec units. Need to devide by 1000*(1000/100) to reach millis
|
||||
uint64 ts = my_getsystime() / (10000);
|
||||
uint64 ts = compat::my_getsystime() / (10000);
|
||||
yajl_add_uint64(gen, "date", ts);
|
||||
yajl_add_uint64(gen, "thread-id", thdid);
|
||||
yajl_add_uint64(gen, "query-id", qid);
|
||||
@@ -945,6 +1008,12 @@ ssize_t Audit_json_formatter::event_format(ThdSesData *pThdData, IWriter *writer
|
||||
yajl_add_uint64(gen, "rows", rows);
|
||||
}
|
||||
|
||||
uint code;
|
||||
if (pThdData->getErrorCode(code))
|
||||
{
|
||||
yajl_add_uint64(gen, "status", code); // 0 - success, otherwise reports specific errno
|
||||
}
|
||||
|
||||
yajl_add_string_val(gen, "cmd", cmd);
|
||||
|
||||
// get objects
|
||||
@@ -1071,10 +1140,19 @@ ssize_t Audit_json_formatter::event_format(ThdSesData *pThdData, IWriter *writer
|
||||
}
|
||||
|
||||
ThdSesData::ThdSesData(THD *pTHD, StatementSource source)
|
||||
: m_pThd (pTHD), m_CmdName(NULL), m_UserName(NULL),
|
||||
m_objIterType(OBJ_NONE), m_tables(NULL), m_firstTable(true),
|
||||
m_tableInf(NULL), m_index(0), m_isSqlCmd(false),
|
||||
m_port(-1), m_source(source)
|
||||
: m_pThd (pTHD)
|
||||
, m_CmdName()
|
||||
, m_UserName()
|
||||
, m_isSqlCmd()
|
||||
, m_objIterType(OBJ_NONE)
|
||||
, m_tables()
|
||||
, m_firstTable(true)
|
||||
, m_tableInf()
|
||||
, m_index()
|
||||
, m_source(source)
|
||||
, m_port(-1)
|
||||
, m_errorCode()
|
||||
, m_setErrorCode()
|
||||
{
|
||||
m_CmdName = retrieve_command (m_pThd, m_isSqlCmd);
|
||||
m_UserName = retrieve_user (m_pThd);
|
||||
@@ -1087,6 +1165,15 @@ ThdSesData::ThdSesData(THD *pTHD, StatementSource source)
|
||||
}
|
||||
}
|
||||
|
||||
void ThdSesData::storeErrorCode()
|
||||
{
|
||||
uint code = 0;
|
||||
if (Audit_formatter::thd_error_code(m_pThd, code))
|
||||
{
|
||||
setErrorCode(code);
|
||||
}
|
||||
}
|
||||
|
||||
bool ThdSesData::startGetObjects()
|
||||
{
|
||||
// reset vars as this may be called multiple times
|
||||
@@ -1094,15 +1181,17 @@ bool ThdSesData::startGetObjects()
|
||||
m_tables = NULL;
|
||||
m_firstTable = true;
|
||||
m_index = 0;
|
||||
m_tableInf = Audit_formatter::getQueryCacheTableList1(getTHD());
|
||||
int command = Audit_formatter::thd_inst_command(getTHD());
|
||||
LEX *pLex = Audit_formatter::thd_lex(getTHD());
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
// query cache case
|
||||
m_tableInf = Audit_formatter::getQueryCacheTableList1(getTHD());
|
||||
if (pLex && command == COM_QUERY && m_tableInf && m_tableInf->num_of_elem > 0)
|
||||
{
|
||||
m_objIterType = OBJ_QUERY_CACHE;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
const char *cmd = getCmdName();
|
||||
// commands which have single database object
|
||||
if (strcmp(cmd,"Init DB") == 0
|
||||
|
||||
2337
src/audit_offsets.cc
2337
src/audit_offsets.cc
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,6 @@
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "mysql_inc.h"
|
||||
#include "hot_patch.h"
|
||||
#include <stdlib.h>
|
||||
@@ -47,14 +46,14 @@ static Audit_socket_handler json_socket_handler;
|
||||
static Audit_json_formatter json_formatter;
|
||||
|
||||
// flags to hold if audit handlers are enabled
|
||||
static my_bool json_file_handler_enable = FALSE;
|
||||
static my_bool force_record_logins_enable = FALSE;
|
||||
static my_bool json_file_handler_flush = FALSE;
|
||||
static my_bool json_socket_handler_enable = FALSE;
|
||||
static my_bool uninstall_plugin_enable = FALSE;
|
||||
static my_bool validate_checksum_enable = FALSE;
|
||||
static my_bool offsets_by_version_enable = FALSE;
|
||||
static my_bool validate_offsets_extended_enable = FALSE;
|
||||
static my_bool json_file_handler_enable;
|
||||
static my_bool force_record_logins_enable;
|
||||
static my_bool json_file_handler_flush;
|
||||
static my_bool json_socket_handler_enable;
|
||||
static my_bool uninstall_plugin_enable;
|
||||
static my_bool validate_checksum_enable;
|
||||
static my_bool offsets_by_version_enable;
|
||||
static my_bool validate_offsets_extended_enable;
|
||||
static char *offsets_string = NULL;
|
||||
static char *checksum_string = NULL;
|
||||
static int delay_ms_val = 0;
|
||||
@@ -104,12 +103,12 @@ static char password_masking_regex_buff[4096] = {0};
|
||||
|
||||
static const char default_pw_masking_regex[] =
|
||||
// identified by [password] '***'
|
||||
"identified"_COMMENT_SPACE_"by"_COMMENT_SPACE_"(?:password)?"_COMMENT_SPACE_ _QUOTED_PSW_
|
||||
"identified" _COMMENT_SPACE_ "by" _COMMENT_SPACE_ "(?:password)?" _COMMENT_SPACE_ _QUOTED_PSW_
|
||||
// password function
|
||||
"|password"_COMMENT_SPACE_"\\("_COMMENT_SPACE_ _QUOTED_PSW_ _COMMENT_SPACE_"\\)"
|
||||
"|password" _COMMENT_SPACE_ "\\(" _COMMENT_SPACE_ _QUOTED_PSW_ _COMMENT_SPACE_ "\\)"
|
||||
// Used at: CHANGE MASTER TO MASTER_PASSWORD='new3cret', SET PASSWORD [FOR user] = 'hash', password 'user_pass';
|
||||
"|password"_COMMENT_SPACE_"(?:for"_COMMENT_SPACE_"\\S+?)?"_COMMENT_SPACE_"="_COMMENT_SPACE_ _QUOTED_PSW_
|
||||
"|password"_COMMENT_SPACE_ _QUOTED_PSW_
|
||||
"|password" _COMMENT_SPACE_ "(?:for" _COMMENT_SPACE_ "\\S+?)?" _COMMENT_SPACE_ "=" _COMMENT_SPACE_ _QUOTED_PSW_
|
||||
"|password" _COMMENT_SPACE_ _QUOTED_PSW_
|
||||
// federated engine create table with connection. See: http://dev.mysql.com/doc/refman/5.5/en/federated-create-connection.html
|
||||
// commented out as federated engine is disabled by default
|
||||
// "|ENGINE"_COMMENT_SPACE_"="_COMMENT_SPACE_"FEDERATED"_COMMENT_SPACE_".*CONNECTION"_COMMENT_SPACE_"="_COMMENT_SPACE_"[\'|\"]\\S+?://\\S+?:(?<psw>.*)@\\S+[\'|\"]"
|
||||
@@ -129,18 +128,15 @@ static char json_socket_name_buff[1024] = {0};
|
||||
*/
|
||||
static int (*trampoline_mysql_execute_command)(THD *thd) = NULL;
|
||||
static unsigned int trampoline_mysql_execute_size = 0;
|
||||
SavedCode trampoline_mysql_execute_saved_code;
|
||||
|
||||
#if MYSQL_VERSION_ID < 50600
|
||||
static void (*trampoline_log_slow_statement)(THD *thd) = NULL;
|
||||
static unsigned int trampoline_log_slow_statement_size = 0;
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
static int (*trampoline_check_user)(THD *thd, enum enum_server_command command, const char *passwd, uint passwd_len, const char *db, bool check_count) = NULL;
|
||||
static unsigned int trampoline_check_user_size = 0;
|
||||
#elif MYSQL_VERSION_ID < 50600
|
||||
SavedCode trampoline_log_slow_statement_saved_code;
|
||||
static bool (*trampoline_acl_authenticate)(THD *thd, uint connect_errors, uint com_change_user_pkt_len) = NULL;
|
||||
static unsigned int trampoline_acl_authenticate_size = 0;
|
||||
SavedCode trampoline_acl_authenticate_saved_code;
|
||||
#endif
|
||||
|
||||
static MYSQL_THDVAR_ULONG(is_thd_printed_list,
|
||||
@@ -251,7 +247,7 @@ static void initializePeerCredentials(THD *pThd)
|
||||
peer = (PeerInfo *) THDVAR(pThd, peer_info);
|
||||
if (peer != NULL)
|
||||
{
|
||||
memset(peer, 0, sizeof(PeerInfo));
|
||||
*peer = PeerInfo();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -371,10 +367,10 @@ static void initializePeerCredentials(THD *pThd)
|
||||
}
|
||||
|
||||
// set that we have a UDS, so that THD vars will be used
|
||||
THDVAR(pThd, peer_is_uds) = TRUE;
|
||||
THDVAR(pThd, peer_is_uds) = true;
|
||||
|
||||
done:
|
||||
THDVAR(pThd, set_peer_cred) = TRUE;
|
||||
THDVAR(pThd, set_peer_cred) = true;
|
||||
}
|
||||
|
||||
PeerInfo *retrieve_peerinfo(THD *thd)
|
||||
@@ -388,7 +384,7 @@ PeerInfo *retrieve_peerinfo(THD *thd)
|
||||
{
|
||||
PeerInfo *peer = (PeerInfo *) THDVAR(thd, peer_info);
|
||||
|
||||
if (THDVAR(thd, peer_is_uds) && peer != NULL);
|
||||
if (THDVAR(thd, peer_is_uds) && peer != NULL)
|
||||
{
|
||||
return peer;
|
||||
}
|
||||
@@ -397,20 +393,25 @@ PeerInfo *retrieve_peerinfo(THD *thd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int check_array(const char *cmds[],const char *array, int length)
|
||||
// cmds[] is a list of "commands" (names, commands, whatever) to
|
||||
// check against the list stored in `array'. Although declared
|
||||
// here as simple `char *', the `array' is actually a two-dimensional
|
||||
// array where each element is `length' bytes long. (An array of
|
||||
// strings.)
|
||||
//
|
||||
// We loop over the array and for each element see if it's also
|
||||
// in `cmds'. If so, we return 1, otherwise we return 0.
|
||||
//
|
||||
// This should really be of type bool and return true/false.
|
||||
static int check_array(const char *cmds[], const char *array, int length)
|
||||
{
|
||||
for (int k = 0; array[k * length] !='\0';k++)
|
||||
{
|
||||
const char *elem = array + (k * length);
|
||||
for (int q = 0; cmds[q] != NULL; q++)
|
||||
{
|
||||
const char *cmd = cmds[q];
|
||||
int j = 0;
|
||||
while (array[k * length + j] != '\0' && cmd[j] != '\0'
|
||||
&& array[k * length + j] == tolower(cmd[j]))
|
||||
{
|
||||
j++;
|
||||
}
|
||||
if (array[k * length + j] == '\0' && j != 0)
|
||||
if (strcasecmp(cmd, elem) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -576,11 +577,15 @@ static void audit(ThdSesData *pThdData)
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 50709
|
||||
static int (*trampoline_send_result_to_client)(Query_cache *pthis, THD *thd, char *sql, uint query_length) = NULL;
|
||||
#else
|
||||
#elif MYSQL_VERSION_ID < 80000
|
||||
static int (*trampoline_send_result_to_client)(Query_cache *pthis, THD *thd, const LEX_CSTRING& sql_query) = NULL;
|
||||
#endif
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100108
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID == 100224
|
||||
static bool (*trampoline_open_tables)(THD *thd, const DDL_options_st &options, TABLE_LIST **start, uint *counter,
|
||||
Sroutine_hash_entry **sroutine_to_open, uint flags, Prelocking_strategy *prelocking_strategy) = NULL;
|
||||
#elif defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100108
|
||||
static bool (*trampoline_open_tables)(THD *thd, const DDL_options_st &options, TABLE_LIST **start, uint *counter, uint flags,
|
||||
Prelocking_strategy *prelocking_strategy) = NULL;
|
||||
#elif MYSQL_VERSION_ID > 50505
|
||||
@@ -591,28 +596,24 @@ static int (*trampoline_open_tables)(THD *thd, TABLE_LIST **start, uint *counter
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
QueryTableInf *Audit_formatter::getQueryCacheTableList1(THD *thd)
|
||||
{
|
||||
return (QueryTableInf*) THDVAR(thd, query_cache_table_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool (*trampoline_check_table_access)(THD *thd, ulong want_access,TABLE_LIST *tables,
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID >= 50505
|
||||
bool any_combination_of_privileges_will_do,
|
||||
#endif
|
||||
uint number, bool no_errors) = NULL;
|
||||
|
||||
static bool audit_check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID >= 50505
|
||||
bool any_combination_of_privileges_will_do,
|
||||
#endif
|
||||
uint number, bool no_errors)
|
||||
{
|
||||
TABLE_LIST *pTables;
|
||||
bool res = trampoline_check_table_access(thd, want_access, tables,
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID >= 50505
|
||||
any_combination_of_privileges_will_do,
|
||||
#endif
|
||||
number, no_errors);
|
||||
if (!res && tables)
|
||||
{
|
||||
@@ -642,7 +643,9 @@ static bool audit_check_table_access(THD *thd, ulong want_access,TABLE_LIST *tab
|
||||
}
|
||||
|
||||
static unsigned int trampoline_check_table_access_size = 0;
|
||||
SavedCode trampoline_check_table_access_saved_code;
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 50709
|
||||
static int audit_send_result_to_client(Query_cache *pthis, THD *thd, char *sql, uint query_length)
|
||||
#else
|
||||
@@ -665,16 +668,25 @@ static int audit_send_result_to_client(Query_cache *pthis, THD *thd, const LEX_
|
||||
#endif
|
||||
if (res)
|
||||
{
|
||||
ThdSesData thd_data(thd, ThdSesData::SOURCE_QUERY_CACHE);
|
||||
audit(&thd_data);
|
||||
ThdSesData thdData(thd, ThdSesData::SOURCE_QUERY_CACHE);
|
||||
thdData.storeErrorCode();
|
||||
audit(&thdData);
|
||||
}
|
||||
THDVAR(thd, query_cache_table_list) = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static unsigned int trampoline_send_result_to_client_size = 0;
|
||||
SavedCode trampoline_send_result_to_client_saved_code;
|
||||
#endif // defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100108
|
||||
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID == 100224
|
||||
static bool audit_open_tables(THD *thd, const DDL_options_st &options, TABLE_LIST **start, uint *counter,
|
||||
Sroutine_hash_entry **sroutine_to_open, uint flags, Prelocking_strategy *prelocking_strategy)
|
||||
{
|
||||
bool res;
|
||||
res = trampoline_open_tables (thd, options, start, counter, sroutine_to_open, flags, prelocking_strategy);
|
||||
#elif defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100108
|
||||
static bool audit_open_tables(THD *thd, const DDL_options_st &options, TABLE_LIST **start, uint *counter, uint flags,
|
||||
Prelocking_strategy *prelocking_strategy)
|
||||
{
|
||||
@@ -697,13 +709,15 @@ static int audit_open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint f
|
||||
&& (Audit_formatter::thd_inst_thread_id(thd)
|
||||
|| Audit_formatter::thd_inst_query_id(thd)))
|
||||
{
|
||||
ThdSesData thd_data (thd);
|
||||
ThdSesData thd_data(thd);
|
||||
// This is before something is run, so no need to set exit status
|
||||
audit(&thd_data);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static unsigned int trampoline_open_tables_size = 0;
|
||||
SavedCode trampoline_open_tables_saved_code;
|
||||
|
||||
// called by log_slow_statement and general audit event caught by audit interface
|
||||
static void audit_post_execute(THD * thd)
|
||||
@@ -712,10 +726,11 @@ static void audit_post_execute(THD * thd)
|
||||
// query events are audited by mysql execute command
|
||||
if (Audit_formatter::thd_inst_command(thd) != COM_QUERY)
|
||||
{
|
||||
ThdSesData ThdData(thd);
|
||||
if (strcasestr(ThdData.getCmdName(), "show_fields") == NULL)
|
||||
ThdSesData thdData(thd);
|
||||
if (strcasestr(thdData.getCmdName(), "show_fields") == NULL)
|
||||
{
|
||||
audit(&ThdData);
|
||||
thdData.storeErrorCode();
|
||||
audit(&thdData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -779,6 +794,7 @@ static int audit_notify(THD *thd, mysql_event_class_t event_class,
|
||||
case ER_ACCOUNT_HAS_BEEN_LOCKED:
|
||||
#endif
|
||||
ThdData.setCmdName("Failed Login");
|
||||
ThdData.setErrorCode(event_general->general_error_code);
|
||||
audit(&ThdData);
|
||||
break;
|
||||
default:
|
||||
@@ -836,21 +852,18 @@ static struct st_mysql_audit audit_plugin =
|
||||
#endif
|
||||
|
||||
// some extern definitions which are not in include files
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
extern void log_slow_statement(THD *thd);
|
||||
#endif
|
||||
extern int mysql_execute_command(THD *thd);
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION)
|
||||
extern void end_connection(THD *thd);
|
||||
static int (*trampoline_end_connection)(THD *thd) = NULL;
|
||||
static unsigned int trampoline_end_connection_size = 0;
|
||||
SavedCode trampoline_end_connection_saved_code;
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID >= 50505
|
||||
// in 5.5 builtins is named differently
|
||||
#define mysqld_builtins mysql_mandatory_plugins
|
||||
#endif
|
||||
extern struct st_mysql_plugin *mysqld_builtins[];
|
||||
|
||||
void remove_hot_functions()
|
||||
{
|
||||
void * target_function = NULL;
|
||||
@@ -858,23 +871,21 @@ void remove_hot_functions()
|
||||
#if MYSQL_VERSION_ID < 50600
|
||||
target_function = (void *) log_slow_statement;
|
||||
remove_hot_patch_function(target_function,
|
||||
(void*) trampoline_log_slow_statement, trampoline_log_slow_statement_size, true);
|
||||
(void*) trampoline_log_slow_statement, trampoline_log_slow_statement_size, true, &trampoline_log_slow_statement_saved_code);
|
||||
trampoline_log_slow_statement_size = 0;
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
target_function = (void *) check_user;
|
||||
remove_hot_patch_function(target_function,
|
||||
(void*) trampoline_check_user, trampoline_check_user_size, true);
|
||||
trampoline_check_user_size = 0;
|
||||
#elif MYSQL_VERSION_ID < 50600
|
||||
trampoline_log_slow_statement_saved_code.size = 0;
|
||||
target_function = (void *) acl_authenticate;
|
||||
remove_hot_patch_function(target_function,
|
||||
(void*) trampoline_acl_authenticate, trampoline_acl_authenticate_size, true);
|
||||
(void*) trampoline_acl_authenticate, trampoline_acl_authenticate_size, true, &trampoline_acl_authenticate_saved_code);
|
||||
trampoline_acl_authenticate_size = 0;
|
||||
trampoline_acl_authenticate_saved_code.size = 0;
|
||||
#endif
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100108
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID == 100224
|
||||
target_function = (void *)*(bool (*)(THD *thd, const DDL_options_st &options, TABLE_LIST **start, uint *counter,
|
||||
Sroutine_hash_entry **sroutine_to_open, uint flags, Prelocking_strategy *prelocking_strategy)) &open_tables;
|
||||
#elif defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100108
|
||||
target_function = (void *)*(bool (*)(THD *thd, const DDL_options_st &options, TABLE_LIST **start, uint *counter, uint flags,
|
||||
Prelocking_strategy *prelocking_strategy)) &open_tables;
|
||||
#elif MYSQL_VERSION_ID > 50505
|
||||
@@ -884,9 +895,11 @@ void remove_hot_functions()
|
||||
target_function = (void *)*(int (*)(THD *thd, TABLE_LIST **start, uint *counter, uint flags)) &open_tables;
|
||||
#endif
|
||||
remove_hot_patch_function(target_function,
|
||||
(void*) trampoline_open_tables, trampoline_open_tables_size, true);
|
||||
(void*) trampoline_open_tables, trampoline_open_tables_size, true, &trampoline_open_tables_saved_code);
|
||||
trampoline_open_tables_size = 0;
|
||||
trampoline_open_tables_saved_code.size = 0;
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 50709
|
||||
int (Query_cache::*pf_send_result_to_client)(THD *,char *, uint) = &Query_cache::send_result_to_client;
|
||||
#else
|
||||
@@ -894,13 +907,16 @@ void remove_hot_functions()
|
||||
#endif
|
||||
target_function = *(void **) &pf_send_result_to_client;
|
||||
remove_hot_patch_function(target_function,
|
||||
(void*) trampoline_send_result_to_client, trampoline_send_result_to_client_size, true);
|
||||
(void*) trampoline_send_result_to_client, trampoline_send_result_to_client_size, true, &trampoline_send_result_to_client_saved_code);
|
||||
trampoline_send_result_to_client_size = 0;
|
||||
trampoline_send_result_to_client_saved_code.size = 0;
|
||||
#endif
|
||||
|
||||
remove_hot_patch_function((void*) check_table_access,
|
||||
(void*) trampoline_check_table_access,
|
||||
trampoline_check_table_access_size, true);
|
||||
trampoline_check_table_access_size, true, &trampoline_check_table_access_saved_code);
|
||||
trampoline_check_table_access_size=0;
|
||||
trampoline_check_table_access_saved_code.size = 0;
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 50709
|
||||
target_function = (void*) mysql_execute_command;
|
||||
@@ -913,14 +929,16 @@ void remove_hot_functions()
|
||||
target_function = (void*) end_connection;
|
||||
remove_hot_patch_function(target_function,
|
||||
(void*) trampoline_end_connection,
|
||||
trampoline_end_connection_size, true);
|
||||
trampoline_end_connection_size, true, &trampoline_end_connection_saved_code);
|
||||
trampoline_end_connection_size = 0;
|
||||
trampoline_end_connection_saved_code.size = 0;
|
||||
#endif
|
||||
|
||||
remove_hot_patch_function(target_function,
|
||||
(void*) trampoline_mysql_execute_command,
|
||||
trampoline_mysql_execute_size, true);
|
||||
trampoline_mysql_execute_size, true, &trampoline_mysql_execute_saved_code);
|
||||
trampoline_mysql_execute_size = 0;
|
||||
trampoline_mysql_execute_saved_code.size = 0;
|
||||
}
|
||||
|
||||
int is_remove_patches(ThdSesData *pThdData)
|
||||
@@ -939,9 +957,11 @@ int is_remove_patches(ThdSesData *pThdData)
|
||||
#endif
|
||||
if (strncasecmp(Lex_comment.str, PLUGIN_NAME, strlen(PLUGIN_NAME)) == 0)
|
||||
{
|
||||
char msgBuffer[200];
|
||||
if (! uninstall_plugin_enable)
|
||||
{
|
||||
my_message(ER_NOT_ALLOWED_COMMAND, "Uninstall AUDIT plugin disabled", MYF(0));
|
||||
sprintf(msgBuffer, "Uninstall %s plugin disabled", PLUGIN_NAME);
|
||||
my_message(ER_NOT_ALLOWED_COMMAND, msgBuffer, MYF(0));
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -951,7 +971,8 @@ int is_remove_patches(ThdSesData *pThdData)
|
||||
if (! called_once)
|
||||
{
|
||||
called_once = true;
|
||||
my_message(WARN_PLUGIN_BUSY, "Uninstall AUDIT plugin must be called again to complete", MYF(0));
|
||||
sprintf(msgBuffer, "Uninstall %s plugin must be called again to complete", PLUGIN_NAME);
|
||||
my_message(WARN_PLUGIN_BUSY, msgBuffer, MYF(0));
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
@@ -989,10 +1010,10 @@ static int audit_mysql_execute_command(THD *thd)
|
||||
}
|
||||
}
|
||||
|
||||
ThdSesData thd_data(thd);
|
||||
const char *cmd = thd_data.getCmdName();
|
||||
ThdSesData thdData(thd);
|
||||
const char *cmd = thdData.getCmdName();
|
||||
|
||||
do_delay(& thd_data);
|
||||
do_delay(& thdData);
|
||||
|
||||
if (before_after_mode == AUDIT_BEFORE || before_after_mode == AUDIT_BOTH)
|
||||
{
|
||||
@@ -1002,7 +1023,7 @@ static int audit_mysql_execute_command(THD *thd)
|
||||
strcasestr(cmd, "truncate") != NULL ||
|
||||
strcasestr(cmd, "rename") != NULL)
|
||||
{
|
||||
audit(&thd_data);
|
||||
audit(&thdData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1017,7 +1038,7 @@ static int audit_mysql_execute_command(THD *thd)
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (is_remove_patches(&thd_data))
|
||||
switch (is_remove_patches(&thdData))
|
||||
{
|
||||
case 1:
|
||||
// hot patch function were removed and we call the real execute (restored)
|
||||
@@ -1037,10 +1058,11 @@ static int audit_mysql_execute_command(THD *thd)
|
||||
}
|
||||
}
|
||||
|
||||
thdData.storeErrorCode();
|
||||
|
||||
if (before_after_mode == AUDIT_AFTER || before_after_mode == AUDIT_BOTH)
|
||||
{
|
||||
audit(&thd_data);
|
||||
audit(&thdData);
|
||||
}
|
||||
|
||||
if (pThdPrintedList && pThdPrintedList->cur_index > 0)
|
||||
@@ -1062,29 +1084,15 @@ static void audit_log_slow_statement(THD *thd)
|
||||
trampoline_log_slow_statement(thd);
|
||||
audit_post_execute(thd);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
static int audit_check_user(THD *thd, enum enum_server_command command,
|
||||
const char *passwd, uint passwd_len, const char *db,
|
||||
bool check_count)
|
||||
{
|
||||
int res = trampoline_check_user(thd, command, passwd, passwd_len, db, check_count);
|
||||
ThdSesData ThdData(thd);
|
||||
|
||||
audit(&ThdData);
|
||||
|
||||
return (res);
|
||||
}
|
||||
#elif MYSQL_VERSION_ID < 50600
|
||||
// only for 5.5
|
||||
// in 5.6: we use audit plugin event to get the login event
|
||||
static bool audit_acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len)
|
||||
{
|
||||
bool res = trampoline_acl_authenticate(thd, connect_errors, com_change_user_pkt_len);
|
||||
ThdSesData ThdData(thd);
|
||||
|
||||
audit(&ThdData);
|
||||
ThdSesData thdData(thd);
|
||||
thdData.storeErrorCode();
|
||||
audit(&thdData);
|
||||
|
||||
return (res);
|
||||
}
|
||||
@@ -1110,10 +1118,10 @@ static void audit_end_connection(THD *thd)
|
||||
|
||||
static bool parse_thd_offsets_string (char *poffsets_string)
|
||||
{
|
||||
char offset_str[2048] = {0};
|
||||
char offset_str[2049] = {0};
|
||||
char *poffset_str = offset_str;
|
||||
|
||||
strncpy(poffset_str,poffsets_string,array_elements(offset_str));
|
||||
strncpy(poffset_str,poffsets_string,array_elements(offset_str)-1);
|
||||
|
||||
char *comma_delimiter = strchr(poffset_str, ',');
|
||||
size_t i = 0;
|
||||
@@ -1224,9 +1232,16 @@ static bool validate_offsets(const ThdOffsets *offset)
|
||||
(*(const char **) (((unsigned char *) sctx) + offset->sec_ctx_user)) = user_test_val;
|
||||
}
|
||||
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80000
|
||||
PSI_mutex_key key_LOCK_thd_query_validate=99999;
|
||||
mysql_mutex_init(key_LOCK_thd_query_validate, &thd->LOCK_thd_query, MY_MUTEX_INIT_FAST);
|
||||
#endif
|
||||
char buffer[2048] = {0};
|
||||
thd_security_context(thd, buffer, 2048, 1000);
|
||||
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80000
|
||||
mysql_mutex_destroy(&thd->LOCK_thd_query);
|
||||
#endif
|
||||
// verfiy our buffer contains query id
|
||||
if (strstr(buffer, " 789") == NULL || strstr(buffer, user_test_val) == NULL)
|
||||
{
|
||||
@@ -1257,9 +1272,17 @@ static bool calc_file_md5(const char *file_name, char *digest_str)
|
||||
|
||||
if ((fd = my_open(file_name, O_RDONLY, MYF(MY_WME))) < 0)
|
||||
{
|
||||
sql_print_error("%s Failed file open: [%s], errno: %d.",
|
||||
log_prefix, file_name, errno);
|
||||
return false;
|
||||
sql_print_error("%s Failed file open: [%s], errno: %d. Retrying with /proc/%d/exe.",
|
||||
log_prefix, file_name, errno, getpid());
|
||||
|
||||
char pidFilename[100];
|
||||
sprintf(pidFilename, "/proc/%d/exe", getpid());
|
||||
if ((fd = my_open(pidFilename, O_RDONLY, MYF(MY_WME))) < 0)
|
||||
{
|
||||
sql_print_error("%s Failed file open: [%s], errno: %d.",
|
||||
log_prefix, pidFilename, errno);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
my_MD5Context context;
|
||||
@@ -1348,7 +1371,7 @@ static int setup_offsets()
|
||||
|
||||
if (parse_thd_offsets_string(offsets_string))
|
||||
{
|
||||
sql_print_information ("%s setup_offsets Audit_formatter::thd_offsets values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu", log_prefix,
|
||||
sql_print_information ("%s setup_offsets Audit_formatter::thd_offsets values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu", log_prefix,
|
||||
Audit_formatter::thd_offsets.query_id,
|
||||
Audit_formatter::thd_offsets.thread_id,
|
||||
Audit_formatter::thd_offsets.main_security_ctx,
|
||||
@@ -1370,7 +1393,10 @@ static int setup_offsets()
|
||||
Audit_formatter::thd_offsets.uninstall_cmd_comment,
|
||||
Audit_formatter::thd_offsets.found_rows,
|
||||
Audit_formatter::thd_offsets.sent_row_count,
|
||||
Audit_formatter::thd_offsets.row_count_func
|
||||
Audit_formatter::thd_offsets.row_count_func,
|
||||
Audit_formatter::thd_offsets.stmt_da,
|
||||
Audit_formatter::thd_offsets.da_status,
|
||||
Audit_formatter::thd_offsets.da_sql_errno
|
||||
);
|
||||
|
||||
if (! validate_offsets(&Audit_formatter::thd_offsets))
|
||||
@@ -1485,11 +1511,23 @@ static int setup_offsets()
|
||||
{
|
||||
decoffsets.row_count_func -= dec;
|
||||
}
|
||||
if (decoffsets.stmt_da)
|
||||
{
|
||||
decoffsets.stmt_da -= dec;
|
||||
}
|
||||
if (decoffsets.da_status)
|
||||
{
|
||||
decoffsets.da_status -= dec;
|
||||
}
|
||||
if (decoffsets.da_sql_errno)
|
||||
{
|
||||
decoffsets.da_sql_errno -= dec;
|
||||
}
|
||||
|
||||
if (validate_offsets(&decoffsets))
|
||||
{
|
||||
Audit_formatter::thd_offsets = decoffsets;
|
||||
sql_print_information("%s Using decrement (%zu) offsets from offset version: %s (%s) values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu",
|
||||
sql_print_information("%s Using decrement (%zu) offsets from offset version: %s (%s) values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu",
|
||||
log_prefix, dec, offset->version, offset->md5digest,
|
||||
Audit_formatter::thd_offsets.query_id,
|
||||
Audit_formatter::thd_offsets.thread_id,
|
||||
@@ -1511,7 +1549,10 @@ static int setup_offsets()
|
||||
Audit_formatter::thd_offsets.uninstall_cmd_comment,
|
||||
Audit_formatter::thd_offsets.found_rows,
|
||||
Audit_formatter::thd_offsets.sent_row_count,
|
||||
Audit_formatter::thd_offsets.row_count_func
|
||||
Audit_formatter::thd_offsets.row_count_func,
|
||||
Audit_formatter::thd_offsets.stmt_da,
|
||||
Audit_formatter::thd_offsets.da_status,
|
||||
Audit_formatter::thd_offsets.da_sql_errno
|
||||
);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
@@ -1529,7 +1570,7 @@ static int setup_offsets()
|
||||
if (validate_offsets(&incoffsets))
|
||||
{
|
||||
Audit_formatter::thd_offsets = incoffsets;
|
||||
sql_print_information("%s Using increment (%zu) offsets from offset version: %s (%s) values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu",
|
||||
sql_print_information("%s Using increment (%zu) offsets from offset version: %s (%s) values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu",
|
||||
log_prefix, inc, offset->version, offset->md5digest,
|
||||
Audit_formatter::thd_offsets.query_id,
|
||||
Audit_formatter::thd_offsets.thread_id,
|
||||
@@ -1551,7 +1592,10 @@ static int setup_offsets()
|
||||
Audit_formatter::thd_offsets.uninstall_cmd_comment,
|
||||
Audit_formatter::thd_offsets.found_rows,
|
||||
Audit_formatter::thd_offsets.sent_row_count,
|
||||
Audit_formatter::thd_offsets.row_count_func
|
||||
Audit_formatter::thd_offsets.row_count_func,
|
||||
Audit_formatter::thd_offsets.stmt_da,
|
||||
Audit_formatter::thd_offsets.da_status,
|
||||
Audit_formatter::thd_offsets.da_sql_errno
|
||||
);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@@ -1737,7 +1781,7 @@ static void *trampoline_mem_free = NULL;
|
||||
* Utility method for hot patching
|
||||
*/
|
||||
static int do_hot_patch(void ** trampoline_func_pp, unsigned int * trampoline_size,
|
||||
void* target_function, void* audit_function, const char * func_name)
|
||||
void* target_function, void* audit_function, const char * func_name, SavedCode* saved_code)
|
||||
{
|
||||
// 16 byte align the pointer
|
||||
DATATYPE_ADDRESS addrs = (DATATYPE_ADDRESS)trampoline_mem_free + 15;
|
||||
@@ -1746,7 +1790,7 @@ static int do_hot_patch(void ** trampoline_func_pp, unsigned int * trampoline_si
|
||||
// hot patch functions
|
||||
unsigned int used_size;
|
||||
int res = hot_patch_function(target_function, audit_function,
|
||||
*trampoline_func_pp, trampoline_size, &used_size, true);
|
||||
*trampoline_func_pp, trampoline_size, &used_size, true, saved_code);
|
||||
if (res != 0)
|
||||
{
|
||||
// hot patch failed.
|
||||
@@ -1762,7 +1806,7 @@ static int do_hot_patch(void ** trampoline_func_pp, unsigned int * trampoline_si
|
||||
}
|
||||
|
||||
#define DECLARE_STRING_ARR_UPDATE_FUNC(NAME) \
|
||||
static void NAME ## _string_update(THD *thd, struct st_mysql_sys_var *var, void *tgt, const void *save)\
|
||||
static void NAME ## _string_update(THD *thd, SYS_VAR *var, void *tgt, const void *save)\
|
||||
{\
|
||||
num_ ## NAME = string_to_array(save, NAME ## _array, array_elements( NAME ## _array), sizeof( NAME ## _array[0]));\
|
||||
/* handle "set global audit_xxx = null;" */ \
|
||||
@@ -1786,7 +1830,7 @@ DECLARE_STRING_ARR_UPDATE_FUNC(password_masking_cmds)
|
||||
DECLARE_STRING_ARR_UPDATE_FUNC(whitelist_users)
|
||||
DECLARE_STRING_ARR_UPDATE_FUNC(record_objs)
|
||||
|
||||
static void password_masking_regex_string_update(THD *thd, struct st_mysql_sys_var *var, void *tgt, const void *save)
|
||||
static void password_masking_regex_string_update(THD *thd, SYS_VAR *var, void *tgt, const void *save)
|
||||
{
|
||||
const char *str_val = "";
|
||||
char *const* save_p = static_cast<char*const*>(save);
|
||||
@@ -1844,7 +1888,7 @@ static void replace_char(char *str, const char tofind, const char rplc)
|
||||
}
|
||||
}
|
||||
|
||||
static void json_socket_name_update(THD *thd, struct st_mysql_sys_var *var, void *tgt, const void *save)
|
||||
static void json_socket_name_update(THD *thd, SYS_VAR *var, void *tgt, const void *save)
|
||||
{
|
||||
const char *str_val = NULL;
|
||||
char *const* save_p = static_cast<char*const*>(save);
|
||||
@@ -1915,7 +1959,7 @@ static void json_socket_name_update(THD *thd, struct st_mysql_sys_var *var, void
|
||||
}
|
||||
|
||||
// check that the regex compiles. Return 0 on success.
|
||||
static int password_masking_regex_check(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value)
|
||||
static int password_masking_regex_check(THD *thd, SYS_VAR *var, void *save, st_mysql_value *value)
|
||||
{
|
||||
int length = array_elements(password_masking_regex_check_buff);
|
||||
const char *str = value->val_str(value, password_masking_regex_check_buff, &length);
|
||||
@@ -1935,7 +1979,7 @@ static int password_masking_regex_check(THD *thd, struct st_mysql_sys_var *var,
|
||||
}
|
||||
|
||||
// extended method to set also record_empty_objs_set
|
||||
static void record_objs_string_update_extended(THD *thd, struct st_mysql_sys_var *var, void *tgt, const void *save)
|
||||
static void record_objs_string_update_extended(THD *thd, SYS_VAR *var, void *tgt, const void *save)
|
||||
{
|
||||
record_objs_string_update(thd, var, tgt, save);
|
||||
if (num_record_objs > 0) // check if to record also the empty set of objects
|
||||
@@ -1960,10 +2004,24 @@ static void record_objs_string_update_extended(THD *thd, struct st_mysql_sys_var
|
||||
* 0 success
|
||||
* 1 failure
|
||||
*/
|
||||
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID > 80000
|
||||
bool (*compat::_vio_socket_connect)(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, int timeout);
|
||||
bool (*compat::_vio_socket_connect_80016)(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, bool nonblocking, int timeout);
|
||||
bool (*compat::_vio_socket_connect_80020)(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, bool nonblocking, int timeout, bool *connect_done);
|
||||
#endif
|
||||
static int audit_plugin_init(void *p)
|
||||
{
|
||||
|
||||
DBUG_ENTER("audit_plugin_init");
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID > 80000
|
||||
const bool compat_init_ok = compat::init();
|
||||
if (!compat_init_ok)
|
||||
{
|
||||
sql_print_error("%s unable to init compatibility layer. Aborting.", log_prefix);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __x86_64__
|
||||
const char * arch = "64bit";
|
||||
@@ -1976,7 +2034,7 @@ static int audit_plugin_init(void *p)
|
||||
interface_ver = interface_ver >> 8;
|
||||
#endif
|
||||
sql_print_information(
|
||||
"%s starting up. Version: %s , Revision: %s (%s). AUDIT plugin interface version: %d (0x%x). MySQL Server version: %s.",
|
||||
"%s starting up. Version: %s , Revision: %s (%s). MySQL AUDIT plugin interface version: %d (0x%x). MySQL Server version: %s.",
|
||||
log_prefix, MYSQL_AUDIT_PLUGIN_VERSION,
|
||||
MYSQL_AUDIT_PLUGIN_REVISION, arch, interface_ver, interface_ver,
|
||||
server_version);
|
||||
@@ -2078,7 +2136,7 @@ static int audit_plugin_init(void *p)
|
||||
trampoline_mem = NULL;
|
||||
|
||||
#ifdef __x86_64__
|
||||
size_t func_in_mysqld = (size_t)log_slow_statement;
|
||||
size_t func_in_mysqld = (size_t)check_table_access;
|
||||
size_t func_in_plugin = (size_t)trampoline_dummy_func_for_mem;
|
||||
if (func_in_mysqld < INT_MAX && func_in_plugin > INT_MAX)
|
||||
{
|
||||
@@ -2139,36 +2197,29 @@ static int audit_plugin_init(void *p)
|
||||
#endif
|
||||
|
||||
if (do_hot_patch((void **)&trampoline_mysql_execute_command, &trampoline_mysql_execute_size,
|
||||
target_function, (void *)audit_mysql_execute_command, "mysql_execute_command"))
|
||||
target_function, (void *)audit_mysql_execute_command, "mysql_execute_command", &trampoline_mysql_execute_saved_code))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
#if MYSQL_VERSION_ID < 50600
|
||||
if (do_hot_patch((void **)&trampoline_log_slow_statement, &trampoline_log_slow_statement_size,
|
||||
(void *)log_slow_statement, (void *)audit_log_slow_statement, "log_slow_statement"))
|
||||
(void *)log_slow_statement, (void *)audit_log_slow_statement, "log_slow_statement", &trampoline_log_slow_statement_saved_code))
|
||||
{
|
||||
sql_print_error("%s Failed hot patch. Continuing as non-critical.",
|
||||
log_prefix);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
if (do_hot_patch((void **)&trampoline_check_user, &trampoline_check_user_size,
|
||||
(void *)check_user, (void *)audit_check_user, "check_user"))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
#elif MYSQL_VERSION_ID < 50600
|
||||
if (do_hot_patch((void **)&trampoline_acl_authenticate, &trampoline_acl_authenticate_size,
|
||||
(void *)acl_authenticate, (void *)audit_acl_authenticate, "acl_authenticate"))
|
||||
(void *)acl_authenticate, (void *)audit_acl_authenticate, "acl_authenticate", &trampoline_acl_authenticate_saved_code))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 50709
|
||||
int (Query_cache::*pf_send_result_to_client)(THD *,char *, uint) = &Query_cache::send_result_to_client;
|
||||
#else
|
||||
@@ -2176,18 +2227,22 @@ static int audit_plugin_init(void *p)
|
||||
#endif
|
||||
target_function = *(void **) &pf_send_result_to_client;
|
||||
if (do_hot_patch((void **)&trampoline_send_result_to_client, &trampoline_send_result_to_client_size,
|
||||
(void *)target_function, (void *)audit_send_result_to_client, "send_result_to_client"))
|
||||
(void *)target_function, (void *)audit_send_result_to_client, "send_result_to_client", &trampoline_send_result_to_client_saved_code))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (do_hot_patch((void **)&trampoline_check_table_access, &trampoline_check_table_access_size,
|
||||
(void *)check_table_access, (void *)audit_check_table_access, "check_table_access"))
|
||||
(void *)check_table_access, (void *)audit_check_table_access, "check_table_access", &trampoline_check_table_access_saved_code))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100108
|
||||
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID == 100224
|
||||
target_function = (void *)*(bool (*)(THD *thd, const DDL_options_st &options, TABLE_LIST **start, uint *counter,
|
||||
Sroutine_hash_entry **sroutine_to_open, uint flags, Prelocking_strategy *prelocking_strategy)) &open_tables;
|
||||
#elif defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100108
|
||||
target_function = (void *)*(bool (*)(THD *thd, const DDL_options_st &options, TABLE_LIST **start, uint *counter, uint flags,
|
||||
Prelocking_strategy *prelocking_strategy)) &open_tables;
|
||||
#elif MYSQL_VERSION_ID > 50505
|
||||
@@ -2197,7 +2252,7 @@ static int audit_plugin_init(void *p)
|
||||
target_function = (void *)*(int (*)(THD *thd, TABLE_LIST **start, uint *counter, uint flags)) &open_tables;
|
||||
#endif
|
||||
if (do_hot_patch((void **)&trampoline_open_tables, &trampoline_open_tables_size,
|
||||
(void *)target_function, (void *)audit_open_tables, "open_tables"))
|
||||
(void *)target_function, (void *)audit_open_tables, "open_tables", &trampoline_open_tables_saved_code))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
@@ -2205,7 +2260,7 @@ static int audit_plugin_init(void *p)
|
||||
#if defined(MARIADB_BASE_VERSION)
|
||||
target_function = (void*) end_connection;
|
||||
if (do_hot_patch((void **)&trampoline_end_connection, &trampoline_end_connection_size,
|
||||
(void *)target_function, (void *)audit_end_connection, "end_connection"))
|
||||
(void *)target_function, (void *)audit_end_connection, "end_connection", &trampoline_end_connection_saved_code))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
@@ -2245,7 +2300,7 @@ static int audit_plugin_deinit(void *p)
|
||||
Plugin status variables for SHOW STATUS
|
||||
*/
|
||||
|
||||
static struct st_mysql_show_var audit_status[] =
|
||||
static SHOW_VAR audit_status[] =
|
||||
{
|
||||
{ "Audit_version",
|
||||
(char *) MYSQL_AUDIT_PLUGIN_VERSION "-" MYSQL_AUDIT_PLUGIN_REVISION,
|
||||
@@ -2266,32 +2321,32 @@ static struct st_mysql_show_var audit_status[] =
|
||||
|
||||
|
||||
|
||||
static void json_log_file_enable(THD *thd, struct st_mysql_sys_var *var,
|
||||
static void json_log_file_enable(THD *thd, SYS_VAR *var,
|
||||
void *tgt, const void *save)
|
||||
{
|
||||
json_file_handler_enable = *(my_bool *) save ? TRUE : FALSE;
|
||||
json_file_handler_enable = *(my_bool *) save ? true : false;
|
||||
if (json_file_handler.is_init())
|
||||
{
|
||||
json_file_handler.set_enable(json_file_handler_enable);
|
||||
}
|
||||
}
|
||||
|
||||
static void json_log_file_flush(THD *thd, struct st_mysql_sys_var *var,
|
||||
static void json_log_file_flush(THD *thd, SYS_VAR *var,
|
||||
void *tgt, const void *save)
|
||||
{
|
||||
// always set to false. as we just flush if set to true and leave at 0
|
||||
json_file_handler_flush = FALSE;
|
||||
my_bool val = *(my_bool *) save ? TRUE : FALSE;
|
||||
json_file_handler_flush = false;
|
||||
my_bool val = *(my_bool *) save ? true : false;
|
||||
if (val && json_file_handler.is_init())
|
||||
{
|
||||
json_file_handler.flush();
|
||||
}
|
||||
}
|
||||
|
||||
static void json_log_socket_enable(THD *thd, struct st_mysql_sys_var *var,
|
||||
static void json_log_socket_enable(THD *thd, SYS_VAR *var,
|
||||
void *tgt, const void *save)
|
||||
{
|
||||
json_socket_handler_enable = *(my_bool *) save ? TRUE : FALSE;
|
||||
json_socket_handler_enable = *(my_bool *) save ? true : false;
|
||||
if (json_socket_handler.is_init())
|
||||
{
|
||||
json_socket_handler.set_enable(json_socket_handler_enable);
|
||||
@@ -2462,7 +2517,7 @@ static MYSQL_SYSVAR_ENUM(before_after, before_after_mode,
|
||||
/*
|
||||
* Plugin system vars
|
||||
*/
|
||||
static struct st_mysql_sys_var* audit_system_variables[] =
|
||||
static SYS_VAR* audit_system_variables[] =
|
||||
{
|
||||
#ifdef HAVE_SESS_CONNECT_ATTRS
|
||||
MYSQL_SYSVAR(sess_connect_attrs),
|
||||
@@ -2514,12 +2569,18 @@ mysql_declare_plugin(audit_plugin)
|
||||
"McAfee Inc",
|
||||
"AUDIT plugin, creates a file mysql-audit.log to log activity",
|
||||
PLUGIN_LICENSE_GPL,
|
||||
audit_plugin_init, /* Plugin Init */
|
||||
audit_plugin_deinit, /* Plugin Deinit */
|
||||
0x0100 /* 1.0 */,
|
||||
audit_status, /* status variables */
|
||||
audit_plugin_init, /* Plugin Init */
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80000
|
||||
nullptr, /* check uninstall function */
|
||||
#endif
|
||||
audit_plugin_deinit, /* Plugin Deinit */
|
||||
0x0100 /* 1.0 */,
|
||||
audit_status, /* status variables */
|
||||
audit_system_variables, /* system variables */
|
||||
NULL /* config options */
|
||||
NULL, /* config options */
|
||||
#if MYSQL_VERSION_ID >= 50516
|
||||
0 /* flags for plugin */
|
||||
#endif
|
||||
}
|
||||
mysql_declare_plugin_end;
|
||||
|
||||
@@ -2542,32 +2603,7 @@ static inline void set_plugin_name_from_env()
|
||||
}
|
||||
}
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
/**
|
||||
* DLL constructor method.
|
||||
* We set here the audit plugin version to the same as the first built in plugin.
|
||||
* This is so we can have a single lib for all versions (needed in 5.1)
|
||||
*/
|
||||
extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
|
||||
{
|
||||
if (mysqld_builtins && mysqld_builtins[0])
|
||||
{
|
||||
audit_plugin.interface_version = *(int *) mysqld_builtins[0]->info;
|
||||
sql_print_information("%s Set interface version to: %d (%d)",
|
||||
log_prefix, audit_plugin.interface_version,
|
||||
audit_plugin.interface_version >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
sql_print_error(
|
||||
"%s mysqld_builtins are null. Plugin will not load unless the mysql version is: %d. \n",
|
||||
log_prefix, audit_plugin.interface_version >> 8);
|
||||
}
|
||||
|
||||
init_peer_info();
|
||||
set_plugin_name_from_env();
|
||||
}
|
||||
#elif MYSQL_VERSION_ID < 50600
|
||||
#if MYSQL_VERSION_ID < 50600
|
||||
extern struct st_mysql_plugin *mysql_mandatory_plugins[];
|
||||
extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
|
||||
{
|
||||
|
||||
@@ -228,7 +228,7 @@ static void WriteJump32(void *pAddress, ULONG_PTR JumpTo)
|
||||
// Hooks a function
|
||||
//
|
||||
static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG_PTR trampolineFunction,
|
||||
unsigned int *trampolinesize, unsigned int *usedsize)
|
||||
unsigned int *trampolinesize, unsigned int *usedsize, SavedCode* saved_code)
|
||||
{
|
||||
#define MAX_INSTRUCTIONS 100
|
||||
uint8_t raw[MAX_INSTRUCTIONS];
|
||||
@@ -293,6 +293,9 @@ static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG_
|
||||
ud_obj.operand[0].type == UD_OP_JIMM)
|
||||
{
|
||||
bool cannot_disassemble = true;
|
||||
sql_print_information("ud_obj.mnemonic == UD_Ijmp: %d", ud_obj.mnemonic == UD_Ijmp);
|
||||
sql_print_information("ud_obj.mnemonic == UD_Icall: %d", ud_obj.mnemonic == UD_Icall);
|
||||
sql_print_information("ud_obj.operand[0].type == UD_OP_JIMM: %d", ud_obj.operand[0].type == UD_OP_JIMM);
|
||||
|
||||
#ifdef __i386__
|
||||
const BYTE *pc = (const BYTE *)targetFunction + InstrSize;
|
||||
@@ -324,7 +327,59 @@ static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG_
|
||||
cannot_disassemble = false;
|
||||
}
|
||||
}
|
||||
sql_print_error("in __i386__");
|
||||
|
||||
#else
|
||||
// If there is a relative jump or call in the to be overwritten chunk,
|
||||
// construct an absolute jump/call in the trampoline.
|
||||
#ifdef __x86_64__
|
||||
sql_print_information("__x86_64__");
|
||||
#endif
|
||||
if (ud_obj.operand[0].type == UD_OP_JIMM && (ud_obj.mnemonic == UD_Ijmp || ud_obj.mnemonic == UD_Icall)) {
|
||||
// jump or call
|
||||
size_t rewrite_size = 0;
|
||||
switch (ud_obj.mnemonic) {
|
||||
case UD_Ijmp:
|
||||
sql_print_information("rewriting relative jump as absolute");
|
||||
memcpy((void*)(trampolineFunction + uCurrentSize), "\xff\x25\x00\x00\x00\x00", 6); // jmpq *0x0(%rip)
|
||||
rewrite_size = 6;
|
||||
break;
|
||||
case UD_Icall:
|
||||
sql_print_information("rewriting relative call as absolute");
|
||||
memcpy((void*)(trampolineFunction + uCurrentSize), "\xff\x15\x02\x00\x00\x00", 6); // callq *0x2(%rip) -- call the function via the address stored at RIP+2
|
||||
memcpy((void*)(trampolineFunction + uCurrentSize + 6), "\xeb\x08", 2); // jmp 0x08 -- jump over the function address (8 bytes forward)
|
||||
rewrite_size = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// calculate the jump target from the instruction pointer and the immediate operand
|
||||
unsigned long jump_target = ud_obj.pc;
|
||||
switch (ud_obj.operand[0].size) {
|
||||
case 8:
|
||||
jump_target += ud_obj.operand[0].lval.sbyte;
|
||||
break;
|
||||
case 16:
|
||||
jump_target += ud_obj.operand[0].lval.sword;
|
||||
break;
|
||||
case 32:
|
||||
jump_target += ud_obj.operand[0].lval.sdword;
|
||||
break;
|
||||
}
|
||||
memcpy((void*)(trampolineFunction + uCurrentSize + rewrite_size), &jump_target, 8);
|
||||
rewrite_size += 8;
|
||||
|
||||
// update the indexes
|
||||
uCurrentSize += rewrite_size;
|
||||
InstrSize += ud_insn_len (&ud_obj);
|
||||
|
||||
// clear the flag
|
||||
cannot_disassemble = false;
|
||||
|
||||
sql_print_information("target address: [0x%016lx]", jump_target);
|
||||
sql_print_information("original instruction: [%s]", ud_insn_asm(&ud_obj));
|
||||
}
|
||||
#endif
|
||||
if (cannot_disassemble)
|
||||
{
|
||||
@@ -381,8 +436,17 @@ static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG_
|
||||
return false;
|
||||
}
|
||||
|
||||
WriteJump((BYTE*)trampolineFunction + uCurrentSize, targetFunction + InstrSize);
|
||||
// Save the original code that is going to be overwitten by the jump.
|
||||
// The code in the trampoline can be larger due to rewriting of RIP
|
||||
// relative instructions and unsuitable for writting back on unhook.
|
||||
memcpy(saved_code->code, (void*)targetFunction, InstrSize);
|
||||
saved_code->size = InstrSize;
|
||||
|
||||
// jump from trampoline back to continue the original function
|
||||
WriteJump((BYTE*)trampolineFunction + uCurrentSize, targetFunction + InstrSize);
|
||||
*usedsize = uCurrentSize + JUMP_SIZE;
|
||||
|
||||
// jump from the begin of the original function to our function
|
||||
#ifndef __x86_64__
|
||||
WriteJump((void *) targetFunction, newFunction);
|
||||
#else
|
||||
@@ -411,7 +475,7 @@ static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG_
|
||||
//
|
||||
|
||||
|
||||
static void UnhookFunction(ULONG_PTR Function, ULONG_PTR trampolineFunction, unsigned int trampolinesize)
|
||||
static void UnhookFunction(ULONG_PTR Function, ULONG_PTR trampolineFunction, unsigned int trampolinesize, SavedCode* saved_code)
|
||||
{
|
||||
DATATYPE_ADDRESS FunctionPage = get_page_address((void*)Function);
|
||||
if (unprotect((void*)FunctionPage, PAGE_SIZE) != 0)
|
||||
@@ -421,7 +485,7 @@ static void UnhookFunction(ULONG_PTR Function, ULONG_PTR trampolineFunction, uns
|
||||
log_prefix, (void *) FunctionPage);
|
||||
return;
|
||||
}
|
||||
memcpy((void *) Function, (void*)trampolineFunction,trampolinesize);
|
||||
memcpy((void *) Function, saved_code->code, saved_code->size);
|
||||
protect((void*)FunctionPage, PAGE_SIZE);
|
||||
}
|
||||
|
||||
@@ -442,12 +506,12 @@ static void UnhookFunction(ULONG_PTR Function, ULONG_PTR trampolineFunction, uns
|
||||
* @Return 0 on success otherwise failure
|
||||
* @See MS Detours paper: http:// research.microsoft.com/pubs/68568/huntusenixnt99.pdf for some background info.
|
||||
*/
|
||||
int hot_patch_function(void *targetFunction, void *newFunction, void *trampolineFunction, unsigned int *trampolinesize, unsigned int *usedsize, bool info_print)
|
||||
int hot_patch_function(void *targetFunction, void *newFunction, void *trampolineFunction, unsigned int *trampolinesize, unsigned int *usedsize, bool info_print, SavedCode* saved_code)
|
||||
{
|
||||
DATATYPE_ADDRESS trampolinePage = get_page_address(trampolineFunction);
|
||||
cond_info_print(info_print, "%s hot patching function: %p, trampolineFunction: %p trampolinePage: %p",log_prefix, (void *)targetFunction, (void *)trampolineFunction, (void *)trampolinePage);
|
||||
if (HookFunction((ULONG_PTR) targetFunction, (ULONG_PTR) newFunction,
|
||||
(ULONG_PTR) trampolineFunction, trampolinesize, usedsize))
|
||||
(ULONG_PTR) trampolineFunction, trampolinesize, usedsize, saved_code))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -466,15 +530,18 @@ int hot_patch_function(void *targetFunction, void *newFunction, void *trampoline
|
||||
* @param trampolineFunction a function which contains a jump back to the targetFunction.
|
||||
* @param log_file if not null will log about progress of installing the plugin
|
||||
*/
|
||||
void remove_hot_patch_function(void *targetFunction, void *trampolineFunction, unsigned int trampolinesize, bool info_print)
|
||||
void remove_hot_patch_function(void *targetFunction, void *trampolineFunction, unsigned int trampolinesize, bool info_print, SavedCode* saved_code)
|
||||
{
|
||||
if (trampolinesize == 0)
|
||||
sql_print_information("trampolinesize: %d", trampolinesize);
|
||||
sql_print_information("saved_code->size: %zd", saved_code->size);
|
||||
if (trampolinesize == 0 || !saved_code->size)
|
||||
{
|
||||
// nothing todo. As hot patch was not set.
|
||||
return;
|
||||
cond_info_print(info_print, "%s not removing as hot patch was not set: %p",log_prefix, (void *)targetFunction);
|
||||
return;
|
||||
}
|
||||
DATATYPE_ADDRESS targetPage = get_page_address(targetFunction);
|
||||
cond_info_print(info_print, "%s removing hot patching function: %p targetPage: %p trampolineFunction: %p",log_prefix, (void *)targetFunction, (void *)targetPage, (void *)trampolineFunction);
|
||||
UnhookFunction ((ULONG_PTR) targetFunction, (ULONG_PTR)trampolineFunction,trampolinesize);
|
||||
UnhookFunction ((ULONG_PTR) targetFunction, (ULONG_PTR)trampolineFunction,trampolinesize, saved_code);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,3 +22,6 @@ libudis86_la_SOURCES = itab.c \
|
||||
|
||||
itab.c itab.h: ../docs/x86optable.xml opgen.py
|
||||
python ./opgen.py
|
||||
|
||||
# generate the generated sources prior to the compilation
|
||||
BUILT_SOURCES = itab.c itab.h
|
||||
|
||||
Reference in New Issue
Block a user