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 */
HWTEST_F(MmapApiTest, MremapDontunmap001, Function | MediumTest | Level1)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 */
HWTEST_F(MmapApiTest, MremapDontunmap002, Function | MediumTest | Level2)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 ASSERT_TRUE(newAddr != MAP_FAILED);
127 int ret = munmap(addr, PAGE_SIZE);
128 ASSERT_TRUE(ret == 0);
129 ret = munmap(fixAddr, PAGE_SIZE);
130 ASSERT_TRUE(ret == 0);
131 ret = munmap(newAddr, PAGE_SIZE);
132 ASSERT_TRUE(ret == 0);
133 addr = nullptr;
134 fixAddr = nullptr;
135 newAddr = nullptr;
136 }
137
138 /*
139 * @tc.number SUB_KERNEL_MEM_MAP_0300
140 * @tc.name MremapDontunmap003
141 * @tc.desc mremap use MREMAP_DONTUNMAP with old len != new len
142 */
HWTEST_F(MmapApiTest, MremapDontunmap003, Function | MediumTest | Level1)143 HWTEST_F(MmapApiTest, MremapDontunmap003, Function | MediumTest | Level1)
144 {
145 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
146 ASSERT_TRUE(addr != MAP_FAILED);
147 void *fixAddr = mmap(nullptr, PAGE_SIZE * 2, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
148 ASSERT_TRUE(fixAddr != MAP_FAILED);
149 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE * 2, MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, fixAddr);
150 ASSERT_TRUE(newAddr == MAP_FAILED);
151 int ret = munmap(addr, PAGE_SIZE);
152 ASSERT_TRUE(ret == 0);
153 ret = munmap(fixAddr, PAGE_SIZE * 2);
154 ASSERT_TRUE(ret == 0);
155 addr = nullptr;
156 fixAddr = nullptr;
157 newAddr = nullptr;
158 }
159 /*
160 * @tc.number SUB_KERNEL_MEM_MAP_0400
161 * @tc.name MremapDontunmap004
162 * @tc.desc mremap use MREMAP_DONTUNMAP without MREMAP_MAYMOVE
163 */
HWTEST_F(MmapApiTest, MremapDontunmap004, Function | MediumTest | Level1)164 HWTEST_F(MmapApiTest, MremapDontunmap004, Function | MediumTest | Level1)
165 {
166 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
167 ASSERT_TRUE(addr != MAP_FAILED);
168 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE, MREMAP_FIXED | MREMAP_DONTUNMAP);
169 ASSERT_TRUE(newAddr == MAP_FAILED);
170 int ret = munmap(addr, PAGE_SIZE);
171 ASSERT_TRUE(ret == 0);
172 addr = nullptr;
173 newAddr = nullptr;
174 }
175
176 /*
177 * @tc.number SUB_KERNEL_MEM_MAP_0500
178 * @tc.name MremapDontunmap005
179 * @tc.desc mremap use MREMAP_DONTUNMAP with MREMAP_MAYMOVE
180 */
HWTEST_F(MmapApiTest, MremapDontunmap005, Function | MediumTest | Level1)181 HWTEST_F(MmapApiTest, MremapDontunmap005, Function | MediumTest | Level1)
182 {
183 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
184 ASSERT_TRUE(addr != MAP_FAILED);
185 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE, MREMAP_MAYMOVE | MREMAP_DONTUNMAP);
186 ASSERT_TRUE(newAddr != MAP_FAILED);
187 int ret = munmap(addr, PAGE_SIZE);
188 ASSERT_TRUE(ret == 0);
189 ret = munmap(newAddr, PAGE_SIZE);
190 ASSERT_TRUE(ret == 0);
191 addr = nullptr;
192 newAddr = nullptr;
193 }
194
195 /*
196 * @tc.number SUB_KERNEL_MEM_MAP_0800
197 * @tc.name MMAPShardValidate001
198 * @tc.desc mmap use MAP_SHARED_VALIDATE or MAP_SHARED with MAP_SYNC
199 */
HWTEST_F(MmapApiTest, MMAPShardValidate001, Function | MediumTest | Level1)200 HWTEST_F(MmapApiTest, MMAPShardValidate001, Function | MediumTest | Level1)
201 {
202 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON | MAP_SYNC, -1, 0);
203 ASSERT_TRUE(va != MAP_FAILED);
204 void *newVa = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED_VALIDATE | MAP_ANON | MAP_SYNC, -1, 0);
205 ASSERT_TRUE(newVa == MAP_FAILED);
206 int ret = munmap(va, PAGE_SIZE);
207 ASSERT_TRUE(ret == 0);
208 va = nullptr;
209 newVa = nullptr;
210 }
211
212 /*
213 * @tc.number SUB_KERNEL_MEM_MAP_0900
214 * @tc.name MMAPShardValidate002
215 * @tc.desc mmap use MAP_SHARED_VALIDATE with no error param
216 */
HWTEST_F(MmapApiTest, MMAPShardValidate002, Function | MediumTest | Level1)217 HWTEST_F(MmapApiTest, MMAPShardValidate002, Function | MediumTest | Level1)
218 {
219 CreateFile();
220 int fd = open("output_file.txt", O_RDWR);
221 ASSERT_TRUE(fd > 0);
222 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED_VALIDATE, fd, 0);
223 ASSERT_TRUE(va != MAP_FAILED);
224 int ret = munmap(va, PAGE_SIZE);
225 ASSERT_TRUE(ret == 0);
226 va = nullptr;
227 close(fd);
228 ret = unlink("output_file.txt");
229 ASSERT_TRUE(ret == 0);
230 }
231
232 /*
233 * @tc.number SUB_KERNEL_MEM_MAP_1000
234 * @tc.name MMAPNonBlock001
235 * @tc.desc mmap use MAP_NONBLOCK
236 */
HWTEST_F(MmapApiTest, MMAPNonBlock001, Function | MediumTest | Level1)237 HWTEST_F(MmapApiTest, MMAPNonBlock001, Function | MediumTest | Level1)
238 {
239 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_NONBLOCK, -1, 0);
240 ASSERT_TRUE(va != MAP_FAILED);
241 int ret = munmap(va, PAGE_SIZE);
242 ASSERT_TRUE(ret == 0);
243 va = nullptr;
244 }
245
246 /*
247 * @tc.number SUB_KERNEL_MEM_MAP_1400
248 * @tc.name MMAPGrownsDown001
249 * @tc.desc MAP_GROWSDONW when the pre-vregion is not MAP_GROWSDONW
250 */
HWTEST_F(MmapApiTest, MMAPGrownsDown001, Function | MediumTest | Level1)251 HWTEST_F(MmapApiTest, MMAPGrownsDown001, Function | MediumTest | Level1)
252 {
253 const size_t lenGdGap = (2UL << 20);
254 const size_t lenLeftMap = 0x1000;
255 const size_t lenGd = 0x1000;
256 const size_t lenReserve = lenLeftMap + lenGdGap + lenGd;
257
258 char *addReserve = nullptr;
259 char *addrGd = nullptr;
260 int ret = -1;
261
262 addReserve = (char *)mmap(nullptr, lenReserve, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
263 ASSERT_TRUE(addReserve != MAP_FAILED);
264 void *addr1 = mmap(addReserve, lenLeftMap, PROT_READ, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
265 ASSERT_TRUE(addr1 != MAP_FAILED);
266 addrGd = (char *)mmap(addReserve + lenLeftMap + lenGdGap, lenGd, PROT_READ | PROT_WRITE,
267 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0);
268 ASSERT_TRUE(addrGd != MAP_FAILED);
269
270 g_sigStarted = 1;
271 struct sigaction sa;
272 sa.sa_handler = SigsegvHandler;
273 sigemptyset(&sa.sa_mask);
274 sa.sa_flags = 0;
275 ret = sigaction(SIGSEGV, &sa, nullptr);
276 ASSERT_TRUE(ret == 0);
277 int cpage = 256;
278 addrGd[cpage * -0x1000] = '1';
279 ret = munmap(addReserve, lenReserve);
280 ASSERT_TRUE(ret == 0);
281 ret = munmap(addr1, lenLeftMap);
282 ASSERT_TRUE(ret == 0);
283 ret = munmap(addrGd, lenGd);
284 ASSERT_TRUE(ret == 0);
285 addReserve = nullptr;
286 addr1 = nullptr;
287 addrGd = nullptr;
288 }
289
290 /*
291 * @tc.number SUB_KERNEL_MEM_MAP_1500
292 * @tc.name MMAPGrownsDown002
293 * @tc.desc mprotect use PROT_GROWSDONW
294 */
HWTEST_F(MmapApiTest, MMAPGrownsDown002, Function | MediumTest | Level1)295 HWTEST_F(MmapApiTest, MMAPGrownsDown002, Function | MediumTest | Level1)
296 {
297 const size_t lenGdGap = (2UL << 20);
298 const size_t lenLeftMap = 0x1000;
299 const size_t lenGd = 0x1000;
300 const size_t lenReserve = lenLeftMap + lenGdGap + lenGd;
301 char *addReserve = nullptr;
302 char *addrGd = nullptr;
303 int ret = -1;
304
305 addReserve = (char *)mmap(nullptr, lenReserve, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
306 ASSERT_TRUE(addReserve != MAP_FAILED);
307 void *addr1 = mmap(addReserve, lenLeftMap, PROT_READ, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
308 ASSERT_TRUE(addr1 != MAP_FAILED);
309 addrGd = (char *)mmap(addReserve + lenLeftMap + lenGdGap, lenGd, PROT_READ,
310 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0);
311 ASSERT_TRUE(addrGd != MAP_FAILED);
312
313 ret = mprotect(addrGd, lenGd, PROT_READ | PROT_WRITE | PROT_GROWSDOWN);
314 ASSERT_TRUE(ret == 0);
315 g_sigStarted = 1;
316 struct sigaction sa;
317 sa.sa_handler = SigsegvHandler;
318 sigemptyset(&sa.sa_mask);
319 sa.sa_flags = 0;
320 ret = sigaction(SIGSEGV, &sa, nullptr);
321 ASSERT_TRUE(ret == 0);
322 int cpage = 256;
323 addrGd[cpage * -0x1000] = '1';
324 ret = munmap(addReserve, lenReserve);
325 ASSERT_TRUE(ret == 0);
326 ret = munmap(addr1, lenLeftMap);
327 ASSERT_TRUE(ret == 0);
328 ret = munmap(addrGd, lenGd);
329 ASSERT_TRUE(ret == 0);
330 addReserve = nullptr;
331 addr1 = nullptr;
332 addrGd = nullptr;
333 }
334
335 /*
336 * @tc.number SUB_KERNEL_MEM_MAP_1600
337 * @tc.name MMAPGrownsDown003
338 * @tc.desc MAP_GROWSDONW when MAP_SHARED
339 */
HWTEST_F(MmapApiTest, MMAPGrownsDown003, Function | MediumTest | Level1)340 HWTEST_F(MmapApiTest, MMAPGrownsDown003, Function | MediumTest | Level1)
341 {
342 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED | MAP_GROWSDOWN, -1, 0);
343 ASSERT_TRUE(va == MAP_FAILED);
344 va = nullptr;
345 }
346
347 /*
348 * @tc.number SUB_KERNEL_MEM_MAP_1700
349 * @tc.name MMAPGrownsDown004
350 * @tc.desc MAP_GROWSDONW when the pre-vregion is MAP_GROWSDONW
351 */
HWTEST_F(MmapApiTest, MMAPGrownsDown004, Function | MediumTest | Level1)352 HWTEST_F(MmapApiTest, MMAPGrownsDown004, Function | MediumTest | Level1)
353 {
354 const size_t lenGd1 = 0x2000;
355 const size_t lenGd2 = 0x2000;
356 const size_t lenReserve = 0x1000 * 6;
357
358 char *addReserve = nullptr;
359 char *addrGd1 = nullptr;
360 char *addrGd2 = nullptr;
361 int ret = -1;
362
363 addReserve = (char *)mmap(nullptr, lenReserve, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
364 ASSERT_TRUE(addReserve != MAP_FAILED);
365 addrGd1 = (char *)mmap(addReserve, lenGd1, PROT_READ | PROT_WRITE,
366 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0);
367 ASSERT_TRUE(addrGd1 != MAP_FAILED);
368 addrGd2 = (char *)mmap(addReserve + (lenReserve - lenGd2), lenGd2, PROT_READ | PROT_WRITE,
369 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0);
370 ASSERT_TRUE(addrGd2 != MAP_FAILED);
371 g_sigStarted = 1;
372 struct sigaction sa;
373 sa.sa_handler = SigsegvHandler;
374 sigemptyset(&sa.sa_mask);
375 sa.sa_flags = 0;
376 ret = sigaction(SIGSEGV, &sa, nullptr);
377 ASSERT_TRUE(ret == 0);
378 addrGd2[-0x1000] = '1';
379 addrGd2[-0x2000] = '1';
380 ret = munmap(addReserve, lenReserve);
381 ASSERT_TRUE(ret == 0);
382 ret = munmap(addrGd1, lenGd1);
383 ASSERT_TRUE(ret == 0);
384 ret = munmap(addrGd2, lenGd2);
385 ASSERT_TRUE(ret == 0);
386 addReserve = nullptr;
387 addrGd1 = nullptr;
388 addrGd2 = nullptr;
389 }