• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 <stdlib.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <errno.h>
20 #include <sys/mman.h>
21 #include <sys/file.h>
22 #include <sys/types.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <gtest/gtest.h>
26 #include "log.h"
27 #include "utils.h"
28 #include "KernelConstants.h"
29 
30 using namespace testing::ext;
31 
32 #define MREMAP_TESTFILE "/storage/testMremap.txt"
33 
34 class MremapApiTest : public testing::Test {
35 };
36 
37 /**
38  * @tc.number SUB_KERNEL_MEM_SBRK_0100
39  * @tc.name   sbrk function increment 0 test
40  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
41  */
42 HWTEST_F(MremapApiTest, testSbrkZero, Function | MediumTest | Level2)
43 {
44     void *mem = sbrk(0);
45     LOG("mem = %p", mem);
46     ASSERT_TRUE(mem != nullptr);
47 }
48 
49 /**
50  * @tc.number SUB_KERNEL_MEM_SBRK_0200
51  * @tc.name   sbrk function errno for ENOMEM test
52  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
53  */
54 HWTEST_F(MremapApiTest, testSbrkENOMEM, Function | MediumTest | Level3)
55 {
56     void *mem = sbrk(GetRandom(4096));
57     LOG("mem = %p, errno = %d", mem, errno);
58     ASSERT_TRUE(mem == (void *)-1);
59     EXPECT_TRUE(errno == ENOMEM) << "ERROR: errno != ENOMEM, errno = " << errno << " ENOMEM = " << ENOMEM;
60 }
61 
62 /**
63  * @tc.number SUB_KERNEL_MEM_MREMAP_0100
64  * @tc.name   mremap function anonymous remap expand area test
65  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
66  */
67 HWTEST_F(MremapApiTest, testMremapAnonExpand, Function | MediumTest | Level2)
68 {
69     size_t len = PAGE_SIZE;
70     size_t expandSize = len * 2;
71     char testChar = 'A';
72     int prot = PROT_READ | PROT_WRITE;
73     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
74 
75     char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
76     LOG("mem = %p", mem);
77     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
78 
79     mem = (char *)mremap(mem, len, expandSize, 0);
80     LOG("__LINE__ = %d, mem = %p", __LINE__, mem);
81     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED, expandSize = " << expandSize;
82 
83     pid_t pid = fork();
84     EXPECT_TRUE(pid >= 0) << "Fork Error";
85     if (pid == 0) {
86         mem[0] = testChar;
87         mem[len - 1] = testChar + 3;
88         /* expand area operate test */
89         mem[len + 0] = testChar;
90         mem[expandSize - 1] = testChar + 3;
91 
92         LOG("mem[0] = 0x%02x", mem[0]);
93         LOG("mem[len - 1] = 0x%02x", mem[len - 1]);
94         LOG("mem[len + 0] = 0x%02x", mem[len + 0]);
95         LOG("mem[expandSize - 1] = 0x%02x", mem[expandSize - 1]);
96 
97         exit(0);
98     } else {
99         WaitProcExitedOK(pid);
100         EXPECT_TRUE(munmap(mem, expandSize) == 0) << "ERROR: munmap() != 0" << errno;
101     }
102 }
103 
104 /**
105  * @tc.number SUB_KERNEL_MEM_MREMAP_0200
106  * @tc.name   mremap function anonymous remap shrink area test
107  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
108  */
109 HWTEST_F(MremapApiTest, testMremapAnonShrink, Function | MediumTest | Level3)
110 {
111     size_t len = PAGE_SIZE * 2;
112     size_t shrinkSize = len / 2;
113     char testChar = 'A';
114     int prot = PROT_READ | PROT_WRITE;
115     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
116 
117     char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
118     LOG("mem = %p", mem);
119     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
120 
121     mem = (char *)mremap(mem, len, shrinkSize, 0);
122     LOG("__LINE__ = %d, mem = %p", __LINE__, mem);
123     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED, shrinkSize = " << shrinkSize;
124 
125     pid_t pid = fork();
126     EXPECT_TRUE(pid >= 0) << "Fork Error";
127     if (pid == 0) {
128         mem[0] = testChar;
129         mem[shrinkSize - 1] = testChar + 3;
130         LOG("mem[0] = 0x%02x", mem[0]);
131         LOG("mem[shrinkSize - 1] = 0x%02x", mem[shrinkSize - 1]);
132         /* this operate will cause process crash */
133         mem[shrinkSize + 4] = testChar;
134 
135         exit(0);
136     } else {
137         ExpectProcCrashed(pid);
138         EXPECT_TRUE(munmap(mem, shrinkSize) == 0) << "ERROR: munmap() != 0" << errno;
139     }
140 }
141 
142 /**
143  * @tc.number SUB_KERNEL_MEM_MREMAP_0300
144  * @tc.name   mremap function anonymous remap and expand area to fix address test
145  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
146  */
147 HWTEST_F(MremapApiTest, testMremapAnonExpandFixAddr, Function | MediumTest | Level3)
148 {
149     size_t len = PAGE_SIZE;
150     size_t expandSize = len * 2;
151     char testChar = 'A';
152     char *fixAddr = (char *)0x27000000;
153     int prot = PROT_READ | PROT_WRITE;
154     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
155     int reFlag = MREMAP_MAYMOVE | MREMAP_FIXED;
156 
157     char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
158     LOG("mem = %p", mem);
159     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
160 
161     mem = (char *)mremap(mem, len, expandSize, reFlag, (void *)fixAddr);
162     LOG("__LINE__ = %d, mem = %p, fixAddr = %p", __LINE__, mem, fixAddr);
163     ASSERT_TRUE(mem == fixAddr) << "mem != fixAddr";
164 
165     pid_t pid = fork();
166     EXPECT_TRUE(pid >= 0) << "Fork Error";
167     if (pid == 0) {
168         fixAddr[0] = testChar;
169         fixAddr[len - 1] = testChar + 3;
170         /* expand area operate test */
171         fixAddr[len + 0] = testChar;
172         fixAddr[expandSize - 1] = testChar + 3;
173 
174         LOG("fixAddr[0] = 0x%02x", fixAddr[0]);
175         LOG("fixAddr[len - 1] = 0x%02x", fixAddr[len - 1]);
176         LOG("fixAddr[len + 0] = 0x%02x", fixAddr[len + 0]);
177         LOG("fixAddr[expandSize - 1] = 0x%02x", fixAddr[expandSize - 1]);
178 
179         exit(0);
180     } else {
181         WaitProcExitedOK(pid);
182         EXPECT_TRUE(munmap(mem, expandSize) == 0) << "ERROR: munmap() != 0" << errno;
183     }
184 }
185 
186 /**
187  * @tc.number SUB_KERNEL_MEM_MREMAP_0400
188  * @tc.name   mremap function anonymous remap and shrink area to fix address test
189  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
190  */
191 HWTEST_F(MremapApiTest, testMremapAnonShrinkFixAddr, Function | MediumTest | Level3)
192 {
193     size_t len = PAGE_SIZE * 2;
194     size_t shrinkSize = len / 2;
195     char testChar = 'A';
196     char *fixAddr = (char *)0x27000000;
197     int prot = PROT_READ | PROT_WRITE;
198     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
199     int reFlag = MREMAP_MAYMOVE | MREMAP_FIXED;
200 
201     char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
202     LOG("mem = %p", mem);
203     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
204 
205     mem = (char *)mremap(mem, len, shrinkSize, reFlag, (void *)fixAddr);
206     LOG("__LINE__ = %d, mem = %p, fixAddr = %p", __LINE__, mem, fixAddr);
207     ASSERT_TRUE(mem == fixAddr) << "mem != fixAddr";
208 
209     pid_t pid = fork();
210     EXPECT_TRUE(pid >= 0) << "Fork Error";
211     if (pid == 0) {
212         fixAddr[0] = testChar;
213         fixAddr[shrinkSize - 1] = testChar + 3;
214         LOG("fixAddr[0] = 0x%02x", fixAddr[0]);
215         LOG("fixAddr[shrinkSize - 1] = 0x%02x", fixAddr[shrinkSize - 1]);
216         /* this operate will cause process crash */
217         fixAddr[shrinkSize + 4] = testChar;
218 
219         exit(0);
220     } else {
221         ExpectProcCrashed(pid);
222         EXPECT_TRUE(munmap(mem, shrinkSize) == 0) << "ERROR: munmap() != 0" <<errno;
223     }
224 }
225 
226 /**
227  * @tc.number SUB_KERNEL_MEM_MREMAP_0500
228  * @tc.name   mremap function file remap expand area test
229  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
230  */
231 HWTEST_F(MremapApiTest, testMremapFileExpand, Function | MediumTest | Level2)
232 {
233     size_t len = PAGE_SIZE;
234     size_t expandSize = len * 2;
235     char testChar = 'A';
236     int prot = PROT_READ | PROT_WRITE;
237     int flags = MAP_SHARED;
238     char buf[PAGE_SIZE * 2] = {0};
239     char file[] = MREMAP_TESTFILE;
240 
241     int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
242     ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
243 
244     int wByte = write(fd, buf, expandSize);
245     EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
246 
247     char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
248     LOG("mem = %p", mem);
249     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
250 
251     mem = (char *)mremap(mem, len, expandSize, 0);
252     LOG("__LINE__ = %d, mem = %p", __LINE__, mem);
253     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED, expandSize = " << expandSize;
254 
255     pid_t pid = fork();
256     EXPECT_TRUE(pid >= 0) << "Fork Error";
257     if (pid == 0) {
258         mem[0] = testChar;
259         mem[len - 1] = testChar + 3;
260         /* expand area operate test */
261         mem[len + 0] = testChar;
262         mem[expandSize - 1] = testChar + 3;
263         LOG("mem[0] = 0x%02x", mem[0]);
264         LOG("mem[len - 1] = 0x%02x", mem[len - 1]);
265         LOG("mem[len + 0] = 0x%02x", mem[len + 0]);
266         LOG("mem[expandSize - 1] = 0x%02x", mem[expandSize - 1]);
267 
268         exit(0);
269     } else {
270         WaitProcExitedOK(pid);
271         EXPECT_TRUE(munmap(mem, expandSize) == 0) << "ERROR: munmap() != 0";
272         EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
273         Msleep(1000);
274         EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
275     }
276 }
277 
278 /**
279  * @tc.number SUB_KERNEL_MEM_MREMAP_0600
280  * @tc.name   mremap function file remap shrink area test
281  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
282  */
283 HWTEST_F(MremapApiTest, testMremapFileShrink, Function | MediumTest | Level3)
284 {
285     size_t len = PAGE_SIZE * 2;
286     size_t shrinkSize = len / 2;
287     char testChar = 'A';
288     int prot = PROT_READ | PROT_WRITE;
289     int flags = MAP_SHARED;
290     char buf[PAGE_SIZE * 2] = {0};
291     char file[] = MREMAP_TESTFILE;
292 
293     int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
294     ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
295 
296     int wByte = write(fd, buf, len);
297     EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
298 
299     char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
300     LOG("mem = %p", mem);
301     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
302 
303     mem = (char *)mremap(mem, len, shrinkSize, 0);
304     LOG("__LINE__ = %d, mem = %p", __LINE__, mem);
305     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED, shrinkSize = " << shrinkSize;
306 
307     pid_t pid = fork();
308     EXPECT_TRUE(pid >= 0) << "Fork Error";
309     if (pid == 0) {
310         mem[0] = testChar;
311         mem[shrinkSize - 1] = testChar + 3;
312         LOG("mem[0] = 0x%02x", mem[0]);
313         LOG("mem[shrinkSize - 1] = 0x%02x", mem[shrinkSize - 1]);
314 
315         /* this operate will cause process crash */
316         mem[shrinkSize + 4] = testChar;
317 
318         exit(0);
319     } else {
320         ExpectProcCrashed(pid);
321         EXPECT_TRUE(munmap(mem, shrinkSize) == 0) << "ERROR: munmap() != 0";
322         EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
323         Msleep(1000);
324         EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
325     }
326 }
327 
328 /**
329  * @tc.number SUB_KERNEL_MEM_MREMAP_0700
330  * @tc.name   mremap function file remap and expand area to fix address test
331  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
332  */
333 HWTEST_F(MremapApiTest, testMremapFileExpandFixAddr, Function | MediumTest | Level3)
334 {
335     size_t len = PAGE_SIZE;
336     size_t expandSize = len * 2;
337     char testChar = 'A';
338     char *fixAddr = (char *)0x27000000;
339     int prot = PROT_READ | PROT_WRITE;
340     int flags = MAP_SHARED;
341     int reFlag = MREMAP_MAYMOVE | MREMAP_FIXED;
342     char buf[PAGE_SIZE * 2] = {0};
343     char file[] = MREMAP_TESTFILE;
344 
345     int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
346     ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
347 
348     int wByte = write(fd, buf, expandSize);
349     EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
350 
351     char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
352     LOG("mem = %p", mem);
353     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
354 
355     mem = (char *)mremap(mem, len, expandSize, reFlag, (void *)fixAddr);
356     LOG("__LINE__ = %d, mem = %p, fixAddr = %p", __LINE__, mem, fixAddr);
357     ASSERT_TRUE(mem == fixAddr) << "mem != fixAddr";
358 
359     pid_t pid = fork();
360     EXPECT_TRUE(pid >= 0) << "Fork Error";
361     if (pid == 0) {
362         fixAddr[0] = testChar;
363         fixAddr[len - 1] = testChar + 3;
364         /* expand area operate test */
365         fixAddr[len + 0] = testChar;
366         fixAddr[expandSize - 1] = testChar + 3;
367 
368         LOG("fixAddr[0] = 0x%02x", fixAddr[0]);
369         LOG("fixAddr[len - 1] = 0x%02x", fixAddr[len - 1]);
370         LOG("fixAddr[len + 0] = 0x%02x", fixAddr[len + 0]);
371         LOG("fixAddr[expandSize - 1] = 0x%02x", fixAddr[expandSize - 1]);
372 
373         exit(0);
374     } else {
375         WaitProcExitedOK(pid);
376         EXPECT_TRUE(munmap(mem, expandSize) == 0) << "ERROR: munmap() != 0";
377         EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
378         Msleep(1000);
379         EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
380     }
381 }
382 
383 /**
384  * @tc.number SUB_KERNEL_MEM_MREMAP_0800
385  * @tc.name   mremap function file remap and shrink area to fix address test
386  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
387  */
388 HWTEST_F(MremapApiTest, testMremapFileShrinkFixAddr, Function | MediumTest | Level3)
389 {
390     size_t len = PAGE_SIZE * 2;
391     size_t shrinkSize = len / 2;
392     char testChar = 'A';
393     char *fixAddr = (char *)0x27000000;
394     int prot = PROT_READ | PROT_WRITE;
395     int flags = MAP_SHARED;
396     int reFlag = MREMAP_MAYMOVE | MREMAP_FIXED;
397 
398     char buf[PAGE_SIZE * 2] = {0};
399     char file[] = MREMAP_TESTFILE;
400 
401     int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
402     ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
403 
404     int wByte = write(fd, buf, len);
405     EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
406 
407     char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
408     LOG("mem = %p", mem);
409     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
410 
411     mem = (char *)mremap(mem, len, shrinkSize, reFlag, (void *)fixAddr);
412     LOG("__LINE__ = %d, mem = %p, fixAddr = %p", __LINE__, mem, fixAddr);
413     ASSERT_TRUE(mem == fixAddr) << "mem != fixAddr";
414 
415     pid_t pid = fork();
416     EXPECT_TRUE(pid >= 0) << "Fork Error";
417     if (pid == 0) {
418         fixAddr[0] = testChar;
419         fixAddr[shrinkSize - 1] = testChar + 3;
420         LOG("fixAddr[0] = 0x%02x", fixAddr[0]);
421         LOG("fixAddr[shrinkSize - 1] = 0x%02x", fixAddr[shrinkSize - 1]);
422 
423         /* this operate will cause process crash */
424         fixAddr[shrinkSize + 4] = testChar;
425 
426         exit(0);
427     } else {
428         ExpectProcCrashed(pid);
429 
430         EXPECT_TRUE(munmap(mem, shrinkSize) == 0) << "ERROR: munmap() != 0";
431         EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
432         Msleep(1000);
433         EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
434     }
435 }
436 
437 /**
438  * @tc.number SUB_KERNEL_MEM_MREMAP_0900
439  * @tc.name   mremap function errno for EINVAL test
440  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
441  */
442 HWTEST_F(MremapApiTest, testMremapEINVAL, Function | MediumTest | Level4)
443 {
444     void *mem = nullptr;
445     void *newMem = nullptr;
446     size_t len = PAGE_SIZE;
447     unsigned long fixAddr = 0x27700000;
448 
449     mem = mmap((void *)fixAddr, len, PROT_READ | PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
450     LOG("__LINE__ = %d, mem = %p", __LINE__, mem);
451     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
452 
453     fixAddr |= 0x123;
454     newMem = mremap((void *)fixAddr, len, len, 0);
455     LOG("__LINE__ = %d, newMem = %p", __LINE__, newMem);
456     EXPECT_TRUE(newMem == MAP_FAILED) << "mem != MAP_FAILED errno = " << errno;
457     EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
458 
459     newMem = mremap(mem, len, len, 0x04);
460     LOG("__LINE__ = %d, newMem = %p", __LINE__, newMem);
461     EXPECT_TRUE(newMem == MAP_FAILED) << "mem != MAP_FAILED errno = " << errno;
462     EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
463 
464     newMem = mremap(mem, len, 0, 0);
465     LOG("__LINE__ = %d, newMem = %p", __LINE__, newMem);
466     EXPECT_TRUE(newMem == MAP_FAILED) << "mem != MAP_FAILED errno = " << errno;
467     EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
468 
469     EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
470 
471     if (newMem != MAP_FAILED && newMem != mem) {
472         EXPECT_TRUE(munmap(newMem, len) == 0) << "ERROR: munmap() != 0" << errno;
473     }
474 }
475