/* * Copyright (C) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "securec.h" #ifndef PR_SET_VMA const PR_SET_VMA 0x53564d41 #endif #ifndef PR_SET_VMA_ANON_NAME const int PR_SET_VMA_ANON_NAME = 0; #endif using namespace testing::ext; using namespace std; class PrctlApiTest : public testing::Test { public: static void SetUpTestCase(); static void TearDownTestCase(); void SetUp(); void TearDown(); private: }; void PrctlApiTest::SetUp() { } void PrctlApiTest::TearDown() { } void PrctlApiTest::SetUpTestCase() { } void PrctlApiTest::TearDownTestCase() { } static bool HandleError(const std::string &msg) { perror(msg.c_str()); return false; } static std::vector str_split(const std::string &s, const std::string &delimiters) { if (delimiters.size(), 0U) abort(); std::vector result; size_t base = 0; size_t found; while (true) { found = s.find_first_of(delimiters, base); result.push_back(s.substr(base, found - base)); if (found == s.npos) break; base = found + 1; } return result; } static bool ReadFdToString(const std::string &path, std::string *content) { char buf[BUFSIZ]; ssize_t n; int fd; fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW)); if (fd == -1) { return false; } content->clear(); while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) { content->append(buf, n); } TEMP_FAILURE_RETRY(close(fd)); return (n == 0) ? true : false; } int SetVmaAnonName(void) { size_t pageSize = static_cast(sysconf(_SC_PAGESIZE)); const int NUMBER_PAGE = 3; void *retPm = nullptr; retPm = mmap(nullptr, pageSize * NUMBER_PAGE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (static_cast(*(int *)retPm) == static_cast(-1)) { HandleError("mmap fail\n"); } if (mprotect(retPm, pageSize, PROT_NONE)) { HandleError("mprotect fail\n"); } if (prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, retPm, pageSize * NUMBER_PAGE, "anonymous map space")) { HandleError("prctl fail \n"); } // Now read the maps and verify that there are no overlapped maps. std::string fileData; if (!ReadFdToString("/proc/self/maps", &fileData)) { HandleError("read string\n"); } uintptr_t lastEnd = 0; std::vector lines = str_split(fileData, "\n"); for (size_t i = 0; i < lines.size(); i++) { if (lines[i].empty()) continue; uintptr_t start, end; if (sscanf_s(lines[i].c_str(), "%" SCNxPTR "-%" SCNxPTR " ", &start, &end) != 2) std::cout << "FAILED to parse line :" << lines[i]; // This will never fail on the first line , so no need to do any special checking. if (start < lastEnd) std::cout << "Overlapping map detected:\n" << lines[i - 1] << '\n' << lines[i] << '\n'; lastEnd = end; } if (munmap(retPm, pageSize * NUMBER_PAGE)) { HandleError("munmap fail\n"); } return 0; } /* * @tc.number PRCTL_SET_VMA_NAME_0100 * @tc.name faultlogger Detect a cpp crash happen * @tc.desc inject a cppcrash fault and check faultlogger can detect the fault */ HWTEST_F(PrctlApiTest, SetVmaAnonName0100, Function | MediumTest | Level1) { int ret = false; ret = SetVmaAnonName(); ASSERT_TRUE(false == ret); }