Fix for bug found with vio. Where mysql 5.1 ndb cluster uses a different struct from mysql 5.1.
parent
e38bc05f0f
commit
dac2dfc2a3
|
@ -432,13 +432,14 @@ protected:
|
||||||
*/
|
*/
|
||||||
virtual void handler_log_audit(ThdSesData *pThdData);
|
virtual void handler_log_audit(ThdSesData *pThdData);
|
||||||
//Vio we write to
|
//Vio we write to
|
||||||
Vio * m_vio;
|
//define as void* so we don't access members directly
|
||||||
|
void * m_vio;
|
||||||
void close_vio()
|
void close_vio()
|
||||||
{
|
{
|
||||||
if (m_vio)
|
if (m_vio)
|
||||||
{
|
{
|
||||||
vio_close(m_vio);
|
vio_close((Vio*)m_vio);
|
||||||
vio_delete(m_vio);
|
vio_delete((Vio*)m_vio);
|
||||||
}
|
}
|
||||||
m_vio = NULL;
|
m_vio = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
#define MYSQL_DYNAMIC_PLUGIN
|
#define MYSQL_DYNAMIC_PLUGIN
|
||||||
#define MYSQL_SERVER 1
|
#define MYSQL_SERVER 1
|
||||||
|
|
||||||
|
//Fix for VIO. We don't want to using method mapping as then a change in the struct will cause the offsets compiled with to
|
||||||
|
//be wrong. As is the case with ndb which uses a version of Vio with support for ipv6 similar to 5.5 but different from 5.1
|
||||||
|
#define DONT_MAP_VIO
|
||||||
|
|
||||||
#include <my_config.h>
|
#include <my_config.h>
|
||||||
#include <mysql_version.h>
|
#include <mysql_version.h>
|
||||||
//version 5.5.x doesn't contain mysql_priv.h . We need to add the includes provided by it.
|
//version 5.5.x doesn't contain mysql_priv.h . We need to add the includes provided by it.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
392
src/hot_patch.cc
392
src/hot_patch.cc
|
@ -1,196 +1,196 @@
|
||||||
#include "hot_patch.h"
|
#include "hot_patch.h"
|
||||||
#include "udis86.h"
|
#include "udis86.h"
|
||||||
|
|
||||||
#define UINT unsigned int
|
#define UINT unsigned int
|
||||||
#define DWORD uint32_t
|
#define DWORD uint32_t
|
||||||
#define BYTE unsigned char
|
#define BYTE unsigned char
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
#define ULONG_PTR uint64_t
|
#define ULONG_PTR uint64_t
|
||||||
#else
|
#else
|
||||||
#define ULONG_PTR uint32_t
|
#define ULONG_PTR uint32_t
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define unprotect(addr,len) (mprotect(addr,len,PROT_READ|PROT_WRITE|PROT_EXEC))
|
#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 protect(addr,len) (mprotect(addr,len,PROT_READ|PROT_EXEC))
|
||||||
#define GETPAGESIZE() sysconf (_SC_PAGE_SIZE)
|
#define GETPAGESIZE() sysconf (_SC_PAGE_SIZE)
|
||||||
|
|
||||||
static const unsigned long PAGE_SIZE = GETPAGESIZE() ;
|
static const unsigned long PAGE_SIZE = GETPAGESIZE() ;
|
||||||
|
|
||||||
//macro to log via sql_print_information only if cond test is enabled
|
//macro to log via sql_print_information only if cond test is enabled
|
||||||
#define cond_info_print(cond_test, ...) do{if(cond_test) sql_print_information(__VA_ARGS__);}while(0)
|
#define cond_info_print(cond_test, ...) do{if(cond_test) sql_print_information(__VA_ARGS__);}while(0)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the page address of a given pointer
|
* Get the page address of a given pointer
|
||||||
*/
|
*/
|
||||||
static DATATYPE_ADDRESS get_page_address(void * pointer)
|
static DATATYPE_ADDRESS get_page_address(void * pointer)
|
||||||
{
|
{
|
||||||
DATATYPE_ADDRESS pageMask = ( ~(PAGE_SIZE - 1) ) ;
|
DATATYPE_ADDRESS pageMask = ( ~(PAGE_SIZE - 1) ) ;
|
||||||
DATATYPE_ADDRESS longp = (unsigned long) pointer;
|
DATATYPE_ADDRESS longp = (unsigned long) pointer;
|
||||||
return (longp & pageMask);
|
return (longp & pageMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// This function retrieves the necessary size for the jump
|
// This function retrieves the necessary size for the jump
|
||||||
//
|
//
|
||||||
|
|
||||||
static UINT GetJumpSize(ULONG_PTR PosA, ULONG_PTR PosB)
|
static UINT GetJumpSize(ULONG_PTR PosA, ULONG_PTR PosB)
|
||||||
{
|
{
|
||||||
#ifndef __x86_64__
|
#ifndef __x86_64__
|
||||||
return 5;
|
return 5;
|
||||||
#else
|
#else
|
||||||
return 14;
|
return 14;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// This function writes unconditional jumps
|
// This function writes unconditional jumps
|
||||||
// both for x86 and x64
|
// both for x86 and x64
|
||||||
//
|
//
|
||||||
|
|
||||||
static void WriteJump(void *pAddress, ULONG_PTR JumpTo)
|
static void WriteJump(void *pAddress, ULONG_PTR JumpTo)
|
||||||
{
|
{
|
||||||
DWORD dwOldProtect = 0;
|
DWORD dwOldProtect = 0;
|
||||||
DATATYPE_ADDRESS AddressPage = get_page_address(pAddress);
|
DATATYPE_ADDRESS AddressPage = get_page_address(pAddress);
|
||||||
unprotect((void*)AddressPage, PAGE_SIZE);
|
unprotect((void*)AddressPage, PAGE_SIZE);
|
||||||
|
|
||||||
BYTE *pCur = (BYTE *) pAddress;
|
BYTE *pCur = (BYTE *) pAddress;
|
||||||
#ifndef __x86_64__
|
#ifndef __x86_64__
|
||||||
|
|
||||||
BYTE * pbJmpSrc = pCur + 5;
|
BYTE * pbJmpSrc = pCur + 5;
|
||||||
*pCur++ = 0xE9; // jmp +imm32
|
*pCur++ = 0xE9; // jmp +imm32
|
||||||
*((ULONG_PTR *)pCur) = JumpTo - (ULONG_PTR)pbJmpSrc;
|
*((ULONG_PTR *)pCur) = JumpTo - (ULONG_PTR)pbJmpSrc;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
*pCur = 0xff; // jmp [rip+addr]
|
*pCur = 0xff; // jmp [rip+addr]
|
||||||
*(++pCur) = 0x25;
|
*(++pCur) = 0x25;
|
||||||
*((DWORD *) ++pCur) = 0; // addr = 0
|
*((DWORD *) ++pCur) = 0; // addr = 0
|
||||||
pCur += sizeof (DWORD);
|
pCur += sizeof (DWORD);
|
||||||
*((ULONG_PTR *)pCur) = JumpTo;
|
*((ULONG_PTR *)pCur) = JumpTo;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
//}
|
//}
|
||||||
|
|
||||||
DWORD dwBuf = 0; // nessary othewrise the function fails
|
DWORD dwBuf = 0; // nessary othewrise the function fails
|
||||||
|
|
||||||
protect((void*)AddressPage, PAGE_SIZE);
|
protect((void*)AddressPage, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Hooks a function
|
// Hooks a function
|
||||||
//
|
//
|
||||||
static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG_PTR trampolineFunction, unsigned int *trampolinesize)
|
static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG_PTR trampolineFunction, unsigned int *trampolinesize)
|
||||||
{
|
{
|
||||||
#define MAX_INSTRUCTIONS 100
|
#define MAX_INSTRUCTIONS 100
|
||||||
uint8_t raw[MAX_INSTRUCTIONS];
|
uint8_t raw[MAX_INSTRUCTIONS];
|
||||||
unsigned int uCurrentSize =0;
|
unsigned int uCurrentSize =0;
|
||||||
|
|
||||||
#ifndef __x86_64__
|
#ifndef __x86_64__
|
||||||
#define ASM_MODE 32
|
#define ASM_MODE 32
|
||||||
#else
|
#else
|
||||||
#define ASM_MODE 64
|
#define ASM_MODE 64
|
||||||
#endif
|
#endif
|
||||||
memcpy (raw,(void*)targetFunction,MAX_INSTRUCTIONS);
|
memcpy (raw,(void*)targetFunction,MAX_INSTRUCTIONS);
|
||||||
ud_t ud_obj;
|
ud_t ud_obj;
|
||||||
ud_init(&ud_obj);
|
ud_init(&ud_obj);
|
||||||
ud_set_input_buffer(&ud_obj, raw, MAX_INSTRUCTIONS);
|
ud_set_input_buffer(&ud_obj, raw, MAX_INSTRUCTIONS);
|
||||||
ud_set_mode(&ud_obj, ASM_MODE);
|
ud_set_mode(&ud_obj, ASM_MODE);
|
||||||
ud_set_syntax(&ud_obj, UD_SYN_INTEL);
|
ud_set_syntax(&ud_obj, UD_SYN_INTEL);
|
||||||
|
|
||||||
|
|
||||||
DWORD InstrSize = 0;
|
DWORD InstrSize = 0;
|
||||||
DATATYPE_ADDRESS trampolineFunctionPage = get_page_address((void*)trampolineFunction);
|
DATATYPE_ADDRESS trampolineFunctionPage = get_page_address((void*)trampolineFunction);
|
||||||
unprotect((void*)trampolineFunctionPage, PAGE_SIZE);
|
unprotect((void*)trampolineFunctionPage, PAGE_SIZE);
|
||||||
while (ud_disassemble(&ud_obj) && (strncmp (ud_insn_asm(&ud_obj),"invalid",7)!=0))
|
while (ud_disassemble(&ud_obj) && (strncmp (ud_insn_asm(&ud_obj),"invalid",7)!=0))
|
||||||
{
|
{
|
||||||
if (InstrSize >= GetJumpSize(targetFunction, newFunction))
|
if (InstrSize >= GetJumpSize(targetFunction, newFunction))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
BYTE *pCurInstr = (BYTE *) (InstrSize + (ULONG_PTR) targetFunction);
|
BYTE *pCurInstr = (BYTE *) (InstrSize + (ULONG_PTR) targetFunction);
|
||||||
memcpy((BYTE*)trampolineFunction + uCurrentSize,
|
memcpy((BYTE*)trampolineFunction + uCurrentSize,
|
||||||
(void *) pCurInstr, ud_insn_len (&ud_obj));
|
(void *) pCurInstr, ud_insn_len (&ud_obj));
|
||||||
|
|
||||||
uCurrentSize += ud_insn_len (&ud_obj);
|
uCurrentSize += ud_insn_len (&ud_obj);
|
||||||
|
|
||||||
|
|
||||||
InstrSize += ud_insn_len (&ud_obj);
|
InstrSize += ud_insn_len (&ud_obj);
|
||||||
}
|
}
|
||||||
protect((void*)trampolineFunctionPage, PAGE_SIZE);
|
protect((void*)trampolineFunctionPage, PAGE_SIZE);
|
||||||
WriteJump( (BYTE*)trampolineFunction + uCurrentSize, targetFunction + InstrSize);
|
WriteJump( (BYTE*)trampolineFunction + uCurrentSize, targetFunction + InstrSize);
|
||||||
WriteJump((void *) targetFunction, newFunction);
|
WriteJump((void *) targetFunction, newFunction);
|
||||||
*trampolinesize = uCurrentSize;
|
*trampolinesize = uCurrentSize;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Unhooks a function
|
// Unhooks a function
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
static void UnhookFunction(ULONG_PTR Function,ULONG_PTR trampolineFunction , unsigned int trampolinesize)
|
static void UnhookFunction(ULONG_PTR Function,ULONG_PTR trampolineFunction , unsigned int trampolinesize)
|
||||||
{
|
{
|
||||||
DATATYPE_ADDRESS FunctionPage = get_page_address((void*)Function);
|
DATATYPE_ADDRESS FunctionPage = get_page_address((void*)Function);
|
||||||
unprotect((void*)FunctionPage, PAGE_SIZE);
|
unprotect((void*)FunctionPage, PAGE_SIZE);
|
||||||
memcpy((void *) Function, (void*)trampolineFunction,trampolinesize);
|
memcpy((void *) Function, (void*)trampolineFunction,trampolinesize);
|
||||||
protect((void*)FunctionPage, PAGE_SIZE);
|
protect((void*)FunctionPage, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hot patch a function.
|
* Hot patch a function.
|
||||||
*
|
*
|
||||||
* We are basically taking the code of the target function and putting at the start a jump to our new function.
|
* We are basically taking the code of the target function and putting at the start a jump to our new function.
|
||||||
* Additionally we generate a trampoline function which the target function can call inorder to call the original function.
|
* Additionally we generate a trampoline function which the target function can call inorder to call the original function.
|
||||||
*
|
*
|
||||||
* trampolineFunction will be modified to contain the original code + jump code
|
* trampolineFunction will be modified to contain the original code + jump code
|
||||||
*
|
*
|
||||||
* @param targetFunction the function to hot patch
|
* @param targetFunction the function to hot patch
|
||||||
* @param newFunction the new function to be called instead of the targetFunction
|
* @param newFunction the new function to be called instead of the targetFunction
|
||||||
* @param trampolineFunction a function which will contain a jump back to the targetFunction. Function need to have
|
* @param trampolineFunction a function which will contain a jump back to the targetFunction. Function need to have
|
||||||
* enough space of TRAMPOLINE_COPY_LENGTH + MIN_REQUIRED_FOR_DETOUR. Recommended to use a static function
|
* enough space of TRAMPOLINE_COPY_LENGTH + MIN_REQUIRED_FOR_DETOUR. Recommended to use a static function
|
||||||
* which contains a bunch of nops. Use macro: TRAMPOLINE_NOP_DEF
|
* which contains a bunch of nops. Use macro: TRAMPOLINE_NOP_DEF
|
||||||
* @param log_file if not null will log about progress of installing the plugin
|
* @param log_file if not null will log about progress of installing the plugin
|
||||||
* @Return 0 on success otherwise failure
|
* @Return 0 on success otherwise failure
|
||||||
* @See MS Detours paper: http://research.microsoft.com/pubs/68568/huntusenixnt99.pdf for some background info.
|
* @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, bool info_print, const char * log_prefix)
|
int hot_patch_function (void* targetFunction, void* newFunction, void * trampolineFunction, unsigned int *trampolinesize, bool info_print, const char * log_prefix)
|
||||||
{
|
{
|
||||||
cond_info_print(info_print, "%s hot patching function: 0x%x", log_prefix, targetFunction);
|
cond_info_print(info_print, "%s hot patching function: 0x%x", log_prefix, targetFunction);
|
||||||
DATATYPE_ADDRESS trampolinePage = get_page_address(trampolineFunction);
|
DATATYPE_ADDRESS trampolinePage = get_page_address(trampolineFunction);
|
||||||
cond_info_print(info_print, "%s trampolineFunction: 0x%x trampolinePage: 0x%x",log_prefix, trampolineFunction, trampolinePage);
|
cond_info_print(info_print, "%s trampolineFunction: 0x%x trampolinePage: 0x%x",log_prefix, trampolineFunction, trampolinePage);
|
||||||
if (HookFunction((ULONG_PTR) targetFunction, (ULONG_PTR) newFunction,
|
if (HookFunction((ULONG_PTR) targetFunction, (ULONG_PTR) newFunction,
|
||||||
(ULONG_PTR) trampolineFunction, trampolinesize))
|
(ULONG_PTR) trampolineFunction, trampolinesize))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore a function back to its orginal state. Based uppon a trampoline function which
|
* Restore a function back to its orginal state. Based uppon a trampoline function which
|
||||||
* contains a copy of the original code.
|
* contains a copy of the original code.
|
||||||
*
|
*
|
||||||
* @param targetFunction the function to fix back
|
* @param targetFunction the function to fix back
|
||||||
* @param trampolineFunction a function which contains a jump back to the targetFunction.
|
* @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
|
* @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, const char * log_prefix)
|
void remove_hot_patch_function (void* targetFunction, void * trampolineFunction, unsigned int trampolinesize, bool info_print, const char * log_prefix)
|
||||||
{
|
{
|
||||||
if(trampolinesize == 0)
|
if(trampolinesize == 0)
|
||||||
{
|
{
|
||||||
//nothing todo. As hot patch was not set.
|
//nothing todo. As hot patch was not set.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cond_info_print(info_print, "%s removing hot patching function: 0x%x",log_prefix, targetFunction);
|
cond_info_print(info_print, "%s removing hot patching function: 0x%x",log_prefix, targetFunction);
|
||||||
DATATYPE_ADDRESS targetPage = get_page_address(targetFunction);
|
DATATYPE_ADDRESS targetPage = get_page_address(targetFunction);
|
||||||
cond_info_print(info_print, "%s targetPage: 0x%x targetFunction: 0x%x",log_prefix, targetPage, 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);
|
UnhookFunction ((ULONG_PTR) targetFunction, (ULONG_PTR)trampolineFunction,trampolinesize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue