• 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 <securec.h>
17 #include <string>
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <dirent.h>
21 #include "napi/native_api.h"
22 
23 constexpr int MAX_BUFFER_SIZE = 128;
24 const int NUMFIVE = 5;
25 const int NUMTEN = 10;
26 const int NUMELEVEN = 11;
27 const int NUMTWELVE = 12;
28 const int NUMNEGATIVEONE = -1;
29 
FindDirAndCheck(DIR * dir,char * fileResult,int pid)30 static int FindDirAndCheck(DIR *dir, char *fileResult, int pid)
31 {
32     struct dirent *ptr;
33     char file[MAX_BUFFER_SIZE];
34     int filenameres = snprintf_s(file, sizeof(file), sizeof(file) - 1, "%s.%d", "asanXtsLog", pid);
35     if (filenameres < 0) {
36         return -1;
37     }
38     while((ptr = readdir(dir)) != NULL) {
39         if (strstr(ptr->d_name, file) != NULL) {
40             int findRes = snprintf_s(fileResult, MAX_BUFFER_SIZE, MAX_BUFFER_SIZE - 1, "%s/%s",
41                 "/data/storage/el2/log/", ptr->d_name);
42             if (findRes < 0) {
43                 return -1;
44             }
45             return 1;
46         }
47     }
48     return -1;
49 }
50 
GetBuffer(int pid)51 static std::string GetBuffer(int pid)
52 {
53     std::string buffer;
54     char file[MAX_BUFFER_SIZE];
55     DIR *logdir = opendir("/data/storage/el2/log/");
56     int findRes = FindDirAndCheck(logdir, file, pid);
57     if (findRes < 0) {
58         return buffer;
59     }
60     FILE *fp = fopen(file, "r+");
61     if (!fp) {
62         return buffer;
63     }
64     if (fseek(fp, 0, SEEK_END) == -1) {
65         return buffer;
66     }
67     int size = ftell(fp);
68     if (size <= 0) {
69         ftruncate(fileno(fp), 0);
70         rewind(fp);
71         fclose(fp);
72         return buffer;
73     }
74     buffer.resize(size);
75     if (fseek(fp, 0, SEEK_SET) == -1) {
76         ftruncate(fileno(fp), 0);
77         rewind(fp);
78         fclose(fp);
79         return buffer;
80     }
81     int rsize = fread(&buffer[0], 1, size, fp);
82     if (rsize == 0) {
83         ftruncate(fileno(fp), 0);
84         rewind(fp);
85         fclose(fp);
86         return buffer;
87     }
88     ftruncate(fileno(fp), 0);
89     rewind(fp);
90     fclose(fp);
91     remove(file);
92     return buffer;
93 }
94 
CheckAsanLog(const std::string & errType,const std::string & buffer)95 static bool CheckAsanLog(const std::string& errType, const std::string& buffer)
96 {
97     if (buffer.empty()) {
98         return false;
99     }
100     bool checkEventTypeFail = buffer.find(errType.c_str()) == std::string::npos;
101     if (checkEventTypeFail) {
102         return false;
103     }
104     return true;
105 }
106 
StackBufferOverflow(napi_env env,napi_callback_info info)107 __attribute__((optnone)) static napi_value StackBufferOverflow(napi_env env, napi_callback_info info)
108 {
109     int a[NUMTEN];
110     a[NUMELEVEN] = 1;
111     std::string bufferLog = GetBuffer(getpid());
112     bool findAsanLog = CheckAsanLog("AddressSanitizer: stack-buffer-overflow", bufferLog) &&
113         CheckAsanLog("WRITE of size 4", bufferLog) &&
114         CheckAsanLog("thread T0", bufferLog) &&
115         CheckAsanLog("'a' (line 108)", bufferLog) &&
116         CheckAsanLog("[f2]", bufferLog);
117     int checkRes = findAsanLog ? 1 : 0;
118     napi_value result = nullptr;
119     napi_create_int32(env, checkRes, &result);
120     return result;
121 }
122 
StackBufferUnderflow(napi_env env,napi_callback_info info)123 __attribute__((optnone)) static napi_value StackBufferUnderflow(napi_env env, napi_callback_info info)
124 {
125     int a[NUMTEN];
126     a[NUMNEGATIVEONE] = 1;
127     std::string bufferLog = GetBuffer(getpid());
128     bool findAsanLog = CheckAsanLog("AddressSanitizer: stack-buffer-underflow", bufferLog) &&
129         CheckAsanLog("WRITE of size 4", bufferLog) &&
130         CheckAsanLog("thread T0", bufferLog) &&
131         CheckAsanLog("'a' (line 124)", bufferLog) &&
132         CheckAsanLog("[f1]", bufferLog);
133     int checkRes = findAsanLog ? 1 : 0;
134     napi_value result = nullptr;
135     napi_create_int32(env, findAsanLog, &result);
136     return result;
137 }
138 
HeapBufferOverflow(napi_env env,napi_callback_info info)139 __attribute__((optnone)) static napi_value HeapBufferOverflow(napi_env env, napi_callback_info info)
140 {
141     char *buffer = (char *)malloc(NUMTEN);
142     if (buffer != nullptr) {
143         *(buffer + NUMTWELVE) = 'n';
144     }
145     free(buffer);
146     std::string bufferLog = GetBuffer(getpid());
147     bool findAsanLog = CheckAsanLog("AddressSanitizer: heap-buffer-overflow", bufferLog) &&
148         CheckAsanLog("WRITE of size 1", bufferLog) &&
149         CheckAsanLog("thread T0", bufferLog) &&
150         CheckAsanLog("[02]", bufferLog);
151     int checkRes = findAsanLog ? 1 : 0;
152     napi_value result = nullptr;
153     napi_create_int32(env, findAsanLog, &result);
154     return result;
155 }
156 
HeapBufferUnderflow(napi_env env,napi_callback_info info)157 __attribute__((optnone)) static napi_value HeapBufferUnderflow(napi_env env, napi_callback_info info)
158 {
159     char *x = (char*)malloc(NUMTEN * sizeof(char));
160     memset_s(x, NUMTEN * sizeof(char), 0, NUMTEN * sizeof(char));
161     int res = x[NUMNEGATIVEONE];
162     free(x);
163     std::string bufferLog = GetBuffer(getpid());
164     bool findAsanLog = CheckAsanLog("AddressSanitizer: heap-buffer-overflow", bufferLog) &&
165         CheckAsanLog("READ of size 1", bufferLog) &&
166         CheckAsanLog("thread T0", bufferLog) &&
167         CheckAsanLog("[fa]", bufferLog);
168     int checkRes = findAsanLog ? 1 : 0;
169     napi_value result = nullptr;
170     napi_create_int32(env, findAsanLog, &result);
171     return result;
172 }
173 
HeapUseAfterFree(napi_env env,napi_callback_info info)174 __attribute__((optnone)) static napi_value HeapUseAfterFree(napi_env env, napi_callback_info info)
175 {
176     char *x = (char*)malloc(NUMTEN * sizeof(char));
177     free(x);
178     char tmp = x[5];
179     std::string bufferLog = GetBuffer(getpid());
180     bool findAsanLog = CheckAsanLog("AddressSanitizer: heap-use-after-free", bufferLog) &&
181         CheckAsanLog("READ of size 1", bufferLog) &&
182         CheckAsanLog("thread T0", bufferLog) &&
183         CheckAsanLog("[fd]", bufferLog);
184     int checkRes = findAsanLog ? 1 : 0;
185     napi_value result = nullptr;
186     napi_create_int32(env, findAsanLog, &result);
187     return result;
188 }
189 
190 volatile int *g_p = nullptr;
StackUseAfterScope(napi_env env,napi_callback_info info)191 __attribute__((optnone)) static napi_value StackUseAfterScope(napi_env env, napi_callback_info info)
192 {
193     {
194         int x = 0;
195         g_p = &x;
196     }
197     *g_p = NUMFIVE;
198     std::string bufferLog = GetBuffer(getpid());
199     bool findAsanLog = CheckAsanLog("AddressSanitizer: stack-use-after-scope", bufferLog) &&
200         CheckAsanLog("WRITE of size 4", bufferLog) &&
201         CheckAsanLog("thread T0", bufferLog) &&
202         CheckAsanLog("'x' (line 193)", bufferLog) &&
203         CheckAsanLog("[f8]", bufferLog);
204     int checkRes = findAsanLog ? 1 : 0;
205     napi_value result = nullptr;
206     napi_create_int32(env, findAsanLog, &result);
207     return result;
208 }
209 
Fun()210 __attribute__((optnone)) int* Fun()
211 {
212     int a = 3;
213     return &a;
214 }
215 
StackUseAfterReturn(napi_env env,napi_callback_info info)216 __attribute__((optnone)) static napi_value StackUseAfterReturn(napi_env env, napi_callback_info info)
217 {
218     g_p = Fun();
219     int c = *g_p;
220     std::string bufferLog = GetBuffer(getpid());
221     bool findAsanLog = CheckAsanLog("AddressSanitizer: stack-use-after-return", bufferLog) &&
222         CheckAsanLog("READ of size 4", bufferLog) &&
223         CheckAsanLog("thread T0", bufferLog) &&
224         CheckAsanLog("'a' (line 211)", bufferLog) &&
225         CheckAsanLog("[f5]", bufferLog);
226     int checkRes = findAsanLog ? 1 : 0;
227     napi_value result = nullptr;
228     napi_create_int32(env, findAsanLog, &result);
229     return result;
230 }
231 
DoubleFree(napi_env env,napi_callback_info info)232 __attribute__((optnone)) static napi_value DoubleFree(napi_env env, napi_callback_info info)
233 {
234     char *x = (char*)malloc(NUMTEN * sizeof(char));
235     memset_s(x, NUMTEN * sizeof(char), 0, NUMTEN * sizeof(char));
236     int res = x[1];
237     free(x);
238     free(x);
239     std::string bufferLog = GetBuffer(getpid());
240     bool findAsanLog = CheckAsanLog("AddressSanitizer: attempting double-free", bufferLog) &&
241         CheckAsanLog("in thread T0", bufferLog);
242     int checkRes = findAsanLog ? 1 : 0;
243     napi_value result = nullptr;
244     napi_create_int32(env, findAsanLog, &result);
245     return result;
246 }
247 
WildFree(napi_env env,napi_callback_info info)248 __attribute__((optnone)) static napi_value WildFree(napi_env env, napi_callback_info info)
249 {
250     char *x = (char*)malloc(NUMTEN * sizeof(char));
251     memset_s(x, NUMTEN * sizeof(char), 0, NUMTEN * sizeof(char));
252     int res = x[NUMTEN];
253     free(x + NUMFIVE);
254     std::string bufferLog = GetBuffer(getpid());
255     bool findAsanLog = CheckAsanLog("AddressSanitizer: attempting free on address which was not malloc()", bufferLog) &&
256         CheckAsanLog("allocated by thread T0", bufferLog);
257     int checkRes = findAsanLog ? 1 : 0;
258     napi_value result = nullptr;
259     napi_create_int32(env, findAsanLog, &result);
260     return result;
261 }
262 
263 EXTERN_C_START
Init(napi_env env,napi_value exports)264 static napi_value Init(napi_env env, napi_value exports)
265 {
266     napi_property_descriptor desc[] = {
267         { "stackBufferOverflow", nullptr, StackBufferOverflow, nullptr, nullptr, nullptr, napi_default, nullptr },
268         { "stackBufferUnderflow", nullptr, StackBufferUnderflow, nullptr, nullptr, nullptr, napi_default, nullptr },
269         { "heapBufferOverflow", nullptr, HeapBufferOverflow, nullptr, nullptr, nullptr, napi_default, nullptr },
270         { "heapBufferUnderflow", nullptr, HeapBufferUnderflow, nullptr, nullptr, nullptr, napi_default, nullptr },
271         { "heapUseAfterFree", nullptr, HeapUseAfterFree, nullptr, nullptr, nullptr, napi_default, nullptr },
272         { "stackUseAfterScope", nullptr, StackUseAfterScope, nullptr, nullptr, nullptr, napi_default, nullptr },
273         { "stackUseAfterReturn", nullptr, StackUseAfterReturn, nullptr, nullptr, nullptr, napi_default, nullptr },
274         { "doubleFree", nullptr, DoubleFree, nullptr, nullptr, nullptr, napi_default, nullptr },
275         { "wildFree", nullptr, WildFree, nullptr, nullptr, nullptr, napi_default, nullptr }
276     };
277     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
278     return exports;
279 }
280 EXTERN_C_END
281 
282 static napi_module demoModule = {
283     .nm_version = 1,
284     .nm_flags = 0,
285     .nm_filename = nullptr,
286     .nm_register_func = Init,
287     .nm_modname = "entry",
288     .nm_priv = ((void*)0),
289     .reserved = { 0 },
290 };
291 
RegisterEntryModule(void)292 extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
293 {
294     napi_module_register(&demoModule);
295 }
296