• 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 "napi/native_api.h"
22 
23 constexpr int MAX_BUFFER_SIZE = 128;
24 constexpr const char *HWASAN_LOG_FILE_PATH = "/data/storage/el2/log/hwasanXtsLog.appspawn";
25 const int NUMBERTEN = 10;
26 const int NUMBERELEVEN = 11;
27 const int NUMBERTWELVE = 12;
28 
GetBuffer(int pid)29 static std::string GetBuffer(int pid)
30 {
31     std::string buffer;
32     char file[MAX_BUFFER_SIZE];
33     int filePathRes = snprintf_s(file, sizeof(file), sizeof(file) - 1, "%s.%d", HWASAN_LOG_FILE_PATH, pid);
34     if (filePathRes < 0) {
35         return buffer;
36     }
37     FILE *fp = fopen(file, "r+");
38     if (!fp) {
39         return buffer;
40     }
41     if (fseek(fp, 0, SEEK_END) == -1) {
42         return buffer;
43     }
44     int size = ftell(fp);
45     if (size <= 0) {
46         ftruncate(fileno(fp), 0);
47         rewind(fp);
48         fclose(fp);
49         return buffer;
50     }
51     buffer.resize(size);
52     if (fseek(fp, 0, SEEK_SET) == -1) {
53         ftruncate(fileno(fp), 0);
54         rewind(fp);
55         fclose(fp);
56         return buffer;
57     }
58     int rsize = fread(&buffer[0], 1, size, fp);
59     if (rsize == 0) {
60         ftruncate(fileno(fp), 0);
61         rewind(fp);
62         fclose(fp);
63         return buffer;
64     }
65     ftruncate(fileno(fp), 0);
66     rewind(fp);
67     fclose(fp);
68     return buffer;
69 }
70 
CheckHWAsanLog(const std::string & errType,const std::string & buffer)71 static bool CheckHWAsanLog(const std::string& errType, const std::string& buffer)
72 {
73     if (buffer.empty()) {
74         return false;
75     }
76     bool checkEventTypeFail = buffer.find(errType.c_str()) == std::string::npos;
77     if (checkEventTypeFail) {
78         return false;
79     }
80     return true;
81 }
82 
StackBufferOverflow(napi_env env,napi_callback_info info)83 __attribute__((optnone)) static napi_value StackBufferOverflow(napi_env env, napi_callback_info info)
84 {
85     int status;
86     int pid = fork();
87     int checkRes = 0;
88     if (pid == -1) {
89         napi_value result = nullptr;
90         napi_create_int32(env, checkRes, &result);
91     } else if (pid == 0) {
92         int a[NUMBERTEN];
93         a[NUMBERELEVEN] = 1;
94     } else {
95         wait(&status);
96     }
97     std::string bufferLog = GetBuffer(pid);
98     bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
99         CheckHWAsanLog("WRITE of size 4", bufferLog) &&
100         CheckHWAsanLog("stack of thread", bufferLog) &&
101         CheckHWAsanLog("[08]", bufferLog);
102     checkRes = findHWAsanLog ? 1 : 0;
103     napi_value result = nullptr;
104     napi_create_int32(env, checkRes, &result);
105     return result;
106 }
107 
StackBufferUnderflow(napi_env env,napi_callback_info info)108 __attribute__((optnone)) static napi_value StackBufferUnderflow(napi_env env, napi_callback_info info)
109 {
110     int status;
111     int pid = fork();
112     int checkRes = 0;
113     if (pid == -1) {
114         napi_value result = nullptr;
115         napi_create_int32(env, checkRes, &result);
116     } else if (pid == 0) {
117         int a[10];
118         a[-1] = 1;
119     } else {
120         wait(&status);
121     }
122     std::string bufferLog = GetBuffer(pid);
123     bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
124         CheckHWAsanLog("WRITE of size 4", bufferLog) &&
125         CheckHWAsanLog("stack of thread", bufferLog) &&
126         CheckHWAsanLog("[08]", bufferLog);
127     checkRes = findHWAsanLog ? 1 : 0;
128     napi_value result = nullptr;
129     napi_create_int32(env, checkRes, &result);
130     return result;
131 }
132 
HeapBufferOverflow(napi_env env,napi_callback_info info)133 __attribute__((optnone)) static napi_value HeapBufferOverflow(napi_env env, napi_callback_info info)
134 {
135     int status;
136     int pid = fork();
137     int checkRes = 0;
138     if (pid == -1) {
139         napi_value result = nullptr;
140         napi_create_int32(env, checkRes, &result);
141     } else if (pid == 0) {
142         char *buffer = (char *)malloc(NUMBERTEN);
143         *(buffer + NUMBERTWELVE) = 'n';
144         free(buffer);
145     } else {
146         wait(&status);
147     }
148     std::string bufferLog = GetBuffer(pid);
149     bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
150         CheckHWAsanLog("WRITE of size 1", bufferLog) &&
151         CheckHWAsanLog("heap-buffer-overflow", bufferLog) &&
152         CheckHWAsanLog("[0a]", bufferLog);
153     checkRes = findHWAsanLog ? 1 : 0;
154     napi_value result = nullptr;
155     napi_create_int32(env, checkRes, &result);
156     return result;
157 }
158 
HeapBufferUnderflow(napi_env env,napi_callback_info info)159 __attribute__((optnone)) static napi_value HeapBufferUnderflow(napi_env env, napi_callback_info info)
160 {
161     int status;
162     int pid = fork();
163     int checkRes = 0;
164     if (pid == -1) {
165         napi_value result = nullptr;
166         napi_create_int32(env, checkRes, &result);
167     } else if (pid == 0) {
168         char *x = (char*)malloc(NUMBERTEN * sizeof(char));
169         memset_s(x, NUMBERTEN * sizeof(char), 0, NUMBERTEN * sizeof(char));
170         int res = x[-1];
171         free(x);
172     } else {
173         wait(&status);
174     }
175     std::string bufferLog = GetBuffer(pid);
176     bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
177         CheckHWAsanLog("READ of size 1", bufferLog) &&
178         CheckHWAsanLog("heap-buffer-overflow", bufferLog);
179     checkRes = findHWAsanLog ? 1 : 0;
180     napi_value result = nullptr;
181     napi_create_int32(env, checkRes, &result);
182     return result;
183 }
184 
HeapUseAfterFree(napi_env env,napi_callback_info info)185 __attribute__((optnone)) static napi_value HeapUseAfterFree(napi_env env, napi_callback_info info)
186 {
187     int status;
188     int pid = fork();
189     int checkRes = 0;
190     if (pid == -1) {
191         napi_value result = nullptr;
192         napi_create_int32(env, checkRes, &result);
193     } else if (pid == 0) {
194         char *x = (char*)malloc(10 * sizeof(char));
195         free(x);
196         char tmp = x[5];
197     } else {
198         wait(&status);
199     }
200     std::string bufferLog = GetBuffer(pid);
201     bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
202         CheckHWAsanLog("use-after-free", bufferLog) &&
203         CheckHWAsanLog("READ of size 1", bufferLog) &&
204         CheckHWAsanLog("freed by thread", bufferLog);
205     checkRes = findHWAsanLog ? 1 : 0;
206     napi_value result = nullptr;
207     napi_create_int32(env, checkRes, &result);
208     return result;
209 }
210 
GetLocalPointer()211 __attribute__((optnone)) int* GetLocalPointer()
212 {
213     int num = 10;
214     return &num;
215 }
216 
StackUseAfterScope(napi_env env,napi_callback_info info)217 __attribute__((optnone)) static napi_value StackUseAfterScope(napi_env env, napi_callback_info info)
218 {
219     int status;
220     int pid = fork();
221     int checkRes = 0;
222     if (pid == -1) {
223         napi_value result = nullptr;
224         napi_create_int32(env, checkRes, &result);
225     } else if (pid == 0) {
226         int* ptr = GetLocalPointer();
227         std::cout << *ptr << std::endl;
228     } else {
229         wait(&status);
230     }
231     std::string bufferLog = GetBuffer(pid);
232     bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
233         CheckHWAsanLog("stack of thread", bufferLog) &&
234         CheckHWAsanLog("READ of size 4", bufferLog) &&
235         CheckHWAsanLog("[00]", bufferLog);
236     checkRes = findHWAsanLog ? 1 : 0;
237     napi_value result = nullptr;
238     napi_create_int32(env, checkRes, &result);
239     return result;
240 }
241 
Fun()242 __attribute__((optnone)) int* Fun()
243 {
244     int a = 3;
245     return &a;
246 }
StackUseAfterReturn(napi_env env,napi_callback_info info)247 __attribute__((optnone)) static napi_value StackUseAfterReturn(napi_env env, napi_callback_info info)
248 {
249     int status;
250     int pid = fork();
251     int checkRes = 0;
252     if (pid == -1) {
253         napi_value result = nullptr;
254         napi_create_int32(env, checkRes, &result);
255     } else if (pid == 0) {
256         int* p = Fun();
257         int c = *p;
258     } else {
259         wait(&status);
260     }
261     std::string bufferLog = GetBuffer(pid);
262     bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: tag-mismatch", bufferLog) &&
263         CheckHWAsanLog("stack of thread", bufferLog) &&
264         CheckHWAsanLog("READ of size 4", bufferLog) &&
265         CheckHWAsanLog("[00]", bufferLog);
266     checkRes = findHWAsanLog ? 1 : 0;
267     napi_value result = nullptr;
268     napi_create_int32(env, checkRes, &result);
269     return result;
270 }
271 
DoubleFree(napi_env env,napi_callback_info info)272 __attribute__((optnone)) static napi_value DoubleFree(napi_env env, napi_callback_info info)
273 {
274     char *x = (char*)malloc(NUMBERTEN * sizeof(char));
275     memset_s(x, NUMBERTEN * sizeof(char), 0, NUMBERTEN * sizeof(char));
276     free(x);
277     free(x);
278     std::string bufferLog = GetBuffer(getpid());
279     bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: invalid-free", bufferLog) &&
280         CheckHWAsanLog("use-after-free", bufferLog) &&
281         CheckHWAsanLog("freed by thread", bufferLog);
282     int checkRes = findHWAsanLog ? 1 : 0;
283     napi_value result = nullptr;
284     napi_create_int32(env, checkRes, &result);
285     return result;
286 }
287 
WildFree(napi_env env,napi_callback_info info)288 __attribute__((optnone)) static napi_value WildFree(napi_env env, napi_callback_info info)
289 {
290     int* ptr = new int(1);
291     delete ptr;
292     delete ptr;
293     std::string bufferLog = GetBuffer(getpid());
294     bool findHWAsanLog = CheckHWAsanLog("HWAddressSanitizer: invalid-free", bufferLog) &&
295         CheckHWAsanLog("use-after-free", bufferLog) &&
296         CheckHWAsanLog("freed by thread", bufferLog);
297     int checkRes = findHWAsanLog ? 1 : 0;
298     napi_value result = nullptr;
299     napi_create_int32(env, checkRes, &result);
300     return result;
301 }
302 
303 EXTERN_C_START
Init(napi_env env,napi_value exports)304 static napi_value Init(napi_env env, napi_value exports)
305 {
306     napi_property_descriptor desc[] = {
307         { "stackBufferOverflow", nullptr, StackBufferOverflow, nullptr, nullptr, nullptr, napi_default, nullptr },
308         { "stackBufferUnderflow", nullptr, StackBufferUnderflow, nullptr, nullptr, nullptr, napi_default, nullptr },
309         { "heapBufferOverflow", nullptr, HeapBufferOverflow, nullptr, nullptr, nullptr, napi_default, nullptr },
310         { "heapBufferUnderflow", nullptr, HeapBufferUnderflow, nullptr, nullptr, nullptr, napi_default, nullptr },
311         { "heapUseAfterFree", nullptr, HeapUseAfterFree, nullptr, nullptr, nullptr, napi_default, nullptr },
312         { "stackUseAfterScope", nullptr, StackUseAfterScope, nullptr, nullptr, nullptr, napi_default, nullptr },
313         { "stackUseAfterReturn", nullptr, StackUseAfterReturn, nullptr, nullptr, nullptr, napi_default, nullptr },
314         { "doubleFree", nullptr, DoubleFree, nullptr, nullptr, nullptr, napi_default, nullptr },
315         { "wildFree", nullptr, WildFree, nullptr, nullptr, nullptr, napi_default, nullptr }
316     };
317     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
318     return exports;
319 }
320 EXTERN_C_END
321 
322 static napi_module demoModule = {
323     .nm_version = 1,
324     .nm_flags = 0,
325     .nm_filename = nullptr,
326     .nm_register_func = Init,
327     .nm_modname = "entry",
328     .nm_priv = ((void*)0),
329     .reserved = { 0 },
330 };
331 
RegisterEntryModule(void)332 extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
333 {
334     napi_module_register(&demoModule);
335 }
336