1 /**
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #define _GNU_SOURCE
17 #include <sys/types.h>
18 #include <sys/wait.h>
19 #include <sys/mman.h>
20 #include <stdbool.h>
21 #include <stdlib.h>
22 #include <dlfcn.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include "common.h"
26 #include "memutils_track.h"
27 
memutils_init(void)28 void memutils_init(void) {
29     real_memalign = dlsym(RTLD_NEXT, "memalign");
30     if (!real_memalign) {
31         return;
32     }
33     real_malloc = dlsym(RTLD_NEXT, "malloc");
34     if (!real_malloc) {
35         return;
36     }
37     real_free = dlsym(RTLD_NEXT, "free");
38     if (!real_free) {
39         return;
40     }
41 
42 #ifdef CHECK_MEMORY_LEAK
43     real_calloc = dlsym(RTLD_NEXT, "calloc");
44     if (!real_calloc) {
45         return;
46     }
47     atexit(exit_vulnerable_if_memory_leak_detected);
48 #endif /* CHECK_MEMORY_LEAK */
49 
50     s_memutils_initialized = true;
51 }
52 
memalign(size_t alignment,size_t size)53 void *memalign(size_t alignment, size_t size) {
54     if (!s_memutils_initialized) {
55         memutils_init();
56     }
57     void* mem_ptr = real_memalign(alignment, size);
58 
59 #ifdef CHECK_UNINITIALIZED_MEMORY
60     if(mem_ptr) {
61         memset(mem_ptr, INITIAL_VAL, size);
62     }
63 #endif /* CHECK_UNINITIALIZED_MEMORY */
64 
65 #ifdef ENABLE_SELECTIVE_OVERLOADING
66     if ((enable_selective_overload & ENABLE_MEMALIGN_CHECK) != ENABLE_MEMALIGN_CHECK) {
67         return mem_ptr;
68     }
69 #endif /* ENABLE_SELECTIVE_OVERLOADING */
70 
71     if (!is_tracking_required(size)) {
72         return mem_ptr;
73     }
74     if (s_allocation_index >= MAX_ENTRIES) {
75         return mem_ptr;
76     }
77     s_allocation_list[s_allocation_index].mem_ptr = mem_ptr;
78     s_allocation_list[s_allocation_index].mem_size = size;
79     ++s_allocation_index;
80     return mem_ptr;
81 }
82 
malloc(size_t size)83 void *malloc(size_t size) {
84     if (!s_memutils_initialized) {
85         memutils_init();
86     }
87     void* mem_ptr = real_malloc(size);
88 
89 #ifdef CHECK_UNINITIALIZED_MEMORY
90     if(mem_ptr) {
91         memset(mem_ptr, INITIAL_VAL, size);
92     }
93 #endif /* CHECK_UNINITIALIZED_MEMORY */
94 
95 #ifdef ENABLE_SELECTIVE_OVERLOADING
96     if ((enable_selective_overload & ENABLE_MALLOC_CHECK) != ENABLE_MALLOC_CHECK) {
97         return mem_ptr;
98     }
99 #endif /* ENABLE_SELECTIVE_OVERLOADING */
100 
101     if (!is_tracking_required(size)) {
102         return mem_ptr;
103     }
104     if (s_allocation_index >= MAX_ENTRIES) {
105         return mem_ptr;
106     }
107     s_allocation_list[s_allocation_index].mem_ptr = mem_ptr;
108     s_allocation_list[s_allocation_index].mem_size = size;
109     ++s_allocation_index;
110     return mem_ptr;
111 }
112 
free(void * ptr)113 void free(void *ptr) {
114     if (!s_memutils_initialized) {
115         memutils_init();
116     }
117     if (ptr) {
118         for (int i = 0; i < s_allocation_index; ++i) {
119             if (ptr == s_allocation_list[i].mem_ptr) {
120                 real_free(ptr);
121                 memset(&s_allocation_list[i], 0,
122                        sizeof(allocated_memory_struct));
123                 return;
124             }
125         }
126     }
127     return real_free(ptr);
128 }
129 
130 #ifdef CHECK_MEMORY_LEAK
calloc(size_t nitems,size_t size)131 void *calloc(size_t nitems, size_t size) {
132     if (!s_memutils_initialized) {
133         memutils_init();
134     }
135     void* mem_ptr = real_calloc(nitems, size);
136 
137 #ifdef ENABLE_SELECTIVE_OVERLOADING
138     if ((enable_selective_overload & ENABLE_CALLOC_CHECK) != ENABLE_CALLOC_CHECK) {
139         return mem_ptr;
140     }
141 #endif /* ENABLE_SELECTIVE_OVERLOADING */
142 
143     if (!is_tracking_required((nitems *size))) {
144         return mem_ptr;
145     }
146     if (s_allocation_index >= MAX_ENTRIES) {
147         return mem_ptr;
148     }
149     s_allocation_list[s_allocation_index].mem_ptr = mem_ptr;
150     s_allocation_list[s_allocation_index].mem_size = nitems * size;
151     ++s_allocation_index;
152     return mem_ptr;
153 }
154 
exit_vulnerable_if_memory_leak_detected(void)155 void exit_vulnerable_if_memory_leak_detected(void) {
156     bool memory_leak_detected = false;
157     for (int i = 0; i < s_allocation_index; ++i) {
158         if (s_allocation_list[i].mem_ptr) {
159             real_free(s_allocation_list[i].mem_ptr);
160             memset(&s_allocation_list[i], 0,
161                     sizeof(allocated_memory_struct));
162             memory_leak_detected = true;
163         }
164     }
165     if(memory_leak_detected) {
166         exit(EXIT_VULNERABLE);
167     }
168     return;
169 }
170 #endif /* CHECK_MEMORY_LEAK */
171 
172 #ifdef CHECK_UNINITIALIZED_MEMORY
is_memory_uninitialized()173 bool is_memory_uninitialized() {
174     for (int i = 0; i < s_allocation_index; ++i) {
175         uint8_t *mem_ptr = s_allocation_list[i].mem_ptr;
176         size_t mem_size = s_allocation_list[i].mem_size;
177         if (mem_ptr) {
178 
179 #ifdef CHECK_FOUR_BYTES
180             if(mem_size > (2 * sizeof(uint32_t))) {
181                 uint8_t *mem_ptr_start = (uint8_t *) s_allocation_list[i].mem_ptr;
182                 uint8_t *mem_ptr_end = (uint8_t *) s_allocation_list[i].mem_ptr + mem_size - 1;
183                 for (size_t j = 0; j < sizeof(uint32_t); ++j) {
184                     if (*mem_ptr_start++ == INITIAL_VAL) {
185                         return true;
186                     }
187                     if (*mem_ptr_end-- == INITIAL_VAL) {
188                         return true;
189                     }
190                 }
191                 continue;
192             }
193 #endif /* CHECK_FOUR_BYTES */
194 
195             for (size_t j = 0; j < mem_size; ++j) {
196                 if (*mem_ptr++ == INITIAL_VAL) {
197                     return true;
198                 }
199             }
200         }
201     }
202     return false;
203 }
204 
205 #endif /* CHECK_UNINITIALIZED_MEMORY */
206