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