1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
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 "napi/native_api.h"
17 #include "common/native_common.h"
18 #include <cerrno>
19 #include <cstdio>
20 #include <cstring>
21 #include <fcntl.h>
22 #include <ifaddrs.h>
23 #include <js_native_api.h>
24 #include <js_native_api_types.h>
25 #include <malloc.h>
26 #include <net/if.h>
27 #include <node_api.h>
28 #include <sys/inotify.h>
29 #include <sys/mman.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32 #include <utmp.h>
33 #include <uv.h>
34 
35 #define PARAM_1 1
36 #define PARAM_2 2
37 #define PARAM_0777 0777
38 #define PARAM_UNNORMAL (-1)
39 #define RETURN_0 0
40 #define FAILD (-1)
41 #define ERRON_0 0
42 #define SIZE_10 10
43 #define SIZE_32 32
44 #define SIZE_0x0 0x0
45 #define SIZE_4096 4096
46 #define SIZE_100 100
47 #define SIZE_4096 4096
48 #define SIZE_0L 0L
49 #define SIZE_8 8
50 #define SIZE_8192 8192
51 #define NO_ERR 0
52 #define SUCCESS 1
53 #define FAIL (-1)
54 #define PARAM_0 0
55 #define TEN 10
56 #define STATERROR (-100)
57 #define OPENERROR (-99)
58 #define MMAPERROR (-98)
59 #define TEST_SIZE 4096
60 #define TEST_M_SIZE 1024
61 #define TEST_M_NEW_SIZE 2048
62 #define TEST_MS_SIZE 1024
63 #define TEST_MODE 0666
64 #define TEST_FLAG 0777
65 #include <sys/mman.h>
66 
MemfdCreate(napi_env env, napi_callback_info info)67 static napi_value MemfdCreate(napi_env env, napi_callback_info info)
68 {
69     char tmpfile[] = "/data/storage/el2/base/files/memfd_create_0100.txt";
70     int retVal = PARAM_0;
71     int fd = memfd_create(tmpfile, PARAM_0);
72     if (fd != PARAM_UNNORMAL) {
73         size_t cnt = write(fd, tmpfile, strlen(tmpfile));
74         if (cnt == strlen(tmpfile)) {
75             retVal = PARAM_0;
76         } else {
77             retVal = FAIL;
78         }
79         close(fd);
80     }
81     napi_value result = nullptr;
82     napi_create_int32(env, retVal, &result);
83     return result;
84 }
Mincore(napi_env env, napi_callback_info info)85 static napi_value Mincore(napi_env env, napi_callback_info info)
86 {
87     size_t stSize = PARAM_1;
88     int retVal = PARAM_0;
89     napi_value result = nullptr;
90     char tmpfile[] = "/data/storage/el2/base/files/memfd_create_0100.txt";
91     int fd = open(tmpfile, O_CREAT | O_RDWR, PARAM_0777);
92     if (fd == PARAM_UNNORMAL) {
93         perror("open failed");
94         napi_create_int32(env, OPENERROR, &result);
95         return result;
96     }
97     void *start = mmap(nullptr, stSize, PROT_READ, MAP_PRIVATE, fd, PARAM_0);
98     close(fd);
99     if (!start) {
100         napi_create_int32(env, MMAPERROR, &result);
101         return result;
102     }
103     unsigned char vec[TEST_SIZE];
104     memset(vec, SIZE_0x0, sizeof(vec));
105     retVal = mincore(start, TEST_SIZE, vec);
106     munmap(start, stSize);
107     remove(tmpfile);
108     napi_create_int32(env, retVal, &result);
109     return result;
110 }
111 
112 #define PAGE_SIZE 256
Mmap(napi_env env, napi_callback_info info)113 static napi_value Mmap(napi_env env, napi_callback_info info)
114 {
115     char ptr[] = "/data/storage/el2/base/files/mmap0100.txt";
116     int retVal = PARAM_0;
117     int fd;
118     void *start;
119     FILE *fptr = fopen(ptr, "w+");
120     NAPI_ASSERT(env, fptr != nullptr, "Mmap fopen Error");
121     struct stat statbuff;
122     fwrite(ptr, sizeof(char), strlen(ptr), fptr);
123     fseek(fptr, SIZE_0L, SEEK_SET);
124     stat(ptr, &statbuff);
125     fclose(fptr);
126     fd = open(ptr, O_RDWR | O_CREAT, TEST_FLAG);
127     start = mmap(nullptr, statbuff.st_size, PROT_READ, MAP_PRIVATE, fd, PARAM_0);
128     if (start == MAP_FAILED) {
129         retVal = FAIL;
130     } else {
131         retVal = PARAM_0;
132     }
133     munmap(start, statbuff.st_size);
134     close(fd);
135     remove(ptr);
136     fptr = nullptr;
137     napi_value result = nullptr;
138     napi_create_int32(env, retVal, &result);
139     return result;
140 }
141 
MProtect(napi_env env, napi_callback_info info)142 static napi_value MProtect(napi_env env, napi_callback_info info)
143 {
144     int retVal = FAIL;
145     size_t align = getpagesize();
146     void *buffer = memalign(align, SIZE_8 * align);
147     int ret = mprotect(buffer, getpagesize(), PROT_READ);
148     retVal = ret;
149     napi_value result = nullptr;
150     napi_create_int32(env, retVal, &result);
151     return result;
152 }
MreMap(napi_env env, napi_callback_info info)153 static napi_value MreMap(napi_env env, napi_callback_info info)
154 {
155     int retVal = FAIL;
156     char tmpfile[] = "/data/storage/el2/base/files/memfd_create_0100.txt";
157     int fd = open(tmpfile, O_CREAT | O_RDWR, PARAM_0777);
158     void *map = mmap(nullptr, TEST_M_SIZE, PROT_READ, MAP_SHARED, fd, PARAM_0);
159     void *map_new = mremap(map, TEST_M_SIZE, TEST_M_NEW_SIZE, MREMAP_MAYMOVE);
160 
161     munmap(map_new, TEST_M_NEW_SIZE);
162     close(fd);
163     if (!map_new) {
164         retVal = PARAM_1;
165     } else {
166         retVal = PARAM_0;
167     }
168     napi_value result = nullptr;
169     napi_create_int32(env, retVal, &result);
170     return result;
171 }
MSync(napi_env env, napi_callback_info info)172 static napi_value MSync(napi_env env, napi_callback_info info)
173 {
174     int retVal = FAIL;
175     char tmpfile[] = "/data/storage/el2/base/files/memfd_creat0100.txt";
176     int fd = open(tmpfile, O_CREAT | O_RDWR, PARAM_0777);
177     void *map = mmap(nullptr, TEST_MS_SIZE, PROT_READ, MAP_SHARED, fd, PARAM_0);
178     int ret = msync(map, TEST_MS_SIZE, MS_ASYNC);
179     munmap(map, TEST_MS_SIZE);
180     close(fd);
181     retVal = ret;
182     napi_value result = nullptr;
183     napi_create_int32(env, retVal, &result);
184     return result;
185 }
186 
MUnLock(napi_env env, napi_callback_info info)187 static napi_value MUnLock(napi_env env, napi_callback_info info)
188 {
189     int retVal = FAIL;
190     char *memory = static_cast<char *>(malloc(TEST_SIZE));
191     memset(memory, SIZE_0x0, TEST_SIZE);
192     int ret = mlock(memory, TEST_SIZE);
193     ret = munlock(memory, TEST_SIZE);
194     free(memory);
195     memory = nullptr;
196     retVal = ret;
197     napi_value result = nullptr;
198     napi_create_int32(env, retVal, &result);
199     return result;
200 }
201 
MUnLockAll(napi_env env, napi_callback_info info)202 static napi_value MUnLockAll(napi_env env, napi_callback_info info)
203 {
204     int ret = FAIL;
205     char *memory = static_cast<char *>(malloc(TEST_SIZE));
206     memset(memory, '\0', TEST_SIZE);
207     mlockall(MCL_CURRENT);
208     ret = munlockall();
209     free(memory);
210     memory = nullptr;
211     napi_value result = nullptr;
212     napi_create_int32(env, ret, &result);
213     return result;
214 }
215 
MAdvise(napi_env env, napi_callback_info info)216 static napi_value MAdvise(napi_env env, napi_callback_info info)
217 {
218     size_t length = SIZE_4096;
219     char path[] = "/data/storage/el2/base/files/memfd_creat0100.txt";
220     if (access(path, F_OK) == PARAM_0) {
221         remove(path);
222     }
223     int fd = open(path, O_RDWR | O_CREAT, TEST_MODE);
224     void *ptr = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PARAM_0);
225     int ret = madvise(ptr, length, MADV_NORMAL);
226     munmap(ptr, length);
227     close(fd);
228     if (access(path, F_OK) == PARAM_0) {
229         remove(path);
230     }
231     napi_value result = nullptr;
232     napi_create_int32(env, ret, &result);
233     return result;
234 }
235 
MLock(napi_env env, napi_callback_info info)236 static napi_value MLock(napi_env env, napi_callback_info info)
237 {
238     errno = ERRON_0;
239     size_t argc = PARAM_1;
240     napi_value args[1] = {nullptr};
241     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
242     int change;
243     size_t lenV = SIZE_32;
244     char *mem = static_cast<char *>(malloc(sizeof(char) * lenV));
245     int ret;
246     napi_get_value_int32(env, args[0], &change);
247     if (change == PARAM_0) {
248         ret = mlock(mem, lenV);
249         munlock(mem, lenV);
250     } else {
251         ret = mlock(nullptr, lenV);
252     }
253 
254     free(mem);
255 
256     napi_value result;
257     napi_create_int32(env, ret, &result);
258     return result;
259 }
260 
MLock2(napi_env env, napi_callback_info info)261 static napi_value MLock2(napi_env env, napi_callback_info info)
262 {
263     errno = ERRON_0;
264     size_t argc = PARAM_1;
265     napi_value args[1] = {nullptr};
266     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
267     int change;
268     size_t lenV = SIZE_32;
269     char *mem = static_cast<char *>(malloc(sizeof(char) * lenV));
270     int ret;
271     napi_get_value_int32(env, args[0], &change);
272     if (change == PARAM_0) {
273         ret = mlock2(mem, lenV, PARAM_0);
274         munlock(mem, lenV);
275     } else {
276         ret = mlock(nullptr, lenV);
277     }
278     free(mem);
279 
280     napi_value result;
281     napi_create_int32(env, ret, &result);
282     return result;
283 }
284 
MLockAll(napi_env env, napi_callback_info info)285 static napi_value MLockAll(napi_env env, napi_callback_info info)
286 {
287     errno = ERRON_0;
288     int ret;
289     ret = mlockall(MCL_FUTURE);
290     munlockall();
291     napi_value result;
292     napi_create_int32(env, ret, &result);
293     return result;
294 }
295 
Mmap64(napi_env env, napi_callback_info info)296 static napi_value Mmap64(napi_env env, napi_callback_info info)
297 {
298     int fd = open("/data/storage/el2/base/files/Fzl.txt", O_CREAT | O_RDWR, PARAM_0777);
299     void *pMap = (unsigned char *)mmap64(PARAM_0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PARAM_0);
300     napi_value result;
301     if (pMap == MAP_FAILED) {
302         napi_create_int32(env, PARAM_UNNORMAL, &result);
303     } else {
304         napi_create_int32(env, PARAM_0, &result);
305     }
306     close(fd);
307     return result;
308 }
Munmap(napi_env env, napi_callback_info info)309 static napi_value Munmap(napi_env env, napi_callback_info info)
310 {
311     size_t argc = PARAM_1;
312     napi_value args[1] = {nullptr};
313     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
314     double value;
315     napi_get_value_double(env, args[0], &value);
316     int fd = open("/data/storage/el2/base/files/test.txt", O_CREAT, PARAM_0777);
317     void *p = mmap(PARAM_0, value, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, fd, PARAM_0);
318     napi_value result = nullptr;
319     napi_create_double(env, munmap(p, value), &result);
320     close(fd);
321     return result;
322 }
RemapFilePages(napi_env env, napi_callback_info info)323 static napi_value RemapFilePages(napi_env env, napi_callback_info info)
324 {
325     char path[] = "/data/storage/el2/base/files/testRemapFilePages.txt";
326     char text[] = "test remap_file_pages";
327     int len = strlen(text);
328     size_t argc = PARAM_1;
329     napi_value args[1] = {nullptr};
330     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
331     int param;
332     napi_get_value_int32(env, args[0], &param);
333 
334     int ret;
335     int fd = open(path, O_CREAT | O_RDWR, PARAM_0777);
336     write(fd, text, len);
337     lseek(fd, PARAM_0, SEEK_SET);
338     char *start = static_cast<char *>(mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PARAM_0));
339     if (param == PARAM_0) {
340         ret = remap_file_pages(start, TEST_SIZE, PARAM_0, PARAM_1, MAP_SHARED);
341     } else {
342         ret = remap_file_pages(start, len, PARAM_0, PARAM_1, MAP_SHARED);
343     }
344     munmap(start, len);
345     close(fd);
346     remove(path);
347 
348     napi_value result = nullptr;
349     napi_create_int32(env, ret, &result);
350     return result;
351 }
352 
353 EXTERN_C_START
Init(napi_env env, napi_value exports)354 static napi_value Init(napi_env env, napi_value exports)
355 {
356     napi_property_descriptor desc[] = {
357         {"remapFilePages", nullptr, RemapFilePages, nullptr, nullptr, nullptr, napi_default, nullptr},
358         {"memfdCreate", nullptr, MemfdCreate, nullptr, nullptr, nullptr, napi_default, nullptr},
359         {"mincore", nullptr, Mincore, nullptr, nullptr, nullptr, napi_default, nullptr},
360         {"mmap", nullptr, Mmap, nullptr, nullptr, nullptr, napi_default, nullptr},
361         {"mProtect", nullptr, MProtect, nullptr, nullptr, nullptr, napi_default, nullptr},
362         {"mreMap", nullptr, MreMap, nullptr, nullptr, nullptr, napi_default, nullptr},
363         {"mSync", nullptr, MSync, nullptr, nullptr, nullptr, napi_default, nullptr},
364         {"mUnLock", nullptr, MUnLock, nullptr, nullptr, nullptr, napi_default, nullptr},
365         {"mUnLockAll", nullptr, MUnLockAll, nullptr, nullptr, nullptr, napi_default, nullptr},
366         {"mAdvise", nullptr, MAdvise, nullptr, nullptr, nullptr, napi_default, nullptr},
367         {"mLock", nullptr, MLock, nullptr, nullptr, nullptr, napi_default, nullptr},
368         {"mLock2", nullptr, MLock2, nullptr, nullptr, nullptr, napi_default, nullptr},
369         {"mLockAll", nullptr, MLockAll, nullptr, nullptr, nullptr, napi_default, nullptr},
370         {"munmap", nullptr, Munmap, nullptr, nullptr, nullptr, napi_default, nullptr},
371         {"mmap64", nullptr, Mmap64, nullptr, nullptr, nullptr, napi_default, nullptr},
372     };
373     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
374     return exports;
375 }
376 
377 EXTERN_C_END
378 
379 static napi_module demoModule = {
380     .nm_version = 1,
381     .nm_flags = 0,
382     .nm_filename = nullptr,
383     .nm_register_func = Init,
384     .nm_modname = "mman",
385     .nm_priv = ((void *)0),
386     .reserved = {0},
387 };
388 
RegisterEntryModule(void)389 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
390