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 }