17 Commits

Author SHA1 Message Date
Guy Lichtman
e38bc05f0f Adding flush support for json log file. Closes #9. 2012-08-13 15:30:49 +03:00
Guy Lichtman
6dae35653a readme improvements 2012-08-01 21:37:49 +03:00
Guy Lichtman
23259986a0 More offsets for latest mysql versions upto 5.1.63 and 5.5.25.
Automatic calculation of offsets seen used in Ubuntu/Debian builds based upon found version offsets when checksum validation is disabled.
Remove usage of strdup for delay_cmds, record_objs and record_cmds and use PLUGIN_VAR_MEMALOC instead.
2012-08-01 21:34:33 +03:00
Guy Lichtman
59f5b82cc9 formating cleanup 2012-08-01 15:52:24 +03:00
Guy Lichtman
eddd9e65e2 check in hot patch remove to return immediatly if not needed 2012-08-01 15:51:45 +03:00
Joseph Mocker
23dd5f824c Changed audit_record_objs syntax to period separator, database.table (instead of colon). Added wildcarding for database or table, so you can specify *.table and database.* 2012-07-30 09:46:30 -07:00
Joseph Mocker
3595c3b6f4 Added an audit_checksum parameter used with audit_offsets as an additional verification that the offsets are for the expected executable. This could be useful in upgrade situations. 2012-07-28 07:28:10 -07:00
Joseph Mocker
68a25232ec Fixed issue where values were not being configured from my.cnf.
Changed audit_json_socket and audit_json_file to required a value of ON/OFF to match other boolean parameters.
2012-07-28 07:06:10 -07:00
Joseph Mocker
ed048a30bb added the ability to limit auditing output to specific commands and objects(tables/views) 2012-07-26 08:03:13 -07:00
Joseph Mocker
60f1b8e6d7 reindented source files 2012-07-26 07:45:39 -07:00
Guy Lichtman
eb3e38116c offset-extract 2012-04-11 16:17:50 +03:00
Guy Lichtman
88159229da added offset-extract. hot_patch cleanup. 2012-04-11 15:58:43 +03:00
Guy Lichtman
2109a1030d added offset-extract. hot_patch cleanup. 2012-04-11 15:56:24 +03:00
Guy Lichtman
6db2a9f158 compiling instructions cleanup 2012-04-10 12:51:44 +03:00
Guy Lichtman
144a8bf69b added download link to mysql source code 2012-04-10 12:46:16 +03:00
Guy Lichtman
d9955f7840 renamed README to support github markdown syntax 2012-04-10 12:28:02 +03:00
Guy Lichtman
026fdbf505 small fixes for command name loading
new readme with ref to github wiki
improve performance of command lookup.
Fix cmd type and object type in cached queries.
Support for MySQL 5.5.21 offsets
2012-04-09 16:35:21 +03:00
11 changed files with 723 additions and 512 deletions

54
README.md Normal file
View File

@@ -0,0 +1,54 @@
MySQL AUDIT Plugin
===================
MySQL AUDIT Plugin is a MySQL plugin from McAfee providing audit capabilities for MySQL,
designed with an emphasis on security and audit requirements. The plugin may be used
as a standalone audit solution or configured to feed data to external monitoring tools.
Installation and Configuration
------------------------------
Please check out our wiki on github for detailed installation and configuration instructions:
https://github.com/mcafee/mysql-audit/wiki
Issues
------------------------------
Found a bug? Got a feature request or question?
Please feel free to report to: https://github.com/mcafee/mysql-audit/issues
If reporting a bug, please describe the problem verbosely. Try to see if it reproduces and
include a detailed description on how to reproduce.
Make sure to include your MySQL Server version and Audit Plugin version.
To print MySQL Server version: log into MySQL and execute the command:
status
Please include with the bug the MySQL error log.
Log file location can be queried by running the following command:
show global variables like 'log_error'
Source Code
-------------------------------
Source code of AUDIT plugin is available at: https://github.com/mcafee/mysql-audit
License
-------------------------------
Copyright (C) 2012 McAfee, Inc.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
See COPYING file for a copy of the GPL Version 2 license.

View File

@@ -1,104 +0,0 @@
Audit Plugin
This is a release of Audit Plugin for MySQL 5.1 and 5.5.
Audit Plugin is brought to you by McAfee, Inc (www.mcafee.com).
==== INSTALLATION =====
Make sure to download the proper binary distribution. There are separate binaries for MySQL 5.1 and 5.5 according
to platform (32 or 64 bit).
Audit Plugin is available in the binary distribution under the lib dir. File name: libaudit_plugin.so.
To install Audit Plugin, copy libaudit_plugin.so to the plugin_dir (for example /usr/lib/mysql/plugin or /usr/lib64/mysql/plugin) of MySQL.
To see the configured plugin dir login to MySQL and issue the following command:
show global variables like 'plugin_dir';
There are 2 options for installing the plugin via plugin-load configuration option or by issuing the
INSTALL PLUGIN statement.
* Installing via: plugin-load
Add to the MySQL option file (my.cnf) at the [mysqld] section the option:
plugin-load=AUDIT=libaudit_plugin.so
Restart the mysqld server for the changes to take effect.
* Installing via: INSTALL PLUGIN
You will need to issue the following sql command to install the plugin:
INSTALL PLUGIN AUDIT SONAME 'libaudit_plugin.so';
A restart to the mysqld server is not necessary.
Note: On production systems, McAfee recommends using the plugin-load option for installing
the audit plugin.
More info on installing MySQL plugins is available at:
http://dev.mysql.com/doc/refman/5.1/en/plugin-installing-uninstalling.html
===== VERIFICATION =====
To check if the plugin is installed successfully you can issue the following command, which will show all installed plugins:
show plugins;
The Audit plugin will show up with the name AUDIT.
Additionally you can verify the version of the Audit Plugin by running the following command:
show global status like 'AUDIT_version';
===== CONFIGURATION =====
By default, after installation the Audit Plugin doesn't log activity. You must explicitly enable
the type of logging desired. Configuration is done through the use of MySQL system variables.
Audit Plugin system variables can be set at server startup using options on the command line or in an option file.
Additionally, the Audit Plugin system variables can be changed dynamically while the server is running
by means of the SET statement.
Available Audit Plugin command line options:
--audit-json-file AUDIT plugin json log file Enable|Disable
--audit-json-file-sync=#
AUDIT plugin json log file sync period. If the value of
this variable is greater than 0, audit log will sync to
disk after every audit_json_file_sync writes.
--audit-json-log-file=name
AUDIT plugin json log file name
--audit-json-socket AUDIT plugin json log unix socket Enable|Disable
--audit-json-socket-name=name
AUDIT plugin json log unix socket name
--audit-uninstall-plugin
AUDIT uninstall plugin Enable|Disable.
If disabled attempts to uninstall the AUDIT plugin via the sql UNINSTALL command will fail.
Provides added security from uninstalling the plugin. Also protection from
CVE-2010-1621 (http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-1621)
affecting versions upto 5.1.46.
===== REPORTING BUGS =====
Please describe the problem verbosely. Try to see if it reproduces and
include a detailed description on how to reproduce.
Make sure to include your MySQL Server version and Audit Plugin version.
To print MySQL Server version log into MySQL and execute the command: status.
Please include with the bug the log files:
* mysql-audit.log
* MySQL error log: log file location can be queried by running the following
command: show global variables like 'log_error'
===== LICENSE =====
The software included in this product contains copyrighted software that is licensed under the GPL Version 2.
See COPYING file for a copy of the GPL Version 2 license.
Source code is available at: https://github.com/mcafee/mysql-audit

129
compiling.txt Normal file → Executable file
View File

@@ -1,63 +1,66 @@
Compiling instructions:
make sure you have installed the following packages:
autoconf
automake
gcc-c++
To compile you will need to obtain the MySQL source code.
==== MySQL 5.1 ======
Extract the MySQL source code in the root directory. For example:
unzip zip-sources/mysql-5.1.40.zip
Then run the following command:
cd mysql-5.1.40
CXX=gcc ./configure
cd include
make
Then goto top dir and run:
chmod +x bootstrap.sh
./bootstrap.sh
This will create configure script. Then run:
CXX='gcc -static-libgcc' CC='gcc -static-libgcc' ./configure --with-mysql=mysql-5.1.40
==== MySQL 5.5 ======
Extract MySQL 5.5 source code
go to mysql-src dir and run:
cd mysql-5.5.8
cmake .
make
back to working dir and run:
CXX='gcc -static-libgcc' CC='gcc -static-libgcc' ./configure --with-mysql=mysql-5.5.8 --with-mysql-libservices=mysql-5.5.8/libservices/libmysqlservices.a
make
==== Compiling with make =====
Go to top source dir and run:
make
Plugin will be compiled at:
src/.libs/libaudit_plugin.so
Some documentation about configure command for mysql:
http://dev.mysql.com/doc/refman/5.1/en/source-configuration-options.html
Compiling instructions
=======================
Make sure you have installed the following packages:
autoconf
automake
gcc-c++
To compile you will need to obtain the MySQL source code. MySQL source code is available at:
http://dev.mysql.com/downloads/mysql/
==== MySQL 5.1 ======
Extract the MySQL source code in the root directory. For example:
unzip zip-sources/mysql-5.1.40.zip
Then run the following command:
cd mysql-5.1.40
CXX=gcc ./configure
cd include
make
Then goto top dir and run:
chmod +x bootstrap.sh
./bootstrap.sh
This will create configure script. Then run:
CXX='gcc -static-libgcc' CC='gcc -static-libgcc' ./configure --with-mysql=mysql-5.1.40
==== MySQL 5.5 ======
Extract MySQL 5.5 source code
go to mysql-src dir and run:
cd mysql-5.5.8
cmake .
make
back to working dir and run:
CXX='gcc -static-libgcc' CC='gcc -static-libgcc' ./configure --with-mysql=mysql-5.5.8 --with-mysql-libservices=mysql-5.5.8/libservices/libmysqlservices.a
make
==== Compiling with make =====
Go to top source dir and run:
make
Plugin will be compiled at:
src/.libs/libaudit_plugin.so
Some documentation about configure command for mysql:
http://dev.mysql.com/doc/refman/5.1/en/source-configuration-options.html

