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 30using namespace testing::ext; 31 32#define MREMAP_TESTFILE "/storage/testMremap.txt" 33 34class 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 */ 42HWTEST_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 */ 54HWTEST_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 */ 67HWTEST_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 */ 109HWTEST_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 */ 147HWTEST_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 */ 191HWTEST_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 */ 231HWTEST_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 */ 283HWTEST_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 */ 333HWTEST_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 */ 388HWTEST_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 */ 442HWTEST_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