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