1/* 2 * Copyright (c) 2023-2024 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 <gtest/gtest.h> 17#include <fcntl.h> 18#include <cinttypes> 19#include <climits> 20#include <cstdio> 21#include <cstdlib> 22#include <unistd.h> 23#include <iomanip> 24#include <iostream> 25#include <string> 26#include <vector> 27#include <sys/mman.h> 28#include <sys/utsname.h> 29#include <string> 30#include <memory.h> 31#include <csetjmp> 32#include "securec.h" 33 34#define PAGE_SIZE 4096 35 36using namespace testing::ext; 37using namespace std; 38 39class MmapApiTest : public testing::Test { 40public: 41 static void SetUpTestCase(); 42 static void TearDownTestCase(); 43 void SetUp(); 44 void TearDown(); 45private: 46}; 47void MmapApiTest::SetUp() 48{ 49} 50void MmapApiTest::TearDown() 51{ 52} 53void MmapApiTest::SetUpTestCase() 54{ 55} 56void MmapApiTest::TearDownTestCase() 57{ 58} 59 60static int g_sigStarted = 0; 61 62static void SigsegvHandler(int signum) 63{ 64 if (g_sigStarted) { 65 g_sigStarted = 0; 66 } else { 67 std::cout << "case failed.\n" << std::endl; 68 ASSERT_TRUE(g_sigStarted != 0); 69 } 70} 71 72static void CreateFile() 73{ 74 FILE *file; 75 int ret = -1; 76 char *buffer = static_cast<char *>(malloc(PAGE_SIZE)); 77 if (buffer != nullptr) { 78 ret = memset_s(buffer, PAGE_SIZE, 'a', PAGE_SIZE); 79 ASSERT_TRUE(ret == 0); 80 file = fopen("output_file.txt", "wb"); 81 if (fwrite(buffer, 1, PAGE_SIZE, file) != PAGE_SIZE) { 82 std::cout << "Error fwrite file.\n" << std::endl; 83 ASSERT_TRUE(ret != 0); 84 } 85 fclose(file); 86 } 87 free(buffer); 88} 89 90/* 91 * @tc.number SUB_KERNEL_MEM_MAP_0100 92 * @tc.name MremapDontunmap001 93 * @tc.desc mremap use MREMAP_DONTUNMAP with old len == new len 94*/ 95HWTEST_F(MmapApiTest, MremapDontunmap001, Function | MediumTest | Level1) 96{ 97 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 98 ASSERT_TRUE(addr != MAP_FAILED); 99 void *fixAddr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 100 ASSERT_TRUE(fixAddr != MAP_FAILED); 101 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE, MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, fixAddr); 102 ASSERT_TRUE(newAddr != MAP_FAILED); 103 int ret = munmap(addr, PAGE_SIZE); 104 ASSERT_TRUE(ret == 0); 105 ret = munmap(fixAddr, PAGE_SIZE); 106 ASSERT_TRUE(ret == 0); 107 ret = munmap(newAddr, PAGE_SIZE); 108 ASSERT_TRUE(ret == 0); 109 addr = nullptr; 110 fixAddr = nullptr; 111 newAddr = nullptr; 112} 113 114/* 115 * @tc.number SUB_KERNEL_MEM_MAP_0200 116 * @tc.name MremapDontunmap002 117 * @tc.desc mremap use MREMAP_DONTUNMAP with MAP_SHARED 118*/ 119HWTEST_F(MmapApiTest, MremapDontunmap002, Function | MediumTest | Level2) 120{ 121 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); 122 ASSERT_TRUE(addr != MAP_FAILED); 123 void *fixAddr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); 124 ASSERT_TRUE(fixAddr != MAP_FAILED); 125 void *newAddr = mremap(fixAddr, PAGE_SIZE, PAGE_SIZE, MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, addr); 126 ASSERT_TRUE(newAddr != MAP_FAILED); 127 int ret = munmap(addr, PAGE_SIZE); 128 ASSERT_TRUE(ret == 0); 129 ret = munmap(fixAddr, PAGE_SIZE); 130 ASSERT_TRUE(ret == 0); 131 ret = munmap(newAddr, PAGE_SIZE); 132 ASSERT_TRUE(ret == 0); 133 addr = nullptr; 134 fixAddr = nullptr; 135 newAddr = nullptr; 136} 137 138/* 139 * @tc.number SUB_KERNEL_MEM_MAP_0300 140 * @tc.name MremapDontunmap003 141 * @tc.desc mremap use MREMAP_DONTUNMAP with old len != new len 142*/ 143HWTEST_F(MmapApiTest, MremapDontunmap003, Function | MediumTest | Level1) 144{ 145 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 146 ASSERT_TRUE(addr != MAP_FAILED); 147 void *fixAddr = mmap(nullptr, PAGE_SIZE * 2, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 148 ASSERT_TRUE(fixAddr != MAP_FAILED); 149 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE * 2, MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, fixAddr); 150 ASSERT_TRUE(newAddr == MAP_FAILED); 151 int ret = munmap(addr, PAGE_SIZE); 152 ASSERT_TRUE(ret == 0); 153 ret = munmap(fixAddr, PAGE_SIZE * 2); 154 ASSERT_TRUE(ret == 0); 155 addr = nullptr; 156 fixAddr = nullptr; 157 newAddr = nullptr; 158} 159/* 160 * @tc.number SUB_KERNEL_MEM_MAP_0400 161 * @tc.name MremapDontunmap004 162 * @tc.desc mremap use MREMAP_DONTUNMAP without MREMAP_MAYMOVE 163*/ 164HWTEST_F(MmapApiTest, MremapDontunmap004, Function | MediumTest | Level1) 165{ 166 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 167 ASSERT_TRUE(addr != MAP_FAILED); 168 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE, MREMAP_FIXED | MREMAP_DONTUNMAP); 169 ASSERT_TRUE(newAddr == MAP_FAILED); 170 int ret = munmap(addr, PAGE_SIZE); 171 ASSERT_TRUE(ret == 0); 172 addr = nullptr; 173 newAddr = nullptr; 174} 175 176/* 177 * @tc.number SUB_KERNEL_MEM_MAP_0500 178 * @tc.name MremapDontunmap005 179 * @tc.desc mremap use MREMAP_DONTUNMAP with MREMAP_MAYMOVE 180*/ 181HWTEST_F(MmapApiTest, MremapDontunmap005, Function | MediumTest | Level1) 182{ 183 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 184 ASSERT_TRUE(addr != MAP_FAILED); 185 void *newAddr = mremap(addr, PAGE_SIZE, PAGE_SIZE, MREMAP_MAYMOVE | MREMAP_DONTUNMAP); 186 ASSERT_TRUE(newAddr != MAP_FAILED); 187 int ret = munmap(addr, PAGE_SIZE); 188 ASSERT_TRUE(ret == 0); 189 ret = munmap(newAddr, PAGE_SIZE); 190 ASSERT_TRUE(ret == 0); 191 addr = nullptr; 192 newAddr = nullptr; 193} 194 195/* 196 * @tc.number SUB_KERNEL_MEM_MAP_0800 197 * @tc.name MMAPShardValidate001 198 * @tc.desc mmap use MAP_SHARED_VALIDATE or MAP_SHARED with MAP_SYNC 199*/ 200HWTEST_F(MmapApiTest, MMAPShardValidate001, Function | MediumTest | Level1) 201{ 202 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON | MAP_SYNC, -1, 0); 203 ASSERT_TRUE(va != MAP_FAILED); 204 void *newVa = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED_VALIDATE | MAP_ANON | MAP_SYNC, -1, 0); 205 ASSERT_TRUE(newVa == MAP_FAILED); 206 int ret = munmap(va, PAGE_SIZE); 207 ASSERT_TRUE(ret == 0); 208 va = nullptr; 209 newVa = nullptr; 210} 211 212/* 213 * @tc.number SUB_KERNEL_MEM_MAP_0900 214 * @tc.name MMAPShardValidate002 215 * @tc.desc mmap use MAP_SHARED_VALIDATE with no error param 216*/ 217HWTEST_F(MmapApiTest, MMAPShardValidate002, Function | MediumTest | Level1) 218{ 219 CreateFile(); 220 int fd = open("output_file.txt", O_RDWR); 221 ASSERT_TRUE(fd > 0); 222 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED_VALIDATE, fd, 0); 223 ASSERT_TRUE(va != MAP_FAILED); 224 int ret = munmap(va, PAGE_SIZE); 225 ASSERT_TRUE(ret == 0); 226 va = nullptr; 227 close(fd); 228 ret = unlink("output_file.txt"); 229 ASSERT_TRUE(ret == 0); 230} 231 232/* 233 * @tc.number SUB_KERNEL_MEM_MAP_1000 234 * @tc.name MMAPNonBlock001 235 * @tc.desc mmap use MAP_NONBLOCK 236*/ 237HWTEST_F(MmapApiTest, MMAPNonBlock001, Function | MediumTest | Level1) 238{ 239 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_NONBLOCK, -1, 0); 240 ASSERT_TRUE(va != MAP_FAILED); 241 int ret = munmap(va, PAGE_SIZE); 242 ASSERT_TRUE(ret == 0); 243 va = nullptr; 244} 245 246/* 247 * @tc.number SUB_KERNEL_MEM_MAP_1400 248 * @tc.name MMAPGrownsDown001 249 * @tc.desc MAP_GROWSDONW when the pre-vregion is not MAP_GROWSDONW 250*/ 251HWTEST_F(MmapApiTest, MMAPGrownsDown001, Function | MediumTest | Level1) 252{ 253 const size_t lenGdGap = (2UL << 20); 254 const size_t lenLeftMap = 0x1000; 255 const size_t lenGd = 0x1000; 256 const size_t lenReserve = lenLeftMap + lenGdGap + lenGd; 257 258 char *addReserve = nullptr; 259 char *addrGd = nullptr; 260 int ret = -1; 261 262 addReserve = (char *)mmap(nullptr, lenReserve, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 263 ASSERT_TRUE(addReserve != MAP_FAILED); 264 void *addr1 = mmap(addReserve, lenLeftMap, PROT_READ, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); 265 ASSERT_TRUE(addr1 != MAP_FAILED); 266 addrGd = (char *)mmap(addReserve + lenLeftMap + lenGdGap, lenGd, PROT_READ | PROT_WRITE, 267 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0); 268 ASSERT_TRUE(addrGd != MAP_FAILED); 269 270 g_sigStarted = 1; 271 struct sigaction sa; 272 sa.sa_handler = SigsegvHandler; 273 sigemptyset(&sa.sa_mask); 274 sa.sa_flags = 0; 275 ret = sigaction(SIGSEGV, &sa, nullptr); 276 ASSERT_TRUE(ret == 0); 277 int cpage = 256; 278 addrGd[cpage * -0x1000] = '1'; 279 ret = munmap(addReserve, lenReserve); 280 ASSERT_TRUE(ret == 0); 281 ret = munmap(addr1, lenLeftMap); 282 ASSERT_TRUE(ret == 0); 283 ret = munmap(addrGd, lenGd); 284 ASSERT_TRUE(ret == 0); 285 addReserve = nullptr; 286 addr1 = nullptr; 287 addrGd = nullptr; 288} 289 290/* 291 * @tc.number SUB_KERNEL_MEM_MAP_1500 292 * @tc.name MMAPGrownsDown002 293 * @tc.desc mprotect use PROT_GROWSDONW 294*/ 295HWTEST_F(MmapApiTest, MMAPGrownsDown002, Function | MediumTest | Level1) 296{ 297 const size_t lenGdGap = (2UL << 20); 298 const size_t lenLeftMap = 0x1000; 299 const size_t lenGd = 0x1000; 300 const size_t lenReserve = lenLeftMap + lenGdGap + lenGd; 301 char *addReserve = nullptr; 302 char *addrGd = nullptr; 303 int ret = -1; 304 305 addReserve = (char *)mmap(nullptr, lenReserve, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 306 ASSERT_TRUE(addReserve != MAP_FAILED); 307 void *addr1 = mmap(addReserve, lenLeftMap, PROT_READ, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); 308 ASSERT_TRUE(addr1 != MAP_FAILED); 309 addrGd = (char *)mmap(addReserve + lenLeftMap + lenGdGap, lenGd, PROT_READ, 310 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0); 311 ASSERT_TRUE(addrGd != MAP_FAILED); 312 313 ret = mprotect(addrGd, lenGd, PROT_READ | PROT_WRITE | PROT_GROWSDOWN); 314 ASSERT_TRUE(ret == 0); 315 g_sigStarted = 1; 316 struct sigaction sa; 317 sa.sa_handler = SigsegvHandler; 318 sigemptyset(&sa.sa_mask); 319 sa.sa_flags = 0; 320 ret = sigaction(SIGSEGV, &sa, nullptr); 321 ASSERT_TRUE(ret == 0); 322 int cpage = 256; 323 addrGd[cpage * -0x1000] = '1'; 324 ret = munmap(addReserve, lenReserve); 325 ASSERT_TRUE(ret == 0); 326 ret = munmap(addr1, lenLeftMap); 327 ASSERT_TRUE(ret == 0); 328 ret = munmap(addrGd, lenGd); 329 ASSERT_TRUE(ret == 0); 330 addReserve = nullptr; 331 addr1 = nullptr; 332 addrGd = nullptr; 333} 334 335/* 336 * @tc.number SUB_KERNEL_MEM_MAP_1600 337 * @tc.name MMAPGrownsDown003 338 * @tc.desc MAP_GROWSDONW when MAP_SHARED 339*/ 340HWTEST_F(MmapApiTest, MMAPGrownsDown003, Function | MediumTest | Level1) 341{ 342 void *va = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED | MAP_GROWSDOWN, -1, 0); 343 ASSERT_TRUE(va == MAP_FAILED); 344 va = nullptr; 345} 346 347/* 348 * @tc.number SUB_KERNEL_MEM_MAP_1700 349 * @tc.name MMAPGrownsDown004 350 * @tc.desc MAP_GROWSDONW when the pre-vregion is MAP_GROWSDONW 351*/ 352HWTEST_F(MmapApiTest, MMAPGrownsDown004, Function | MediumTest | Level1) 353{ 354 const size_t lenGd1 = 0x2000; 355 const size_t lenGd2 = 0x2000; 356 const size_t lenReserve = 0x1000 * 6; 357 358 char *addReserve = nullptr; 359 char *addrGd1 = nullptr; 360 char *addrGd2 = nullptr; 361 int ret = -1; 362 363 addReserve = (char *)mmap(nullptr, lenReserve, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 364 ASSERT_TRUE(addReserve != MAP_FAILED); 365 addrGd1 = (char *)mmap(addReserve, lenGd1, PROT_READ | PROT_WRITE, 366 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0); 367 ASSERT_TRUE(addrGd1 != MAP_FAILED); 368 addrGd2 = (char *)mmap(addReserve + (lenReserve - lenGd2), lenGd2, PROT_READ | PROT_WRITE, 369 MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0); 370 ASSERT_TRUE(addrGd2 != MAP_FAILED); 371 g_sigStarted = 1; 372 struct sigaction sa; 373 sa.sa_handler = SigsegvHandler; 374 sigemptyset(&sa.sa_mask); 375 sa.sa_flags = 0; 376 ret = sigaction(SIGSEGV, &sa, nullptr); 377 ASSERT_TRUE(ret == 0); 378 addrGd2[-0x1000] = '1'; 379 addrGd2[-0x2000] = '1'; 380 ret = munmap(addReserve, lenReserve); 381 ASSERT_TRUE(ret == 0); 382 ret = munmap(addrGd1, lenGd1); 383 ASSERT_TRUE(ret == 0); 384 ret = munmap(addrGd2, lenGd2); 385 ASSERT_TRUE(ret == 0); 386 addReserve = nullptr; 387 addrGd1 = nullptr; 388 addrGd2 = nullptr; 389}