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
27#include "log.h"
28#include "utils.h"
29#include "KernelConstants.h"
30
31using namespace testing::ext;
32
33#define MMAP_TESTFILE "/storage/testMmap.txt"
34
35class MmapApiTest : public testing::Test {
36};
37
38/**
39 * @tc.number SUB_KERNEL_MEM_MMAP_0100
40 * @tc.name   mmap function anonymous private map and read and write permission test
41 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
42 */
43HWTEST_F(MmapApiTest, testMmapAnonPrivate, Function | MediumTest | Level3)
44{
45    size_t len = PAGE_SIZE;
46    int sum = 0;
47    char testChar = 'A';
48    int prot = PROT_READ | PROT_WRITE;
49    int flags = MAP_ANONYMOUS | MAP_PRIVATE;
50
51    char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
52    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
53
54    for (size_t i = 0; i < len; i++) {
55        sum += mem[i];
56    }
57    ASSERT_TRUE(sum == 0) << "sum != 0, sum = " << sum;
58
59    pid_t pid = fork();
60    EXPECT_TRUE(pid >= 0) << "Fork Error";
61    if (pid == 0) {
62        mem[0] = testChar;
63        mem[1] = testChar + 3;
64        LOG("child: mem[0] = %c (0x%02x)", mem[0], mem[0]);
65        LOG("child: mem[1] = %c (0x%02x)", mem[1], mem[1]);
66        exit(0);
67    } else {
68        WaitProcExitedOK(pid);
69        LOG("parent: mem[0] = %c (0x%02x)", mem[0], mem[0]);
70        LOG("parent: mem[1] = %c (0x%02x)", mem[1], mem[1]);
71
72        EXPECT_TRUE(mem[0] != testChar) << "mem[0] = " << mem[0];
73        EXPECT_TRUE(mem[1] != (testChar + 3)) << "mem[1] = " << mem[1];
74        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
75    }
76}
77
78/**
79 * @tc.number SUB_KERNEL_MEM_MMAP_0200
80 * @tc.name   mmap function anonymous share map and read and write permission test
81 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
82 */
83HWTEST_F(MmapApiTest, testMmapAnonShare, Function | MediumTest | Level3)
84{
85    size_t len = PAGE_SIZE;
86    char testChar = 'A';
87    int prot = PROT_READ | PROT_WRITE;
88    int flags = MAP_ANONYMOUS | MAP_SHARED;
89
90    char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
91    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
92
93    pid_t pid = fork();
94    EXPECT_TRUE(pid >= 0) << "Fork Error";
95    if (pid == 0) {
96        mem[0] = testChar;
97        mem[1] = testChar + 3;
98        LOG("child: mem[0] = %c (0x%02x)", mem[0], mem[0]);
99        LOG("child: mem[1] = %c (0x%02x)", mem[1], mem[1]);
100        exit(0);
101    } else {
102        WaitProcExitedOK(pid);
103        LOG("parent: mem[0] = %c (0x%02x)", mem[0], mem[0]);
104        LOG("parent: mem[1] = %c (0x%02x)", mem[1], mem[1]);
105        // not support at present, suggest shm, after support need change to ==
106        EXPECT_TRUE(mem[0] != testChar) << "mem[0] = " << mem[0];
107        EXPECT_TRUE(mem[1] != (testChar + 3)) << "mem[1] = " << mem[1];
108        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
109    }
110}
111
112/**
113 * @tc.number SUB_KERNEL_MEM_MMAP_0300
114 * @tc.name   mmap function anonymous share map and only read permission test
115 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
116 */
117HWTEST_F(MmapApiTest, testMmapAnonShareOnlyRead, Function | MediumTest | Level1)
118{
119    size_t len = PAGE_SIZE;
120    char testChar = 'A';
121    int prot = PROT_READ;
122    int flags = MAP_ANONYMOUS | MAP_SHARED;
123
124    char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
125    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
126
127    pid_t pid = fork();
128    EXPECT_TRUE(pid >= 0) << "Fork Error";
129    if (pid == 0) {
130        /* Only read permit and write data to this area cause process crash */
131        mem[0] = testChar;
132        mem[1] = testChar + 3;
133        exit(0);
134    } else {
135        ExpectProcCrashed(pid);
136
137        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
138    }
139}
140
141/**
142 * @tc.number SUB_KERNEL_MEM_MMAP_0400
143 * @tc.name   mmap function anonymous share map and only write permission test
144 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
145 */
146HWTEST_F(MmapApiTest, testMmapAnonShareOnlyWrite, Function | MediumTest | Level3)
147{
148    size_t len = PAGE_SIZE;
149    int prot = PROT_WRITE;
150    int flags = MAP_ANONYMOUS | MAP_SHARED;
151
152    char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
153    LOG("mem = %p", mem);
154    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
155
156    pid_t pid = fork();
157    EXPECT_TRUE(pid >= 0) << "Fork Error";
158    if (pid == 0) {
159        char testChar = 'A';
160        mem[0] = testChar;
161        mem[1] = testChar + 3;
162
163        LOG("mem[0] = 0x%02x", mem[0]);
164        LOG("mem[1] = 0x%02x", mem[1]);
165        exit(0);
166    } else {
167        WaitProcExitedOK(pid);
168        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
169    }
170}
171
172/**
173 * @tc.number SUB_KERNEL_MEM_MMAP_0500
174 * @tc.name   mmap function anonymous private map and execute permission test
175 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
176 */
177HWTEST_F(MmapApiTest, testMmapAnonPrivateExec, Function | MediumTest | Level4)
178{
179    char *mem = nullptr;
180    size_t len = PAGE_SIZE / 4;
181    size_t i;
182    int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
183    int flags = MAP_ANONYMOUS | MAP_PRIVATE;
184    int (*fun)(void);
185
186    mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
187    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
188
189    unsigned long fnReturnFive[] = {0xe52db004, 0xe28db000, 0xe3a03005,
190                                    0xe1a00003, 0xe28bd000, 0xe49db004, 0xe12fff1e};
191    char *ptr = (char *)fnReturnFive;
192
193    for (i = 0; i < sizeof(fnReturnFive); i++) {
194        mem[i] = ptr[i];
195    }
196
197    for (i = 0; i < 30; i++) {
198        printf("%02x ", mem[i]);
199    }
200    printf("\r\n");
201
202    pid_t pid = fork();
203    EXPECT_TRUE(pid >= 0) << "Fork Error";
204    if (pid == 0) {
205        fun = (int (*)(void))mem;
206        int five = fun();
207        LOG("five = 0x%02x", five);
208
209        if (five == 0x05) {
210            exit(0);
211        }
212        exit(-1);
213    } else {
214        WaitProcExitedOK(pid);
215
216        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
217    }
218}
219
220/**
221 * @tc.number SUB_KERNEL_MEM_MMAP_0600
222 * @tc.name   mmap function anonymous share map and execute permission test
223 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
224 */
225HWTEST_F(MmapApiTest, testMmapAnonShareExec, Function | MediumTest | Level4)
226{
227    char *mem = nullptr;
228    size_t len = PAGE_SIZE / 4;
229    size_t i;
230    int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
231    int flags = MAP_ANONYMOUS | MAP_SHARED;
232    int (*fun)(void);
233
234    mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
235    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
236
237    unsigned long fnReturnFive[] = {0xe52db004, 0xe28db000, 0xe3a03005,
238                                    0xe1a00003, 0xe28bd000, 0xe49db004, 0xe12fff1e};
239    char *ptr = (char *)fnReturnFive;
240
241    for (i = 0; i < sizeof(fnReturnFive); i++) {
242        mem[i] = ptr[i];
243    }
244
245    for (i = 0; i < 30; i++) {
246        printf("%02x ", mem[i]);
247    }
248    printf("\r\n");
249
250    pid_t pid = fork();
251    EXPECT_TRUE(pid >= 0) << "Fork Error";
252
253    if (pid == 0) {
254        fun = (int (*)(void))mem;
255        int five = fun();
256        LOG("five = 0x%02x", five);
257
258        if (five == 0x05) {
259            exit(0);
260        }
261        exit(-1);
262    } else {
263        WaitProcExitedOK(pid);
264
265        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
266    }
267}
268
269/**
270 * @tc.number SUB_KERNEL_MEM_MMAP_0700
271 * @tc.name   mmap function anonymous share map and NO execute permission test
272 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
273 */
274HWTEST_F(MmapApiTest, testMmapAnonShareNoExec, Function | MediumTest | Level2)
275{
276    char *mem = nullptr;
277    size_t len = PAGE_SIZE / 4;
278    size_t i;
279    int prot = PROT_READ | PROT_WRITE;
280    int flags = MAP_ANONYMOUS | MAP_SHARED;
281    int (*fun)(void);
282
283    mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
284    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
285
286    unsigned long fnReturnFive[] = {0xe52db004, 0xe28db000, 0xe3a03005,
287                                    0xe1a00003, 0xe28bd000, 0xe49db004, 0xe12fff1e};
288    char *ptr = (char *)fnReturnFive;
289
290    for (i = 0; i < sizeof(fnReturnFive); i++) {
291        mem[i] = ptr[i];
292    }
293
294    pid_t pid = fork();
295    EXPECT_TRUE(pid >= 0) << "Fork Error";
296
297    if (pid == 0) {
298        fun = (int (*)(void))mem;
299        int five = fun();
300        LOG("five = 0x%02x", five);
301
302        exit(0);
303    } else {
304        ExpectProcCrashed(pid);
305
306        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
307    }
308}
309
310/**
311 * @tc.number SUB_KERNEL_MEM_MMAP_0800
312 * @tc.name   mmap function file private map and read and write permission test
313 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
314 */
315HWTEST_F(MmapApiTest, testMmapFilePrivate, Function | MediumTest | Level3)
316{
317    const size_t len = PAGE_SIZE;
318    char testChar = 'A';
319    int prot = PROT_READ | PROT_WRITE;
320    int flags = MAP_PRIVATE;
321    char buf[PAGE_SIZE] = {0};
322    char file[] = MMAP_TESTFILE;
323
324    int fd = open(file, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
325    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
326
327    int wByte = write(fd, buf, len);
328    EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
329
330    char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
331    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
332
333    pid_t pid = fork();
334    EXPECT_TRUE(pid >= 0) << "Fork Error";
335
336    if (pid == 0) {
337        mem[0] = testChar;
338        mem[1] = testChar + 3;
339        exit(0);
340    } else {
341        WaitProcExitedOK(pid);
342
343        LOG("mem[0] = %c (0x%02x)", mem[0], mem[0]);
344        LOG("mem[1] = %c (0x%02x)", mem[1], mem[1]);
345
346        EXPECT_TRUE(mem[0] != testChar) << "mem[0] = " << mem[0];
347        EXPECT_TRUE(mem[1] != (testChar + 3)) << "mem[1] = " << mem[1];
348        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
349
350        EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
351        Msleep(1000);
352        EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
353    }
354}
355
356/**
357 * @tc.number SUB_KERNEL_MEM_MMAP_0900
358 * @tc.name   mmap function file share map and read and write permission test
359 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
360 */
361HWTEST_F(MmapApiTest, testMmapFileShare, Function | MediumTest | Level3)
362{
363    const size_t len = PAGE_SIZE;
364    char testChar = 'A';
365    int prot = PROT_READ | PROT_WRITE;
366    int flags = MAP_SHARED;
367    char buf[PAGE_SIZE] = {0};
368    char file[] = MMAP_TESTFILE;
369
370    int fd = open(file, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
371    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
372
373    int wByte = write(fd, buf, len);
374    EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
375
376    char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
377    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
378
379    pid_t pid = fork();
380    EXPECT_TRUE(pid >= 0) << "Fork Error";
381
382    if (pid == 0) {
383        mem[0] = testChar;
384        mem[1] = testChar + 3;
385        exit(0);
386    } else {
387        WaitProcExitedOK(pid);
388
389        LOG("mem[0] = %c (0x%02x)", mem[0], mem[0]);
390        LOG("mem[1] = %c (0x%02x)", mem[1], mem[1]);
391
392        EXPECT_TRUE(mem[0] == testChar) << "mem[0] = " << mem[0];
393        EXPECT_TRUE(mem[1] == (testChar + 3)) << "mem[1] = " << mem[1];
394        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
395
396        EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
397        Msleep(1000);
398        EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
399    }
400}
401
402/**
403 * @tc.number SUB_KERNEL_MEM_MMAP_1000
404 * @tc.name   mmap function file share map and only read permission test
405 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
406 */
407HWTEST_F(MmapApiTest, testMmapFileShareOnlyRead, Function | MediumTest | Level1)
408{
409    const size_t len = PAGE_SIZE;
410    char testChar = 'A';
411    int prot = PROT_READ;
412    int flags = MAP_SHARED;
413    char buf[PAGE_SIZE] = {0};
414    char file[] = MMAP_TESTFILE;
415    int fd = open(file, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
416    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
417
418    int wByte = write(fd, buf, len);
419    EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
420
421    char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
422    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
423
424    pid_t pid = fork();
425    EXPECT_TRUE(pid >= 0) << "Fork Error";
426
427    if (pid == 0) {
428        /* Only read permit and write data to this area cause process crash */
429        mem[0] = testChar;
430        mem[1] = testChar + 3;
431
432        exit(0);
433    } else {
434        ExpectProcCrashed(pid);
435
436        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
437        EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
438        Msleep(1000);
439        EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
440    }
441}
442
443/**
444 * @tc.number SUB_KERNEL_MEM_MMAP_1100
445 * @tc.name   mmap function file share map and only write permission test
446 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
447 */
448HWTEST_F(MmapApiTest, testMmapFileShareOnlyWrite, Function | MediumTest | Level3)
449{
450    const size_t len = PAGE_SIZE;
451    int prot = PROT_WRITE;
452    int flags = MAP_SHARED;
453    char buf[PAGE_SIZE] = {0};
454    char file[] = MMAP_TESTFILE;
455
456    int fd = open(file, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
457    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
458
459    int wByte = write(fd, buf, len);
460    EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
461
462    char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
463    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
464
465    pid_t pid = fork();
466    EXPECT_TRUE(pid >= 0) << "Fork Error";
467
468    if (pid == 0) {
469        char testChar = 'A';
470        mem[0] = testChar;
471        mem[1] = testChar + 3;
472
473        LOG("mem[0] = 0x%02x", mem[0]);
474        LOG("mem[1] = 0x%02x", mem[1]);
475        exit(0);
476    } else {
477        WaitProcExitedOK(pid);
478
479        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
480        EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
481        Msleep(1000);
482        EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
483    }
484}
485
486/**
487 * @tc.number SUB_KERNEL_MEM_MMAP_1200
488 * @tc.name   mmap function file private map and execute permission test
489 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
490 */
491HWTEST_F(MmapApiTest, testMmapFilePrivateExec, Function | MediumTest | Level4)
492{
493    char *mem = nullptr;
494    size_t len = PAGE_SIZE / 4;
495    int prot = PROT_READ | PROT_EXEC;
496    int flags = MAP_PRIVATE;
497    int (*fun)(void);
498    unsigned long fnReturnFive[] = {0xe52db004, 0xe28db000, 0xe3a03005,
499                                    0xe1a00003, 0xe28bd000, 0xe49db004, 0xe12fff1e};
500    char file[] = MMAP_TESTFILE;
501
502    int fd = open(file, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
503    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
504
505    int wByte = write(fd, fnReturnFive, sizeof(fnReturnFive));
506    EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
507
508    mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
509    EXPECT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
510
511    pid_t pid = fork();
512    EXPECT_TRUE(pid >= 0) << "Fork Error";
513
514    if (pid == 0) {
515        fun = (int (*)(void))mem;
516        int five = fun();
517        LOG("five = 0x%02x", five);
518
519        if (five == 0x05) {
520            exit(0);
521        }
522        exit(-1);
523    } else {
524        WaitProcExitedOK(pid);
525
526        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
527        EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
528        Msleep(1000);
529        EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
530    }
531}
532
533/**
534 * @tc.number SUB_KERNEL_MEM_MMAP_1300
535 * @tc.name   mmap function file share map and execute permission test
536 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
537 */
538HWTEST_F(MmapApiTest, testMmapFileShareExec, Function | MediumTest | Level4)
539{
540    char *mem = nullptr;
541    size_t len = PAGE_SIZE / 4;
542    int prot = PROT_READ | PROT_EXEC;
543    int flags = MAP_SHARED;
544    int (*fun)(void);
545    unsigned long fnReturnFive[] = {0xe52db004, 0xe28db000, 0xe3a03005,
546                                    0xe1a00003, 0xe28bd000, 0xe49db004, 0xe12fff1e};
547    char file[] = MMAP_TESTFILE;
548
549    int fd = open(file, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
550    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
551
552    int wByte = write(fd, fnReturnFive, sizeof(fnReturnFive));
553    EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
554
555    mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
556    EXPECT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
557
558    pid_t pid = fork();
559    EXPECT_TRUE(pid >= 0) << "Fork Error";
560
561    if (pid == 0) {
562        fun = (int (*)(void))mem;
563        int five = fun();
564        LOG("five = 0x%02x", five);
565
566        if (five == 0x05) {
567            exit(0);
568        }
569        exit(-1);
570    } else {
571        WaitProcExitedOK(pid);
572
573        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
574        EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
575        Msleep(1000);
576        EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
577    }
578}
579
580/**
581 * @tc.number SUB_KERNEL_MEM_MMAP_1400
582 * @tc.name   mmap function file share map and NO execute permission test
583 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
584 */
585HWTEST_F(MmapApiTest, testMmapFileShareNoExec, Function | MediumTest | Level2)
586{
587    char *mem = nullptr;
588    size_t len = PAGE_SIZE / 4;
589    int prot = PROT_READ;
590    int flags = MAP_SHARED;
591    int (*fun)(void);
592    unsigned long fnReturnFive[] = {0xe52db004, 0xe28db000, 0xe3a03005,
593                                    0xe1a00003, 0xe28bd000, 0xe49db004, 0xe12fff1e};
594    char file[] = MMAP_TESTFILE;
595
596    int fd = open(file, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
597    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
598
599    int wByte = write(fd, fnReturnFive, sizeof(fnReturnFive));
600    EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
601
602    mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
603    EXPECT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
604
605    pid_t pid = fork();
606    EXPECT_TRUE(pid >= 0) << "Fork Error";
607
608    if (pid == 0) {
609        fun = (int (*)(void))mem;
610        int five = fun();
611        LOG("five = 0x%02x", five);
612
613        exit(0);
614    } else {
615        ExpectProcCrashed(pid);
616
617        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
618        EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
619        Msleep(1000);
620        EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
621    }
622}
623
624/**
625 * @tc.number SUB_KERNEL_MEM_MMAP_1500
626 * @tc.name   mmap function overlay map test
627 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
628 */
629HWTEST_F(MmapApiTest, testMmapOverlay, Function | MediumTest | Level3)
630{
631    int i;
632    void *addr[3];
633    size_t len = 0x00200000;
634    unsigned long fixAddr = 0x24000000UL;
635
636    for (i = 0; i < 3; i++) {
637        addr[i] = nullptr;
638    }
639
640    void *mem = mmap((void *)fixAddr, len, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
641    LOG("mem = %p, mem + len = %p", mem, (char *)mem + len);
642    EXPECT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
643    addr[0] = mem;
644
645    unsigned long before = fixAddr - 0x00100000;
646    void *prev = mmap((void *)before, len, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
647    LOG("prev = %p, prev + len = %p", prev, (char *)prev + len);
648    EXPECT_TRUE(prev != MAP_FAILED) << "mem != MAP_FAILED";
649    EXPECT_TRUE(prev != mem) << "prev == mem";
650    addr[1] = prev;
651
652    unsigned long after = fixAddr + 0x00100000;
653    void *next = mmap((void *)after, len, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
654    LOG("next = %p, next + len = %p", next, (char *)next + len);
655    EXPECT_TRUE(next != MAP_FAILED) << "mem != MAP_FAILED";
656
657    for (i = 0; i < 2; i++) {
658        if (next == addr[i]) {
659            break;
660        }
661    }
662    EXPECT_EQ(i, 2) << "i != 2";
663    addr[2] = next;
664
665    size_t small = len - 0x00100000;
666    void *belong = mmap((void *)after, small, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
667    LOG("belong = %p, belong + shinkLen = %p", belong, (char *)belong + small);
668    EXPECT_TRUE(belong != MAP_FAILED) << "belong != MAP_FAILED";
669
670    for (i = 0; i < 3; i++) {
671        LOG("belong = %p, addr[%d] = %p", belong, i, addr[i]);
672        if (belong == addr[i]) {
673            break;
674        }
675    }
676    EXPECT_EQ(i, 3) << "i != 3";
677
678    if (belong != MAP_FAILED) {
679        EXPECT_TRUE(munmap(belong, small) == 0) << "ERROR: munmap() != 0";
680    }
681
682    if (next != MAP_FAILED) {
683        EXPECT_TRUE(munmap(next, len) == 0) << "ERROR: munmap() != 0";
684    }
685
686    if (prev != MAP_FAILED) {
687        EXPECT_TRUE(munmap(prev, len) == 0) << "ERROR: munmap() != 0";
688    }
689
690    if (mem != MAP_FAILED) {
691        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
692    }
693}
694
695/**
696 * @tc.number SUB_KERNEL_MEM_MMAP_1600
697 * @tc.name   mmap function write back to the file test
698 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
699 */
700HWTEST_F(MmapApiTest, testMmapWriteBack, Function | MediumTest | Level3)
701{
702    char testChar = 'A';
703    size_t i, len = PAGE_SIZE;
704    int failure = 0;
705    int bufSize = len / 4;
706    char wBuffer[PAGE_SIZE / 4];
707    char rBuffer[PAGE_SIZE / 4];
708    char file[] = MMAP_TESTFILE;
709
710    int fd = open(file, O_CREAT | O_RDWR, 0777);
711    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
712
713    for (i = 0; i < (size_t)bufSize; i++) {
714        rBuffer[i] = 0;
715        wBuffer[i] = '0';
716    }
717
718    EXPECT_TRUE(write(fd, wBuffer, bufSize) == bufSize) << "ERROR: write() != bufSize";
719
720    void *mem = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
721    LOG("TAG1 mem = %p", mem);
722    EXPECT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
723
724    memset(mem, testChar, len);
725
726    char *ptr = (char *)mem;
727    for (i = 0; i < len; i++) {
728        if (ptr[i] != testChar) {
729            failure = 1;
730            break;
731        }
732    }
733    EXPECT_TRUE(failure == 0) << "i = " << i << ", ptr = " << ptr[i];
734
735    EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
736    EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
737
738    fd = open(file, O_RDONLY, 0777);
739    EXPECT_TRUE(fd != -1) << "ERROR: open() == -1";
740
741    EXPECT_TRUE(read(fd, rBuffer, bufSize) == bufSize) << "ERROR: read() != bufSize";
742
743    failure = 0;
744    for (i = 0; i < (size_t)bufSize; i++) {
745        if (rBuffer[i] != testChar) {
746            failure = 1;
747            break;
748        }
749    }
750    EXPECT_TRUE(failure == 0) << "i = " << i << ", rBuffer = " << rBuffer[i];
751
752    EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
753    Msleep(1000);
754    EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
755}
756
757/**
758 * @tc.number SUB_KERNEL_MEM_MMAP_1700
759 * @tc.name   mmap function errno for EACCES test
760 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
761 */
762HWTEST_F(MmapApiTest, testMmapEACCES, Function | MediumTest | Level3)
763{
764    int fd;
765    void *mem = nullptr;
766    size_t len = PAGE_SIZE;
767    char file[] = MMAP_TESTFILE;
768
769    /* file open read only access mode */
770    fd = open(file, O_CREAT | O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
771    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
772
773    mem = mmap(nullptr, len, PROT_WRITE, MAP_SHARED, fd, 0);
774    EXPECT_TRUE(mem == MAP_FAILED) << "mem != MAP_FAILED, mem = " << mem;
775    EXPECT_TRUE(errno == EACCES) << "ERROR: errno != EACCES, errno = " << errno << " EACCES = " << EACCES;
776
777    if (mem != MAP_FAILED) {
778        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
779    }
780    EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
781
782    /* file open append access mode */
783    fd = open(file, O_APPEND, S_IRWXU | S_IRWXG | S_IRWXO);
784    EXPECT_TRUE(fd != -1) << "ERROR: open() == -1";
785
786    mem = mmap(nullptr, len, PROT_WRITE, MAP_SHARED, fd, 0);
787    EXPECT_TRUE(mem == MAP_FAILED) << "mem != MAP_FAILED, mem = " << mem;
788    EXPECT_TRUE(errno == EACCES) << "ERROR: errno != EACCES, errno = " << errno << " EACCES = " << EACCES;
789
790    if (mem != MAP_FAILED) {
791        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
792    }
793    EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
794    Msleep(1000);
795    EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
796}
797
798/**
799 * @tc.number SUB_KERNEL_MEM_MMAP_1800
800 * @tc.name   mmap function errno for EBADF test
801 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
802 */
803HWTEST_F(MmapApiTest, testMmapEBADF, Function | MediumTest | Level3)
804{
805    void *mem = nullptr;
806    size_t len = PAGE_SIZE;
807    char file[] = MMAP_TESTFILE;
808    int flags[] = {MAP_PRIVATE, MAP_SHARED};
809
810    int fd = open(file, O_CREAT | O_RDWR, 0777);
811    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
812    EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
813
814    for (int i = 0; i < 2; i++) {
815        mem = mmap(nullptr, len, PROT_READ | PROT_WRITE, flags[i], fd, 0);
816        EXPECT_TRUE(mem == MAP_FAILED) << "mem == MAP_FAILED";
817        EXPECT_TRUE(errno == EBADF) << "ERROR: errno != EBADF, errno = " << errno << " EBADF = " << EBADF;
818
819        if (mem != MAP_FAILED) {
820            EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
821        }
822    }
823
824    EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0";
825}
826
827/**
828 * @tc.number SUB_KERNEL_MEM_MMAP_1900
829 * @tc.name   mmap function errno for EINVAL test
830 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
831 */
832HWTEST_F(MmapApiTest, testMmapEINVAL, Function | MediumTest | Level3)
833{
834    void *mem = nullptr;
835    size_t len = PAGE_SIZE;
836    char file[] = MMAP_TESTFILE;
837
838    int fd = open(file, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
839    ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
840
841    void *invalueAddr = (void *)(0x21f20000 | 0x123);
842    mem = mmap(invalueAddr, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0);
843    EXPECT_TRUE(mem == MAP_FAILED) << "mem != MAP_FAILED, mem = " << mem;
844    EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
845
846    if (mem != MAP_FAILED) {
847        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
848    }
849
850    len = 0x40000000;
851    mem = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
852    EXPECT_TRUE(mem == MAP_FAILED) << "mem != MAP_FAILED, mem = " << mem;
853    EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
854
855    if (mem != MAP_FAILED) {
856        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
857    }
858
859    len = PAGE_SIZE;
860    mem = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xFFFFFFFF);
861    EXPECT_TRUE(mem == MAP_FAILED) << "mem != MAP_FAILED, mem = " << mem;
862    EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
863
864    if (mem != MAP_FAILED) {
865        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
866    }
867
868    len = 0;
869    mem = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
870    EXPECT_TRUE(mem == MAP_FAILED) << "mem != MAP_FAILED, mem = " << mem;
871    EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
872
873    if (mem != MAP_FAILED) {
874        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
875    }
876
877    len = PAGE_SIZE;
878    mem = mmap(nullptr, len, 0, MAP_SHARED, fd, 0);
879    EXPECT_TRUE(mem != MAP_FAILED) << "mem != MAP_FAILED, mem = " << mem;
880
881    if (mem != MAP_FAILED) {
882        EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
883    }
884
885    int flags[3] = {0, MAP_ANON, MAP_PRIVATE | MAP_SHARED};
886
887    len = PAGE_SIZE;
888    for (int i = 0; i < 3; i++) {
889        mem = mmap(nullptr, len, PROT_READ | PROT_WRITE, flags[i], fd, 0);
890        EXPECT_TRUE(mem == MAP_FAILED) << "mem != MAP_FAILED, mem = " << mem;
891        EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
892
893        if (mem != MAP_FAILED) {
894            EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
895        }
896    }
897
898    EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
899    Msleep(1000);
900    EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
901}
902
903/**
904 * @tc.number SUB_KERNEL_MEM_MMAP_2000
905 * @tc.name   mmap function errno for ENOMEM test
906 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
907 */
908HWTEST_F(MmapApiTest, testMmapENOMEM, Function | MediumTest | Level3)
909{
910    pid_t pid = fork();
911    ASSERT_TRUE(pid >= 0) << "Fork Error";
912
913    if (pid == 0) {
914        int i, k, ret;
915        void *mem[100];
916        size_t len = 0x1000000;
917        int flags = MAP_ANONYMOUS | MAP_PRIVATE;
918
919        for (i = 0; i < 100; i++) {
920            mem[i] = mmap(nullptr, len, PROT_READ | PROT_WRITE, flags, -1, 0);
921            if (mem[i] == MAP_FAILED) {
922                LOG("MAP_FAILED: i = %d, errno = %d, ENOMEM = %d", i, errno, ENOMEM);
923                break;
924            }
925        }
926
927        ret = 0;
928        if (i == 100 || mem[i] != MAP_FAILED || errno != ENOMEM) {
929            ret = 1;
930            LOG("ERROR: i = %d, mem[i] = %p, MAP_FAILED = %d, errno = %d", i, mem[i], MAP_FAILED, errno);
931        }
932
933        for (k = 0; k < i; k++) {
934            munmap(mem[k], len);
935        }
936        exit(ret);
937    } else {
938        WaitProcExitedOK(pid);
939    }
940}
941
942
943/**
944 * @tc.number SUB_KERNEL_MEM_MUNMAP_0100
945 * @tc.name   munmap function errno for EINVAL test
946 * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
947 */
948HWTEST_F(MmapApiTest, testMunmapEINVAL, Function | MediumTest | Level3)
949{
950    size_t len = PAGE_SIZE;
951
952    void *mem = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
953    LOG("__LINE__ = %d, mem = %p", __LINE__, mem);
954    ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
955
956    EXPECT_TRUE(munmap(NULL, len) == -1) << "ERROR: munmap() != -1";
957    EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
958
959    EXPECT_TRUE(munmap(mem, 0) == -1) << "ERROR: munmap() != -1";
960    EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
961
962    EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
963}
964