Home | History | Annotate | Download | only in windows_kernel
      1 /**
      2  * @file libc.cpp
      3  * @author created by: Peter Hlavaty
      4  */
      5 
      6 #include "libc.h"
      7 #include <memory>
      8 #include <Ntintsafe.h>
      9 
     10 #pragma warning(push)
     11 #pragma warning (disable : 4565)
     12 
     13 #ifndef _LIBC_POOL_TAG
     14 #define _LIBC_POOL_TAG	'colM'
     15 #endif
     16 
     17 // very nice for debug forensics!
     18 struct MEMBLOCK
     19 {
     20 	size_t	size;
     21 #pragma warning(push)
     22 #pragma warning (disable : 4200)
     23 	char data[0];
     24 #pragma warning(pop)
     25 };
     26 
     27 EXTERN_C
     28 __drv_when(return!=0, __drv_allocatesMem(pBlock))
     29 __checkReturn
     30 __drv_maxIRQL(DISPATCH_LEVEL)
     31 __bcount_opt(size)
     32 void*
     33 __cdecl malloc(
     34 	__in size_t size
     35 	)
     36 {
     37 	/* A specially crafted size value can trigger the overflow.
     38 	If the sum in a value that overflows or underflows the capacity of the type,
     39 	the function returns nullptr. */
     40 	size_t number_of_bytes = 0;
     41 	if (!NT_SUCCESS(RtlSizeTAdd(size, sizeof(MEMBLOCK), &number_of_bytes))){
     42 		return nullptr;
     43 	}
     44 	MEMBLOCK *pBlock = static_cast<MEMBLOCK*>(
     45 		ExAllocatePoolWithTag(
     46 			NonPagedPoolNxCacheAligned,
     47 			number_of_bytes,
     48 			_LIBC_POOL_TAG));
     49 
     50 	if (nullptr == pBlock)
     51 		return nullptr;
     52 
     53 	pBlock->size = size;
     54 	return pBlock->data;
     55 }
     56 
     57 EXTERN_C
     58 __drv_when(return != 0, __drv_allocatesMem(p))
     59 __checkReturn
     60 __drv_maxIRQL(DISPATCH_LEVEL)
     61 __bcount_opt(size * n)
     62 void*
     63 __cdecl calloc(size_t n, size_t size)
     64 {
     65 	size_t total = n * size;
     66 	void *p = malloc(total);
     67 
     68 	if (!p) return NULL;
     69 
     70 	return memset(p, 0, total);
     71 }
     72 
     73 EXTERN_C
     74 __drv_when(return!=0, __drv_allocatesMem(inblock))
     75 __checkReturn
     76 __drv_maxIRQL(DISPATCH_LEVEL)
     77 __bcount_opt(size)
     78 void*
     79 __cdecl realloc(
     80 	__in_opt void* ptr,
     81 	__in size_t size
     82 	)
     83 {
     84 	if (!ptr)
     85 		return malloc(size);
     86 
     87 	std::unique_ptr<unsigned char> inblock = std::unique_ptr<unsigned char>(static_cast<unsigned char*>(ptr));
     88 
     89 	// alloc new block
     90 	void* mem = malloc(size);
     91 	if (!mem)
     92 		return nullptr;
     93 
     94 	// copy from old one, not overflow ..
     95 	memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data)->size, size));
     96 	return mem;
     97 }
     98 
     99 EXTERN_C
    100 __drv_maxIRQL(DISPATCH_LEVEL)
    101 void
    102 __cdecl free(
    103 	__inout_opt __drv_freesMem(Mem) void* ptr
    104 	)
    105 {
    106 	if (ptr)
    107 		ExFreePoolWithTag(CONTAINING_RECORD(ptr, MEMBLOCK, data), _LIBC_POOL_TAG);
    108 }
    109 
    110 #pragma warning(pop)
    111 
    112 __drv_when(return!=0, __drv_allocatesMem(ptr))
    113 __checkReturn
    114 __drv_maxIRQL(DISPATCH_LEVEL)
    115 __bcount_opt(size)
    116 void*
    117 __cdecl operator new(
    118 	__in size_t size
    119 	)
    120 {
    121 	return malloc(size);
    122 }
    123 
    124 __drv_maxIRQL(DISPATCH_LEVEL)
    125 void
    126 __cdecl operator delete(
    127 	__inout void* ptr
    128 	)
    129 {
    130 	free(ptr);
    131 }
    132 
    133 int
    134 __cdecl vsnprintf(
    135 	char *buffer,
    136 	size_t count,
    137 	const char *format,
    138 	va_list argptr
    139 )
    140 {
    141 	return vsprintf_s(buffer, count, format, argptr);
    142 }
    143