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 }