1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <iostream>
17 #include <securec.h>
18 #include <string>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include <dirent.h>
22 #include "napi/native_api.h"
23
24 constexpr int MAX_BUFFER_SIZE = 128;
25 const int NUMBERTEN = 10;
26 const int NUMBERELEVEN = 11;
27 const int NUMBERTWELVE = 12;
28
FindDirAndCheck(DIR * dir,char * fileResult,int pid)29 static int FindDirAndCheck(DIR *dir, char *fileResult, int pid)
30 {
31 struct dirent *ptr;
32 char file[MAX_BUFFER_SIZE];
33 int filenameres = snprintf_s(file, sizeof(file), sizeof(file) - 1, "%s.%d", "hwasanXtsLog", pid);
34 if (filenameres < 0) {
35 return -1;
36 }
37 while((ptr = readdir(dir)) != NULL) {
38 if (strstr(ptr->d_name, file) != NULL) {
39 int findRes = snprintf_s(fileResult, MAX_BUFFER_SIZE, MAX_BUFFER_SIZE - 1, "%s/%s",
40 "/data/storage/el2/log/", ptr->d_name);
41 if (findRes < 0) {
42 return -1;
43 }
44 return 1;
45 }
46 }
47 return -1;
48 }
49
GetBuffer(int pid)50 static std::string GetBuffer(int pid)
51 {
52 std::string buffer;
53 char file[MAX_BUFFER_SIZE];
54 DIR *logdir = opendir("/data/storage/el2/log/");
55 int findRes = FindDirAndCheck(logdir, file, pid);
56 if (findRes < 0) {
57 return buffer;
58 }
59 FILE *fp = fopen(file, "r+");
60 if (!fp) {
61 return buffer;
62 }
63 if (fseek(fp, 0, SEEK_END) == -1) {
64 return buffer;
65 }
66 int size = ftell(fp);
67 if (size <= 0) {
68 ftruncate(fileno(fp), 0);
69 rewind(fp);
70 fclose(fp);
71 return buffer;
72 }
73 buffer.resize(size);
74 if (fseek(fp, 0, SEEK_SET) == -1) {
75 ftruncate(fileno(fp), 0);
76 rewind(fp);
77 fclose(fp);
78 return buffer;
79 }
80 int rsize = fread(&buffer[0], 1, size, fp);
81 if (rsize == 0) {
82 ftruncate(fileno(fp), 0);
83 rewind(fp);
84 fclose(fp);
85 return buffer;
86 }
87 ftruncate(fileno(fp), 0);
88 rewind(fp);
89 fclose(fp);
90 remove(file);
91 return buffer;
92 }
93
CheckHWAsanLog(const std::string & errType,const std::string & buffer)94 static bool CheckHWAsanLog(const std::string& errType, const std::string& buffer)
95 {
96 if (buffer.empty()) {
97 return false;
98 }
99 bool checkEventTypeFail = buffer.find(errType.c_str()) == std::string::npos;
100 if (checkEventTypeFail) {
101 return false;
102 }
103 return true;
104 }
105
StackBufferOverflow(napi_env env,napi_callback_info info)106 __attribute__((optnone)) static napi_value StackBufferOverflow(napi_env env, napi_callback_info info)
107 {
108 int status;
109 int pid = fork();
110 int checkRes = 0;
111 if (pid == -1) {
112 napi_value result = nullptr;
113 napi_create_int32(env, checkRes, &result);
114 } else if (pid == 0) {
115 int a[NUMBERTEN];
116 a[NUMBERELEVEN] = 1;
117 } else {
118 wait(&status);
119 }
120 std::string bufferLog = GetBuffer(pid);
121 bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
122 CheckHWAsanLog("WRITE of size 4", bufferLog) &&
123 CheckHWAsanLog("stack of thread", bufferLog) &&
124 CheckHWAsanLog("[08]", bufferLog);
125 checkRes = findHWAsanLog ? 1 : 0;
126 napi_value result = nullptr;
127 napi_create_int32(env, checkRes, &result);
128 return result;
129 }
130
StackBufferUnderflow(napi_env env,napi_callback_info info)131 __attribute__((optnone)) static napi_value StackBufferUnderflow(napi_env env, napi_callback_info info)
132 {
133 int status;
134 int pid = fork();
135 int checkRes = 0;
136 if (pid == -1) {
137 napi_value result = nullptr;
138 napi_create_int32(env, checkRes, &result);
139 } else if (pid == 0) {
140 int a[10];
141 a[-1] = 1;
142 } else {
143 wait(&status);
144 }
145 std::string bufferLog = GetBuffer(pid);
146 bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
147 CheckHWAsanLog("WRITE of size 4", bufferLog) &&
148 CheckHWAsanLog("stack of thread", bufferLog) &&
149 CheckHWAsanLog("[08]", bufferLog);
150 checkRes = findHWAsanLog ? 1 : 0;
151 napi_value result = nullptr;
152 napi_create_int32(env, checkRes, &result);
153 return result;
154 }
155
HeapBufferOverflow(napi_env env,napi_callback_info info)156 __attribute__((optnone)) static napi_value HeapBufferOverflow(napi_env env, napi_callback_info info)
157 {
158 int status;
159 int pid = fork();
160 int checkRes = 0;
161 if (pid == -1) {
162 napi_value result = nullptr;
163 napi_create_int32(env, checkRes, &result);
164 } else if (pid == 0) {
165 char *buffer = (char *)malloc(NUMBERTEN);
166 *(buffer + NUMBERTWELVE) = 'n';
167 free(buffer);
168 } else {
169 wait(&status);
170 }
171 std::string bufferLog = GetBuffer(pid);
172 bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
173 CheckHWAsanLog("WRITE of size 1", bufferLog) &&
174 CheckHWAsanLog("heap-buffer-overflow", bufferLog) &&
175 CheckHWAsanLog("[0a]", bufferLog);
176 checkRes = findHWAsanLog ? 1 : 0;
177 napi_value result = nullptr;
178 napi_create_int32(env, checkRes, &result);
179 return result;
180 }
181
HeapBufferUnderflow(napi_env env,napi_callback_info info)182 __attribute__((optnone)) static napi_value HeapBufferUnderflow(napi_env env, napi_callback_info info)
183 {
184 int status;
185 int pid = fork();
186 int checkRes = 0;
187 if (pid == -1) {
188 napi_value result = nullptr;
189 napi_create_int32(env, checkRes, &result);
190 } else if (pid == 0) {
191 char *x = (char*)malloc(NUMBERTEN * sizeof(char));
192 memset_s(x, NUMBERTEN * sizeof(char), 0, NUMBERTEN * sizeof(char));
193 int res = x[-1];
194 free(x);
195 } else {
196 wait(&status);
197 }
198 std::string bufferLog = GetBuffer(pid);
199 bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
200 CheckHWAsanLog("READ of size 1", bufferLog) &&
201 CheckHWAsanLog("heap-buffer-overflow", bufferLog);
202 checkRes = findHWAsanLog ? 1 : 0;
203 napi_value result = nullptr;
204 napi_create_int32(env, checkRes, &result);
205 return result;
206 }
207
HeapUseAfterFree(napi_env env,napi_callback_info info)208 __attribute__((optnone)) static napi_value HeapUseAfterFree(napi_env env, napi_callback_info info)
209 {
210 int status;
211 int pid = fork();
212 int checkRes = 0;
213 if (pid == -1) {
214 napi_value result = nullptr;
215 napi_create_int32(env, checkRes, &result);
216 } else if (pid == 0) {
217 char *x = (char*)malloc(10 * sizeof(char));
218 free(x);
219 char tmp = x[5];
220 } else {
221 wait(&status);
222 }
223 std::string bufferLog = GetBuffer(pid);
224 bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
225 CheckHWAsanLog("use-after-free", bufferLog) &&
226 CheckHWAsanLog("READ of size 1", bufferLog) &&
227 CheckHWAsanLog("freed by thread", bufferLog);
228 checkRes = findHWAsanLog ? 1 : 0;
229 napi_value result = nullptr;
230 napi_create_int32(env, checkRes, &result);
231 return result;
232 }
233
GetLocalPointer()234 __attribute__((optnone)) int* GetLocalPointer()
235 {
236 int num = 10;
237 return #
238 }
239
StackUseAfterScope(napi_env env,napi_callback_info info)240 __attribute__((optnone)) static napi_value StackUseAfterScope(napi_env env, napi_callback_info info)
241 {
242 int status;
243 int pid = fork();
244 int checkRes = 0;
245 if (pid == -1) {
246 napi_value result = nullptr;
247 napi_create_int32(env, checkRes, &result);
248 } else if (pid == 0) {
249 int* ptr = GetLocalPointer();
250 std::cout << *ptr << std::endl;
251 } else {
252 wait(&status);
253 }
254 std::string bufferLog = GetBuffer(pid);
255 bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
256 CheckHWAsanLog("stack of thread", bufferLog) &&
257 CheckHWAsanLog("READ of size 4", bufferLog) &&
258 CheckHWAsanLog("[00]", bufferLog);
259 checkRes = findHWAsanLog ? 1 : 0;
260 napi_value result = nullptr;
261 napi_create_int32(env, checkRes, &result);
262 return result;
263 }
264
Fun()265 __attribute__((optnone)) int* Fun()
266 {
267 int a = 3;
268 return &a;
269 }
StackUseAfterReturn(napi_env env,napi_callback_info info)270 __attribute__((optnone)) static napi_value StackUseAfterReturn(napi_env env, napi_callback_info info)
271 {
272 int status;
273 int pid = fork();
274 int checkRes = 0;
275 if (pid == -1) {
276 napi_value result = nullptr;
277 napi_create_int32(env, checkRes, &result);
278 } else if (pid == 0) {
279 int* p = Fun();
280 int c = *p;
281 } else {
282 wait(&status);
283 }
284 std::string bufferLog = GetBuffer(pid);
285 bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
286 CheckHWAsanLog("stack of thread", bufferLog) &&
287 CheckHWAsanLog("READ of size 4", bufferLog) &&
288 CheckHWAsanLog("[00]", bufferLog);
289 checkRes = findHWAsanLog ? 1 : 0;
290 napi_value result = nullptr;
291 napi_create_int32(env, checkRes, &result);
292 return result;
293 }
294
DoubleFree(napi_env env,napi_callback_info info)295 __attribute__((optnone)) static napi_value DoubleFree(napi_env env, napi_callback_info info)
296 {
297 char *x = (char*)malloc(NUMBERTEN * sizeof(char));
298 memset_s(x, NUMBERTEN * sizeof(char), 0, NUMBERTEN * sizeof(char));
299 free(x);
300 free(x);
301 std::string bufferLog = GetBuffer(getpid());
302 bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: invalid-free", bufferLog) &&
303 CheckHWAsanLog("use-after-free", bufferLog) &&
304 CheckHWAsanLog("freed by thread", bufferLog);
305 int checkRes = findHWAsanLog ? 1 : 0;
306 napi_value result = nullptr;
307 napi_create_int32(env, checkRes, &result);
308 return result;
309 }
310
WildFree(napi_env env,napi_callback_info info)311 __attribute__((optnone)) static napi_value WildFree(napi_env env, napi_callback_info info)
312 {
313 int* ptr = new int(1);
314 delete ptr;
315 delete ptr;
316 std::string bufferLog = GetBuffer(getpid());
317 bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: invalid-free", bufferLog) &&
318 CheckHWAsanLog("use-after-free", bufferLog) &&
319 CheckHWAsanLog("freed by thread", bufferLog);
320 int checkRes = findHWAsanLog ? 1 : 0;
321 napi_value result = nullptr;
322 napi_create_int32(env, checkRes, &result);
323 return result;
324 }
325
326 EXTERN_C_START
Init(napi_env env,napi_value exports)327 static napi_value Init(napi_env env, napi_value exports)
328 {
329 napi_property_descriptor desc[] = {
330 { "stackBufferOverflow", nullptr, StackBufferOverflow, nullptr, nullptr, nullptr, napi_default, nullptr },
331 { "stackBufferUnderflow", nullptr, StackBufferUnderflow, nullptr, nullptr, nullptr, napi_default, nullptr },
332 { "heapBufferOverflow", nullptr, HeapBufferOverflow, nullptr, nullptr, nullptr, napi_default, nullptr },
333 { "heapBufferUnderflow", nullptr, HeapBufferUnderflow, nullptr, nullptr, nullptr, napi_default, nullptr },
334 { "heapUseAfterFree", nullptr, HeapUseAfterFree, nullptr, nullptr, nullptr, napi_default, nullptr },
335 { "stackUseAfterScope", nullptr, StackUseAfterScope, nullptr, nullptr, nullptr, napi_default, nullptr },
336 { "stackUseAfterReturn", nullptr, StackUseAfterReturn, nullptr, nullptr, nullptr, napi_default, nullptr },
337 { "doubleFree", nullptr, DoubleFree, nullptr, nullptr, nullptr, napi_default, nullptr },
338 { "wildFree", nullptr, WildFree, nullptr, nullptr, nullptr, napi_default, nullptr }
339 };
340 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
341 return exports;
342 }
343 EXTERN_C_END
344
345 static napi_module demoModule = {
346 .nm_version = 1,
347 .nm_flags = 0,
348 .nm_filename = nullptr,
349 .nm_register_func = Init,
350 .nm_modname = "entry",
351 .nm_priv = ((void*)0),
352 .reserved = { 0 },
353 };
354
RegisterEntryModule(void)355 extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
356 {
357 napi_module_register(&demoModule);
358 }
359