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 <memory.h>
31 #include <csetjmp>
32 #include "securec.h"
33
34 #define PAGE_SIZE 4096
35
36 using namespace testing::ext;
37 using namespace std;
38
39 class MmapApiTest : 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 MmapApiTest::SetUp()
48 {
49 }
TearDown()50 void MmapApiTest::TearDown()
51 {
52 }
SetUpTestCase()53 void MmapApiTest::SetUpTestCase()
54 {
55 }
TearDownTestCase()56 void MmapApiTest::TearDownTestCase()
57 {
58 }
59
60 static int g_sigStarted = 0;
61
SigsegvHandler(int signum)62 static void SigsegvHandler(int signum)
63 {
64 if (g_sigStarted) {
65 g_sigStarted = 0;
66 } else {
67 std::cout << "case failed.\n" << std::endl;
68 ASSERT_TRUE(g_sigStarted != 0);
69 }
70 }
71
CreateFile()72 static void CreateFile()
73 {
74 FILE *file;
75 int ret = -1;
76 char *buffer = static_cast<char *>(malloc(PAGE_SIZE));
77 if (buffer != nullptr) {
78 ret = memset_s(buffer, PAGE_SIZE, 'a', PAGE_SIZE);
79 ASSERT_TRUE(ret == 0);
80 file = fopen("output_file.txt", "wb");
81 if (fwrite(buffer, 1, PAGE_SIZE, file) != PAGE_SIZE) {
82 std::cout << "Error fwrite file.\n" << std::endl;
83 ASSERT_TRUE(ret != 0);
84 }
85 fclose(file);
86 }
87 free(buffer);
88 }
89
90 /*
91 * @tc.number SUB_KERNEL_MEM_MAP_0100
92 * @tc.name MremapDontunmap001
93 * @tc.desc mremap use MREMAP_DONTUNMAP with old len == new len
94 */
95 HWTEST_F(MmapApiTest, MremapDontunmap001, Function | MediumTest | Level1)
96 {
97 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
98 ASSERT_TRUE(addr != MAP_FAILED);
99 void *fixAddr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
100 ASSERT_TRUE(fixAddr != MAP_FAILED);
101 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE, MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, fixAddr);
102 ASSERT_TRUE(newAddr != MAP_FAILED);
103 int ret = munmap(addr, PAGE_SIZE);
104 ASSERT_TRUE(ret == 0);
105 ret = munmap(fixAddr, PAGE_SIZE);
106 ASSERT_TRUE(ret == 0);
107 ret = munmap(newAddr, PAGE_SIZE);
108 ASSERT_TRUE(ret == 0);
109 addr = nullptr;
110 fixAddr = nullptr;
111 newAddr = nullptr;
112 }
113
114 /*
115 * @tc.number SUB_KERNEL_MEM_MAP_0200
116 * @tc.name MremapDontunmap002
117 * @tc.desc mremap use MREMAP_DONTUNMAP with MAP_SHARED
118 */
119 HWTEST_F(MmapApiTest, MremapDontunmap002, Function | MediumTest | Level2)
120 {
121 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
122 ASSERT_TRUE(addr != MAP_FAILED);
123 void *fixAddr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
124 ASSERT_TRUE(fixAddr != MAP_FAILED);
125 void *newAddr = mremap(fixAddr, PAGE_SIZE, PAGE_SIZE, MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, addr);
126 #ifdef DISPLAY_COMMUNITY
127 ASSERT_TRUE(newAddr == MAP_FAILED);
128 #else
129 ASSERT_TRUE(newAddr != MAP_FAILED);
130 #endif
131 int ret = munmap(addr, PAGE_SIZE);
132 ASSERT_TRUE(ret == 0);
133 ret = munmap(fixAddr, PAGE_SIZE);
134 ASSERT_TRUE(ret == 0);
135 addr = nullptr;
136 fixAddr = nullptr;
137 newAddr = nullptr;
138 }
139
140 /*
141 * @tc.number SUB_KERNEL_MEM_MAP_0300
142 * @tc.name MremapDontunmap003
143 * @tc.desc mremap use MREMAP_DONTUNMAP with old len != new len
144 */
145 HWTEST_F(MmapApiTest, MremapDontunmap003, Function | MediumTest | Level1)
146 {
147 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
148 ASSERT_TRUE(addr != MAP_FAILED);
149 void *fixAddr = mmap(nullptr, PAGE_SIZE * 2, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
150 ASSERT_TRUE(fixAddr != MAP_FAILED);
151 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE * 2, MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, fixAddr);
152 ASSERT_TRUE(newAddr == MAP_FAILED);
153 int ret = munmap(addr, PAGE_SIZE);
154 ASSERT_TRUE(ret == 0);
155 ret = munmap(fixAddr, PAGE_SIZE * 2);
156 ASSERT_TRUE(ret == 0);
157 addr = nullptr;
158 fixAddr = nullptr;
159 newAddr = nullptr;
160 }
161 /*
162 * @tc.number SUB_KERNEL_MEM_MAP_0400
163 * @tc.name MremapDontunmap004
164 * @tc.desc mremap use MREMAP_DONTUNMAP without MREMAP_MAYMOVE
165 */
166 HWTEST_F(MmapApiTest, MremapDontunmap004, Function | MediumTest | Level1)
167 {
168 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
169 ASSERT_TRUE(addr != MAP_FAILED);
170 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE, MREMAP_FIXED | MREMAP_DONTUNMAP);
171 ASSERT_TRUE(newAddr == MAP_FAILED);
172 int ret = munmap(addr, PAGE_SIZE);
173 ASSERT_TRUE(ret == 0);
174 addr = nullptr;
175 newAddr = nullptr;
176 }
177
178 /*
179 * @tc.number SUB_KERNEL_MEM_MAP_0500
180 * @tc.name MremapDontunmap005
181 * @tc.desc mremap use MREMAP_DONTUNMAP with MREMAP_MAYMOVE
182 */
183 HWTEST_F(MmapApiTest, MremapDontunmap005, Function | MediumTest | Level1)
184 {
185 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
186 ASSERT_TRUE(addr != MAP_FAILED);
187 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE, MREMAP_MAYMOVE | MREMAP_DONTUNMAP);
188 ASSERT_TRUE(newAddr != MAP_FAILED);
189 int ret = munmap(addr, PAGE_SIZE);
190 ASSERT_TRUE(ret == 0);
191 ret = munmap(newAddr, PAGE_SIZE);
192 ASSERT_TRUE(ret == 0);
193 addr = nullptr;
194 newAddr = nullptr;
195 }
196
197 /*
198 * @tc.number SUB_KERNEL_MEM_MAP_0800
199 * @tc.name MMAPShardValidate001
200 * @tc.desc mmap use MAP_SHARED_VALIDATE or MAP_SHARED with MAP_SYNC
201 */
202 HWTEST_F(MmapApiTest, MMAPShardValidate001, Function | MediumTest | Level1)
203 {
204 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON | MAP_SYNC, -1, 0);
205 ASSERT_TRUE(va != MAP_FAILED);
206 void *newVa = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED_VALIDATE | MAP_ANON | MAP_SYNC, -1, 0);
207 ASSERT_TRUE(newVa == MAP_FAILED);
208 int ret = munmap(va, PAGE_SIZE);
209 ASSERT_TRUE(ret == 0);
210 va = nullptr;
211 newVa = nullptr;
212 }
213
214 /*
215 * @tc.number SUB_KERNEL_MEM_MAP_0900
216 * @tc.name MMAPShardValidate002
217 * @tc.desc mmap use MAP_SHARED_VALIDATE with no error param
218 */
219 HWTEST_F(MmapApiTest, MMAPShardValidate002, Function | MediumTest | Level1)
220 {
221 CreateFile();
222 int fd = open("output_file.txt", O_RDWR);
223 ASSERT_TRUE(fd > 0);
224 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED_VALIDATE, fd, 0);
225 ASSERT_TRUE(va != MAP_FAILED);
226 int ret = munmap(va, PAGE_SIZE);
227 ASSERT_TRUE(ret == 0);
228 va = nullptr;
229 close(fd);
230 ret = unlink("output_file.txt");
231 ASSERT_TRUE(ret == 0);
232 }
233
234 /*
235 * @tc.number SUB_KERNEL_MEM_MAP_1000
236 * @tc.name MMAPNonBlock001
237 * @tc.desc mmap use MAP_NONBLOCK
238 */
239 HWTEST_F(MmapApiTest, MMAPNonBlock001, Function | MediumTest | Level1)
240 {
241 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_NONBLOCK, -1, 0);
242 ASSERT_TRUE(va != MAP_FAILED);
243 int ret = munmap(va, PAGE_SIZE);
244 ASSERT_TRUE(ret == 0);
245 va = nullptr;
246 }
247
248 /*
249 * @tc.number SUB_KERNEL_MEM_MAP_1400
250 * @tc.name MMAPGrownsDown001
251 * @tc.desc MAP_GROWSDONW when the pre-vregion is not MAP_GROWSDONW
252 */
253 HWTEST_F(MmapApiTest, MMAPGrownsDown001, Function | MediumTest | Level1)
254 {
255 const size_t lenGdGap = (2UL << 20);
256 const size_t lenLeftMap = 0x1000;
257 const size_t lenGd = 0x1000;
258 const size_t lenReserve = lenLeftMap + lenGdGap + lenGd;
259
260 char *addReserve = nullptr;
261 char *addrGd = nullptr;
262 int ret = -1;
263
264 addReserve = (char *)mmap(nullptr, lenReserve, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
265 ASSERT_TRUE(addReserve != MAP_FAILED);
266 void *addr1 = mmap(addReserve, lenLeftMap, PROT_READ, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
267 ASSERT_TRUE(addr1 != MAP_FAILED);
268 addrGd = (char *)mmap(addReserve + lenLeftMap + lenGdGap, lenGd, PROT_READ | PROT_WRITE,
269 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0);
270 ASSERT_TRUE(addrGd != MAP_FAILED);
271
272 g_sigStarted = 1;
273 struct sigaction sa;
274 sa.sa_handler = SigsegvHandler;
275 sigemptyset(&sa.sa_mask);
276 sa.sa_flags = 0;
277 ret = sigaction(SIGSEGV, &sa, nullptr);
278 ASSERT_TRUE(ret == 0);
279 int cpage = 256;
280 addrGd[cpage * -0x1000] = '1';
281 ret = munmap(addReserve, lenReserve);
282 ASSERT_TRUE(ret == 0);
283 ret = munmap(addr1, lenLeftMap);
284 ASSERT_TRUE(ret == 0);
285 ret = munmap(addrGd, lenGd);
286 ASSERT_TRUE(ret == 0);
287 addReserve = nullptr;
288 addr1 = nullptr;
289 addrGd = nullptr;
290 }
291
292 /*
293 * @tc.number SUB_KERNEL_MEM_MAP_1500
294 * @tc.name MMAPGrownsDown002
295 * @tc.desc mprotect use PROT_GROWSDONW
296 */
297 HWTEST_F(MmapApiTest, MMAPGrownsDown002, Function | MediumTest | Level1)
298 {
299 const size_t lenGdGap = (2UL << 20);
300 const size_t lenLeftMap = 0x1000;
301 const size_t lenGd = 0x1000;
302 const size_t lenReserve = lenLeftMap + lenGdGap + lenGd;
303 char *addReserve = nullptr;
304 char *addrGd = nullptr;
305 int ret = -1;
306
307 addReserve = (char *)mmap(nullptr, lenReserve, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
308 ASSERT_TRUE(addReserve != MAP_FAILED);
309 void *addr1 = mmap(addReserve, lenLeftMap, PROT_READ, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
310 ASSERT_TRUE(addr1 != MAP_FAILED);
311 addrGd = (char *)mmap(addReserve + lenLeftMap + lenGdGap, lenGd, PROT_READ,
312 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0);
313 ASSERT_TRUE(addrGd != MAP_FAILED);
314
315 ret = mprotect(addrGd, lenGd, PROT_READ | PROT_WRITE | PROT_GROWSDOWN);
316 ASSERT_TRUE(ret == 0);
317 g_sigStarted = 1;
318 struct sigaction sa;
319 sa.sa_handler = SigsegvHandler;
320 sigemptyset(&sa.sa_mask);
321 sa.sa_flags = 0;
322 ret = sigaction(SIGSEGV, &sa, nullptr);
323 ASSERT_TRUE(ret == 0);
324 int cpage = 256;
325 addrGd[cpage * -0x1000] = '1';
326 ret = munmap(addReserve, lenReserve);
327 ASSERT_TRUE(ret == 0);
328 ret = munmap(addr1, lenLeftMap);
329 ASSERT_TRUE(ret == 0);
330 ret = munmap(addrGd, lenGd);
331 ASSERT_TRUE(ret == 0);
332 addReserve = nullptr;
333 addr1 = nullptr;
334 addrGd = nullptr;
335 }
336
337 /*
338 * @tc.number SUB_KERNEL_MEM_MAP_1600
339 * @tc.name MMAPGrownsDown003
340 * @tc.desc MAP_GROWSDONW when MAP_SHARED
341 */
342 HWTEST_F(MmapApiTest, MMAPGrownsDown003, Function | MediumTest | Level1)
343 {
344 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED | MAP_GROWSDOWN, -1, 0);
345 ASSERT_TRUE(va == MAP_FAILED);
346 va = nullptr;
347 }
348
349 /*
350 * @tc.number SUB_KERNEL_MEM_MAP_1700
351 * @tc.name MMAPGrownsDown004
352 * @tc.desc MAP_GROWSDONW when the pre-vregion is MAP_GROWSDONW
353 */
354 HWTEST_F(MmapApiTest, MMAPGrownsDown004, Function | MediumTest | Level1)
355 {
356 const size_t lenGd1 = 0x2000;
357 const size_t lenGd2 = 0x2000;
358 const size_t lenReserve = 0x1000 * 6;
359
360 char *addReserve = nullptr;
361 char *addrGd1 = nullptr;
362 char *addrGd2 = nullptr;
363 int ret = -1;
364
365 addReserve = (char *)mmap(nullptr, lenReserve, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
366 ASSERT_TRUE(addReserve != MAP_FAILED);
367 addrGd1 = (char *)mmap(addReserve, lenGd1, PROT_READ | PROT_WRITE,
368 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0);
369 ASSERT_TRUE(addrGd1 != MAP_FAILED);
370 addrGd2 = (char *)mmap(addReserve + (lenReserve - lenGd2), lenGd2, PROT_READ | PROT_WRITE,
371 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0);
372 ASSERT_TRUE(addrGd2 != MAP_FAILED);
373 g_sigStarted = 1;
374 struct sigaction sa;
375 sa.sa_handler = SigsegvHandler;
376 sigemptyset(&sa.sa_mask);
377 sa.sa_flags = 0;
378 ret = sigaction(SIGSEGV, &sa, nullptr);
379 ASSERT_TRUE(ret == 0);
380 addrGd2[-0x1000] = '1';
381 addrGd2[-0x2000] = '1';
382 ret = munmap(addReserve, lenReserve);
383 ASSERT_TRUE(ret == 0);
384 ret = munmap(addrGd1, lenGd1);
385 ASSERT_TRUE(ret == 0);
386 ret = munmap(addrGd2, lenGd2);
387 ASSERT_TRUE(ret == 0);
388 addReserve = nullptr;
389 addrGd1 = nullptr;
390 addrGd2 = nullptr;
391 }