• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &num;
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