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