1 /*
2 * Copyright (c) 2023-2024 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 <gtest/gtest.h>
17 #include <fcntl.h>
18 #include <cinttypes>
19 #include <climits>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <unistd.h>
23 #include <iomanip>
24 #include <iostream>
25 #include <string>
26 #include <vector>
27 #include <sys/mman.h>
28 #include <sys/utsname.h>
29 #include <string>
30 #include <regex>
31 #include "securec.h"
32
33 #define PAGE_SIZE 4096
34
35
36 using namespace testing::ext;
37 using namespace std;
38
39 class MadviseApiTest : public testing::Test {
40 public:
41 static void SetUpTestCase();
42 static void TearDownTestCase();
43 void SetUp();
44 void TearDown();
45 private:
46 };
SetUp()47 void MadviseApiTest::SetUp()
48 {
49 }
TearDown()50 void MadviseApiTest::TearDown()
51 {
52 }
SetUpTestCase()53 void MadviseApiTest::SetUpTestCase()
54 {
55 }
TearDownTestCase()56 void MadviseApiTest::TearDownTestCase()
57 {
58 }
59
CreateFile()60 static void CreateFile()
61 {
62 FILE *file;
63 int ret = -1;
64 char *buffer = static_cast<char *>(malloc(PAGE_SIZE));
65 if (buffer != nullptr) {
66 ret = memset_s(buffer, PAGE_SIZE, 'a', PAGE_SIZE);
67 ASSERT_TRUE(ret == 0);
68 file = fopen("output_file.txt", "wb");
69 if (fwrite(buffer, 1, PAGE_SIZE, file) != PAGE_SIZE) {
70 std::cout << "Error fwrite file.\n" << std::endl;
71 ASSERT_TRUE(ret != 0);
72 }
73 fclose(file);
74 }
75 free(buffer);
76 }
77
78 /*
79 * @tc.number SUB_KERNEL_MEM_MADVISE_0100
80 * @tc.name MadviseMadvCold001
81 * @tc.desc MADV_COLD with MAP_PRIVATE
82 */
83 HWTEST_F(MadviseApiTest, MadviseMadvCold001, Function | MediumTest | Level1)
84 {
85 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
86 ASSERT_TRUE(addr != MAP_FAILED);
87 int err = madvise(addr, PAGE_SIZE, MADV_COLD);
88 ASSERT_TRUE(err == 0);
89 int ret = munmap(addr, PAGE_SIZE);
90 ASSERT_TRUE(ret == 0);
91 addr = nullptr;
92 }
93
94 /*
95 * @tc.number SUB_KERNEL_MEM_MADVISE_0200
96 * @tc.name MadviseMadvCold002
97 * @tc.desc MADV_COLD with MAP_SHARED
98 */
99 HWTEST_F(MadviseApiTest, MadviseMadvCold002, Function | MediumTest | Level1)
100 {
101 CreateFile();
102 int fd = open("output_file.txt", O_RDWR);
103 ASSERT_TRUE(fd > 0);
104 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0);
105 ASSERT_TRUE(addr != MAP_FAILED);
106 int ret = madvise(addr, PAGE_SIZE, MADV_COLD);
107 ASSERT_TRUE(ret == 0);
108 ret = munmap(addr, PAGE_SIZE);
109 ASSERT_TRUE(ret == 0);
110 addr = nullptr;
111 close(fd);
112 ret = unlink("output_file.txt");
113 ASSERT_TRUE(ret == 0);
114 addr = nullptr;
115 }
116
117 /*
118 * @tc.number SUB_KERNEL_MEM_MADVISE_0300
119 * @tc.name MadviseMadvCold003
120 * @tc.desc MADV_COLD with mlock MAP_PRIVATE FILE
121 */
122 HWTEST_F(MadviseApiTest, MadviseMadvCold003, Function | MediumTest | Level1)
123 {
124 CreateFile();
125 int fd = open("output_file.txt", O_RDWR);
126 ASSERT_TRUE(fd > 0);
127 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0);
128 ASSERT_TRUE(addr != MAP_FAILED);
129 int ret = mlock(addr, PAGE_SIZE);
130 ASSERT_TRUE(ret == 0);
131 ret = madvise(addr, PAGE_SIZE, MADV_COLD);
132 ASSERT_TRUE(ret == -1);
133 ret = munmap(addr, PAGE_SIZE);
134 ASSERT_TRUE(ret == 0);
135 addr = nullptr;
136 close(fd);
137 ret = unlink("output_file.txt");
138 ASSERT_TRUE(ret == 0);
139 addr = nullptr;
140 }
141
142 /*
143 * @tc.number SUB_KERNEL_MEM_MADVISE_0400
144 * @tc.name MadviseMadvCold004
145 * @tc.desc MADV_COLD with mlock MAP_PRIVATE anon
146 */
147 HWTEST_F(MadviseApiTest, MadviseMadvCold004, Function | MediumTest | Level1)
148 {
149 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
150 ASSERT_TRUE(addr != MAP_FAILED);
151 int ret = mlock(addr, PAGE_SIZE);
152 ASSERT_TRUE(ret == 0);
153 ret = madvise(addr, PAGE_SIZE, MADV_COLD);
154 ASSERT_TRUE(ret == -1);
155 ret = munmap(addr, PAGE_SIZE);
156 ASSERT_TRUE(ret == 0);
157 addr = nullptr;
158 }
159
160 /*
161 * @tc.number SUB_KERNEL_MEM_MADVISE_0500
162 * @tc.name MadviseMadvPageOut001
163 * @tc.desc MADV_PAGEOUT with MAP_PRIVATE anon
164 */
165 HWTEST_F(MadviseApiTest, MadviseMadvPageOut001, Function | MediumTest | Level1)
166 {
167 int ret = -1;
168 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
169 ASSERT_TRUE(addr != MAP_FAILED);
170 ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE);
171 ASSERT_TRUE(ret == 0);
172 ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT);
173 ASSERT_TRUE(ret == 0);
174 ret = munmap(addr, PAGE_SIZE);
175 ASSERT_TRUE(ret == 0);
176 addr = nullptr;
177 }
178
179 /*
180 * @tc.number SUB_KERNEL_MEM_MADVISE_0600
181 * @tc.name MadviseMadvPageOut002
182 * @tc.desc MADV_PAGEOUT with MAP_SHARED FILE
183 */
184 HWTEST_F(MadviseApiTest, MadviseMadvPageOut002, Function | MediumTest | Level1)
185 {
186 CreateFile();
187 int fd = open("output_file.txt", O_RDWR);
188 ASSERT_TRUE(fd > 0);
189 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0);
190 ASSERT_TRUE(addr != MAP_FAILED);
191 int ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE);
192 ASSERT_TRUE(ret == 0);
193 ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT);
194 ASSERT_TRUE(ret == 0);
195 ret = munmap(addr, PAGE_SIZE);
196 ASSERT_TRUE(ret == 0);
197 close(fd);
198 ret = unlink("output_file.txt");
199 ASSERT_TRUE(ret == 0);
200 addr = nullptr;
201 }
202
203 /*
204 * @tc.number SUB_KERNEL_MEM_MADVISE_0700
205 * @tc.name MadviseMadvPageOut003
206 * @tc.desc MADV_PAGEOUT with mlock MAP_SHARED FILE
207 */
208 HWTEST_F(MadviseApiTest, MadviseMadvPageOut003, Function | MediumTest | Level1)
209 {
210 CreateFile();
211 int fd = open("output_file.txt", O_RDWR);
212 ASSERT_TRUE(fd > 0);
213 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0);
214 ASSERT_TRUE(addr != MAP_FAILED);
215 int ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE);
216 ASSERT_TRUE(ret == 0);
217 ret = mlock(addr, PAGE_SIZE);
218 ASSERT_TRUE(ret == 0);
219 ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT);
220 ASSERT_TRUE(ret == -1);
221 ret = munmap(addr, PAGE_SIZE);
222 ASSERT_TRUE(ret == 0);
223 close(fd);
224 ret = unlink("output_file.txt");
225 ASSERT_TRUE(ret == 0);
226 addr = nullptr;
227 }
228
229 /*
230 * @tc.number SUB_KERNEL_MEM_MADVISE_0800
231 * @tc.name MadviseMadvPageOut004
232 * @tc.desc MADV_PAGEOUT with mlock MAP_PRIVATE anon
233 */
234 HWTEST_F(MadviseApiTest, MadviseMadvPageOut004, Function | MediumTest | Level1)
235 {
236 int ret = -2;
237 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
238 ASSERT_TRUE(addr != MAP_FAILED);
239 ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE);
240 ASSERT_TRUE(ret == 0);
241 ret = mlock(addr, PAGE_SIZE);
242 ASSERT_TRUE(ret == 0);
243 ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT);
244 ASSERT_TRUE(ret == -1);
245 ret = munmap(addr, PAGE_SIZE);
246 ASSERT_TRUE(ret == 0);
247 addr = nullptr;
248 }
249
250 /*
251 * @tc.number SUB_KERNEL_MEM_MADVISE_0900
252 * @tc.name MadviseMadvWipeOnFork001
253 * @tc.desc MADV_WIPEONFORK with MAP_PRIVATE anon
254 */
255 HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork001, Function | MediumTest | Level1)
256 {
257 int status = 0;
258 char *addr = static_cast<char*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE,
259 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
260 ASSERT_TRUE(addr != MAP_FAILED);
261 *addr = 'A';
262 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK);
263 ASSERT_TRUE(err == 0);
264 pid_t pid = fork();
265 ASSERT_TRUE(pid >= 0);
266 if (pid == 0)
267 {
268 ASSERT_TRUE(*addr == 0);
269 exit(0);
270 } else {
271 ASSERT_TRUE(*addr == 'A');
272 waitpid(0, &status, 0);
273 }
274 int ret = munmap(addr, PAGE_SIZE);
275 ASSERT_TRUE(ret == 0);
276 addr = nullptr;
277 }
278
279 /*
280 * @tc.number SUB_KERNEL_MEM_MADVISE_1000
281 * @tc.name MadviseMadvWipeOnFork002
282 * @tc.desc MADV_WIPEONFORK with MAP_SHARED
283 */
284 HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork002, Function | MediumTest | Level1)
285 {
286 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
287 ASSERT_TRUE(addr != MAP_FAILED);
288 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK);
289 ASSERT_TRUE(err == -1);
290 int ret = munmap(addr, PAGE_SIZE);
291 ASSERT_TRUE(ret == 0);
292 addr = nullptr;
293 }
294
295 /*
296 * @tc.number SUB_KERNEL_MEM_MADVISE_1100
297 * @tc.name MadviseMadvWipeOnFork003
298 * @tc.desc MADV_KEEPONFORK after MADV_WIPEONFORK
299 */
300 HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork003, Function | MediumTest | Level1)
301 {
302 int status = 0;
303 char *addr = static_cast<char*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE,
304 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
305 ASSERT_TRUE(addr != MAP_FAILED);
306 *addr = 'A';
307 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK);
308 ASSERT_TRUE(err == 0);
309 err = madvise(addr, PAGE_SIZE, MADV_KEEPONFORK);
310 ASSERT_TRUE(err == 0);
311 pid_t pid = fork();
312 ASSERT_TRUE(pid >= 0);
313 if (pid == 0)
314 {
315 ASSERT_TRUE(*addr == 'A');
316 exit(0);
317 } else {
318 ASSERT_TRUE(*addr == 'A');
319 waitpid(0, &status, 0);
320 }
321 int ret = munmap(addr, PAGE_SIZE);
322 ASSERT_TRUE(ret == 0);
323 addr = nullptr;
324 }
325
326 /*
327 * @tc.number SUB_KERNEL_MEM_MADVISE_1200
328 * @tc.name MadviseMadvWipeOnFork004
329 * @tc.desc next vregion is no MADV_WIPEONFORK
330 */
331 HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork004, Function | MediumTest | Level1)
332 {
333 int status = 0;
334 char *addr = static_cast<char*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE,
335 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
336 ASSERT_TRUE(addr != MAP_FAILED);
337 char *nextAddr = static_cast<char*>(mmap(addr, PAGE_SIZE, PROT_READ | PROT_WRITE,
338 MAP_ANONYMOUS | MAP_PRIVATE, -1, PAGE_SIZE));
339 ASSERT_TRUE(nextAddr != MAP_FAILED);
340 *addr = 'A';
341 *nextAddr = 'B';
342 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK);
343 ASSERT_TRUE(err == 0);
344 pid_t pid = fork();
345 ASSERT_TRUE(pid >= 0);
346 if (pid == 0)
347 {
348 ASSERT_TRUE(*addr == 0);
349 ASSERT_TRUE(*nextAddr == 'B');
350 exit(0);
351 } else {
352 ASSERT_TRUE(*addr == 'A');
353 ASSERT_TRUE(*nextAddr == 'B');
354 waitpid(0, &status, 0);
355 }
356 int ret = munmap(addr, PAGE_SIZE);
357 ASSERT_TRUE(ret == 0);
358 ret = munmap(nextAddr, PAGE_SIZE);
359 ASSERT_TRUE(ret == 0);
360 addr = nullptr;
361 nextAddr = nullptr;
362 }
363
364 /*
365 * @tc.number SUB_KERNEL_MEM_MADVISE_1300
366 * @tc.name MadviseMadvWipeOnFork005
367 * @tc.desc next vregion is MADV_WIPEONFORK
368 */
369 HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork005, Function | MediumTest | Level1)
370 {
371 int status = 0;
372 char *addr = static_cast<char*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE,
373 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
374 ASSERT_TRUE(addr != MAP_FAILED);
375 char *nextAddr = static_cast<char*>(mmap(addr, PAGE_SIZE, PROT_READ | PROT_WRITE,
376 MAP_ANONYMOUS | MAP_PRIVATE, -1, PAGE_SIZE));
377 ASSERT_TRUE(nextAddr != MAP_FAILED);
378 *addr = 'A';
379 *nextAddr = 'B';
380 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK);
381 ASSERT_TRUE(err == 0);
382 err = madvise(nextAddr, PAGE_SIZE, MADV_WIPEONFORK);
383 ASSERT_TRUE(err == 0);
384 pid_t pid = fork();
385 ASSERT_TRUE(pid >= 0);
386 if (pid == 0)
387 {
388 ASSERT_TRUE(*addr == 0);
389 ASSERT_TRUE(*nextAddr == 0);
390 exit(0);
391 } else {
392 ASSERT_TRUE(*addr == 'A');
393 ASSERT_TRUE(*nextAddr == 'B');
394 waitpid(0, &status, 0);
395 }
396 int ret = munmap(addr, PAGE_SIZE);
397 ASSERT_TRUE(ret == 0);
398 ret = munmap(nextAddr, PAGE_SIZE);
399 ASSERT_TRUE(ret == 0);
400 addr = nullptr;
401 nextAddr = nullptr;
402 }
403
404 /*
405 * @tc.number SUB_KERNEL_MEM_MADVISE_1400
406 * @tc.name MadviseMadvWipeOnFork006
407 * @tc.desc next vregion is MADV_KEEPONFORK
408 */
409 HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork006, Function | MediumTest | Level1)
410 {
411 int status = 0;
412 char *addr = static_cast<char*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE,
413 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
414 ASSERT_TRUE(addr != MAP_FAILED);
415 char *nextAddr = static_cast<char*>(mmap(addr, PAGE_SIZE, PROT_READ | PROT_WRITE,
416 MAP_ANONYMOUS | MAP_PRIVATE, -1, PAGE_SIZE));
417 ASSERT_TRUE(nextAddr != MAP_FAILED);
418 *addr = 'A';
419 *nextAddr = 'B';
420 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK);
421 ASSERT_TRUE(err == 0);
422 err = madvise(nextAddr, PAGE_SIZE, MADV_WIPEONFORK);
423 ASSERT_TRUE(err == 0);
424 err = madvise(addr, PAGE_SIZE, MADV_KEEPONFORK);
425 ASSERT_TRUE(err == 0);
426 err = madvise(nextAddr, PAGE_SIZE, MADV_KEEPONFORK);
427 ASSERT_TRUE(err == 0);
428 pid_t pid = fork();
429 ASSERT_TRUE(pid >= 0);
430 if (pid == 0)
431 {
432 ASSERT_TRUE(*addr == 'A');
433 ASSERT_TRUE(*nextAddr == 'B');
434 exit(0);
435 } else {
436 ASSERT_TRUE(*addr == 'A');
437 ASSERT_TRUE(*nextAddr == 'B');
438 waitpid(0, &status, 0);
439 }
440 int ret = munmap(addr, PAGE_SIZE);
441 ASSERT_TRUE(ret == 0);
442 ret = munmap(nextAddr, PAGE_SIZE);
443 ASSERT_TRUE(ret == 0);
444 addr = nullptr;
445 nextAddr = nullptr;
446 }