Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/SoftEtherVPN/SoftEtherVPN_Stable.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/Mayaqua/Memory.c')
-rw-r--r--src/Mayaqua/Memory.c243
1 files changed, 207 insertions, 36 deletions
diff --git a/src/Mayaqua/Memory.c b/src/Mayaqua/Memory.c
index f9e0dfde..dc9abd8b 100644
--- a/src/Mayaqua/Memory.c
+++ b/src/Mayaqua/Memory.c
@@ -127,6 +127,105 @@ static UINT fifo_current_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
static ACTIVE_PATCH_ENTRY ActivePatchList[MAX_ACTIVE_PATCH] = CLEAN;
+static bool canary_inited = false;
+typedef struct CANARY_RAND_DATA
+{
+ UCHAR Data[CANARY_RAND_SIZE + 4];
+} CANARY_RAND_DATA;
+
+static CANARY_RAND_DATA canary_rand_data[NUM_CANARY_RAND] = CLEAN;
+
+static UINT64 canary_memtag_magic1 = 0;
+static UINT64 canary_memtag_magic2 = 0;
+
+UCHAR *GetCanaryRand(UINT id)
+{
+ if (id >= NUM_CANARY_RAND)
+ {
+ id = NUM_CANARY_RAND - 1;
+ }
+
+ return &((canary_rand_data[id].Data)[0]);
+}
+
+void InitCanaryRand()
+{
+ SYSTEMTIME st = CLEAN;
+ char random_seed[1024] = CLEAN;
+ UINT64 t1 = 0, t2 = 0;
+ if (canary_inited)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32GetSystemTime(&st);
+ memcpy(&t1, ((UCHAR *)&st) + 0, 8);
+ memcpy(&t2, ((UCHAR *)&st) + 8, 8);
+#else // OS_WIN32
+ struct timeval tv = CLEAN;
+ struct timezone tz = CLEAN;
+ gettimeofday(&tv, &tz);
+ t1 = (UINT64)tv.tv_sec;
+ t2 = (UINT64)tv.tv_usec;
+#endif // OS_WIN32
+
+ {
+ UINT64 dos_rand = (UINT64)rand();
+ UINT64 tick1 = TickHighresNano64(true);
+ UINT64 tick2 = TickHighresNano64(true);
+
+ UINT i;
+
+ void *p1 = malloc(1);
+ void *p2 = malloc(1);
+
+ for (i = 0;i < NUM_CANARY_RAND;i++)
+ {
+ // using sprintf() here is safe.
+ sprintf(random_seed,
+ "%u "
+ "%llu "
+ "%llu "
+ "%llu "
+ "%llu "
+ "%llu "
+ "%llu "
+ "%llu "
+ "%llu "
+ "%llu "
+ "%llu "
+ "%llu "
+ "%u "
+ ,
+ i,
+ (UINT64)InitCanaryRand,
+ (UINT64)&canary_inited,
+ (UINT64)&((canary_rand_data[0].Data)[0]),
+ (UINT64)&random_seed[0],
+ tick1,
+ tick2,
+ dos_rand,
+ (UINT64)p1,
+ (UINT64)p2,
+ t1,
+ t2,
+ ~i
+ );
+
+ Hash(canary_rand_data[i].Data, random_seed, (UINT)strlen(random_seed), true);
+ }
+
+ free(p1);
+ free(p2);
+
+ canary_memtag_magic1 = *((UINT64 *)(GetCanaryRand(CANARY_RAND_ID_MEMTAG_MAGIC) + 0));
+ canary_memtag_magic2 = *((UINT64 *)(GetCanaryRand(CANARY_RAND_ID_MEMTAG_MAGIC) + 8));
+
+ canary_inited = true;
+ }
+}
+
// Add active patch
bool Vars_ActivePatch_AddStr(char* name, char* str_value)
{
@@ -3923,6 +4022,10 @@ void AdjustBufSize(BUF *b, UINT new_size)
while (b->SizeReserved < new_size)
{
+ if (b->SizeReserved > 0x7FFFFFFF)
+ {
+ AbortExitEx("AdjustBufSize(): too large buffer size");
+ }
b->SizeReserved = b->SizeReserved * 2;
}
b->Buf = ReAlloc(b->Buf, b->SizeReserved);
@@ -4556,33 +4659,52 @@ void *Malloc(UINT size)
}
void *MallocEx(UINT size, bool zero_clear_when_free)
{
- MEMTAG *tag;
+ MEMTAG1 *tag1;
+ MEMTAG2 *tag2;
UINT real_size;
+ if (canary_inited == false)
+ {
+ InitCanaryRand();
+ }
+
+ if (size > MAX_MALLOC_MEM_SIZE)
+ {
+ AbortExitEx("MallocEx() error: too large size");
+ }
+
real_size = CALC_MALLOCSIZE(size);
- tag = InternalMalloc(real_size);
+ tag1 = InternalMalloc(real_size);
+
+ tag1->Magic = canary_memtag_magic1 ^ ((UINT64)tag1 * GOLDEN_RATION_PRIME_U64);
+ tag1->Size = size;
+ tag1->ZeroFree = zero_clear_when_free;
- Zero(tag, sizeof(MEMTAG));
- tag->Magic = MEMTAG_MAGIC;
- tag->Size = size;
- tag->ZeroFree = zero_clear_when_free;
+ tag2 = (MEMTAG2 *)(((UCHAR *)tag1) + CALC_MALLOCSIZE(tag1->Size) - sizeof(MEMTAG2));
+ tag2->Magic = canary_memtag_magic2 ^ ((UINT64)tag2 * GOLDEN_RATION_PRIME_U64);
- return MEMTAG_TO_POINTER(tag);
+ return MEMTAG1_TO_POINTER(tag1);
}
// Get memory size
UINT GetMemSize(void *addr)
{
- MEMTAG *tag;
+ MEMTAG1 *tag;
+
+ if (canary_inited == false)
+ {
+ InitCanaryRand();
+ }
+
// Validate arguments
if (IS_NULL_POINTER(addr))
{
return 0;
}
- tag = POINTER_TO_MEMTAG(addr);
- CheckMemTag(tag);
+ tag = POINTER_TO_MEMTAG1(addr);
+ CheckMemTag1(tag);
return tag->Size;
}
@@ -4590,20 +4712,35 @@ UINT GetMemSize(void *addr)
// ReAlloc
void *ReAlloc(void *addr, UINT size)
{
- MEMTAG *tag;
+ MEMTAG1 *tag1;
+ MEMTAG2 *tag2;
bool zerofree;
+
+ if (canary_inited == false)
+ {
+ InitCanaryRand();
+ }
+
+ if (size > MAX_MALLOC_MEM_SIZE)
+ {
+ AbortExitEx("ReAlloc() error: too large size");
+ }
+
// Validate arguments
if (IS_NULL_POINTER(addr))
{
return NULL;
}
- tag = POINTER_TO_MEMTAG(addr);
- CheckMemTag(tag);
+ tag1 = POINTER_TO_MEMTAG1(addr);
+ CheckMemTag1(tag1);
+
+ tag2 = (MEMTAG2 *)(((UCHAR *)tag1) + CALC_MALLOCSIZE(tag1->Size) - sizeof(MEMTAG2));
+ CheckMemTag2(tag2);
- zerofree = tag->ZeroFree;
+ zerofree = tag1->ZeroFree;
- if (tag->Size == size)
+ if (tag1->Size == size)
{
// No size change
return addr;
@@ -4615,10 +4752,10 @@ void *ReAlloc(void *addr, UINT size)
// Size changed (zero clearing required)
void *new_p = MallocEx(size, true);
- if (tag->Size <= size)
+ if (tag1->Size <= size)
{
// Size expansion
- Copy(new_p, addr, tag->Size);
+ Copy(new_p, addr, tag1->Size);
}
else
{
@@ -4634,13 +4771,22 @@ void *ReAlloc(void *addr, UINT size)
else
{
// Size changed
- MEMTAG *tag2 = InternalReAlloc(tag, CALC_MALLOCSIZE(size));
+ MEMTAG1 *tag1_new;
+ MEMTAG2 *tag2_new;
+
+ tag1->Magic = 0;
+ tag2->Magic = 0;
+
+ tag1_new = InternalReAlloc(tag1, CALC_MALLOCSIZE(size));
- Zero(tag2, sizeof(MEMTAG));
- tag2->Magic = MEMTAG_MAGIC;
- tag2->Size = size;
+ tag1_new->Magic = canary_memtag_magic1 ^ ((UINT64)tag1_new * GOLDEN_RATION_PRIME_U64);
+ tag1_new->Size = size;
+ tag1_new->ZeroFree = 0;
- return MEMTAG_TO_POINTER(tag2);
+ tag2_new = (MEMTAG2 *)(((UCHAR *)tag1_new) + CALC_MALLOCSIZE(size) - sizeof(MEMTAG2));
+ tag2_new->Magic = canary_memtag_magic2 ^ ((UINT64)tag2_new * GOLDEN_RATION_PRIME_U64);
+
+ return MEMTAG1_TO_POINTER(tag1_new);
}
}
}
@@ -4648,44 +4794,69 @@ void *ReAlloc(void *addr, UINT size)
// Free
void Free(void *addr)
{
- MEMTAG *tag;
+ MEMTAG1 *tag1;
+ MEMTAG2 *tag2;
// Validate arguments
if (IS_NULL_POINTER(addr))
{
return;
}
- tag = POINTER_TO_MEMTAG(addr);
- CheckMemTag(tag);
+ if (canary_inited == false)
+ {
+ InitCanaryRand();
+ }
+
+ tag1 = POINTER_TO_MEMTAG1(addr);
+ CheckMemTag1(tag1);
+
+ tag2 = (MEMTAG2 *)(((UCHAR *)tag1) + CALC_MALLOCSIZE(tag1->Size) - sizeof(MEMTAG2));
+ CheckMemTag2(tag2);
- if (tag->ZeroFree)
+ if (tag1->ZeroFree)
{
// Zero clear
- Zero(addr, tag->Size);
+ Zero(addr, tag1->Size);
}
// Memory release
- tag->Magic = 0;
- InternalFree(tag);
+ tag1->Magic = 0;
+ tag2->Magic = 0;
+ InternalFree(tag1);
+}
+
+// Check the memtag1
+void CheckMemTag1(MEMTAG1 *tag)
+{
+ // Validate arguments
+ if (tag == NULL)
+ {
+ AbortExitEx("CheckMemTag1: tag1 == NULL");
+ return;
+ }
+
+ if (tag->Magic != (canary_memtag_magic1 ^ ((UINT64)tag * GOLDEN_RATION_PRIME_U64)))
+ {
+ AbortExitEx("CheckMemTag1: tag1->Magic != canary_memtag_magic1");
+ return;
+ }
}
-// Check the memtag
-void CheckMemTag(MEMTAG *tag)
+// Check the memtag2
+void CheckMemTag2(MEMTAG2 *tag)
{
-#ifndef DONT_CHECK_HEAP
// Validate arguments
if (tag == NULL)
{
- AbortExitEx("CheckMemTag: tag == NULL");
+ AbortExitEx("CheckMemTag2: tag2 == NULL");
return;
}
- if (tag->Magic != MEMTAG_MAGIC)
+ if (tag->Magic != (canary_memtag_magic2 ^ ((UINT64)tag * GOLDEN_RATION_PRIME_U64)))
{
- AbortExitEx("CheckMemTag: tag->Magic != MEMTAG_MAGIC");
+ AbortExitEx("CheckMemTag2: tag2->Magic != canary_memtag_magic2");
return;
}
-#endif // DONT_CHECK_HEAP
}
// ZeroMalloc