• 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 MPROTECT_TESTFILE "/storage/testMprotect.txt"
33 
34 class MprotectApiTest : public testing::Test {
35 };
36 
37 /**
38  * @tc.number SUB_KERNEL_MEM_MPROTECT_0100
39  * @tc.name   mprotect function add read permission to the anonymous map area test
40  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
41  */
42 HWTEST_F(MprotectApiTest, testMprotectAnonAddReadPerm, Function | MediumTest | Level1)
43 {
44     size_t len = PAGE_SIZE;
45     volatile int sum = 0;
46     int prot = PROT_WRITE;
47     int mprot = prot | PROT_READ;
48     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
49 
50     char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
51     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
52 
53     EXPECT_TRUE(mprotect(mem, len, mprot) == 0) << "ERROR: mprotect() != 0";
54 
55     pid_t pid = fork();
56     EXPECT_TRUE(pid >= 0) << "Fork Error";
57     if (pid == 0) {
58         sum = mem[0] + mem[1];
59         LOG("child: sum    = %d (0x%04x)", sum, sum);
60         LOG("child: mem[0] = %c (0x%02x)", mem[0], mem[0]);
61         LOG("child: mem[1] = %c (0x%02x)", mem[1], mem[1]);
62 
63         exit(0);
64     } else {
65         WaitProcExitedOK(pid);
66         EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
67     }
68 }
69 
70 /**
71  * @tc.number SUB_KERNEL_MEM_MPROTECT_0200
72  * @tc.name   mprotect function add write permission to the anonymous map area test
73  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
74  */
75 HWTEST_F(MprotectApiTest, testMprotectAnonAddWritePerm, Function | MediumTest | Level2)
76 {
77     size_t len = PAGE_SIZE;
78     char testChar = 'A';
79     int prot = PROT_READ;
80     int mprot = prot | PROT_WRITE;
81     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
82 
83     char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
84     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
85 
86     EXPECT_TRUE(mprotect(mem, len, mprot) == 0) << "ERROR: mprotect() != 0";
87 
88     pid_t pid = fork();
89     EXPECT_TRUE(pid >= 0) << "Fork Error";
90     if (pid == 0) {
91         mem[0] = testChar;
92         mem[1] = testChar + 3;
93         LOG("child: mem[0] = %c (0x%02x)", mem[0], mem[0]);
94         LOG("child: mem[1] = %c (0x%02x)", mem[1], mem[1]);
95 
96         exit(0);
97     } else {
98         WaitProcExitedOK(pid);
99         EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
100     }
101 }
102 
103 /**
104  * @tc.number SUB_KERNEL_MEM_MPROTECT_0300
105  * @tc.name   mprotect function add execute permission to the anonymous map area test
106  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
107  */
108 HWTEST_F(MprotectApiTest, testMprotectAnonAddExecutePerm, Function | MediumTest | Level3)
109 {
110     size_t len = PAGE_SIZE;
111     int prot = PROT_READ | PROT_WRITE;
112     int mprot = prot | PROT_EXEC;
113     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
114 
115     char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
116     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
117 
118     unsigned long fnReturnFive[] = {0xe52db004, 0xe28db000, 0xe3a03005,
119                                     0xe1a00003, 0xe28bd000, 0xe49db004, 0xe12fff1e};
120     char *ptr = (char *)fnReturnFive;
121     for (size_t i = 0; i < sizeof(fnReturnFive); i++) {
122         mem[i] = ptr[i];
123     }
124 
125     EXPECT_TRUE(mprotect(mem, len, mprot) == 0) << "ERROR: mprotect() != 0";
126 
127     pid_t pid = fork();
128     EXPECT_TRUE(pid >= 0) << "Fork Error";
129     if (pid == 0) {
130         int (*fun)(void) = (int (*)(void))mem;
131         int five = fun();
132         LOG("five = 0x%02x", five);
133         exit(0);
134     } else {
135         WaitProcExitedOK(pid);
136         EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
137     }
138 }
139 
140 /**
141  * @tc.number SUB_KERNEL_MEM_MPROTECT_0500
142  * @tc.name   mprotect function delete write permission to the anonymous map area test
143  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
144  */
145 HWTEST_F(MprotectApiTest, testMprotectAnonDelWritePerm, Function | MediumTest | Level3)
146 {
147     size_t len = PAGE_SIZE;
148     char testChar = 'A';
149     int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
150     int mprot = PROT_READ | PROT_EXEC;
151     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
152 
153     char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
154     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
155 
156     EXPECT_TRUE(mprotect(mem, len, mprot) == 0) << "ERROR: mprotect() != 0";
157 
158     pid_t pid = fork();
159     EXPECT_TRUE(pid >= 0) << "Fork Error";
160     if (pid == 0) {
161         mem[0] = testChar;
162         mem[1] = testChar + 3;
163         LOG("child: mem[0] = %c (0x%02x)", mem[0], mem[0]);
164         LOG("child: mem[1] = %c (0x%02x)", mem[1], mem[1]);
165         exit(0);
166     } else {
167         ExpectProcCrashed(pid);
168         EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
169     }
170 }
171 
172 /**
173  * @tc.number SUB_KERNEL_MEM_MPROTECT_0600
174  * @tc.name   mprotect function delete execute permission to the anonymous map area test
175  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
176  */
177 HWTEST_F(MprotectApiTest, testMprotectAnonDelExecutePerm, Function | MediumTest | Level3)
178 {
179     size_t len = PAGE_SIZE;
180     int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
181     int mprot = PROT_READ | PROT_WRITE;
182     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
183 
184     char *mem = (char *)mmap(nullptr, len, prot, flags, -1, 0);
185     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
186 
187     unsigned long fnReturnFive[] = {0xe52db004, 0xe28db000, 0xe3a03005,
188                                     0xe1a00003, 0xe28bd000, 0xe49db004, 0xe12fff1e};
189     char *ptr = (char *)fnReturnFive;
190 
191     for (size_t i = 0; i < sizeof(fnReturnFive); i++) {
192         mem[i] = ptr[i];
193     }
194 
195     EXPECT_TRUE(mprotect(mem, len, mprot) == 0) << "ERROR: mprotect() != 0";
196 
197     pid_t pid = fork();
198     EXPECT_TRUE(pid >= 0) << "Fork Error";
199     if (pid == 0) {
200         int (*fun)(void) = (int (*)(void))mem;
201         int five = fun();
202         LOG("five = 0x%02x", five);
203         exit(0);
204     } else {
205         ExpectProcCrashed(pid);
206         EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
207     }
208 }
209 
210 /**
211  * @tc.number SUB_KERNEL_MEM_MPROTECT_0700
212  * @tc.name   mprotect function add read permission to the file map area test
213  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
214  */
215 HWTEST_F(MprotectApiTest, testMprotectFileAddReadPerm, Function | MediumTest | Level2)
216 {
217     size_t len = PAGE_SIZE;
218     char testChar = 'A';
219     int failure = 0;
220     int prot = PROT_WRITE;
221     int mprot = prot | PROT_READ;
222     int flags = MAP_PRIVATE;
223 
224     char buf[PAGE_SIZE] = {testChar, (char)(testChar + 3)};
225     char file[] = MPROTECT_TESTFILE;
226 
227     int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
228     ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
229 
230     int wByte = write(fd, buf, len);
231     EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
232 
233     char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
234     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
235 
236     EXPECT_TRUE(mprotect(mem, len, mprot) == 0) << "ERROR: mprotect() != 0";
237 
238     pid_t pid = fork();
239     EXPECT_TRUE(pid >= 0) << "Fork Error";
240     if (pid == 0) {
241         read(fd, buf, len);
242         if (buf[0] != mem[0] || mem[0] != testChar) {
243             failure = -1;
244         }
245         if (buf[1] != mem[1] || mem[1] != (testChar + 3)) {
246             failure = -1;
247         }
248         LOG("child: mem[0] = %c (0x%02x)", mem[0], mem[0]);
249         LOG("child: mem[1] = %c (0x%02x)", mem[1], mem[1]);
250         exit(failure);
251     } else {
252         WaitProcExitedOK(pid);
253         EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
254         EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
255         Msleep(1000);
256         EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
257     }
258 }
259 
260 /**
261  * @tc.number SUB_KERNEL_MEM_MPROTECT_0800
262  * @tc.name   mprotect function add write permission to the file map area test
263  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
264  */
265 HWTEST_F(MprotectApiTest, testMprotectFileAddWritePerm, Function | MediumTest | Level3)
266 {
267     size_t len = PAGE_SIZE;
268     char testChar = 'A';
269     int failure = 0;
270     int prot = PROT_READ;
271     int mprot = prot | PROT_WRITE;
272     int flags = MAP_SHARED;
273 
274     char buf[PAGE_SIZE] = {0};
275     char file[] = MPROTECT_TESTFILE;
276 
277     int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
278     ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
279 
280     int wByte = write(fd, buf, len);
281     EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
282 
283     char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
284     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
285 
286     EXPECT_TRUE(mprotect(mem, len, mprot) == 0) << "ERROR: mprotect() != 0";
287 
288     pid_t pid = fork();
289     EXPECT_TRUE(pid >= 0) << "Fork Error";
290     if (pid == 0) {
291         mem[0] = testChar;
292         mem[1] = testChar + 3;
293         LOG("child: mem[0] = %c (0x%02x)", mem[0], mem[0]);
294         LOG("child: mem[1] = %c (0x%02x)", mem[1], mem[1]);
295         exit(failure);
296     } else {
297         WaitProcExitedOK(pid);
298         EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
299         EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
300 
301         fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
302         EXPECT_TRUE(fd != -1) << "ERROR: open() == -1";
303 
304         read(fd, buf, len);
305 
306         LOG("parent: buf[0] = %c (0x%02x)", buf[0], buf[0]);
307         LOG("parent: buf[1] = %c (0x%02x)", buf[1], buf[1]);
308 
309         EXPECT_TRUE(buf[0] == testChar) << "ERROR: buf[0] != testChar";
310         EXPECT_TRUE(buf[1] == (testChar + 3)) << "ERROR: buf[1] != (testChar + 3)";
311         EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
312         Msleep(1000);
313         EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
314     }
315 }
316 
317 /**
318  * @tc.number SUB_KERNEL_MEM_MPROTECT_0900
319  * @tc.name   mprotect function add execute permission to the file map area test
320  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
321  */
322 HWTEST_F(MprotectApiTest, testMprotectFileAddExecutePerm, Function | MediumTest | Level3)
323 {
324     size_t len = PAGE_SIZE;
325     int prot = PROT_READ | PROT_WRITE;
326     int mprot = prot | PROT_EXEC;
327     int flags = MAP_PRIVATE;
328     char file[] = MPROTECT_TESTFILE;
329 
330     unsigned long fnReturnFive[] = {0xe52db004, 0xe28db000, 0xe3a03005,
331                                     0xe1a00003, 0xe28bd000, 0xe49db004, 0xe12fff1e};
332 
333     int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
334     ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
335 
336     int wByte = write(fd, fnReturnFive, sizeof(fnReturnFive));
337     EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
338 
339     char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
340     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
341 
342     EXPECT_TRUE(mprotect(mem, len, mprot) == 0) << "ERROR: mprotect() != 0";
343 
344     pid_t pid = fork();
345     EXPECT_TRUE(pid >= 0) << "Fork Error";
346     if (pid == 0) {
347         int (*fun)(void) = (int (*)(void))mem;
348         int five = fun();
349         LOG("five = 0x%02x", five);
350         exit(0);
351     } else {
352         WaitProcExitedOK(pid);
353         EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
354         EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
355         Msleep(1000);
356         EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
357     }
358 }
359 
360 /**
361  * @tc.number SUB_KERNEL_MEM_MPROTECT_1100
362  * @tc.name   mprotect function delete write permission to the file map area test
363  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
364  */
365 HWTEST_F(MprotectApiTest, testMprotectFileDelWritePerm, Function | MediumTest | Level3)
366 {
367     size_t len = PAGE_SIZE;
368     char testChar = 'A';
369     int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
370     int mprot = PROT_READ | PROT_EXEC;
371     int flags = MAP_PRIVATE;
372 
373     char buf[PAGE_SIZE] = {0};
374     char file[] = MPROTECT_TESTFILE;
375 
376     int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
377     ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
378 
379     int wByte = write(fd, buf, len);
380     EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
381 
382     char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
383     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
384 
385     EXPECT_TRUE(mprotect(mem, len, mprot) == 0) << "ERROR: mprotect() != 0";
386 
387     pid_t pid = fork();
388     EXPECT_TRUE(pid >= 0) << "Fork Error";
389     if (pid == 0) {
390         mem[0] = testChar;
391         mem[1] = testChar + 3;
392         LOG("child: mem[0] = %c (0x%02x)", mem[0], mem[0]);
393         LOG("child: mem[1] = %c (0x%02x)", mem[1], mem[1]);
394         exit(0);
395     } else {
396         ExpectProcCrashed(pid);
397 
398         EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
399         EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
400         Msleep(1000);
401         EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
402     }
403 }
404 
405 /**
406  * @tc.number SUB_KERNEL_MEM_MPROTECT_1200
407  * @tc.name   mprotect function delete execute permission to the file map area test
408  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
409  */
410 HWTEST_F(MprotectApiTest, testMprotectFileDelExecutePerm, Function | MediumTest | Level3)
411 {
412     size_t len = PAGE_SIZE;
413     int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
414     int mprot = PROT_READ | PROT_WRITE;
415     int flags = MAP_PRIVATE;
416     char file[] = MPROTECT_TESTFILE;
417 
418     unsigned long fnReturnFive[] = {0xe52db004, 0xe28db000, 0xe3a03005,
419                                     0xe1a00003, 0xe28bd000, 0xe49db004, 0xe12fff1e};
420 
421     int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
422     ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
423 
424     int wByte = write(fd, fnReturnFive, sizeof(fnReturnFive));
425     EXPECT_TRUE(wByte > 0) << "ERROR: write() <= 0";
426 
427     char *mem = (char *)mmap(nullptr, len, prot, flags, fd, 0);
428     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED";
429 
430     EXPECT_TRUE(mprotect(mem, len, mprot) == 0) << "ERROR: mprotect() != 0";
431 
432     pid_t pid = fork();
433     EXPECT_TRUE(pid >= 0) << "Fork Error";
434     if (pid == 0) {
435         int (*fun)(void) = (int (*)(void))mem;
436         int five = fun();
437         LOG("five = 0x%02x", five);
438         exit(0);
439     } else {
440         ExpectProcCrashed(pid);
441 
442         EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
443         EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
444         Msleep(1000);
445         EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
446     }
447 }
448 
449 /**
450  * @tc.number SUB_KERNEL_MEM_MPROTECT_1300
451  * @tc.name   mprotect function errno for EACCES test
452  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
453  */
454 HWTEST_F(MprotectApiTest, testMprotectEACCES, Function | MediumTest | Level4)
455 {
456     void *mem = nullptr;
457     size_t len = PAGE_SIZE;
458     char file[] = MPROTECT_TESTFILE;
459 
460     int fd = open(file, O_CREAT|O_RDONLY, S_IRUSR|S_IRGRP|S_IROTH);
461     ASSERT_TRUE(fd != -1) << "ERROR: open() == -1";
462 
463     mem = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
464     LOG("__LINE__ = %d, mem = %p", __LINE__, mem);
465     EXPECT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED, errno = " << errno;
466 
467     int ret = mprotect(mem, len, PROT_WRITE);
468     EXPECT_TRUE(ret == -1) << "mprotect() != -1, ret = " << ret;
469     EXPECT_TRUE(errno == EACCES) << "ERROR: errno != EACCES, errno = " << errno << " EACCES = " << EACCES;
470 
471     EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
472     EXPECT_TRUE(close(fd) != -1) << "ERROR: close() == -1";
473     Msleep(1000);
474     EXPECT_TRUE(remove(file) == 0) << "ERROR: remove() != 0" << errno;
475 }
476 
477 /**
478  * @tc.number SUB_KERNEL_MEM_MPROTECT_1400
479  * @tc.name   mprotect function errno for EINVAL test
480  * @tc.desc   [C-L*-311] MUST NOT alter NDK API behavior.
481  */
482 HWTEST_F(MprotectApiTest, testMprotectEINVAL, Function | MediumTest | Level4)
483 {
484     size_t len = PAGE_SIZE;
485 
486     void *mem = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
487     LOG("__LINE__ = %d, mem = %p", __LINE__, mem);
488     ASSERT_TRUE(mem != MAP_FAILED) << "mem == MAP_FAILED, errno = " << errno;
489 
490     size_t invalueAddr = ((size_t)(uintptr_t)mem) | 0x123;
491     int ret = mprotect((void *)invalueAddr, len, PROT_WRITE);
492     EXPECT_TRUE(ret == -1) << "mprotect() != -1, ret = " << ret;
493     EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
494 
495     ret = mprotect((void *)nullptr, len, PROT_WRITE);
496     EXPECT_TRUE(ret == -1) << "mprotect() != -1, ret = " << ret;
497     EXPECT_TRUE(errno == EINVAL) << "ERROR: errno != EINVAL, errno = " << errno << " EINVAL = " << EINVAL;
498 
499     EXPECT_TRUE(munmap(mem, len) == 0) << "ERROR: munmap() != 0";
500 }