View File

@@ -95,6 +95,9 @@ CXXFLAGS="-fno-implicit-templates -fno-exceptions -fno-rtti "
#add pthread libs
LIBS="$LIBS -lpthread"
#make sure we have const
AC_C_CONST
AC_TYPE_SIZE_T
@@ -113,11 +116,13 @@ echo "Version: $MYSQL_AUDIT_PLUGIN_VERSION-$MYSQL_AUDIT_PLUGIN_REVISION"
CPPFLAGS="$CPPFLAGS -DMYSQL_AUDIT_PLUGIN_VERSION='\"$MYSQL_AUDIT_PLUGIN_VERSION\"'"
CPPFLAGS="$CPPFLAGS -DMYSQL_AUDIT_PLUGIN_REVISION='\"$MYSQL_AUDIT_PLUGIN_REVISION\"'"
#subst the relevant variables
AC_SUBST(CPPFLAGS)
AC_SUBST(CXXLAGS)
AC_SUBST(CLAGS)
AC_CONFIG_FILES([Makefile
src/Makefile
yajl/Makefile

15
include/audit_handler.h Normal file → Executable file
View File

@@ -33,6 +33,10 @@ typedef struct _THDPRINTED {
const char * retrieve_command (THD * thd);
typedef size_t OFFSET;
#define MAX_COM_STATUS_VARS_RECORDS 512
#define MAX_OBJECT_CHAR_NUMBERS 130
#define MAX_NUM_OBJECT_ELEM 256
/**
* The struct usd to hold offsets. We should have one per version.
@@ -158,7 +162,7 @@ public:
return thd->query;
#endif
}
//virtual char * retrieve_command (THD * thd);
};
@@ -209,8 +213,8 @@ public:
static const size_t MAX_AUDIT_HANDLERS_NUM = 4;
static const size_t BSON_FILE_HANDLER = 1;
static const size_t BSON_SOCKET_HANDLER = 3;
static const size_t JSON_FILE_HANDLER = 1;
static const size_t JSON_SOCKET_HANDLER = 3;
static Audit_handler * m_audit_handler_list[];
@@ -273,6 +277,11 @@ public:
}
void set_enable(bool val);
/**
* will close and start the handler
*/
void flush();
/**
* Will get relevant shared lock and call internal method of handler

View File

@@ -0,0 +1,47 @@
#!/bin/sh
if [ $# = 0 ]; then
echo "Usage: $0 <mysqld executable> [optional mysqld symbols]"
echo "Will extract offsets from mysqld. Requires gdb, md5sum and mysqld symbols."
exit 1
fi
#extract the version of mysqld
FULL_MYVER=`$1 --version | grep -P -o 'Ver\s+[\w\.-]+'| awk '{print $2}'`
#extract the md5 digest
MYMD5=`md5sum -b $1 | awk -v Field=1 '{print $1}'`
MYVER="$FULL_MYVER"
echo $FULL_MYVER | grep 'log' > /dev/null
if [ $? = 0 ]; then
MYVER=`echo "$MYVER" | grep -P -o '.+(?=-log)'`
fi
echo "set logging on" > offsets.gdb
echo 'printf "{\"'$MYVER'\",\"'$MYMD5'\", %d, %d, %d, %d, %d, %d}", ((size_t)&((THD *)log_slow_statement)->query_id) - (size_t)log_slow_statement, ((size_t)&((THD *)log_slow_statement)->thread_id) - (size_t)log_slow_statement, ((size_t)&((THD *)log_slow_statement)->main_security_ctx) - (size_t)log_slow_statement, ((size_t)&((THD *)log_slow_statement)->command) - (size_t)log_slow_statement, ((size_t)&((THD *)log_slow_statement)->lex) - (size_t)log_slow_statement, (size_t)&((LEX*)log_slow_statement)->comment - (size_t) log_slow_statement' >> offsets.gdb
SYMPARAM=""
if [ -n "$2" ]; then
SYMPARAM="-s $2 -e"
fi
gdb -n -q -batch -x offsets.gdb $SYMPARAM $1 > /dev/null 2>&1
if [ $? != 0 ]; then
echo "GDB failed!!!" > /dev/stderr
exit 2
fi
OFFSETS=`cat gdb.txt`
echo "//offsets for: $1 ($FULL_MYVER)"
echo "$OFFSETS,"
#clean up
rm gdb.txt
rm offsets.gdb

View File

@@ -18,11 +18,11 @@ INCLUDES = $(MYSQL_INC) $(YAJL_INC) $(UDIS_INC)
pkgplugindir = $(MYSQL_PLUGIN_DIR)
pkgplugin_LTLIBRARIES = libaudit_plugin.la
libaudit_plugin_la_LDFLAGS = -module
libaudit_plugin_la_LDFLAGS = -module -Wl,--version-script=MySQLPlugin.map
libaudit_plugin_la_SOURCES = hot_patch.cc audit_plugin.cc audit_handler.cc
libaudit_plugin_la_LIBADD = $(top_srcdir)/yajl/src/libyajl.la $(top_srcdir)/udis86/libudis86/libudis86.la $(MYSQL_LIBSERVICES)
libaudit_plugin_la_LIBADD = $(top_srcdir)/yajl/src/libyajl.la $(top_srcdir)/udis86/libudis86/libudis86.la $(MYSQL_LIBSERVICES)

10
src/MySQLPlugin.map Normal file
View File

@@ -0,0 +1,10 @@
{
global:
_mysql_plugin_declarations_;
_mysql_plugin_interface_version_;
_mysql_sizeof_struct_st_plugin_;
audit_plugin_so_init;
thd_alloc_service;
local: *;
};

130
src/audit_handler.cc Normal file → Executable file
View File

@@ -78,52 +78,6 @@ const char * Audit_formatter::retrive_object_type (TABLE_LIST *pObj)
return "TABLE";
}
const char * retrieve_command (THD * thd)
{
const char *cmd;
SHOW_VAR *com_status_vars;
int sv_idx =0;
int command = Audit_formatter::thd_inst_command(thd);
if (command < 0 || command > COM_END)
{
command = COM_END;
}
const int sql_command = thd_sql_command(thd);
while (strcmp (status_vars[sv_idx].name,"Com") !=0 && status_vars[sv_idx].name != NullS)
{
sv_idx ++;
}
if (strcmp (status_vars[sv_idx].name,"Com")==0)
{
int status_vars_index =0;
com_status_vars = (SHOW_VAR*)status_vars[sv_idx].value;
size_t initial_offset = (size_t) com_status_vars[0].value;
while (com_status_vars[status_vars_index].value != (char*) (sizeof (ulong) * (sql_command + 1) + initial_offset)
&& com_status_vars[status_vars_index].name != NullS)
{
status_vars_index ++;
}
if (com_status_vars[status_vars_index].value != NullS)
{
cmd = com_status_vars[status_vars_index].name;
}
else
{
cmd = command_name[command].str;
}
}
else
{
cmd = "UNKNOWN";
}
Security_context * sctx = Audit_formatter::thd_inst_main_security_ctx(thd);
if (strcmp (cmd, "Connect") ==0 && (sctx->priv_user == NULL || *sctx->priv_user ==0x0))
{
cmd = "Failed Login";
}
return cmd;
}
void Audit_handler::stop_all()
{
@@ -169,6 +123,22 @@ void Audit_handler::set_enable(bool val)
unlock();
}
void Audit_handler::flush()
{
lock_exclusive();
if (!m_enabled) //if not running we don't flush
{
unlock();
return;
}
//call the cleanup of the handler
handler_stop();
//call the startup of the handler
handler_start();
sql_print_information("%s Log flush complete.", AUDIT_LOG_PREFIX);
unlock();
}
void Audit_handler::log_audit(ThdSesData *pThdData)
{
lock_shared();
@@ -363,6 +333,15 @@ static inline void yajl_add_uint64(yajl_gen gen, const char * name, uint64 num)
snprintf(buf, max_int64_str_len, "%llu", num);
yajl_add_string_val(gen, name, buf);
}
static inline void yajl_add_obj( yajl_gen gen, const char *db,const char* ptype,const char * name =NULL)
{
yajl_add_string_val(gen, "db", db);
if (name)
{
yajl_add_string_val(gen, "name", name);
}
yajl_add_string_val(gen, "obj_type",ptype);
}
//void Audit_file_handler::print_sleep (THD *thd, int delay_ms)
//{
@@ -388,7 +367,7 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
unsigned long thdid = thd_get_thread_id(pThdData->getTHD());
query_id_t qid = thd_inst_query_id(pThdData->getTHD());
int command = thd_inst_command(pThdData->getTHD());
const char *cmd = pThdData->getCmdName();
Security_context * sctx = thd_inst_main_security_ctx(pThdData->getTHD());
@@ -407,7 +386,31 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
yajl_add_string_val(gen, "priv_user", sctx->priv_user);
yajl_add_string_val(gen, "host", sctx->host);
yajl_add_string_val(gen, "ip", sctx->ip);
yajl_add_string_val(gen, "cmd", cmd);
const char *cmd = pThdData->getCmdName();
//only print tables if lex is not null and it is not a quit command
LEX * pLex = Audit_formatter::thd_lex(pThdData->getTHD());
QueryTableInf *pQuery_cache_table_list = getQueryCacheTableList1 (pThdData->getTHD());
if (pLex && command != COM_QUIT && pLex->query_tables == NULL && pQuery_cache_table_list)
{
yajl_add_string_val(gen, "cmd", "select");
yajl_add_string(gen, "objects");
yajl_gen_array_open(gen);
for (int i=0;i<pQuery_cache_table_list->num_of_elem && i < MAX_NUM_QUERY_TABLE_ELEM && pQuery_cache_table_list->num_of_elem >=0;i++)
{
yajl_gen_map_open(gen);
yajl_add_obj (gen, pQuery_cache_table_list->db[i],pQuery_cache_table_list->object_type[i],pQuery_cache_table_list->table_name[i] );
yajl_gen_map_close(gen);
}
yajl_gen_array_close(gen);
}
else
{
yajl_add_string_val(gen, "cmd", cmd);
}
if (strcmp (cmd,"Init DB") ==0 || strcmp (cmd, "SHOW TABLES")== 0 || strcmp (cmd, "SHOW TABLE")==0)
{
@@ -415,14 +418,12 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
{
yajl_add_string(gen, "objects");
yajl_gen_array_open(gen);
yajl_add_string_val(gen, "db",(pThdData->getTHD())->db);
yajl_add_string_val(gen, "obj_type","database");
yajl_add_obj (gen,(pThdData->getTHD())->db,"database", NULL);
yajl_gen_array_close(gen);
}
}
//only print tables if lex is not null and it is not a quit command
LEX * pLex = Audit_formatter::thd_lex(pThdData->getTHD());
if (pLex && command != COM_QUIT && pLex->query_tables)
{
yajl_add_string(gen, "objects");
@@ -433,16 +434,14 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
while (table)
{
yajl_gen_map_open(gen);
yajl_add_string_val(gen, "db", table->get_db_name());
yajl_add_string_val(gen, "name", table->get_table_name());
if (isFirstElementInView && strstr (cmd,"_view")!=NULL )
{
yajl_add_string_val(gen, "obj_type","view");
yajl_add_obj (gen,table->get_db_name(), "view",table->get_table_name());
isFirstElementInView = false;
}
else
{
yajl_add_string_val(gen, "obj_type",retrive_object_type(table));
yajl_add_obj (gen,table->get_db_name(), retrive_object_type(table),table->get_table_name());
}
yajl_gen_map_close(gen);
table = table->next_global;
@@ -450,25 +449,6 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
yajl_gen_array_close(gen);
}
QueryTableInf *pQuery_cache_table_list = getQueryCacheTableList1 (pThdData->getTHD());
if (pLex && command != COM_QUIT && pLex->query_tables == NULL && pQuery_cache_table_list)
{
yajl_add_string(gen, "objects");
yajl_gen_array_open(gen);
for (int i=0;i<pQuery_cache_table_list->num_of_elem && i < MAX_NUM_QUERY_TABLE_ELEM && pQuery_cache_table_list->num_of_elem >=0;i++)
{
yajl_gen_map_open(gen);
yajl_add_string_val(gen, "db", pQuery_cache_table_list->db[i]);
yajl_add_string_val(gen, "name", pQuery_cache_table_list->table_name[i]);
yajl_add_string_val(gen,"type",pQuery_cache_table_list->object_type[i]);
yajl_gen_map_close(gen);
}
yajl_gen_array_close(gen);
}
size_t qlen = 0;

651
src/audit_plugin.cc Normal file → Executable file
View File

@@ -103,7 +103,11 @@ static const ThdOffsets thd_offsets_arr[] =
//offsets for: /mysqlrpm/5.1.60/usr/sbin/mysqld (5.1.60-community)
{"5.1.60-community","d9497964e8983a348538c0d05eaee7f0", 6328, 6392, 3688, 3960, 88, 2048},
//offsets for: /mysqlrpm/5.1.61/usr/sbin/mysqld (5.1.61-community)
{"5.1.61-community","bda6030d35e7fafa5b1e57154a53b804", 6328, 6392, 3688, 3960, 88, 2048},
{"5.1.61-community","bda6030d35e7fafa5b1e57154a53b804", 6328, 6392, 3688, 3960, 88, 2048},
//offsets for: /mysqlrpm/5.1.62/usr/sbin/mysqld (5.1.62-community)
{"5.1.62-community","a4e8de89e0d9a353d09687d3b4560cb3", 6328, 6392, 3688, 3960, 88, 2048},
//offsets for: /mysqlrpm/5.1.63/usr/sbin/mysqld (5.1.63-community)
{"5.1.63-community","0f4d7e3b17eb36f17aafe4360993a769", 6328, 6392, 3688, 3960, 88, 2048},
//offsets for: mysqlrpm/5.5.8/usr/sbin/mysqld (5.5.8)
{"5.5.8","70a882693d54df8ab7c7d9f256e317bb", 6032, 6080, 3776, 4200, 88, 2560},
//offsets for: mysqlrpm/5.5.9/usr/sbin/mysqld (5.5.9)
@@ -132,7 +136,18 @@ static const ThdOffsets thd_offsets_arr[] =
{"5.5.19","0765dadb23315bb076bc6e21cfb2de40", 6048, 6096, 3800, 4224, 88, 2560},
//offsets for: /mysqlrpm/5.5.20/usr/sbin/mysqld (5.5.20)
{"5.5.20","9f6122576930c5d09ca9244094c83f24", 6048, 6096, 3800, 4224, 88, 2560},
//offsets for: mysqlrpm/5.5.21/usr/sbin/mysqld (5.5.21)
{"5.5.21","4a03ad064ed393dabdde175f3ea05ff2", 6048, 6096, 3800, 4224, 88, 2560},
//offsets for: mysqlrpm/5.5.22/usr/sbin/mysqld (5.5.22)
{"5.5.22","f3592147108e65d92cb18fb4d900c4ab", 6048, 6096, 3800, 4224, 88, 2560},
//offsets for: mysqlrpm/5.5.23/usr/sbin/mysqld (5.5.23)
{"5.5.23","aac33433f75b9758e7f42fad6991fa9e", 6048, 6096, 3800, 4224, 88, 2568},
//offsets for: mysqlrpm/5.5.24/usr/sbin/mysqld (5.5.24)
{"5.5.24","2915a9dd079446149b17d0d1c478fb11", 6048, 6096, 3800, 4224, 88, 2568},
//offsets for: /mysqlrpm/5.5.25/usr/sbin/mysqld (5.5.25)
{"5.5.25","6043eff2cfa493d4e020cae65c41b030", 6056, 6104, 3808, 4232, 88, 2568},
//offsets for: mysqlrpm/5.5.25a/usr/sbin/mysqld (5.5.25a)
{"5.5.25a","b59c03244daf51d4327409288d8c889f", 6056, 6104, 3808, 4232, 88, 2568},
//DISTRIBUTION: tar.gz
//offsets for: /mysql/5.1.30/bin/mysqld (5.1.30)
@@ -199,7 +214,13 @@ static const ThdOffsets thd_offsets_arr[] =
//offsets for: /mysql/5.1.60/bin/mysqld (5.1.60)
{"5.1.60","5407e492f802cca03eccb2211205632d", 6336, 6400, 3696, 3968, 88, 2048},
//offsets for: /mysql/5.1.61/bin/mysqld (5.1.61)
{"5.1.61","c2ce56446b33ee22c16160b3f8206541", 6336, 6400, 3696, 3968, 88, 2048},
{"5.1.61","c2ce56446b33ee22c16160b3f8206541", 6336, 6400, 3696, 3968, 88, 2048},
//offsets for: /mysql/5.1.62/bin/mysqld (5.1.62)
{"5.1.62","5ab9ae376d93b71120e1c9dc2129c580", 6336, 6400, 3696, 3968, 88, 2048},
//offsets for: /mysql/5.1.63/bin/mysqld (5.1.63)
{"5.1.63","ea56cc85859f146c42957177524492c3", 6336, 6400, 3696, 3968, 88, 2048},
//offsets set by https://github.com/creechy
{"5.1.63","2a6d7c81179baf6bc6bbb807b8b54967", 6336, 6400, 3696, 3968, 88, 2048},
//offsets for: mysql/5.5.8/bin/mysqld (5.5.8)
{"5.5.8","a32b163f08ca8bfd7486cd77200d9df3", 6032, 6080, 3776, 4200, 88, 2560},
//offsets for: mysql/5.5.9/bin/mysqld (5.5.9)
@@ -228,10 +249,17 @@ static const ThdOffsets thd_offsets_arr[] =
{"5.5.18","099d31c0cd0754934b84c17f683d019e", 6040, 6088, 3792, 4216, 88, 2560},
{"5.5.19","f000f941c4e4f7b84e66d7b8c115ca8f", 6048, 6096, 3800, 4224, 88, 2560},
//offsets for: /mysql/5.5.20/bin/mysqld (5.5.20)
{"5.5.20","8b68e84332b442d58a46ae4299380a99", 6048, 6096, 3800, 4224, 88, 2560}
{"5.5.20","8b68e84332b442d58a46ae4299380a99", 6048, 6096, 3800, 4224, 88, 2560},
//offsets for: mysql/5.5.21/bin/mysqld (5.5.21)
{"5.5.21","66d23cb577e2bcfe29da08833f5e7d8b", 6048, 6096, 3800, 4224, 88, 2560},
//offsets for: /mysql/5.5.22/bin/mysqld (5.5.22)
{"5.5.22","9152de65a0de0594f46e1db0d0c9a182", 6048, 6096, 3800, 4224, 88, 2560},
//offsets for: /mysql/5.5.23/bin/mysqld (5.5.23)
{"5.5.23","da3c9d8e3bf1c1235d283cbfad1631ab", 6048, 6096, 3800, 4224, 88, 2568},
//offsets for: /mysql/5.5.24/bin/mysqld (5.5.24)
{"5.5.24","5cb90eb8d4080f50fd7a432ad9eb75e0", 6048, 6096, 3800, 4224, 88, 2568},
//offsets for: /mysql/5.5.25/bin/mysqld (5.5.25)
{"5.5.25","3c19465f6b6f2daecb7a2d7ac1592824", 6056, 6104, 3808, 4232, 88, 2568}
};
#else
@@ -305,7 +333,11 @@ static const ThdOffsets thd_offsets_arr[] =
//offsets for: /mysqlrpm/5.1.60/usr/sbin/mysqld (5.1.60-community)
{"5.1.60-community","bc2d74ea58d22d998f8f8c88139fc5f7", 4096, 4136, 2240, 2420, 44, 1176},
//offsets for: /mysqlrpm/5.1.61/usr/sbin/mysqld (5.1.61-community)
{"5.1.61-community","f73013eb2001a02c84ddd0ac42a307ac", 4096, 4136, 2240, 2420, 44, 1176},
{"5.1.61-community","f73013eb2001a02c84ddd0ac42a307ac", 4096, 4136, 2240, 2420, 44, 1176},
//offsets for: /mysqlrpm/5.1.62/usr/sbin/mysqld (5.1.62-community)
{"5.1.62-community","f410638e7414c6cc709b7d5cda24669c", 4096, 4136, 2240, 2420, 44, 1176},
//offsets for: /mysqlrpm/5.1.63/usr/sbin/mysqld (5.1.63-community)
{"5.1.63-community","2b39264a67466c6f1dfa37c37a8a6bd0", 4096, 4136, 2240, 2420, 44, 1176},
//offsets for: mysqlrpm/5.5.8/usr/sbin/mysqld (5.5.8)
{"5.5.8","3132e8c883f72caf4c8eddb24fd005b4", 3792, 3820, 2336, 2668, 44, 1640},
//offsets for: mysqlrpm/5.5.9/usr/sbin/mysqld (5.5.9)
@@ -332,7 +364,16 @@ static const ThdOffsets thd_offsets_arr[] =
{"5.5.19","f3c31e2a5d95d3511b7106441f38929e", 3808, 3836, 2360, 2692, 44, 1640},
//offsets for: /mysqlrpm/5.5.20/usr/sbin/mysqld (5.5.20)
{"5.5.20","c73100bcb0d967b627cad72e66503194", 3808, 3836, 2360, 2692, 44, 1640},
//offsets for: mysqlrpm/5.5.21/usr/sbin/mysqld (5.5.21)
{"5.5.21","18d78ced97227b83e62e9b43ba5b3883", 3808, 3836, 2360, 2692, 44, 1640},
//offsets for: /mysqlrpm/5.5.22/usr/sbin/mysqld (5.5.22)
{"5.5.22","9da3081f83069a2762831d0ead5a97c8", 3808, 3836, 2360, 2692, 44, 1640},
//offsets for: /mysqlrpm/5.5.23/usr/sbin/mysqld (5.5.23)
{"5.5.23","c94f20f31cfa674d5763da7d2344c219", 3808, 3836, 2360, 2692, 44, 1644},
//offsets for: /mysqlrpm/5.5.24/usr/sbin/mysqld (5.5.24)
{"5.5.24","10e0ced8d28daf6a9c16d2b57be7c6af", 3808, 3836, 2360, 2692, 44, 1644},
//offsets for: /mysqlrpm/5.5.25/usr/sbin/mysqld (5.5.25)
{"5.5.25","bd20af37978967a145724098e913eeda", 3812, 3840, 2364, 2696, 44, 1644},
//DISTRIBUTION: tar.gz
//offsets for: mysql/5.1.30/bin/mysqld (5.1.30)
@@ -399,7 +440,11 @@ static const ThdOffsets thd_offsets_arr[] =
//offsets for: /mysql/5.1.60/bin/mysqld (5.1.60)
{"5.1.60","520270041d8c490d49233e88741c025c", 4104, 4144, 2248, 2428, 44, 1176},
//offsets for: /mysql/5.1.61/bin/mysqld (5.1.61)
{"5.1.61","1a7a0981d77f4d212e899efaa581bd42", 4104, 4144, 2248, 2428, 44, 1176},
{"5.1.61","1a7a0981d77f4d212e899efaa581bd42", 4104, 4144, 2248, 2428, 44, 1176},
//offsets for: /mysql/5.1.62/bin/mysqld (5.1.62)
{"5.1.62","4c5fd81faa9fe407c8a7fbd11b29351a", 4104, 4144, 2248, 2428, 44, 1176},
//offsets for: /mysql/5.1.63/bin/mysqld (5.1.63)
{"5.1.63","576124febe6310985e432f6346031ff4", 4104, 4144, 2248, 2428, 44, 1176},
//offsets for: /mysqlrpm/5.5.8/usr/sbin/mysqld (5.5.8)
{"5.5.8","3132e8c883f72caf4c8eddb24fd005b4", 3792, 3820, 2336, 2668, 44, 1640},
{"5.5.8","ad8a16d9bbfb783dab53f38cef757900", 3792, 3820, 2336, 2668, 44, 1640},
@@ -428,8 +473,19 @@ static const ThdOffsets thd_offsets_arr[] =
//offsets for: /mysql/5.5.19/bin/mysqld (5.5.19)
{"5.5.19","b407d678b9b855bfd29ba3c9f014d4b0", 3808, 3836, 2360, 2692, 44, 1640},
//offsets for: /mysql/5.5.20/bin/mysqld (5.5.20)
{"5.5.20","cb9b6887ea525fe9965121d357163fe4", 3808, 3836, 2360, 2692, 44, 1640}
{"5.5.20","cb9b6887ea525fe9965121d357163fe4", 3808, 3836, 2360, 2692, 44, 1640},
//offsets for: mysql/5.5.21/bin/mysqld (5.5.21)
{"5.5.21","a0762cee3ad5d4e77480956144900213", 3808, 3836, 2360, 2692, 44, 1640},
//offsets for: /mysql/5.5.22/bin/mysqld (5.5.22)
{"5.5.22","f635047c7ddf74dcac98612a65e40fe1", 3808, 3836, 2360, 2692, 44, 1640},
//offsets for: /mysql-5.5_5.5.22-0ubuntu1_i386/bin/mysqld (5.5.22-0ubuntu1)
{"5.5.22-0ubuntu1","9cc7d4582b1fae0ebf43dbe5ffb56008", 3784, 3812, 2336, 2668, 44, 1640},
//offsets for: /mysql/5.5.23/bin/mysqld (5.5.23)
{"5.5.23","8f51987d3f0d0dc044adcf42937050f6", 3808, 3836, 2360, 2692, 44, 1644},
//offsets for: /mysql/5.5.24/bin/mysqld (5.5.24)
{"5.5.24","a3916dca234905bd49b3fefe5d6ad738", 3808, 3836, 2360, 2692, 44, 1644},
//offsets for: /mysql/5.5.25/bin/mysqld (5.5.25)
{"5.5.25","f16c3fa53f77e5f25fd25694b5a27c48", 3812, 3840, 2364, 2696, 44, 1644}
};
#endif
@@ -445,39 +501,48 @@ 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 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 char * offsets_string = NULL;
static char * checksum_string = NULL;
static int delay_ms_val =0;
static char *delay_cmds_string = NULL;
static char *record_cmds_string = NULL;
static char *record_objs_string = NULL;
static char delay_cmds_array [SQLCOM_END + 2][MAX_COMMAND_CHAR_NUMBERS];
static char delay_cmds_array [SQLCOM_END + 2][MAX_COMMAND_CHAR_NUMBERS] = {0};
static char record_cmds_array [SQLCOM_END + 2][MAX_COMMAND_CHAR_NUMBERS] = {0};
static char record_objs_array [MAX_NUM_OBJECT_ELEM + 2][MAX_OBJECT_CHAR_NUMBERS] = {0};
static int num_delay_cmds = 0;
static int num_record_cmds = 0;
static int num_record_objs = 0;
static SHOW_VAR com_status_vars_array [MAX_COM_STATUS_VARS_RECORDS] = {0};
/**
* The trampoline function we use. Define it via a macro which simply fills it with nops.
*/
static int trampoline_mysql_execute_command(THD *thd)
__attribute__ ((noinline)) static int trampoline_mysql_execute_command(THD *thd)
{
TRAMPOLINE_NOP_DEF;
return 0; //dummy return as this does a jump.
}
static unsigned int trampoline_mysql_execute_size =0;
static void trampoline_log_slow_statement(THD *thd)
__attribute__ ((noinline)) static void trampoline_log_slow_statement(THD *thd)
{
TRAMPOLINE_NOP_DEF
}
static unsigned int trampoline_log_slow_statement_size =0;
static int trampoline_check_user(THD *thd, enum enum_server_command command, const char *passwd, uint passwd_len, const char *db, bool check_count)
__attribute__ ((noinline)) static int trampoline_check_user(THD *thd, enum enum_server_command command, const char *passwd, uint passwd_len, const char *db, bool check_count)
{
TRAMPOLINE_NOP_DEF;
return 0; //dummy return as this does a jump.
}
static unsigned int trampoline_check_user_size =0;
bool trampoline_acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len){
__attribute__ ((noinline)) static bool trampoline_acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len){
TRAMPOLINE_NOP_DEF;
return 0; //dummy return as this does a jump.
}
@@ -503,9 +568,63 @@ THDPRINTED * GetThdPrintedList (THD *thd)
return NULL;
}
static int check_array(const char *cmds[],const char *array, int length) {
for (int k=0; array[k * length] !='\0';k++) {
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) {
return 1;
}
}
}
return 0;
}
static void audit(ThdSesData *pThdData)
{
THDPRINTED *pThdPrintedList = GetThdPrintedList (pThdData->getTHD());
if (num_record_cmds > 0) {
const char * cmd = pThdData->getCmdName();
const char *cmds[2];
cmds[0] = cmd;
cmds[1] = NULL;
if (!check_array(cmds, (char *) record_cmds_array, MAX_COMMAND_CHAR_NUMBERS)) {
return;
}
}
if (num_record_objs > 0) {
LEX *pLex = Audit_formatter::thd_lex(pThdData->getTHD());
TABLE_LIST * table = pLex->query_tables;
int matched = 0;
while (table && !matched) {
char *name = table->get_table_name();
char *db = table->get_db_name();
char db_obj[MAX_OBJECT_CHAR_NUMBERS];
char wildcard_obj[MAX_OBJECT_CHAR_NUMBERS];
char db_wildcard[MAX_OBJECT_CHAR_NUMBERS];
strcpy(db_obj, db);
strcat(db_obj, ".");
strcat(db_obj, name);
strcpy(wildcard_obj, "*.");
strcat(wildcard_obj, name);
strcpy(db_wildcard, db);
strcat(db_wildcard, ".*");
const char *objects[4];
objects[0] = db_obj;
objects[1] = wildcard_obj;
objects[2] = db_wildcard;
objects[3] = NULL;
matched = check_array(objects, (char *) record_objs_array, MAX_OBJECT_CHAR_NUMBERS);
table = table->next_global;
}
if (!matched) {
return;
}
}
if (pThdPrintedList && pThdPrintedList->cur_index < MAX_NUM_QUEUE_ELEM)
{
if (pThdPrintedList->is_thd_printed_queue[pThdPrintedList->cur_index] == 0)
@@ -525,34 +644,27 @@ static void audit(ThdSesData *pThdData)
if (delay_ms_val > 0)
{
const char * cmd = pThdData->getCmdName();
for (int k=0; delay_cmds_array[k][0] !='\0';k++)
{
int j=0;
for (;delay_cmds_array[k][j] !='\0'
&& cmd[j] !='\0'
&& delay_cmds_array[k][j] == tolower (cmd[j]);j++)
{
}
if (delay_cmds_array[k][j] == '\0' && j !=0)
const char *cmds[2];
cmds[0] = cmd;
cmds[1] = NULL;
int delay = check_array(cmds, (char *) delay_cmds_array, MAX_COMMAND_CHAR_NUMBERS);
if (delay)
{
//Audit_file_handler::print_sleep(thd,delay_ms_val);
my_sleep (delay_ms_val *1000);
break;
}
}
}
}
static int trampoline_send_result_to_client(Query_cache *pthis, THD *thd, char *sql, uint query_length)
__attribute__ ((noinline)) static int trampoline_send_result_to_client(Query_cache *pthis, THD *thd, char *sql, uint query_length)
{
TRAMPOLINE_NOP_DEF;
return 0 ; //dummy return as this does a jump.
}
#if MYSQL_VERSION_ID > 50505
bool trampoline_open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
__attribute__ ((noinline)) static bool trampoline_open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
Prelocking_strategy *prelocking_strategy)
{
TRAMPOLINE_NOP_DEF;
@@ -560,7 +672,7 @@ bool trampoline_open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint fl
return true ; //dummy return as this does a jump.
}
#else
static int trampoline_open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
__attribute__ ((noinline)) static int trampoline_open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
{
TRAMPOLINE_NOP_DEF;
TRAMPOLINE_NOP_DEF;
@@ -586,7 +698,7 @@ NULL, NULL,0,0,
return (QueryTableInf*) THDVAR(thd, query_cache_table_list);
}
static bool trampoline_check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, uint number, bool no_errors)
__attribute__ ((noinline)) static bool trampoline_check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, uint number, bool no_errors)
{
TRAMPOLINE_NOP_DEF
return true;
@@ -927,6 +1039,31 @@ static bool parse_thd_offsets_string (char *poffsets_string)
return true;
}
static bool validate_offsets(const ThdOffsets * offset)
{
//check that offsets are actually correct. We use a buff of memory as a dummy THD (32K is high enough)
char buf[32*1024] = {0};
THD * thd = (THD *)buf;
//sanity check that offsets match
//we can also consider using secutiry context function to do some sanity checks
// char buffer[2048];
// thd_security_context(thd, buffer, 2048, 2000);
// fprintf(log_file, "info from security context: %s\n", buffer);
//we set the thread id to a value using the offset and then check that the value matches what thd_get_thread_id returns
const my_thread_id test_val = 123456;
(*(my_thread_id *) (((char *) thd)+ offset->thread_id)) = test_val;
my_thread_id res= thd_get_thread_id(thd);
bool retval = res == test_val;
if (!retval)
{
sql_print_error(
"%s Offsets version: %s match thread validation check fails with value: %lu. Skipping offest.",
log_prefix, offset->version, res);
}
return retval;
}
/**
* Setup the offsets needs to extract data from THD.
*
@@ -935,22 +1072,73 @@ static bool parse_thd_offsets_string (char *poffsets_string)
static int setup_offsets()
{
DBUG_ENTER("setup_offsets");
sql_print_information ("%s setup_offsets offsets_string %s",log_prefix, offsets_string);
sql_print_information ("%s setup_offsets audit_offsets: %s",log_prefix, offsets_string);
unsigned char digest[16] = {0};
char digest_str [128] = {0};
const ThdOffsets * offset;
//if present in my.cnf
//[mysqld]
//audit_validate_checksum=1
// or if
//audit_checksum=0f4d7e3b17eb36f17aafe4360993a769
//need to calculate digest
if (validate_checksum_enable || (checksum_string != NULL && strlen(checksum_string) > 0))
{
//setup digest_str to contain the md5sum in hex
sql_print_information(
"%s Validate checksum enabled. Mysqld %s ",
log_prefix, my_progname);
my_MD5Context context;
my_MD5Init(&context);
unsigned char * file_buff;
MY_STAT stat_arg;
File fd;
if (my_stat(my_progname, &stat_arg, MYF(MY_WME)))
{
if ((fd = my_open(my_progname, O_RDONLY,
MYF(MY_WME))) > 0)
{
file_buff = (unsigned char*) my_malloc(
(uint) stat_arg.st_size, MYF (MY_WME));
if (read(fd, (char*) file_buff,
(uint) stat_arg.st_size) >= 0L)
{
my_MD5Update(&context, file_buff,
stat_arg.st_size);
my_MD5Final(digest, &context);
}
(void) my_close(fd, MYF(0));
#if MYSQL_VERSION_ID > 50505
my_free(file_buff);
#else
my_free(file_buff, MYF(0));
#endif
}
}
for (int j = 0; j < 16; j++)
{
sprintf(&(digest_str[j * 2]), "%02x", digest[j]);
}
}
//if present the offset_string specified in my.cnf
//[mysqld]
//audit_offsets=6200, 6264, 3672, 3944, 88, 2048
if (offsets_string !=NULL)
{
char buf[32*1024] = {0};
THD * thd = (THD *)buf;
const my_thread_id test_val = 123456;
if (offsets_string != NULL)
{
if (checksum_string != NULL && strlen(checksum_string) > 0)
{
if (strncasecmp(checksum_string, digest_str, 32))
{
sql_print_information(
"%s checksum check failed for %s, but found %s",
log_prefix, checksum_string, digest_str);
DBUG_RETURN(1);
}
}
if (parse_thd_offsets_string (offsets_string))
{
sql_print_information ("%s setup_offsets Audit_formatter::thd_offsets values: %d %d %d %d %d %d ", log_prefix,
@@ -961,60 +1149,26 @@ static int setup_offsets()
Audit_formatter::thd_offsets.lex,
Audit_formatter::thd_offsets.lex_comment);
(*(my_thread_id *) (((char *) thd)+ Audit_formatter::thd_offsets.thread_id)) = test_val;
my_thread_id res= thd_get_thread_id(thd);
if (res != test_val)
{
sql_print_error("%s thread id check fails with value: %lu. Skipping offest.", log_prefix, res);
DBUG_RETURN(1);
}
if (!validate_offsets(&Audit_formatter::thd_offsets))
{
sql_print_error("%s Offsets set didn't pass validation. audit_offsets: %s .", log_prefix, offsets_string);
DBUG_RETURN(1);
}
}
else
{
sql_print_error("%s Audit offsets parser error. Skipping offest.", log_prefix);
sql_print_error("%s Failed parsing audit_offsets: %s", log_prefix, offsets_string);
DBUG_RETURN(1);
}
sql_print_information ("%s Validation passed. Using offsets from audit_offsets: %s",log_prefix, offsets_string);
DBUG_RETURN(0);
//exit from function
}
size_t arr_size = (sizeof(thd_offsets_arr) / sizeof(thd_offsets_arr[0]));
//iterate and search for the first offset which matches the version
//if present in my.cnf
//[mysqld]
//audit_validate_checksum=1
//plugin-load=AUDIT=libaudit_plugin.so
if (validate_checksum_enable)
{
sql_print_information ("%s Audit validate checksum enabled. Mysqld %s ",log_prefix, my_progname);
my_MD5Context context;
my_MD5Init (&context);
unsigned char * file_buff;
MY_STAT stat_arg;
File fd;
if (my_stat(my_progname,&stat_arg,MYF(MY_WME)))
{
if ((fd = my_open(my_progname,O_RDONLY, MYF(MY_WME))) > 0)
{
file_buff = (unsigned char*) my_malloc ((uint) stat_arg.st_size, MYF (MY_WME));
if (read(fd,(char*) file_buff,(uint) stat_arg.st_size) >= 0L)
{
my_MD5Update (&context, file_buff, stat_arg.st_size);
my_MD5Final (digest, &context);
}
(void) my_close(fd,MYF(0));
free (file_buff);
}
}
}
bool bCheckSumValidation = false;
for(int i=0; i < arr_size; i++)
{
offset = thd_offsets_arr + i;
//if present in my.cnf
//[mysqld]
@@ -1022,23 +1176,8 @@ static int setup_offsets()
//plugin-load=AUDIT=libaudit_plugin.so
if (validate_checksum_enable && strlen (offset->md5digest) >0)
{
memset (digest_str,0,sizeof (digest_str));
bCheckSumValidation = true;
int kd=0;
for (int j=0;j<16;j++)
{
unsigned char Dig=0;
char DigStr[3]={0};
DigStr[0]= offset->md5digest[kd++];
DigStr[1]= offset->md5digest[kd++];
sscanf (DigStr,"%x",&Dig);
sprintf (digest_str,"%s %2x",digest_str,digest[j]);
if (Dig != digest[j])
{
bCheckSumValidation = false;
}
}
if (bCheckSumValidation)
if (!strncasecmp(digest_str, offset->md5digest, 32))
{
sql_print_information ("%s Checksum is %s verified", log_prefix, digest_str);
sql_print_information("%s Using offsets from offset version: %s", log_prefix, offset->version);
@@ -1046,7 +1185,6 @@ static int setup_offsets()
DBUG_RETURN(0);
//return
}
}
//if present in my.cnf
@@ -1054,35 +1192,36 @@ static int setup_offsets()
//audit_validate_checksum=0
//plugin-load=AUDIT=libaudit_plugin.so
if(!validate_checksum_enable && (strstr(server_version, offset->version)))
{
//check that offsets are actually correct. We use a buff of memory as a dummy THD (32K is high enough)
char buf[32*1024] = {0};
THD * thd = (THD *)buf;
//sanity check that offsets match
//we can also consider using secutiry context function to do some sanity checks
// char buffer[2048];
// thd_security_context(thd, buffer, 2048, 2000);
// fprintf(log_file, "info from security context: %s\n", buffer);
//we set the thread id to a value using the offset and then check that the value matches what thd_get_thread_id returns
unsigned long inst_thread_id = Audit_formatter::thd_inst_thread_id(thd);
const my_thread_id test_val = 123456;
(*(my_thread_id *) (((char *) thd)+ offset->thread_id)) = test_val;
my_thread_id res= thd_get_thread_id(thd);
if (res != test_val)
{
if (validate_offsets(offset))
{
sql_print_error(
"%s Offsets version: %s match server version: %s but thread id check fails with value: %lu. Skipping offest.",
log_prefix, offset->version, server_version, res);
}
sql_print_information("%s Using offsets from offset version: %s, digest: %s", log_prefix, offset->version, offset->md5digest);
Audit_formatter::thd_offsets = *offset;
DBUG_RETURN(0);
}
else
{
sql_print_information("%s Using offsets from offset version: %s", log_prefix, offset->version);
Audit_formatter::thd_offsets = *offset;
DBUG_RETURN(0);
}
//try doing 24 byte decrement on THD offsets. Seen that on Ubuntu/Debian this is valid.
OFFSET dec = 24;
ThdOffsets decoffsets = *offset;
decoffsets.query_id -= dec;
decoffsets.thread_id -= dec;
decoffsets.main_security_ctx -= dec;
decoffsets.command -= dec;
if (validate_offsets(&decoffsets))
{
Audit_formatter::thd_offsets = decoffsets;
sql_print_information("%s Using decrement (%d) offsets from offset version: %s, digest: %s values: %d %d %d %d %d %d", log_prefix, dec, offset->version, offset->md5digest,
Audit_formatter::thd_offsets.query_id,
Audit_formatter::thd_offsets.thread_id,
Audit_formatter::thd_offsets.main_security_ctx,
Audit_formatter::thd_offsets.command,
Audit_formatter::thd_offsets.lex,
Audit_formatter::thd_offsets.lex_comment);
DBUG_RETURN(0);
}
}
}
}
@@ -1090,6 +1229,116 @@ static int setup_offsets()
DBUG_RETURN(1);
}
const char * retrieve_command (THD * thd)
{
const char *cmd = NULL;
int command = Audit_formatter::thd_inst_command(thd);
if (command < 0 || command > COM_END)
{
command = COM_END;
}
const int sql_command = thd_sql_command(thd);
if (sql_command >=0 && sql_command <= (MAX_COM_STATUS_VARS_RECORDS -1) )
{
cmd = com_status_vars_array[sql_command + 1].name;
}
if(!cmd)
{
cmd = command_name[command].str;
}
Security_context * sctx = Audit_formatter::thd_inst_main_security_ctx(thd);
if (strcmp (cmd, "Connect") ==0 && (sctx->priv_user == NULL || *sctx->priv_user == 0x0))
{
cmd = "Failed Login";
}
return cmd;
}
static int set_com_status_vars_array ()
{
DBUG_ENTER("set_com_status_vars_array");
SHOW_VAR *com_status_vars;
int sv_idx =0;
while (strcmp (status_vars[sv_idx].name,"Com") !=0 && status_vars[sv_idx].name != NullS)
{
sv_idx ++;
}
if (strcmp (status_vars[sv_idx].name,"Com")==0)
{
int status_vars_index =0;
com_status_vars = (SHOW_VAR*)status_vars[sv_idx].value;
size_t initial_offset = (size_t) com_status_vars[0].value;
while (com_status_vars[status_vars_index].name != NullS)
{
int sql_command_idx = (com_status_vars[status_vars_index].value - (char*) (initial_offset)) / sizeof (ulong);
if (sql_command_idx >=0 && sql_command_idx < MAX_COM_STATUS_VARS_RECORDS)
{
com_status_vars_array [sql_command_idx].name = com_status_vars[status_vars_index].name;
com_status_vars_array [sql_command_idx].type = com_status_vars[status_vars_index].type;
com_status_vars_array [sql_command_idx].value = com_status_vars[status_vars_index].value;
}
else
{
sql_print_error("%s Failed sql_command_idx [%d] is out of bounds. Plugin Init failed.",
log_prefix, sql_command_idx);
DBUG_RETURN (1);
}
status_vars_index ++;
}
}
else
{
sql_print_error("%s Failed looking up 'Com' entry in status_vars. Plugin Init failed.",
log_prefix);
DBUG_RETURN (1);
}
DBUG_RETURN (0);
}
static int string_to_array(const void *save, void *array,
int rows, int length)
{
const char* save_string;
save_string = *static_cast<const char* const *> (save);
char* string_array;
string_array = (char *) array;
int r = 0;
if (save_string != NULL)
{
int p = 0;
for (int i = 0; save_string[i] != '\0'; i++)
{
if (save_string[i] == ' ' || save_string[i] == '\t'
|| save_string[i] == ',')
{
if (p > 0)
{
string_array[r * length + p] = '\0';
p = 0;
r++;
if (r == (rows - 1))
{
break;
}
}
}
else
{
string_array[r * length + p] = tolower(save_string[i]);
p++;
}
}
if (p > 0)
{
string_array[r * length + p] = '\0';
r++;
}
string_array[r * length + 0] = '\0';
}
return r;
}
/*
Initialize the daemon plugin installation.
@@ -1105,17 +1354,36 @@ static int audit_plugin_init(void *p)
{
DBUG_ENTER("audit_plugin_init");
#ifdef __x86_64__
const char * arch = "64bit";
#else
const char * arch = "32bit";
#endif
sql_print_information(
"%s starting up. Version: %s, Revision: %s. AUDIT plugin interface version: %d. MySQL Server version: %s.",
"%s starting up. Version: %s , Revision: %s (%s). AUDIT plugin interface version: %d. MySQL Server version: %s.",
log_prefix, MYSQL_AUDIT_PLUGIN_VERSION,
MYSQL_AUDIT_PLUGIN_REVISION, audit_plugin.interface_version >> 8,
MYSQL_AUDIT_PLUGIN_REVISION, arch, audit_plugin.interface_version >> 8,
server_version);
//setup our offsets.
if(setup_offsets() != 0)
{
DBUG_RETURN(1);
}
if (delay_cmds_string != NULL) {
num_delay_cmds = string_to_array(&delay_cmds_string, delay_cmds_array, SQLCOM_END + 2, MAX_COMMAND_CHAR_NUMBERS);
sql_print_information("%s Set num_delay_cmds: %d", log_prefix, num_delay_cmds);
}
if (record_cmds_string != NULL) {
num_record_cmds = string_to_array(&record_cmds_string, record_cmds_array, SQLCOM_END + 2, MAX_COMMAND_CHAR_NUMBERS);
sql_print_information("%s Set num_record_cmds: %d", log_prefix, num_record_cmds);
}
if (record_objs_string != NULL) {
num_record_objs = string_to_array(&record_objs_string, record_objs_array, MAX_NUM_OBJECT_ELEM + 2, MAX_OBJECT_CHAR_NUMBERS);
sql_print_information("%s Set num_record_objs: %d", log_prefix, num_record_objs);
}
//setup audit handlers (initially disabled)
int res = json_file_handler.init(&json_formatter);
if (res != 0)
@@ -1136,9 +1404,9 @@ static int audit_plugin_init(void *p)
//enable according to what we have in *file_handler_enable (this is set accordingly by sysvar functionality)
json_file_handler.set_enable(json_file_handler_enable);
json_socket_handler.set_enable(json_socket_handler_enable);
Audit_handler::m_audit_handler_list[Audit_handler::BSON_FILE_HANDLER]
Audit_handler::m_audit_handler_list[Audit_handler::JSON_FILE_HANDLER]
= &json_file_handler;
Audit_handler::m_audit_handler_list[Audit_handler::BSON_SOCKET_HANDLER]
Audit_handler::m_audit_handler_list[Audit_handler::JSON_SOCKET_HANDLER]
= &json_socket_handler;
//hot patch functions
@@ -1254,7 +1522,7 @@ static int audit_plugin_init(void *p)
DBUG_RETURN(1);
}
sql_print_information(
"%s hot patch open_tables address %p. Trampoline size: %ud.",
"%s hot patch open_tables address %p. Trampoline size: %u.",
log_prefix, *(bool (*)(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
Prelocking_strategy *prelocking_strategy)) &open_tables,
trampoline_open_tables_size);
@@ -1276,7 +1544,11 @@ static int audit_plugin_init(void *p)
log_prefix, *(bool (*)(THD *thd, TABLE_LIST **start, uint *counter, uint flags)) &open_tables,
trampoline_open_tables_size);
#endif
if (set_com_status_vars_array () !=0)
{
DBUG_RETURN(1);
}
sql_print_information("%s Init completed successfully.", log_prefix);
DBUG_RETURN(0);
}
@@ -1294,8 +1566,9 @@ static int audit_plugin_init(void *p)
*/
static int audit_plugin_deinit(void *p)
{
{
DBUG_ENTER("audit_plugin_deinit");
sql_print_information("%s deinit", log_prefix);
remove_hot_functions();
//disable handlers
DBUG_RETURN(0);
@@ -1328,6 +1601,20 @@ static void json_log_file_enable(THD *thd, struct st_mysql_sys_var *var,
}
}
static void json_log_file_flush(THD *thd, struct st_mysql_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;
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,
void *tgt, const void *save)
@@ -1339,56 +1626,28 @@ static void json_log_socket_enable(THD *thd, struct st_mysql_sys_var *var,
}
}
static void delay_cmds_string_handler (THD *thd, struct st_mysql_sys_var *var,
void *tgt, const void *save)
static void delay_cmds_string_update(THD *thd,
struct st_mysql_sys_var *var, void *tgt,
const void *save)
{
num_delay_cmds = string_to_array(save, delay_cmds_array, SQLCOM_END + 2, MAX_COMMAND_CHAR_NUMBERS);
sql_print_information("%s Set num_delay_cmds: %d", log_prefix, num_delay_cmds);
}
char *old= *(char **) tgt;
*(char **)tgt= my_strdup(*(char **) save, MYF(0));
#if MYSQL_VERSION_ID > 50505
my_free(old);
#else
my_free(old, MYF(0));
#endif
static void record_cmds_string_update(THD *thd,
struct st_mysql_sys_var *var, void *tgt,
const void *save)
{
num_record_cmds = string_to_array(save, record_cmds_array, SQLCOM_END + 2, MAX_COMMAND_CHAR_NUMBERS);
sql_print_information("%s Set num_record_cmds: %d", log_prefix, num_record_cmds);
}
const char* save_string;
save_string = *static_cast<const char*const*>(save);
int k =0;
if (save_string !=NULL)
{
int j =0;
for (int i=0; save_string[i] !='\0'; i++,j++)
{
while (save_string[i] ==' ' || save_string[i] == '\t' || save_string[i] == ',' )
{
if (save_string[i] == ',')
{
if (j+1 < MAX_COMMAND_CHAR_NUMBERS)
{
delay_cmds_array[k][j] = '\0';
}
k++;
j=0;
}
i++;
}
if (k < SQLCOM_END && j < MAX_COMMAND_CHAR_NUMBERS)
{
delay_cmds_array[k][j] = tolower (save_string[i]);
}
}
if (k < SQLCOM_END && j < MAX_COMMAND_CHAR_NUMBERS)
{
delay_cmds_array[k][j] = '\0';
}
}
if (k < SQLCOM_END)
{
delay_cmds_array[k+1][0]='\0';
}
static void record_objs_string_update(THD *thd,
struct st_mysql_sys_var *var, void *tgt,
const void *save)
{
num_record_objs = string_to_array(save, record_objs_array, MAX_NUM_OBJECT_ELEM + 2, MAX_OBJECT_CHAR_NUMBERS);
sql_print_information("%s Set num_record_objs: %d", log_prefix, num_record_objs);
}
//setup sysvars which update directly the relevant plugins
@@ -1405,8 +1664,12 @@ static MYSQL_SYSVAR_UINT(json_file_sync, json_file_handler.m_sync_period,
NULL, NULL, 0, 0, UINT_MAX32, 0);
static MYSQL_SYSVAR_BOOL(json_file, json_file_handler_enable,
PLUGIN_VAR_OPCMDARG,
PLUGIN_VAR_RQCMDARG,
"AUDIT plugin json log file Enable|Disable", NULL, json_log_file_enable, 0);
static MYSQL_SYSVAR_BOOL(json_file_flush, json_file_handler_flush,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOCMDOPT,
"AUDIT plugin json log file flush. Set to ON to perform a flush of the log.", NULL, json_log_file_flush, 0);
static MYSQL_SYSVAR_STR(json_socket_name, json_socket_handler.m_sockname,
@@ -1419,6 +1682,10 @@ static MYSQL_SYSVAR_STR(offsets, offsets_string,
"AUDIT plugin offsets. Comma separated list of offsets to use for extracting data",
NULL, NULL, NULL);
static MYSQL_SYSVAR_STR(checksum, checksum_string,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
"AUDIT plugin checksum. Checksum for mysqld corresponding to offsets",
NULL, NULL, "");
static MYSQL_SYSVAR_BOOL(uninstall_plugin, uninstall_plugin_enable,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY ,
"AUDIT uninstall plugin Enable|Disable. Default disabled. If disabled attempts to uninstall the AUDIT plugin via the sql UNINSTALL command will fail.", NULL, NULL, 0);
@@ -1429,7 +1696,7 @@ static MYSQL_SYSVAR_BOOL(validate_checksum, validate_checksum_enable,
"AUDIT plugin binary checksum validation Enable|Disable", NULL, NULL, 1);
static MYSQL_SYSVAR_BOOL(json_socket, json_socket_handler_enable,
PLUGIN_VAR_OPCMDARG,
PLUGIN_VAR_RQCMDARG,
"AUDIT plugin json log unix socket Enable|Disable", NULL, json_log_socket_enable, 0);
static MYSQL_SYSVAR_INT(delay_ms, delay_ms_val,
@@ -1438,9 +1705,17 @@ static MYSQL_SYSVAR_INT(delay_ms, delay_ms_val,
NULL, NULL, 0, 0, INT_MAX32, 0);
static MYSQL_SYSVAR_STR(delay_cmds, delay_cmds_string,
PLUGIN_VAR_RQCMDARG,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
"AUDIT plugin delay commands to match against comma separated. If empty then delay is disabled.",
NULL, delay_cmds_string_handler, NULL);
NULL, delay_cmds_string_update, NULL);
static MYSQL_SYSVAR_STR(record_cmds, record_cmds_string,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
"AUDIT plugin commands to record, comma separated",
NULL, record_cmds_string_update, NULL);
static MYSQL_SYSVAR_STR(record_objs, record_objs_string,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
"AUDIT plugin objects to record, comma separated",
NULL, record_objs_string_update, NULL);
/*
* Plugin system vars
@@ -1450,6 +1725,7 @@ static struct st_mysql_sys_var* audit_system_variables[] =
MYSQL_SYSVAR(json_log_file),
MYSQL_SYSVAR(json_file_sync),
MYSQL_SYSVAR(json_file),
MYSQL_SYSVAR(json_file_flush),
MYSQL_SYSVAR(uninstall_plugin),
MYSQL_SYSVAR(validate_checksum),
MYSQL_SYSVAR(json_socket_name),
@@ -1459,6 +1735,9 @@ static struct st_mysql_sys_var* audit_system_variables[] =
MYSQL_SYSVAR(is_thd_printed_list),
MYSQL_SYSVAR(delay_ms),
MYSQL_SYSVAR(delay_cmds),
MYSQL_SYSVAR(record_cmds),
MYSQL_SYSVAR(record_objs),
MYSQL_SYSVAR(checksum),
NULL };
//declare our plugin
@@ -1485,7 +1764,7 @@ mysql_declare_plugin_end;
* 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)
*/
void __attribute__ ((constructor)) audit_plugin_so_init(void)
extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
{
if (mysqld_builtins && mysqld_builtins[0])
{
@@ -1503,7 +1782,7 @@ void __attribute__ ((constructor)) audit_plugin_so_init(void)
}
#else
extern struct st_mysql_plugin *mysql_mandatory_plugins[];
void __attribute__ ((constructor)) audit_plugin_so_init(void)
extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
{

View File

@@ -12,11 +12,6 @@
#define unprotect(addr,len) (mprotect(addr,len,PROT_READ|PROT_WRITE|PROT_EXEC))
#define protect(addr,len) (mprotect(addr,len,PROT_READ|PROT_EXEC))
#define GETPAGESIZE() sysconf (_SC_PAGE_SIZE)
#define unprotect(addr,len) (mprotect(addr,len,PROT_READ|PROT_WRITE|PROT_EXEC))
#define protect(addr,len) (mprotect(addr,len,PROT_READ|PROT_EXEC))
#define GETPAGESIZE() sysconf (_SC_PAGE_SIZE)
@@ -68,15 +63,6 @@ static void WriteJump(void *pAddress, ULONG_PTR JumpTo)
*pCur++ = 0xE9; // jmp +imm32
*((ULONG_PTR *)pCur) = JumpTo - (ULONG_PTR)pbJmpSrc;
/* old jump indirect requires 10 bytes (TOO big)
*pCur = 0xff; // jmp [addr]
*(++pCur) = 0x25;
pCur++;
*((DWORD *) pCur) = (DWORD)(((ULONG_PTR) pCur) + sizeof (DWORD));
pCur += sizeof (DWORD);
*((ULONG_PTR *)pCur) = JumpTo;
*/
#else
*pCur = 0xff; // jmp [rip+addr]
@@ -182,54 +168,7 @@ int hot_patch_function (void* targetFunction, void* newFunction, void * trampoli
else
{
return -1;
}
/* OLD unused code
int res = unprotect((void *)trampolinePage,PAGE_SIZE);
if(res != 0)
{
sql_print_error("%s error un protecting trampoline page: 0x%x errno: %s. Aborting.",log_prefix, trampolinePage, strerror(errno));
return -1;
}
//copy original code we are going to write over
memcpy( trampolineFunction, targetFunction, TRAMPOLINE_COPY_LENGTH) ;
//copy the jmp back to original code
memset( (void *)((DATATYPE_ADDRESS)trampolineFunction + TRAMPOLINE_COPY_LENGTH), JMP_OPCODE, OPCODE_LENGTH ) ;
//calculate where we want to jump back. The jump is relative.
//We are jumping from: trampolineFunction + TRAMPOLINE_COPY_LENGTH + MIN_REQUIRED_FOR_DETOUR
//to: targetFunction + TRAMPOLINE_COPY_LENGTH
//the diff is: targetFunction + TRAMPOLINE_COPY_LENGTH - (trampolineFunction + TRAMPOLINE_COPY_LENGTH + MIN_REQUIRED_FOR_DETOUR)
//TRAMPOLINE_COPY_LENGTH can be removed from both sides to get:
DATATYPE_ADDRESS jumpBackAddress = (DATATYPE_ADDRESS)targetFunction - ((DATATYPE_ADDRESS)trampolineFunction + MIN_REQUIRED_FOR_DETOUR);
//copy the location to the trampolineFunction
memcpy( (void *)((DATATYPE_ADDRESS) trampolineFunction + TRAMPOLINE_COPY_LENGTH + OPCODE_LENGTH), &jumpBackAddress, ADDRESS_LENGTH) ;
//protect the page
protect((void *)trampolinePage,PAGE_SIZE);
//now modify the code of the target function
DATATYPE_ADDRESS targetPage = get_page_address(targetFunction);
cond_info_print(info_print, "%s targetPage: 0x%x targetFunction: 0x%x",log_prefix, targetPage, targetFunction);
res = unprotect((void *)targetPage,PAGE_SIZE);
if(res == 0)
{
cond_info_print(info_print, "%s unprotect res: %d",log_prefix, res);
cond_info_print(info_print, "%s setting jump code: 0x%x length: %d at: 0x%x", log_prefix, JMP_OPCODE, OPCODE_LENGTH, targetFunction);
memset(targetFunction, JMP_OPCODE, OPCODE_LENGTH) ;
//calculate where we want to jump to. Jump is relative (see above jump calcluation)
DATATYPE_ADDRESS jumpAddress = (DATATYPE_ADDRESS)newFunction - ((DATATYPE_ADDRESS)targetFunction + MIN_REQUIRED_FOR_DETOUR);
DATATYPE_ADDRESS targetFuncJumpAddress = (DATATYPE_ADDRESS)targetFunction + OPCODE_LENGTH;
cond_info_print(info_print, "%s setting jump address: 0x%x length: %d at: 0x%x", log_prefix, jumpAddress, ADDRESS_LENGTH, targetFuncJumpAddress);
memcpy((void *)targetFuncJumpAddress, &jumpAddress, ADDRESS_LENGTH) ;
res = protect((void *)targetPage,PAGE_SIZE);
cond_info_print(info_print, "%s protect res: %d",log_prefix, res);
}
else
{
sql_print_error("%s error un protecting target function page: 0x%x errno: %s. Aborted.", log_prefix, targetPage, strerror(errno));
return -2;
}
return 0;
*/
}
}
@@ -243,26 +182,15 @@ int hot_patch_function (void* targetFunction, void* newFunction, void * trampoli
*/
void remove_hot_patch_function (void* targetFunction, void * trampolineFunction, unsigned int trampolinesize, bool info_print, const char * log_prefix)
{
if(trampolinesize == 0)
{
//nothing todo. As hot patch was not set.
return;
}
cond_info_print(info_print, "%s removing hot patching function: 0x%x",log_prefix, targetFunction);
DATATYPE_ADDRESS targetPage = get_page_address(targetFunction);
cond_info_print(info_print, "%s targetPage: 0x%x targetFunction: 0x%x",log_prefix, targetPage, targetFunction);
UnhookFunction ((ULONG_PTR) targetFunction, (ULONG_PTR)trampolineFunction,trampolinesize);
return;
/** OLD unused code
int res = unprotect((void *)targetPage,PAGE_SIZE);
if(res == 0)
{
cond_info_print(info_print, "%s unprotect res: %d", log_prefix, res);
cond_info_print(info_print, "%s copying org code from trampoline function: 0x%x length: %d to: 0x%x", log_prefix, trampolineFunction, TRAMPOLINE_COPY_LENGTH, targetFunction);
memcpy(targetFunction, trampolineFunction, TRAMPOLINE_COPY_LENGTH) ;
res = protect((void *)targetPage,PAGE_SIZE);
cond_info_print(info_print, "%s protect res: %d",log_prefix, res);
}
else
{
cond_info_print(info_print, "%s ERROR un protecting page: 0x%x errno: %d", log_prefix, targetPage, errno);
}
*/
return;
}