• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }