diff --git a/bundle.json b/bundle.json index 873ce1141bb1c0d3967a459d1731b0ff823e548e..3fddf38202e4295b22764c429769c71993314b37 100644 --- a/bundle.json +++ b/bundle.json @@ -38,11 +38,13 @@ "huks", "ipc", "safwk", - "samgr" + "samgr", + "code_signature" ], "third_party": [ "cJSON", - "openssl" + "openssl", + "selinux" ] }, "build": { @@ -71,7 +73,8 @@ ], "test": [ "//base/security/device_security_level/test/dslm_unit_test:dslm_test", - "//base/security/device_security_level/test/dslm_fuzz_test:dslm_fuzz" + "//base/security/device_security_level/test/dslm_fuzz_test:dslm_fuzz", + "//base/security/device_security_level/test/xpm_unit_test:xpm_test" ] } } diff --git a/test/xpm_unit_test/BUILD.gn b/test/xpm_unit_test/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..58d0e555323cf5097606b6622064c6738538c9ef --- /dev/null +++ b/test/xpm_unit_test/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 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. + +import("//build/ohos.gni") +import("//build/test.gni") + +group("xpm_test") { + testonly = true + deps = [] + + if (os_level == "standard") { + deps += [ + "lib:libxpm", + ":xpm_unit_test", + ] + } +} + +ohos_unittest("xpm_unit_test") { + sources = [ + "common/xpm_common.cpp", + "xpm_normal_elf_test.cpp", + "xpm_webview_test.cpp", + "xpm_normal_hap_test.cpp", + "xpm_debug_hap_test.cpp", + "xpm_integrity_test.cpp", + "xpm_ownerid_test.cpp" + ] + + include_dirs = [ + ".", + "common", + ] + + cflags = [ + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-DSUPPORT_KNOWN_EXCEPTION", + ] + cflags_cc = cflags + + deps = [ + "//third_party/selinux:libselinux", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "code_signature:libcode_sign_attr_utils", + "code_signature:libcode_sign_utils", + ] + + install_enable = true + testonly = true + part_name = "device_security_level" + subsystem_name = "security" + module_out_path = "${part_name}/${target_name}" +} diff --git a/test/xpm_unit_test/common/xpm_common.cpp b/test/xpm_unit_test/common/xpm_common.cpp new file mode 100755 index 0000000000000000000000000000000000000000..192be667304d714aaa0436070fa934dc4ab7aed3 --- /dev/null +++ b/test/xpm_unit_test/common/xpm_common.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (c) 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 "xpm_common.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "selinux/selinux.h" +#include "file_ex.h" + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +int GetXpmRegion(struct XpmRegionArea &area) +{ + if (InitXpmRegion() != 0) { + XPM_LOG_ERROR("init xpm region failed"); + return -1; + } + + pid_t pid = getpid(); + std::string path = XPM_PROC_PREFIX_PATH + std::to_string(pid) + XPM_PROC_SUFFIX_PATH; + int fd = open(path.c_str(), O_RDWR); + if (fd < 0) { + XPM_LOG_ERROR("open xpm proc file failed(%{public}s)", strerror(errno)); + return -1; + } + + char xpm_region[XPM_PROC_LENGTH] = {0}; + int ret = read(fd, xpm_region, sizeof(xpm_region)); + if (ret < 0) { + XPM_LOG_ERROR("read xpm proc file failed(%{public}s)", strerror(errno)); + return -1; + } + + ret = sscanf(xpm_region, "%llx-%llx", &area.start, &area.end); + if (ret < 0) { + XPM_LOG_ERROR("sscanf xpm region string failed(%{public}s)", strerror(errno)); + return -1; + } + + close(fd); + return 0; +} + +bool IsXpmRegionInner(unsigned long start, unsigned long end) +{ + struct XpmRegionArea area = {0}; + + int ret = GetXpmRegion(area); + if (ret < 0) { + XPM_LOG_ERROR("get xpm region failed"); + return false; + } + + if (start >= area.start && end <= area.end) { + return true; + } + + return false; +} + +bool IsXpmRegionOuter(unsigned long start, unsigned long end) +{ + struct XpmRegionArea area = {0}; + + int ret = GetXpmRegion(area); + if (ret < 0) { + XPM_LOG_ERROR("get xpm region failed"); + return false; + } + + if (start >= area.end || end <= area.start) { + return true; + } + + return false; +} + +int SetCon(const std::string &type) +{ + return setcon(type.c_str()); +} + +int ExecSumFun(void *addr) +{ + int ret = ((SumFunc)addr)(1, 2); + + printf("ret is %d\n", ret); + return ret == 4 ? 0 : -1; +} + +int AccessData(void *addr, int op) +{ + uint8_t val; + switch (op) { + case OP_READ: //只读 + val = ((uint8_t *)addr)[0]; + break; + case OP_WRITE:{ //写前读 + val = ((uint8_t *)addr)[0]; + ((uint8_t *)addr)[100] = val; + } + break; + case OP_WRITE_ONLY: //只写 + ((uint8_t *)addr)[100] = 3; + break; + default: + break; + } + + return 0; +} + +static int GetElf64Segment(uint8_t *buf, unsigned long &offset, unsigned long &size, uint32_t flag) +{ + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)buf; + uint32_t phNum = ehdr->e_phnum; + Elf64_Phdr *phdr = (Elf64_Phdr *)&buf[ehdr->e_phoff]; + + for (int i = phNum - 1; i >= 0; i--) { + if ((phdr[i].p_type == PT_LOAD) && ((phdr[i].p_flags & flag) == flag)) { + offset = phdr[i].p_offset; + size = phdr[i].p_filesz; + return 0; + } + } + + return -1; +} + +static int GetElf32Segment(uint8_t *buf, unsigned long &offset, unsigned long &size, uint32_t flag) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)buf; + uint32_t phNum = ehdr->e_phnum; + Elf32_Phdr *phdr = (Elf32_Phdr *)&buf[ehdr->e_phoff]; + + for (int i = phNum - 1; i >= 0; i--) { + if ((phdr[i].p_type == PT_LOAD) && ((phdr[i].p_flags & flag) == flag)) { + offset = phdr[i].p_offset; + size = phdr[i].p_filesz; + return 0; + } + } + + return -1; +} + +static int GetFileStat(const std::string &path, int &fd, uint32_t &length) +{ + fd = open(path.c_str(), O_RDONLY); + if (fd < 0) { + XPM_LOG_ERROR("open file %{public}s failed: %{public}s", path.c_str(), strerror(errno)); + return -1; + } + + struct stat fileState = {0}; + if (fstat(fd, &fileState) != 0) { + XPM_LOG_ERROR("fsstat %{public}s failed", path.c_str()); + close(fd); + return -1; + } + + if (fileState.st_size < EI_NIDENT) { + XPM_LOG_ERROR("file %{public}s stat size invalid", path.c_str()); + close(fd); + return -1; + } + length = fileState.st_size; + + return 0; +} + +static int ParseElfInfo(uint8_t *addr, unsigned long &offset, unsigned long &size, uint32_t flag) +{ + int ret = -1; + + switch (addr[EI_CLASS]) { + case ELFCLASS64: + ret = GetElf64Segment(addr, offset, size, flag); + break; + case ELFCLASS32: + ret = GetElf32Segment(addr, offset, size, flag); + break; + default: + break; + } + + return ret; +} + +static int GetSegment(const std::string &path, unsigned long &offset, unsigned long &size, uint32_t flag) +{ + int fd; + uint32_t length; + + if (path.length() == 0) { + XPM_LOG_ERROR("input path is invalid"); + return -1; + } + + int ret = GetFileStat(path, fd, length); + if (ret != 0) { + XPM_LOG_ERROR("get file %{public}s stat failed", path.c_str()); + return ret; + } + + void *addr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0); + if (addr == MAP_FAILED) { + XPM_LOG_ERROR("mmap failed: %{public}s", strerror(errno)); + close(fd); + return -1; + } + + ret = -1; + do { + if (memcmp(addr, ELFMAG, SELFMAG) != 0) { + XPM_LOG_ERROR("file is not elf"); + break; + } + + ret = ParseElfInfo(reinterpret_cast(addr), offset, size, flag); + if (ret != 0) { + XPM_LOG_ERROR("parset elf info failed"); + break; + } + } while (0); + munmap(addr, length); + close(fd); + + return ret; +} + +int GetCodeSegment(const std::string &path, unsigned long &offset, unsigned long &size) +{ + + return GetSegment(path, offset, size, PF_X); +} + +int GetDataSegment(const std::string &path, unsigned long &offset, unsigned long &size) +{ + return GetSegment(path, offset, size, PF_R | PF_W); +} +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/test/xpm_unit_test/common/xpm_common.h b/test/xpm_unit_test/common/xpm_common.h new file mode 100755 index 0000000000000000000000000000000000000000..fcb8d64040da78e805e07c0d03428a88e5f69f69 --- /dev/null +++ b/test/xpm_unit_test/common/xpm_common.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef XPM_COMMON_H +#define XPM_COMMON_H + +#include +#include + +#include "code_sign_attr_utils.h" +#include "xpm_log.h" + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +struct XpmRegionArea { + uint64_t start; + uint64_t end; +}; + +const std::string XPM_LIB_PATH = "/system/lib/libxpm.z.so"; +const std::string XPM_PROC_PREFIX_PATH = "/proc/"; +const std::string XPM_PROC_SUFFIX_PATH = "/xpm_region"; +const std::string XPM_DEBUG_FS_MODE_PATH = "/sys/kernel/debug/xpm/xpm_mode"; +const std::string SELINUX_MODE_PATH = "/sys/fs/selinux/enforce"; + +const std::string SELINUX_TYPE_NWEBSPAWN = "u:r:isolated_render:s0"; +const std::string SELINUX_TYPE_DEBUG_HAP = "u:r:debug_hap:s0"; +const std::string SELINUX_TYPE_SH = "u:r:sh:s0"; +const std::string PERMISSIVE_MODE = "0"; +const std::string ENFORCE_MODE = "1"; + +constexpr unsigned long XPM_PROC_LENGTH = 50; +constexpr unsigned long MAP_XPM = 0x40; + +constexpr unsigned long SUM_FUN_OFFSET = 0x0; +constexpr unsigned long ANON_SIZE = 0x1000; +constexpr unsigned long NEW_ANON_SIZE = ANON_SIZE; + +const unsigned long PAGE_SIZE = (sysconf(_SC_PAGESIZE)); +const unsigned long PAGE_MASK = ~(PAGE_SIZE - 1); + +constexpr unsigned int OP_READ = 0; +constexpr unsigned int OP_WRITE = 1; +constexpr unsigned int OP_WRITE_ONLY = 2; + +typedef int (*SumFunc)(int, int); + +int GetXpmRegion(struct XpmRegionArea &area); +bool IsXpmRegionInner(unsigned long start, unsigned long end); +bool IsXpmRegionOuter(unsigned long start, unsigned long end); + +int ExecSumFun(void *addr); +int AccessData(void *addr, int op); + +int SetCon(const std::string &type); + +int GetDataSegment(const std::string &path, unsigned long &start, unsigned long &end); +int GetCodeSegment(const std::string &path, unsigned long &start, unsigned long &end); + +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/test/xpm_unit_test/common/xpm_log.h b/test/xpm_unit_test/common/xpm_log.h new file mode 100755 index 0000000000000000000000000000000000000000..e848d1b28a49949f4b0fc8edcd64e54a3f7ea620 --- /dev/null +++ b/test/xpm_unit_test/common/xpm_log.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 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. + */ + +#ifndef XPM_LOG_H +#define XPM_LOG_H + +#include "hilog/log.h" + +#ifndef __cplusplus +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "XPM_TEST" + +#ifdef LOG_DOMAIN +#undef LOG_DOMAIN +#endif +#define LOG_DOMAIN 0xD002F00 + +#define XPM_LOG_DEBUG(fmt, ...) HILOG_DEBUG(LOG_CORE, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) +#define XPM_LOG_INFO(fmt, ...) HILOG_INFO(LOG_CORE, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) +#define XPM_LOG_WARN(fmt, ...) HILOG_WARN(LOG_CORE, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) +#define XPM_LOG_ERROR(fmt, ...) HILOG_ERROR(LOG_CORE, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) +#define XPM_LOG_FATAL(fmt, ...) HILOG_FATAL(LOG_CORE, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) + +#else // __cplusplus +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD002F00, "XPM_TEST"}; + +#define XPM_LOG_DEBUG(fmt, ...) \ + OHOS::HiviewDFX::HiLog::Debug(LABEL, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) +#define XPM_LOG_INFO(fmt, ...) \ + OHOS::HiviewDFX::HiLog::Info(LABEL, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) +#define XPM_LOG_WARN(fmt, ...) \ + OHOS::HiviewDFX::HiLog::Warn(LABEL, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) +#define XPM_LOG_ERROR(fmt, ...) \ + OHOS::HiviewDFX::HiLog::Error(LABEL, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) +#define XPM_LOG_FATAL(fmt, ...) \ + OHOS::HiviewDFX::HiLog::Fatal(LABEL, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) + +#endif // __cplusplus +#endif // XPM_LOG_H \ No newline at end of file diff --git a/test/xpm_unit_test/lib/BUILD.gn b/test/xpm_unit_test/lib/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..ab5c8521f1df5dd8f067ef041aa93ae8a053fd55 --- /dev/null +++ b/test/xpm_unit_test/lib/BUILD.gn @@ -0,0 +1,28 @@ +# Copyright (c) 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. + +import("//build/ohos.gni") +import("//build/test.gni") + +ohos_shared_library("libxpm") { + sources = [ "xpm_lib.c" ] + + ldflags = [ + "-Wl,-z,max-page-size=4096", + "-Wl,-z,separate-code", +] + + install_enable = true + part_name = "device_security_level" + subsystem_name = "security" +} diff --git a/test/xpm_unit_test/lib/xpm_lib.c b/test/xpm_unit_test/lib/xpm_lib.c new file mode 100755 index 0000000000000000000000000000000000000000..fef40222b74eb35b003167200c5271b8831b77eb --- /dev/null +++ b/test/xpm_unit_test/lib/xpm_lib.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 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 + +#define SIZE (4096 * 4) + +int abc[SIZE] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6}; + +int XpmSum(int b, int c) +{ + int sum = abc[0] + b + c; + printf("sum is %d\n", sum); + return sum; +} \ No newline at end of file diff --git a/test/xpm_unit_test/lib/xpm_lib.h b/test/xpm_unit_test/lib/xpm_lib.h new file mode 100755 index 0000000000000000000000000000000000000000..210fee3eb4f6b64026811e94bd90e23cd316ed1d --- /dev/null +++ b/test/xpm_unit_test/lib/xpm_lib.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef XPM_LIB_H +#define XPM_LIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +int XpmSum(int b, int c); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/test/xpm_unit_test/resources/hap1-shared-lib-id.hap b/test/xpm_unit_test/resources/hap1-shared-lib-id.hap new file mode 100755 index 0000000000000000000000000000000000000000..f038d7d8aca63dcd6ac9cac38cc4bf60083a6b9a Binary files /dev/null and b/test/xpm_unit_test/resources/hap1-shared-lib-id.hap differ diff --git a/test/xpm_unit_test/resources/hap2-without-ownerid.hap b/test/xpm_unit_test/resources/hap2-without-ownerid.hap new file mode 100755 index 0000000000000000000000000000000000000000..4ed30f56c2733021f21b891e2a9b1c3a17505c5e Binary files /dev/null and b/test/xpm_unit_test/resources/hap2-without-ownerid.hap differ diff --git a/test/xpm_unit_test/resources/hap3-debug-lib-id.hap b/test/xpm_unit_test/resources/hap3-debug-lib-id.hap new file mode 100755 index 0000000000000000000000000000000000000000..e76b2b08d8126a5e9c843f03ba06d498565b1773 Binary files /dev/null and b/test/xpm_unit_test/resources/hap3-debug-lib-id.hap differ diff --git a/test/xpm_unit_test/resources/hap4-ownerid-1.hap b/test/xpm_unit_test/resources/hap4-ownerid-1.hap new file mode 100755 index 0000000000000000000000000000000000000000..a955f6f466f0f1f1a7a7c27a2a25eb90e46618f6 Binary files /dev/null and b/test/xpm_unit_test/resources/hap4-ownerid-1.hap differ diff --git a/test/xpm_unit_test/resources/hap5-ownerid-2.hap b/test/xpm_unit_test/resources/hap5-ownerid-2.hap new file mode 100755 index 0000000000000000000000000000000000000000..e05ae2a4d73cb5edddb0e97344e4479490799bc4 Binary files /dev/null and b/test/xpm_unit_test/resources/hap5-ownerid-2.hap differ diff --git a/test/xpm_unit_test/resources/ohos_test.xml b/test/xpm_unit_test/resources/ohos_test.xml new file mode 100755 index 0000000000000000000000000000000000000000..3b86f3a3423835db4ab9ad9f36e31d84f4a16ae9 --- /dev/null +++ b/test/xpm_unit_test/resources/ohos_test.xml @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/xpm_unit_test/xpm_debug_hap_test.cpp b/test/xpm_unit_test/xpm_debug_hap_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..9ca4ccaf3550801feeaff127e26e009c9a12ca39 --- /dev/null +++ b/test/xpm_unit_test/xpm_debug_hap_test.cpp @@ -0,0 +1,259 @@ +/* + * Copyright (c) 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 "xpm_debug_hap_test.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "file_ex.h" +#include "xpm_common.h" + +using namespace std; +using namespace std::chrono; +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +static int g_fd; +static struct XpmRegionArea g_area; +static uint64_t g_addrStart, g_addrEnd; +static unsigned long g_dataOffset, g_dataSize; +static unsigned long g_codeOffset, g_codeSize; +void XpmDebugHapTest::SetUpTestCase() +{ + SaveStringToFile(SELINUX_MODE_PATH, PERMISSIVE_MODE); + g_fd = open(XPM_LIB_PATH.c_str(), O_RDONLY); + ASSERT_NE(-1, g_fd) << "open dev file failed" << g_fd; + + int ret = GetDataSegment(XPM_LIB_PATH, g_dataOffset, g_dataSize); + ASSERT_EQ(0, ret) << "GetDataSegment failed: " << ret; + + ret = GetCodeSegment(XPM_LIB_PATH, g_codeOffset, g_codeSize); + ASSERT_EQ(0, ret) << "GetCodeSegment failed: " << ret; + + ret = GetXpmRegion(g_area); + ASSERT_EQ(0, ret) << "GetXpmRegion failed: " << ret; + + ret = SetCon(SELINUX_TYPE_DEBUG_HAP); + ASSERT_EQ(0, ret); + + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, ENFORCE_MODE); +} + +void XpmDebugHapTest::TearDownTestCase() +{ + close(g_fd); + SetCon(SELINUX_TYPE_SH); + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, PERMISSIVE_MODE); + SaveStringToFile(SELINUX_MODE_PATH, ENFORCE_MODE); +} + +void XpmDebugHapTest::SetUp() +{ +} + +void XpmDebugHapTest::TearDown() +{ +} + +/** + * @tc.number 2 + * @tc.name: FileMmapDataToRxTest + * @tc.desc: 调试应用中数据段文件映射到r-x权限内存 + * @tc.result: 映射成功,调试应用不管控签名和代码段 + */ +HWTEST_F(XpmDebugHapTest, FileMmapDataToRxTest, TestSize.Level0) +{ + // 1. 数据段映射r-x权限 + void *addr = mmap(NULL, g_dataSize, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // release resource + munmap(addr, g_dataSize); +} + +/** + * @tc.number 6 + * @tc.name: FileMprotectDataRoToRxTest + * @tc.desc: 调试应用中数据段文件映射的r--权限内存通过mprotect修改为r-x权限 + * @tc.result: 修改操作成功,调试应用不管控签名和代码段 + */ +HWTEST_F(XpmDebugHapTest, FileMprotectDataRoToRxTest, TestSize.Level0) +{ + // 1. 数据段映射r--权限 + void *addr = mmap(NULL, g_dataSize, PROT_READ, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改数据段映射为r-x权限 + int ret = mprotect(addr, g_dataSize, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr, g_dataSize); +} + +/** + * @tc.number 12 + * @tc.name: FileRemapDataRoToRxTest + * @tc.desc: 调试应用中数据段文件映射的r--权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作成功,调试应用不管控签名和代码段 + */ +HWTEST_F(XpmDebugHapTest, FileRemapDataRoToRxTest, TestSize.Level0) +{ + // 1. 数据段映射r--权限 + void *addr1 = mmap(NULL, g_dataSize, PROT_READ, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射数据段映射 + void *addr2 = mremap(addr1, g_dataSize, g_dataSize, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射内存为r-x权限 + int ret = mprotect(addr2, g_dataSize, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr2, g_dataSize); +} + +/** + * @tc.number 13 + * @tc.name: FileRemapDataRwToRxTest + * @tc.desc: 调试应用中数据段文件映射的rw-权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作成功,调试应用不管控签名和代码段 + */ +HWTEST_F(XpmDebugHapTest, FileRemapDataRwToRxTest, TestSize.Level0) +{ + // 1. 映射数据段为rw-权限 + void *addr1 = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射数据段 + void *addr2 = mremap(addr1, g_dataSize, g_dataSize, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射数据为为r-x权限 + int ret = mprotect(addr2, g_dataSize, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr2, g_dataSize); +} + +/** + * @tc.number 18 + * @tc.name: AnonMmapRwTest + * @tc.desc: 调试应用匿名映射rw-权限内存 + * @tc.result: 匿名映射成功,rw-匿名内存不做管控 + */ +HWTEST_F(XpmDebugHapTest, AnonMmapRwTest, TestSize.Level0) +{ + // 1. 匿名映射rw-权限 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); + + munmap(addr, ANON_SIZE); +} + +/** + * @tc.number 19 + * @tc.name: AnonMmapRwxTest + * @tc.desc: 调试应用匿名映射rwx权限内存 + * @tc.result: 匿名映射成功,调试应用允许匿名映射x权限 + */ +HWTEST_F(XpmDebugHapTest, AnonMmapRwxTest, TestSize.Level0) +{ + // 1. 匿名映射rwx权限 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); +} + +/** + * @tc.number 20 + * @tc.name: AnonMprotectRwToRwxTest + * @tc.desc: 调试应用匿名映射的rw权限内存通过mprotect修改为rwx匿名内存 + * @tc.result: 修改匿名内存为rwx成功,调试应用允许匿名映射x权限 + */ +HWTEST_F(XpmDebugHapTest, AnonMprotectRwToRwxTest, TestSize.Level0) +{ + // 1. 匿名映射映射rw-内存 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改匿名内存为rwx + int ret = mprotect(addr, ANON_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_EQ(0, ret); + + // release resource + munmap(addr, ANON_SIZE); +} + +/** + * @tc.number 21 + * @tc.name: AnonMprotectRwToRwxTest + * @tc.desc: 调试应用匿名映射的rw-权限内存通过mprotect修改为r--匿名内存,之后再修改为r-x匿名内存 + * @tc.result: 修改匿名内存为rx成功,调试应用允许匿名映射x权限 + */ +HWTEST_F(XpmDebugHapTest, AnonMprotectRwToRoToRxTest, TestSize.Level0) +{ + // 1. 匿名映射映射rw-内存 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改匿名内存为r-- + int ret = mprotect(addr, ANON_SIZE, PROT_READ); + EXPECT_EQ(0, ret); + + // 3. 修改匿名内存为r-x + ret = mprotect(addr, ANON_SIZE, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + // release resource + munmap(addr, ANON_SIZE); +} + +/** + * @tc.number 22 + * @tc.name: AnonRmapRwToRxTest + * @tc.desc: 调试应用匿名映射的rw-权限内存重映射到r-x匿名内存 + * @tc.result: 重映射到r-x成功,调试应用允许匿名映射x权限 + */ +HWTEST_F(XpmDebugHapTest, AnonRmapRwToRxTest, TestSize.Level0) +{ + // 1. 匿名映射映射rw-内存 + void *addr1 = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射匿名内存 + void *addr2 = mremap(addr1, ANON_SIZE, NEW_ANON_SIZE, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改匿名内存为r-x + int ret = mprotect(addr2, NEW_ANON_SIZE, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + // release resource + munmap(addr2, ANON_SIZE); +} + +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/test/xpm_unit_test/xpm_debug_hap_test.h b/test/xpm_unit_test/xpm_debug_hap_test.h new file mode 100755 index 0000000000000000000000000000000000000000..27c4d80654f3248e519f190ff8665b66c49ef168 --- /dev/null +++ b/test/xpm_unit_test/xpm_debug_hap_test.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef XPM_ENFORCE_ABC_DEBUG_TEST +#define XPM_ENFORCE_ABC_DEBUG_TEST + +#include + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +using namespace testing::ext; +class XpmDebugHapTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS + +#endif // XPM_ENFORCE_ABC_DEBUG_TEST \ No newline at end of file diff --git a/test/xpm_unit_test/xpm_integrity_test.cpp b/test/xpm_unit_test/xpm_integrity_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..85babb85f9661cfb675d712fb7b4bb6598d6320f --- /dev/null +++ b/test/xpm_unit_test/xpm_integrity_test.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (c) 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 "xpm_integrity_test.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "file_ex.h" +#include "xpm_common.h" + +using namespace std; +using namespace std::chrono; +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +static int g_fd; +static struct XpmRegionArea g_area; +static unsigned long g_dataOffset, g_dataSize; +static unsigned long g_codeOffset, g_codeSize; + +void XpmIntegrityTest::SetUpTestCase() +{ + SaveStringToFile(SELINUX_MODE_PATH, PERMISSIVE_MODE); + g_fd = open(XPM_LIB_PATH.c_str(), O_RDWR); + ASSERT_NE(g_fd, -1) << "open xpm lib failed: " << strerror(errno); + + int ret = GetDataSegment(XPM_LIB_PATH, g_dataOffset, g_dataSize); + ASSERT_EQ(0, ret) << "GetDataSegment failed: " << ret; + + ret = GetCodeSegment(XPM_LIB_PATH, g_codeOffset, g_codeSize); + ASSERT_EQ(0, ret) << "GetCodeSegment failed: " << ret; + + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, ENFORCE_MODE); +} + +void XpmIntegrityTest::TearDownTestCase() +{ + close(g_fd); + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, PERMISSIVE_MODE); + SaveStringToFile(SELINUX_MODE_PATH, ENFORCE_MODE); +} + +void XpmIntegrityTest::SetUp() +{ +} + +void XpmIntegrityTest::TearDown() +{ +} + +/** + * @tc.number 38.ReadBeforeWrite + * @tc.name: FileRemapRoToRwTest + * @tc.desc: ABC代码同时映射到xpm region外,并设置写权限 + * @tc.result: ABC代码映射成功,但在尝试写的时候(先读后写),缺页中断处理产生XPM完整性保护异常 + */ +HWTEST_F(XpmIntegrityTest, FileRemapRoToRBWTest, TestSize.Level0) +{ + // 1. 映射为r-- + void *addr1 = mmap(NULL, g_dataOffset, PROT_READ, MAP_SHARED | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 可以读操作 + int ret = AccessData(addr1, OP_READ); + EXPECT_EQ(0, ret); + + // 3. remap到外部r-w区域 + void *addr2 = mmap(NULL, g_dataOffset, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr2); + + // 4. 写操作异常 + EXPECT_EXIT(AccessData(addr2, OP_WRITE), KilledBySignal(SIGSEGV), ""); + + munmap(addr1, g_dataOffset); + munmap(addr2, g_dataOffset); +} + + +/** + * @tc.number 38.OnlyWrite + * @tc.name: FileRemapRoToRwTest + * @tc.desc: ABC代码同时映射到xpm region外,并设置写权限 + * @tc.result: ABC代码映射成功,但在尝试写的时候(只写),缺页中断处理产生XPM完整性保护异常 + */ +HWTEST_F(XpmIntegrityTest, FileRemapRoToRWOTest, TestSize.Level0) +{ + // 1. 映射为r-- + void *addr1 = mmap(NULL, g_dataOffset, PROT_READ, MAP_SHARED | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 可以读操作 + int ret = AccessData(addr1, OP_READ); + EXPECT_EQ(0, ret); + + // 3. remap到外部r-w区域 + void *addr2 = mmap(NULL, g_dataOffset, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr2); + + // 4. 写操作异常 + EXPECT_EXIT(AccessData(addr2, OP_WRITE_ONLY), KilledBySignal(SIGSEGV), ""); + + munmap(addr1, g_dataOffset); + munmap(addr2, g_dataOffset); +} + +/** + * @tc.number 39 + * @tc.name: FileRemapOutRwToInRoTest + * @tc.desc: ABC代码先映射到xpm region外,设置写权限,更新后,再映射到xpm region内,设置为只读 + * @tc.result: ABC代码映射到xpm region外成功,并可以成功更新,但在xpm_region内尝试读的时候,缺页中断处理产生XPM完整性保护异常 + */ +HWTEST_F(XpmIntegrityTest, FileRemapOutRwToInRoTest, TestSize.Level0) +{ + // 1. 映射到外部r-w区域 + void *addr1 = mmap(NULL, g_dataOffset, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 写操作正常 + int ret = AccessData(addr1, OP_WRITE); + EXPECT_EQ(ret, 0); + + // 3. 映射到region 内设置为r-- + void *addr2 = mmap(NULL, g_dataOffset, PROT_READ, MAP_SHARED | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr2); + + // 4. 读操作触发完整性保护,执行异常 + EXPECT_EXIT(AccessData(addr2, OP_READ), KilledBySignal(SIGSEGV), ""); + + // release resource + munmap(addr1, g_dataOffset); + munmap(addr2, g_dataOffset); +} + +// 11.解析文件得到代码段信息.share +// 应用为映射代码段内容(代码)的可写区域(rw-) +// 先删除(mprotect)可写权权限(r--) +// 然后增加(mprotect)可执行权限(r-x) +// 映射操作会被放行,在运行时,页完整性阻止执行 +HWTEST_F(XpmIntegrityTest, SharedFileMprotectRWToROToRXTest, TestSize.Level0) +{ + int ret; + + //1. 映射代码为rw- + void *addr = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + //1.1 修改代码内容, 触发页污点 + ret = AccessData(addr, OP_WRITE); + EXPECT_EQ(0, ret); //通过 + + //2. 删除代码写权限 --> r-- + ret = mprotect(addr, g_codeOffset & PAGE_MASK, PROT_READ); + EXPECT_EQ(0, ret); + + //3. 增加代码执行权限 --> r-x + ret = mprotect(addr, g_codeOffset & PAGE_MASK, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + +// //4. 执行对应代码, 失败 + EXPECT_EXIT(ExecSumFun(addr), KilledBySignal(SIGSEGV), ""); + + munmap(addr, g_codeSize); +} + +// 11.解析文件得到代码段信息.private +// 应用为映射代码段内容(代码)的可写区域(rw-) +// 先删除(mprotect)可写权权限(r--) +// 然后增加(mprotect)可执行权限(r-x) +// 映射操作会被放行,在运行时,页完整性阻止执行 +HWTEST_F(XpmIntegrityTest, PrivateFileMprotectRWToROToRXTest, TestSize.Level0) +{ + int ret; + + //1. 映射代码为rw- + void *addr = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + //1.1 修改代码内容, 触发页污点 + ret = AccessData(addr, OP_WRITE); + EXPECT_EQ(0, ret); //通过 + + //2. 删除代码写权限 --> r-- + ret = mprotect(addr, g_codeOffset & PAGE_MASK, PROT_READ); + EXPECT_EQ(0, ret); + + //3. 增加代码执行权限 --> r-x + ret = mprotect(addr, g_codeOffset & PAGE_MASK, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + +// //4. 执行对应代码, 失败 + EXPECT_EXIT(ExecSumFun(addr), KilledBySignal(SIGSEGV), ""); + + munmap(addr, g_codeSize); +} + + +/** + * @tc.number 17.shared + * @tc.name: BIN_NormalFileMprotectCodeRwToRwxTest + * @tc.desc: 二进制普通文件代码段文件映射的rw-权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作成功,执行代码段时失败,代码段不允许先设置rw权限,后设置rx权限 + */ +HWTEST_F(XpmIntegrityTest, SharedFileRemapCodeRwToRxTest, TestSize.Level0) +{ + int ret; + unsigned long offset, size; + + void *addr1 = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, g_codeOffset & PAGE_MASK); + ASSERT_NE(MAP_FAILED, addr1); + + //1.1 修改代码内容, 触发页污点 + ret = AccessData(addr1, OP_WRITE); + EXPECT_EQ(0, ret); //通过 + + void *addr2 = mmap(NULL, g_codeSize, PROT_READ | PROT_EXEC, MAP_SHARED, g_fd, g_codeOffset & PAGE_MASK); + ASSERT_NE(MAP_FAILED, addr2); + + //4. 执行对应代码, 失败 + EXPECT_EXIT(ExecSumFun(addr2), KilledBySignal(SIGSEGV), ""); + + // release resource + munmap(addr1, g_codeSize); + munmap(addr2, g_codeSize); +} + + +/** + * @tc.number 17.private + * @tc.name: BIN_NormalFileMprotectCodeRwToRwxTest + * @tc.desc: 二进制普通文件代码段文件映射的rw-权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作成功,执行代码段时失败,代码段不允许先设置rw权限,后设置rx权限 + */ +HWTEST_F(XpmIntegrityTest, PrivateFileRemapCodeRwToRxTest, TestSize.Level0) +{ + void *addr1 = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + ASSERT_NE(MAP_FAILED, addr1); + + //1.1 修改代码内容, 触发页拷贝,对应页被标记为WT + int ret = AccessData(addr1, OP_WRITE); + EXPECT_EQ(0, ret); //通过 + + void *addr2 = mmap(NULL, g_codeSize, PROT_READ | PROT_EXEC, MAP_SHARED, g_fd, g_codeOffset & PAGE_MASK); + ASSERT_NE(MAP_FAILED, addr2); + + + //4. 执行对应代码, 对应页被标记为RO,可以被执行 + ret = ExecSumFun(addr2); + EXPECT_EQ(0, ret); //通过 + + // release resource + munmap(addr1, g_codeSize); + munmap(addr2, g_codeSize); + + close(g_fd); +} + +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/test/xpm_unit_test/xpm_integrity_test.h b/test/xpm_unit_test/xpm_integrity_test.h new file mode 100755 index 0000000000000000000000000000000000000000..b2d705614259a0af9fafa37f2f0766387f415ed3 --- /dev/null +++ b/test/xpm_unit_test/xpm_integrity_test.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef XPM_INTEGRITY_TEST +#define XPM_INTEGRITY_TEST + +#include + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +using namespace testing::ext; +class XpmIntegrityTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS + +#endif // XPM_INTEGRITY_TEST \ No newline at end of file diff --git a/test/xpm_unit_test/xpm_normal_elf_test.cpp b/test/xpm_unit_test/xpm_normal_elf_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..940f3d0b0472fb32fdff2babe7b89c2c0e398444 --- /dev/null +++ b/test/xpm_unit_test/xpm_normal_elf_test.cpp @@ -0,0 +1,455 @@ +/* + * Copyright (c) 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 "xpm_normal_elf_test.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "file_ex.h" +#include "xpm_common.h" + +using namespace std; +using namespace std::chrono; +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +static int g_fd; +static unsigned long g_dataOffset, g_dataSize; +static unsigned long g_codeOffset, g_codeSize; + +void XpmNormalElfTest::SetUpTestCase() +{ + SaveStringToFile(SELINUX_MODE_PATH, PERMISSIVE_MODE); + g_fd = open(XPM_LIB_PATH.c_str(), O_RDWR); + ASSERT_NE(g_fd, -1) << "open xpm lib failed: " << strerror(errno); + + int ret = GetDataSegment(XPM_LIB_PATH.c_str(), g_dataOffset, g_dataSize); + ASSERT_EQ(0, ret) << "GetDataSegment failed: " << ret; + + ret = GetCodeSegment(XPM_LIB_PATH.c_str(), g_codeOffset, g_codeSize); + ASSERT_EQ(0, ret) << "GetCodeSegment failed: " << ret; + + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, ENFORCE_MODE); +} + +void XpmNormalElfTest::TearDownTestCase() +{ + close(g_fd); + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, PERMISSIVE_MODE); + SaveStringToFile(SELINUX_MODE_PATH, ENFORCE_MODE); +} + +void XpmNormalElfTest::SetUp() +{ +} + +void XpmNormalElfTest::TearDown() +{ +} + +/** + * @tc.number 2 + * @tc.name: FileMmapDataToRxTest + * @tc.desc: 二进制普通文件数据段文件映射到r-x权限内存 + * @tc.result: 映射失败,数据段不允许映射执行权限 + */ +HWTEST_F(XpmNormalElfTest, FileMmapDataToRxTest, TestSize.Level0) +{ + // 1. 映射数据段到r-x权限内存 + void *addr = mmap(NULL, g_dataSize, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 3 + * @tc.name: FileMmapCodeToRxTest + * @tc.desc: 二进制普通文件代码段文件映射到r-x权限内存 + * @tc.result: 映射成功,代码段允许映射执行权限 + */ +HWTEST_F(XpmNormalElfTest, FileMmapCodeToRxTest, TestSize.Level0) +{ + // 1. 映射代码段到r-x权限内存 + void *addr = mmap(NULL, g_codeSize, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + munmap(addr, g_codeSize); +} + +/** + * @tc.number 4 + * @tc.name: FileMmapDataToRwxTest + * @tc.desc: 二进制普通文件数据段文件映射到rwx权限内存 + * @tc.result: 映射失败,文件映射不允许同时映射wx权限 + */ +HWTEST_F(XpmNormalElfTest, FileMmapDataToRwxTest, TestSize.Level0) +{ + // 1. 同时映射数据段到wx权限内存 + void *addr = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 5 + * @tc.name: FileMmapCodeToRwxTest + * @tc.desc: 二进制普通文件代码段文件映射到rwx权限内存 + * @tc.result: 映射失败,文件映射不允许同时映射wx权限 + */ +HWTEST_F(XpmNormalElfTest, FileMmapCodeToRwxTest, TestSize.Level0) +{ + // 1. 同时映射代码段到wx权限内存 + void *addr = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 6 + * @tc.name: FileMprotectDataRoToRxTest + * @tc.desc: 二进制普通文件数据段文件映射的r--权限内存通过mprotect修改为r-x权限 + * @tc.result: 修改操作失败,数据段不允许映射x权限 + */ +HWTEST_F(XpmNormalElfTest, FileMprotectDataRoToRxTest, TestSize.Level0) +{ + // 1. 映射数据段到只读权限内存 + void *addr = mmap(NULL, g_dataSize, PROT_READ, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 数据段映射添加执行权限 + int ret = mprotect(addr, g_dataSize, PROT_READ | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr, g_dataSize); +} + +/** + * @tc.number 7 + * @tc.name: FileMprotectDataRwToRwxTest + * @tc.desc: 二进制普通文件数据段文件映射的rw-权限内存通过mprotect修改为rwx权限 + * @tc.result: 修改操作失败,文件映射不允许同时映射wx权限 + */ +HWTEST_F(XpmNormalElfTest, FileMprotectDataRwToRwxTest, TestSize.Level0) +{ + // 1. 映射数据段为读写权限内存 + void *addr = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 数据段映射添加执行权限 + int ret = mprotect(addr, g_dataSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr, g_dataSize); +} + +/** + * @tc.number 8 + * @tc.name: FileMprotectCodeRoToRxTest + * @tc.desc: 二进制普通文件代码段文件映射的r--权限内存通过mprotect修改为r-x权限 + * @tc.result: 修改操作成功,代码段允许映射rx权限 + */ +HWTEST_F(XpmNormalElfTest, FileMprotectCodeRoToRxTest, TestSize.Level0) +{ + // 1. 映射代码段为只读权限 + void *addr = mmap(NULL, g_codeSize, PROT_READ, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 代码段映射添加执行权限 + int ret = mprotect(addr, g_codeSize, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr, g_codeSize); +} + +/** + * @tc.number 9 + * @tc.name: FileMprotectCodeRxToRwxTest + * @tc.desc: 二进制普通文件代码段文件映射的r-x权限内存通过mprotect修改为rwx权限 + * @tc.result: 修改操作失败,代码段允许映射同时映射wx权限 + */ +HWTEST_F(XpmNormalElfTest, FileMprotectCodeRxToRwxTest, TestSize.Level0) +{ + // 1. 映射代码段为r-x权限 + void *addr = mmap(NULL, g_codeSize, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改映射代码段为rwx权限 + int ret = mprotect(addr, g_codeSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr, g_codeSize); +} + +/** + * @tc.number 10 + * @tc.name: FileMprotectDataRwToRwxTest + * @tc.desc: 二进制普通文件代码段文件映射的rw-权限内存通过mprotect修改为rwx权限 + * @tc.result: 修改操作失败,代码段允许映射同时映射wx权限 + */ +HWTEST_F(XpmNormalElfTest, FileMprotectCodeRwToRwxTest, TestSize.Level0) +{ + // 1. 映射代码段为rw-权限 + void *addr = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改映射代码段为rwx权限 + int ret = mprotect(addr, g_codeSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr, g_codeSize); +} + +/** + * @tc.number 12 + * @tc.name: FileMprotectDataRwToRwxTest + * @tc.desc: 二进制普通文件数据段文件映射的r--权限内存通过mremap修改为rwx权限 + * @tc.result: 修改操作失败,数据段不允许映射x权限 + */ +HWTEST_F(XpmNormalElfTest, FileRemapDataRoToRxTest, TestSize.Level0) +{ + // 1. 映射数据段为rw-权限 + void *addr1 = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射该数据段 + void *addr2 = mremap(addr1, g_dataSize, g_dataSize, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3, 修改重映射数据段为rwx权限 + int ret = mprotect(addr2, g_dataSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr2, g_dataSize); +} + +/** + * @tc.number 13 + * @tc.name: FileRemapDataRwToRxTest + * @tc.desc: 二进制普通文件数据段文件映射的rw-权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作失败,数据段不允许映射x权限 + */ +HWTEST_F(XpmNormalElfTest, FileRemapDataRwToRxTest, TestSize.Level0) +{ + // 1. 映射数据段为rw-权限 + void *addr1 = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射该数据段 + void *addr2 = mremap(addr1, g_dataSize, g_dataSize, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射数据段为r-x权限 + int ret = mprotect(addr2, g_dataSize, PROT_READ | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr2, g_dataSize); +} + +/** + * @tc.number 14 + * @tc.name: FileRemapDataRwToRwxTest + * @tc.desc: 二进制普通文件数据段文件映射的rw-权限内存通过mremap修改为rwx权限 + * @tc.result: 修改操作失败,文件映射不允许wx权限 + */ +HWTEST_F(XpmNormalElfTest, FileRemapDataRwToRwxTest, TestSize.Level0) +{ + // 1. 映射数据段为rw-权限 + void *addr1 = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射该数据段 + void *addr2 = mremap(addr1, g_dataSize, g_dataSize, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射数据段为rwx权限 + int ret = mprotect(addr1, g_dataSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr2, g_dataSize); +} + +/** + * @tc.number 15 + * @tc.name: FileRemapCodeRoToRxTest + * @tc.desc: 二进制普通文件代码段文件映射的r--权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作成功,代码段允许映射x权限 + */ +HWTEST_F(XpmNormalElfTest, FileRemapCodeRoToRxTest, TestSize.Level0) +{ + // 1. 映射代码段为r--权限 + void *addr1 = mmap(NULL, g_codeSize, PROT_READ, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射该代码段 + void *addr2 = mremap(addr1, g_codeSize, g_codeSize, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射代码段为r-x权限 + int ret = mprotect(addr2, g_codeSize, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr2, g_codeSize); +} + +/** + * @tc.number 16 + * @tc.name: FileRemapCodeRwToRwxTest + * @tc.desc: 二进制普通文件代码段文件映射的rw-权限内存通过mremap修改为rwx权限 + * @tc.result: 修改操作失败,映射不允许同时拥有wx权限 + */ +HWTEST_F(XpmNormalElfTest, FileRemapCodeRwToRwxTest, TestSize.Level0) +{ + // 1. 映射代码段为rw-权限 + void *addr1 = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + ASSERT_NE(MAP_FAILED, addr1); + + // 2. 重映射该代码段 + void *addr2 = mremap(addr1, g_codeSize, g_codeSize, MREMAP_MAYMOVE); + ASSERT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射代码段为rwx权限 + int ret = mprotect(addr2, g_codeSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr2, g_codeSize); +} + +/** + * @tc.number 17 + * @tc.name: FileMprotectCodeRwToRwxTest + * @tc.desc: 二进制普通文件代码段文件映射的rw-权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作成功,执行代码段时失败,代码段不允许先设置rw权限,后设置rx权限 + */ +HWTEST_F(XpmNormalElfTest, FileRemapCodeRwToRxTest, TestSize.Level0) +{ + // 1. 映射代码段为rw-权限 + void *addr1 = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + ASSERT_NE(MAP_FAILED, addr1); + + // 2. 重映射该代码段 + void *addr2 = mremap(addr1, g_codeSize, g_codeSize, MREMAP_MAYMOVE); + ASSERT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射代码段为r-x权限 + int ret = mprotect(addr2, g_codeSize, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr2, g_codeSize); +} + +/** + * @tc.number 18 + * @tc.name: AnonMmapRwTest + * @tc.desc: 二进制匿名映射rw-权限内存 + * @tc.result: 匿名映射成功,代码执行权限管控允许映射rw-匿名内存 + */ +HWTEST_F(XpmNormalElfTest, AnonMmapRwTest, TestSize.Level0) +{ + // 1. 匿名映射rw-权限内存 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); + + munmap(addr, ANON_SIZE); +} + +/** + * @tc.number 19 + * @tc.name: AnonMmapRwxTest + * @tc.desc: 二进制匿名映射rwx权限内存 + * @tc.result: 匿名映射失败,匿名映射不允许x权限 + */ +HWTEST_F(XpmNormalElfTest, AnonMmapRwxTest, TestSize.Level0) +{ + // 1. 匿名映射rwx权限内存 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 20 + * @tc.name: AnonMprotectRwToRwxTest + * @tc.desc: 二进制匿名映射的rw权限内存通过mprotect修改为rwx匿名内存 + * @tc.result: 修改匿名内存为rwx失败,匿名映射不允许x权限 + */ +HWTEST_F(XpmNormalElfTest, AnonMprotectRwToRwxTest, TestSize.Level0) +{ + // 1. 匿名映射映射rw-内存 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改匿名内存为rwx + int ret = mprotect(addr, ANON_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr, ANON_SIZE); +} + +/** + * @tc.number 21 + * @tc.name: AnonMprotectRwToRwxTest + * @tc.desc: 二进制匿名映射的rw-权限内存通过mprotect修改为r--匿名内存,之后再修改为r-x匿名内存 + * @tc.result: 修改匿名内存为rx失败,匿名映射不允许x权限 + */ +HWTEST_F(XpmNormalElfTest, AnonMprotectRwToRoToRxTest, TestSize.Level0) +{ + // 1. 匿名映射映射rw-内存 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改匿名内存为r-- + int ret = mprotect(addr, ANON_SIZE, PROT_READ); + EXPECT_EQ(0, ret); + + // 3. 修改匿名内存为r-x + ret = mprotect(addr, ANON_SIZE, PROT_READ | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr, ANON_SIZE); +} + +/** + * @tc.number 22 + * @tc.name: AnonRmapRwToRxTest + * @tc.desc: 二进制匿名映射的rw-权限内存重映射到r-x匿名内存 + * @tc.result: 重映射到r-x失败,匿名映射不允许x权限 + */ +HWTEST_F(XpmNormalElfTest, AnonRmapRwToRxTest, TestSize.Level0) +{ + // 1. 匿名映射映射rw-内存 + void *addr1 = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射匿名内存 + void *addr2 = mremap(addr1, ANON_SIZE, NEW_ANON_SIZE, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改匿名内存为r-x + int ret = mprotect(addr2, NEW_ANON_SIZE, PROT_READ | PROT_EXEC); + EXPECT_NE(0, ret); + + // release resource + munmap(addr2, ANON_SIZE); +} + +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/test/xpm_unit_test/xpm_normal_elf_test.h b/test/xpm_unit_test/xpm_normal_elf_test.h new file mode 100755 index 0000000000000000000000000000000000000000..bebf5b842e9dbf0dbba8ac8e30f9f9ec66e61dda --- /dev/null +++ b/test/xpm_unit_test/xpm_normal_elf_test.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef XPM_NORMAL_ELF_TEST +#define XPM_NORMAL_ELF_TEST + +#include + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +using namespace testing::ext; +class XpmNormalElfTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS + +#endif // XPM_NORMAL_ELF_TEST \ No newline at end of file diff --git a/test/xpm_unit_test/xpm_normal_hap_test.cpp b/test/xpm_unit_test/xpm_normal_hap_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..bde6e52e65635e2a0831c37c395ba99b68242db6 --- /dev/null +++ b/test/xpm_unit_test/xpm_normal_hap_test.cpp @@ -0,0 +1,395 @@ +/* + * Copyright (c) 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 "xpm_normal_hap_test.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "file_ex.h" +#include "xpm_common.h" + +using namespace std; +using namespace std::chrono; +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +static int g_fd; +static struct XpmRegionArea g_area; +static unsigned long g_dataOffset, g_dataSize; +static unsigned long g_codeOffset, g_codeSize; + +void XpmNormalHapTest::SetUpTestCase() +{ + SaveStringToFile(SELINUX_MODE_PATH, PERMISSIVE_MODE); + g_fd = open(XPM_LIB_PATH.c_str(), O_RDWR); + + int ret = GetDataSegment(XPM_LIB_PATH, g_dataOffset, g_dataSize); + ASSERT_EQ(0, ret) << "GetDataSegment failed: " << ret; + + ret = GetCodeSegment(XPM_LIB_PATH, g_codeOffset, g_codeSize); + ASSERT_EQ(0, ret) << "GetCodeSegment failed: " << ret; + + ret = GetXpmRegion(g_area); + ASSERT_EQ(0, ret) << "GetXpmRegion failed: " << ret; + + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, ENFORCE_MODE); +} + +void XpmNormalHapTest::TearDownTestCase() +{ + close(g_fd); + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, PERMISSIVE_MODE); + SaveStringToFile(SELINUX_MODE_PATH, ENFORCE_MODE); +} + +void XpmNormalHapTest::SetUp() +{ +} + +void XpmNormalHapTest::TearDown() +{ +} + +/** + * @tc.name: XpmRegionAllocTest + * @tc.desc: 安全内存分配测试 + * tc.result: 分配成功,且进程对应/proc/pid/xpm_region范围有值 + */ +HWTEST_F(XpmNormalHapTest, XpmRegionAllocTest, TestSize.Level0) +{ + struct XpmRegionArea area = {0}; + + // 1. 初始化安全内存 + int ret = GetXpmRegion(area); + EXPECT_EQ(0, ret); + + EXPECT_NE(0UL, area.start); + EXPECT_NE(0UL, area.end); +} + +/** + * @tc.name: XpmRegionAllocMultiTest + * @tc.desc: 安全内存多次分配测试 + * tc.result: 调用成功,但是安全内存并未重新分配 + */ +HWTEST_F(XpmNormalHapTest, XpmRegionAllocMultiTest, TestSize.Level0) +{ + struct XpmRegionArea area1 = {0}; + struct XpmRegionArea area2 = {0}; + + // 1. 第一次初始化安全内存 + int ret = GetXpmRegion(area1); + EXPECT_EQ(0, ret); + + // 1. 第二次初始化安全内存 + ret = GetXpmRegion(area2); + EXPECT_EQ(0, ret); + + EXPECT_EQ(area1.start, area2.start); + EXPECT_EQ(area2.end, area2.end); +} + +/** + * @tc.number: 30 + * @tc.name: FileMmapXpmFlagTest + * @tc.desc: ABC代码指定MAP_XPM映射到安全内存 + * @tc.result: ABC代码映射成功,映射地址在安全内存范围内 + */ +HWTEST_F(XpmNormalHapTest, FileMmapXpmFlagTest, TestSize.Level0) +{ + // 1. 映射只读权限到安全内存 + void *addr = mmap(NULL, g_dataSize, PROT_READ, MAP_PRIVATE | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 映射数据段地址在安全内存中 + bool ret = IsXpmRegionInner(reinterpret_cast(addr), + reinterpret_cast(addr) + g_dataSize); + EXPECT_TRUE(ret); + + munmap(addr, g_dataSize); +} + +/** + * @tc.number: 31 + * @tc.name: FileMmapXpmFlagLimitTest + * @tc.desc: ABC代码指定MAP_XPM映射超过安全内存大小的size到安全内存 + * @tc.result: ABC代码映射失败 + */ +HWTEST_F(XpmNormalHapTest, FileMmapXpmFlagLimitTest, TestSize.Level0) +{ + // 1. 映射超过安全内存大小的范围到安全内存 + void *addr = mmap(NULL, XPM_REGION_LEN + PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number: 32 + * @tc.name: FileMmapXpmAddrTest + * @tc.desc: ABC代码通过指定xpm_region地址映射到安全内存 + * @tc.result: ABC代码映射成功,映射地址在安全内存范围外 + */ +HWTEST_F(XpmNormalHapTest, FileMmapXpmAddrTest, TestSize.Level0) +{ + // 1. 通过指定安全内存的地址映射到安全内存中 + void *addr = mmap((void *)g_area.start, g_dataSize, PROT_READ, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 映射范围不在安全内存中 + bool ret = IsXpmRegionOuter((unsigned long)addr, (unsigned long)addr + g_dataSize); + EXPECT_TRUE(ret); + + munmap(addr, g_dataSize); +} + +/** + * @tc.number: 32 + * @tc.name: FileMmapXpmAddrTest + * @tc.desc: ABC代码指定xpm region地址和MAP_FIXED映射到安全内存 + * @tc.result: ABC代码映射失败,安全内存地址不允许MAP_FIXED强制指定 + */ +HWTEST_F(XpmNormalHapTest, FileMmapXpmAddrAndFixedFlagTest, TestSize.Level0) +{ + // 1. 强制指定安全内存的地址和MAP_FIXED映射数据段到安全内存中 + void *addr = mmap((void *)g_area.start, g_dataSize, PROT_READ, MAP_PRIVATE | MAP_FIXED, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); + + // 2. 左边界行为 + addr = mmap((void *)(g_area.start - PAGE_SIZE), 2 * PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_FIXED, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); + + // 3. 右边界行为 + addr = mmap((void *)(g_area.end - PAGE_SIZE), 2 * PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_FIXED, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number: 33 + * @tc.name: FileMmapAddrAndXpmFlagTest + * @tc.desc: ABC代码指定地址&MAP_XPM标识文件映射到安全内存 + * @tc.result: ABC代码映射失败,安全内存映射不允许指定地址 + */ +HWTEST_F(XpmNormalHapTest, FileMmapAddrAndXpmFlagTest, TestSize.Level0) +{ + // 1. 通过执行地址和MAP_XPM映射到安全内存 + void *addr = mmap((void *)g_area.start, g_dataSize, PROT_READ, MAP_PRIVATE | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number: 34 + * @tc.name: FileMmapRoTest + * @tc.desc: ABC代码映射只读权限到安全内存 + * @tc.result: ABC代码映射成功,安全内存允许映射读权限 + */ +HWTEST_F(XpmNormalHapTest, FileMmapRoTest, TestSize.Level0) +{ + // 1、 通过指定MAP_XPM映射只读权限到安全内存 + void *addr = mmap(NULL, g_dataSize, PROT_READ, MAP_PRIVATE | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 映射地址在安全内存范围内 + bool ret = IsXpmRegionInner((unsigned long)addr, (unsigned long)addr + g_dataSize); + EXPECT_TRUE(ret); + + munmap(addr, g_dataSize); +} + +/** + * @tc.number: 35 + * @tc.name: FileMmapRwxTest + * @tc.desc: ABC代码映射读&写&执行权限到安全内存 + * @tc.result: ABC代码映射失败,安全内存不允许映射写和执行权限 + */ +HWTEST_F(XpmNormalHapTest, FileMmapRwxTest, TestSize.Level0) +{ + // 1. 通过指定MAP_XPM私有映射写权限到安全内存中 + void *addr = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + ASSERT_NE(MAP_FAILED, addr); + + // 2. 通过指定MAP_XPM共享映射写权限到安全内存中 + addr = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + ASSERT_NE(MAP_FAILED, addr); + + // 3. 通过指定MAP_XPM私有映射执行权限到安全内存中 + addr = mmap(NULL, g_dataSize, PROT_READ | PROT_EXEC, MAP_PRIVATE | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + ASSERT_EQ(MAP_FAILED, addr); + + // 4. 通过指定MAP_XPM共享映射执行权限到安全内存中 + addr = mmap(NULL, g_dataSize, PROT_READ | PROT_EXEC, MAP_SHARED | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + ASSERT_EQ(MAP_FAILED, addr); + + // 5. 通过指定MAP_XPM私有映射执行&写权限到安全内存中 + addr = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + ASSERT_EQ(MAP_FAILED, addr); + + // 6. 通过指定MAP_XPM共享映射执行&写权限到安全内存中 + addr = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + ASSERT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 36 + * @tc.name: FileRemapXpmRegionLimitTest + * @tc.desc: ABC代码重映射超过xpm_region范围的大小到xpm region内 + * @tc.result: ABC代码重映射失败 + */ +HWTEST_F(XpmNormalHapTest, FileRemapXpmRegionLimitTest, TestSize.Level0) +{ + // 1. 映射普通只读内存 + void *addr1 = mmap(NULL, g_dataSize, PROT_READ, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 强制重映射只读内存到xpm region范围内 + void *addr2 = mremap(addr1, g_dataSize, XPM_REGION_LEN + PAGE_SIZE, MREMAP_MAYMOVE | MREMAP_FIXED, g_area.start); + EXPECT_EQ(MAP_FAILED, addr2); + EXPECT_EQ(EFAULT, errno); + + // 3. 左边界 + addr2 = mremap(addr1, g_dataSize, XPM_REGION_LEN, MREMAP_MAYMOVE | MREMAP_FIXED, g_area.start - PAGE_SIZE); + EXPECT_EQ(MAP_FAILED, addr2); + EXPECT_EQ(EFAULT, errno); + + // 3. 右边界 + addr2 = mremap(addr1, g_dataSize, XPM_REGION_LEN, MREMAP_MAYMOVE | MREMAP_FIXED, g_area.start + PAGE_SIZE); + EXPECT_EQ(MAP_FAILED, addr2); + EXPECT_EQ(EFAULT, errno); + + int ret = AccessData(addr1, OP_READ); + EXPECT_EQ(0, ret); + + // release resource + munmap(addr1, g_dataSize); +} + +/** + * @tc.number 39 + * @tc.name: FileRemapDataXpmRegionToOutRxTest + * @tc.desc: ABC数据段重映射到xpm region外,并添加执行权限 + * @tc.result: ABC数据段映射失败,数据段无法添加执行权限 + */ +HWTEST_F(XpmNormalHapTest, FileRemapDataXpmRegionToOutRxTest, TestSize.Level0) +{ + // 1. 映射r--权限到安全内存 + void *addr1 = mmap(NULL, g_dataSize, PROT_READ, MAP_SHARED | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 映射r-x权限到安全内存 + void *addr2 = mmap(NULL, g_dataSize, PROT_READ | PROT_EXEC, MAP_SHARED, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr2); + + munmap(addr1, g_dataSize); +} + +/** + * @tc.number 40 + * @tc.name: FileRemapCodeXpmRegionToOutRxTest + * @tc.desc: ABC数据段重映射到xpm region外,并添加执行权限 + * @tc.result: ABC数据段映射失败,数据段无法添加执行权限 + */ +HWTEST_F(XpmNormalHapTest, FileRemapCodeXpmRegionToOutRxTest, TestSize.Level0) +{ + // 1. 映射r--权限到安全内存 + void *addr1 = mmap(NULL, g_codeSize, PROT_READ, MAP_SHARED | MAP_XPM, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 映射r-x权限到非安全内存 + void *addr2 = mmap(NULL, g_codeSize, PROT_READ | PROT_EXEC, MAP_SHARED, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr2); + + int ret = ExecSumFun(addr2); + EXPECT_EQ(0, ret); + + munmap(addr1, g_codeSize); + munmap(addr2, g_codeSize); +} + +/** + * @tc.number 41 + * @tc.name: FileMprotectRwxTest + * @tc.desc: ABC代码通过mprotect添加写或执行权限 + * @tc.result: ABC代码在添加写或执行权限时失败,安全内存无法添加写&执行权限 + */ +HWTEST_F(XpmNormalHapTest, FileMprotectRwxTest, TestSize.Level0) +{ + // 1. 映射只读数据到安全内存 + void *addr = mmap(NULL, g_dataSize, PROT_READ, MAP_PRIVATE | MAP_XPM, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 增加写权限 + int ret = mprotect(addr, g_dataSize, PROT_READ | PROT_WRITE); + EXPECT_EQ(0, ret); + + // 3. 增加执行权限 + ret = mprotect(addr, g_dataSize, PROT_READ | PROT_EXEC); + EXPECT_EQ(-1, ret); + + // 4. 增加写&执行权限 + ret = mprotect(addr, g_dataSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_EQ(-1, ret); + + munmap(addr, g_dataSize); +} + +/** + * @tc.number: 42 + * @tc.name: AnonMmapXpmFlagTest + * @tc.desc: ABC代码使用MAP_XPM匿名映射到安全内存(私有映射&共享映射) + * @tc.result: ABC代码映射失败,安全内存不允许匿名映射 + */ +HWTEST_F(XpmNormalHapTest, AnonMmapXpmFlagTest, TestSize.Level0) +{ + // 1. 匿名映射只读权限 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_XPM, -1, 0); + ASSERT_EQ(MAP_FAILED, addr); + + // 2. 匿名映射只读权限到安全内存 + addr = mmap(NULL, ANON_SIZE, PROT_READ, MAP_SHARED | MAP_ANONYMOUS | MAP_XPM, -1, 0); + ASSERT_EQ(MAP_FAILED, addr); + + // 3. 匿名映射读&写权限到安全内存 + addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS | MAP_XPM, -1, 0); + ASSERT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number: 43 + * @tc.name: AnonMmapXpmAddrTest + * @tc.desc: ABC代码指定安全内存地址映射内存 + * @tc.result: ABC代码映射成功,映射区域不在安全内存中 + */ +HWTEST_F(XpmNormalHapTest, AnonMmapXpmAddrTest, TestSize.Level0) +{ + // 1. 匿名映射到安全内存地址范围 + void *addr = mmap((void *)g_area.start, ANON_SIZE, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + ASSERT_NE(MAP_FAILED, addr); + + // 2. 匿名映射地址不在安全内存范围内 + bool ret = IsXpmRegionOuter((unsigned long)addr, (unsigned long)addr + PAGE_SIZE); + EXPECT_TRUE(ret); + munmap(addr, PAGE_SIZE); +} + +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/test/xpm_unit_test/xpm_normal_hap_test.h b/test/xpm_unit_test/xpm_normal_hap_test.h new file mode 100755 index 0000000000000000000000000000000000000000..c50d35b0008608657456fe68efbfd21753b7f4bc --- /dev/null +++ b/test/xpm_unit_test/xpm_normal_hap_test.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef XPM_NORMAL_HAP_TEST +#define XPM_NORMAL_HAP_TEST + +#include + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +using namespace testing::ext; +class XpmNormalHapTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS + +#endif // XPM_NORMAL_HAP_TEST diff --git a/test/xpm_unit_test/xpm_ownerid_test.cpp b/test/xpm_unit_test/xpm_ownerid_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..382af3232a532b03935fa7bc28aa52d4a4530f2d --- /dev/null +++ b/test/xpm_unit_test/xpm_ownerid_test.cpp @@ -0,0 +1,307 @@ +/* + * Copyright (c) 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 "xpm_ownerid_test.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "code_sign_utils.h" +#include "file_ex.h" +#include "xpm_common.h" + +using namespace std; +using namespace std::chrono; +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +using namespace OHOS::Security::CodeSign; +static int g_systemFd, g_sharedFd, g_compatFd, g_debugFd, g_appFd1, g_appFd2; +static const std::string APP_BASE_PATH = "/data/app/el1/bundle/public/tmp"; +static const std::string SharedOwnerIDHAPPath = APP_BASE_PATH + "/demo_ownerid/hap1-shared-lib-id.hap"; +static const std::string WOOwnerIDHAPPath = APP_BASE_PATH + "/demo_ownerid/hap2-without-ownerid.hap"; +static const std::string DebugOwnerIDPath = APP_BASE_PATH + "/demo_ownerid/hap3-debug-lib-id.hap"; +static const std::string OwnerID1HAPPath = APP_BASE_PATH + "/demo_ownerid/hap4-ownerid-1.hap"; +static const std::string OwnerID2HAPPath = APP_BASE_PATH + "/demo_ownerid/hap5-ownerid-2.hap"; + +void XpmOwnerIDTest::SetUpTestCase() +{ + SaveStringToFile(SELINUX_MODE_PATH, PERMISSIVE_MODE); + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, ENFORCE_MODE); + + EntryMap entryMap1; + int ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("SHARED_LIB_ID", SharedOwnerIDHAPPath, entryMap1, FILE_SELF); + EXPECT_EQ(ret, CS_SUCCESS); + + EntryMap entryMap2; + ret = CodeSignUtils::EnforceCodeSignForApp(WOOwnerIDHAPPath, entryMap2, FILE_SELF); + EXPECT_EQ(ret, CS_SUCCESS); + + EntryMap entryMap3; + ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("DEBUG_LIB_ID", DebugOwnerIDPath, entryMap3, FILE_SELF); + EXPECT_EQ(ret, CS_SUCCESS); + + EntryMap entryMap4; + ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("1234567890", OwnerID1HAPPath, entryMap4, FILE_SELF); + EXPECT_EQ(ret, CS_SUCCESS); + + EntryMap entryMap5; + ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("12345678901", OwnerID2HAPPath, entryMap5, FILE_SELF); + EXPECT_EQ(ret, CS_SUCCESS); + + g_systemFd = open(XPM_LIB_PATH.c_str(), O_RDONLY); + EXPECT_NE(g_systemFd, -1); + g_sharedFd = open(SharedOwnerIDHAPPath.c_str(), O_RDONLY); + EXPECT_NE(g_sharedFd, -1); + g_compatFd = open(WOOwnerIDHAPPath.c_str(), O_RDONLY); + EXPECT_NE(g_compatFd, -1); + g_debugFd = open(DebugOwnerIDPath.c_str(), O_RDONLY); + EXPECT_NE(g_debugFd, -1); + g_appFd1 = open(OwnerID1HAPPath.c_str(), O_RDONLY); + EXPECT_NE(g_appFd1, -1); + g_appFd2 = open(OwnerID2HAPPath.c_str(), O_RDONLY); + EXPECT_NE(g_appFd2, -1); +} + +void XpmOwnerIDTest::TearDownTestCase() +{ + close(g_systemFd); + close(g_sharedFd); + close(g_compatFd); + close(g_debugFd); + close(g_appFd1); + close(g_appFd2); + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, PERMISSIVE_MODE); + SaveStringToFile(SELINUX_MODE_PATH, ENFORCE_MODE); +} + +void XpmOwnerIDTest::SetUp() +{ +} + +void XpmOwnerIDTest::TearDown() +{ +} + +#define FILE_MAP_SIZE 40 + +/** + * @tc.number 39.system进程打开所有文件 + * @tc.name: SystemProcess + * @tc.desc: + * @tc.result: SystemProcess + */ +HWTEST_F(XpmOwnerIDTest, SystemProcessTest, TestSize.Level0) +{ + // 设置当前进程为system进程 + SetXpmOwnerId(PROCESS_OWNERID_SYSTEM, NULL); + + // 1. LIB_SYSTEM_ID可以加载 + void *addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_systemFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 2. SHARED_LIB_ID的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_sharedFd, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 3. w/o Owner ID的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_compatFd, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 4. DEBUG_LIB_ID的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_debugFd, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 5. owner ID A的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_appFd1, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 6. owner ID B的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_appFd2, 0); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 40. Debug进程 + * @tc.name: DebugProcess + * @tc.desc: + * @tc.result: DebugProcess + */ +HWTEST_F(XpmOwnerIDTest, DebugProcessTest, TestSize.Level0) +{ + // 设置当前进程为debug进程 + SetXpmOwnerId(PROCESS_OWNERID_DEBUG, NULL); + + // 1. LIB_SYSTEM_ID可以加载 + void *addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_systemFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 2. SHARED_LIB_ID的文件可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_sharedFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 3. w/o Owner ID的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_compatFd, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 4. DEBUG_LIB_ID的文件可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_debugFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 5. owner ID A的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_appFd1, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 6. owner ID B的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_appFd2, 0); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 41. APPID进程 + * @tc.name: APPID Process + * @tc.desc: + * @tc.result: APPID Process + */ +HWTEST_F(XpmOwnerIDTest, APPProcessTest, TestSize.Level0) +{ + std::string str = "1234567890"; + // 设置当前进程为s进程 + SetXpmOwnerId(PROCESS_OWNERID_APP, str.c_str()); + + // 1. LIB_SYSTEM_ID可以加载 + void *addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_systemFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 2. SHARED_LIB_ID的文件可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_sharedFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 3. w/o Owner ID的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_compatFd, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 4. DEBUG_LIB_ID的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_debugFd, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 5. owner ID A的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_appFd1, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 6. owner ID B的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_appFd2, 0); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 42.COMPAT进程 + * @tc.name: COMPAT Process + * @tc.desc: + * @tc.result: COMPAT Process + */ +HWTEST_F(XpmOwnerIDTest, COMPATProcessTest, TestSize.Level0) +{ + // 设置当前进程为COMPAT进程 + SetXpmOwnerId(PROCESS_OWNERID_COMPAT, NULL); + + // 1. LIB_SYSTEM_ID可以加载 + void *addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_systemFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 2. SHARED_LIB_ID的文件可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_sharedFd, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 3. w/o Owner ID的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_compatFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 4. DEBUG_LIB_ID的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_debugFd, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 5. owner ID A的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_appFd1, 0); + EXPECT_EQ(MAP_FAILED, addr); + + // 6. owner ID B的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_appFd2, 0); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 43. EXTEND进程 + * @tc.name: EXTEND Process + * @tc.desc: + * @tc.result: EXTEND + */ +HWTEST_F(XpmOwnerIDTest, EXTENDProcessTest, TestSize.Level0) +{ + // 设置当前进程为s进程 + SetXpmOwnerId(PROCESS_OWNERID_EXTEND, NULL); + + // 1. LIB_SYSTEM_ID可以加载 + void *addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_systemFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 2. SHARED_LIB_ID的文件可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_sharedFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 3. w/o Owner ID的文件可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_compatFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 4. DEBUG_LIB_ID的文件可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_debugFd, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 5. owner ID A的文件不可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_appFd1, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); + + // 6. owner ID B的文件可以加载 + addr = mmap(NULL, FILE_MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_XPM, g_appFd2, 0); + EXPECT_NE(MAP_FAILED, addr); + munmap(addr, FILE_MAP_SIZE); +} + +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/test/xpm_unit_test/xpm_ownerid_test.h b/test/xpm_unit_test/xpm_ownerid_test.h new file mode 100755 index 0000000000000000000000000000000000000000..7990173b94e6be2c64dbdc37db7476c428c19523 --- /dev/null +++ b/test/xpm_unit_test/xpm_ownerid_test.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef XPM_OWNERID_TEST +#define XPM_OWNERID_TEST + +#include + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +using namespace testing::ext; +enum { + DENY = 0, + ALLOW, +}; +class XpmOwnerIDTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS + +#endif // XPM_OWNERID_TEST \ No newline at end of file diff --git a/test/xpm_unit_test/xpm_webview_test.cpp b/test/xpm_unit_test/xpm_webview_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..943f06d1be767c0f094e782622cd05172d7cbd21 --- /dev/null +++ b/test/xpm_unit_test/xpm_webview_test.cpp @@ -0,0 +1,461 @@ +/* + * Copyright (c) 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 "xpm_webview_test.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "file_ex.h" +#include "xpm_common.h" + +using namespace std; +using namespace std::chrono; +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +static int g_fd; +static unsigned long g_dataOffset, g_dataSize; +static unsigned long g_codeOffset, g_codeSize; + +void XpmWebviewTest::SetUpTestCase() +{ + SaveStringToFile(SELINUX_MODE_PATH, PERMISSIVE_MODE); + + g_fd = open(XPM_LIB_PATH.c_str(), O_RDWR); + ASSERT_NE(g_fd, -1) << "open xpm lib failed: " << strerror(errno); + + int ret = GetDataSegment(XPM_LIB_PATH, g_dataOffset, g_dataSize); + ASSERT_EQ(0, ret) << "GetDataSegment failed: " << ret; + + ret = GetCodeSegment(XPM_LIB_PATH, g_codeOffset, g_codeSize); + ASSERT_EQ(0, ret) << "GetCodeSegment failed: " << ret; + + ret = SetCon(SELINUX_TYPE_NWEBSPAWN); + ASSERT_EQ(0, ret) << "SetCon failed: " << strerror(errno); + + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, ENFORCE_MODE); +} + +void XpmWebviewTest::TearDownTestCase() +{ + close(g_fd); + SetCon(SELINUX_TYPE_SH); + SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, PERMISSIVE_MODE); + SaveStringToFile(SELINUX_MODE_PATH, ENFORCE_MODE); +} + +void XpmWebviewTest::SetUp() +{ +} + +void XpmWebviewTest::TearDown() +{ +} + +/** + * @tc.number 2 + * @tc.name: FileMmapDataToRxTest + * @tc.desc: Webview数据段文件映射到r-x权限内存 + * @tc.result: 映射失败,数据段不允许映射执行权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileMmapDataToRxTest, TestSize.Level0) +{ + // 1. webview进程映射数据段为r-x权限 + void *addr = mmap(NULL, g_dataSize, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 3 + * @tc.name: FileMmapCodeToRxTest + * @tc.desc: Webview代码段文件映射到r-x权限内存 + * @tc.result: 映射成功,代码段允许映射执行权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileMmapCodeToRxTest, TestSize.Level0) +{ + // 1. webview进程映射代码段为r-x权限 + void *addr = mmap(NULL, g_codeSize, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + munmap(addr, g_codeSize); +} + +/** + * @tc.number 4 + * @tc.name: FileMmapDataToRwxTest + * @tc.desc: Webview数据段文件映射到rwx权限内存 + * @tc.result: 映射失败,文件映射不允许同时映射wx权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileMmapDataToRwxTest, TestSize.Level0) +{ + // 1. webview进程映射数据段为rwx权限 + void *addr = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 5 + * @tc.name: FileMmapCodeToRwxTest + * @tc.desc: 二Webview代码段文件映射到rwx权限内存 + * @tc.result: 映射失败,文件映射不允许同时映射wx权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileMmapCodeToRwxTest, TestSize.Level0) +{ + // 1. webview进程映射代码段为rwx权限 + void *addr = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_EQ(MAP_FAILED, addr); +} + +/** + * @tc.number 6 + * @tc.name: FileMprotectDataRoToRxTest + * @tc.desc: Webview数据段文件映射的r--权限内存通过mprotect修改为r-x权限 + * @tc.result: 修改操作失败,数据段不允许映射x权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileMprotectDataRoToRxTest, TestSize.Level0) +{ + // 1. webview进程映射数据段为r--权限 + void *addr = mmap(NULL, g_dataSize, PROT_READ, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改映射为r-x权限 + int ret = mprotect(addr, g_dataSize, PROT_READ | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr, g_dataSize); +} + +/** + * @tc.number 7 + * @tc.name: FileMprotectDataRwToRwxTest + * @tc.desc: Webview数据段文件映射的rw-权限内存通过mprotect修改为rwx权限 + * @tc.result: 修改操作失败,数据段不允许映射x权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileMprotectDataRwToRwxTest, TestSize.Level0) +{ + // 1. webview进程映射数据段为rw-权限 + void *addr = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改映射为rwx权限 + int ret = mprotect(addr, g_dataSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr, g_dataSize); +} + +/** + * @tc.number 8 + * @tc.name: FileMprotectCodeRoToRxTest + * @tc.desc: Webview代码段文件映射的r--权限内存通过mprotect修改为r-x权限 + * @tc.result: 修改操作成功,代码段允许映射rx权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileMprotectCodeRoToRxTest, TestSize.Level0) +{ + // 1. webview进程映射代码段为rw-权限 + void *addr = mmap(NULL, g_codeSize, PROT_READ, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改映射为r-x权限 + int ret = mprotect(addr, g_codeSize, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr, g_codeSize); +} + +/** + * @tc.number 9 + * @tc.name: FileMprotectCodeRxToRwxTest + * @tc.desc: Webview代码段文件映射的r-x权限内存通过mprotect修改为rwx权限 + * @tc.result: 修改操作失败,代码段允许映射同时映射wx权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileMprotectCodeRxToRwxTest, TestSize.Level0) +{ + // 1. webview进程映射代码段为r-x权限 + void *addr = mmap(NULL, g_codeSize, PROT_READ | PROT_EXEC, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改映射为rwx权限 + int ret = mprotect(addr, g_codeSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr, g_codeSize); +} + +/** + * @tc.number 10 + * @tc.name: FileMprotectDataRwToRwxTest + * @tc.desc: Webview代码段文件映射的rw-权限内存通过mprotect修改为rwx权限 + * @tc.result: 修改操作失败,代码段允许映射同时映射wx权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileMprotectCodeRwToRwxTest, TestSize.Level0) +{ + // 1. webview进程映射代码段为rw-权限 + void *addr = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改映射为rwx权限 + int ret = mprotect(addr, g_codeSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr, g_codeSize); +} + +/** + * @tc.number 12 + * @tc.name: FileMprotectDataRwToRwxTest + * @tc.desc: Webview数据段文件映射的r--权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作失败,数据段不允许映射x权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileRemapDataRoToRxTest, TestSize.Level0) +{ + // 1. webview进程映射数据段为r--权限 + void *addr1 = mmap(NULL, g_dataSize, PROT_READ, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射 + void *addr2 = mremap(addr1, g_dataSize, g_dataSize, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射为r-x权限 + int ret = mprotect(addr2, g_dataSize, PROT_READ | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr2, g_dataSize); +} + +/** + * @tc.number 13 + * @tc.name: FileRemapDataRwToRxTest + * @tc.desc: Webview数据段文件映射的rw-权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作失败,数据段不允许映射x权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileRemapDataRwToRxTest, TestSize.Level0) +{ + // 1. webview进程映射数据段为rw-权限 + void *addr1 = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射 + void *addr2 = mremap(addr1, g_dataSize, g_dataSize, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射为r-x权限 + int ret = mprotect(addr2, g_dataSize, PROT_READ | PROT_EXEC); + EXPECT_NE(0, ret); + + munmap(addr2, g_dataSize); +} + +/** + * @tc.number 14 + * @tc.name: FileRemapDataRwToRwxTest + * @tc.desc: Webview数据段文件映射的rw-权限内存通过mremap修改为rwx权限 + * @tc.result: 修改操作失败,数据段不允许映射x权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileRemapDataRwToRwxTest, TestSize.Level0) +{ + // 1. webview进程映射数据段为rw-权限 + void *addr1 = mmap(NULL, g_dataSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_dataOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射 + void *addr2 = mremap(addr1, g_dataSize, g_dataSize, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射为rwx权限 + int ret = mprotect(addr1, g_dataSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + // release resource + munmap(addr2, g_dataSize); +} + +/** + * @tc.number 15 + * @tc.name: FileRemapCodeRoToRxTest + * @tc.desc: Webview代码段文件映射的r--权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作成功,代码段允许映射x权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileRemapCodeRoToRxTest, TestSize.Level0) +{ + // 1. webview进程映射代码段为r--权限 + void *addr1 = mmap(NULL, g_codeSize, PROT_READ, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射 + void *addr2 = mremap(addr1, g_codeSize, g_codeSize, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射为r-x权限 + int ret = mprotect(addr2, g_codeSize, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr2, g_codeSize); +} + +/** + * @tc.number 16 + * @tc.name: FileRemapCodeRwToRwxTest + * @tc.desc: Webview代码段文件映射的rw-权限内存通过mremap修改为rwx权限 + * @tc.result: 修改操作失败,映射不允许同时拥有wx权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileRemapCodeRwToRwxTest, TestSize.Level0) +{ + // 1. webview进程映射代码段为rw-权限 + void *addr1 = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + ASSERT_NE(MAP_FAILED, addr1); + + // 2. 重映射 + void *addr2 = mremap(addr1, g_codeSize, g_codeSize, MREMAP_MAYMOVE); + ASSERT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射为rwx权限 + int ret = mprotect(addr2, g_codeSize, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_NE(0, ret); + + // release resource + munmap(addr2, g_codeSize); +} + +/** + * @tc.number 17 + * @tc.name: FileMprotectCodeRwToRwxTest + * @tc.desc: Webview代码段文件映射的rw-权限内存通过mremap修改为r-x权限 + * @tc.result: 修改操作成功,执行代码段时失败,代码段不允许先设置rw权限,后设置rx权限(同普通进程) + */ +HWTEST_F(XpmWebviewTest, FileRemapCodeRwToRxTest, TestSize.Level0) +{ + // 1. webview进程映射代码段为rw-权限 + void *addr1 = mmap(NULL, g_codeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_fd, g_codeOffset & PAGE_MASK); + ASSERT_NE(MAP_FAILED, addr1); + + // 2. 重映射 + void *addr2 = mremap(addr1, g_codeSize, g_codeSize, MREMAP_MAYMOVE); + ASSERT_NE(MAP_FAILED, addr2); + + // 3. 修改重映射为r-x权限 + int ret = mprotect(addr2, g_codeSize, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr2, g_codeSize); +} + +/** + * @tc.number 18 + * @tc.name: AnonMmapRwTest + * @tc.desc: Webview匿名映射rw-权限内存 + * @tc.result: 匿名映射成功,rw-匿名内存不管控 + */ +HWTEST_F(XpmWebviewTest, AnonMmapRwTest, TestSize.Level0) +{ + // 1. webview进程匿名映射rw-权限 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); + + munmap(addr, ANON_SIZE); +} + +/** + * @tc.number 19 + * @tc.name: AnonMmapRwxTest + * @tc.desc: weebview匿名映射rwx权限内存 + * @tc.result: 匿名映射成功,webview匿名映射x权限内存(同debug_hap进程) + */ +HWTEST_F(XpmWebviewTest, AnonMmapRwxTest, TestSize.Level0) +{ + // 1. webview进程匿名映射rwx权限 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); +} + +/** + * @tc.number 20 + * @tc.name: AnonMprotectRwToRwxTest + * @tc.desc: webview匿名映射的rw权限内存通过mprotect修改为rwx匿名内存 + * @tc.result: 修改webview匿名内存为rwx成功,webview匿名映射x权限内存(同debug_hap进程) + */ +HWTEST_F(XpmWebviewTest, AnonMprotectRwToRwxTest, TestSize.Level0) +{ + // 1. 匿名映射映射rw-内存 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改匿名内存为rwx + int ret = mprotect(addr, ANON_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr, ANON_SIZE); +} + +/** + * @tc.number 21 + * @tc.name: AnonMprotectRwToRwxTest + * @tc.desc: webview匿名映射的rw-权限内存通过mprotect修改为r--匿名内存,之后再修改为r-x匿名内存 + * @tc.result: 修改匿名内存为rx成功,webview匿名映射x权限内存(同debug_hap进程) + */ +HWTEST_F(XpmWebviewTest, AnonMprotectRwToRoToRxTest, TestSize.Level0) +{ + // 1. 匿名映射映射rw-内存 + void *addr = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr); + + // 2. 修改匿名内存为r-- + int ret = mprotect(addr, ANON_SIZE, PROT_READ); + EXPECT_EQ(0, ret); + + // 3. 修改匿名内存为r-x + ret = mprotect(addr, ANON_SIZE, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr, ANON_SIZE); +} + +/** + * @tc.number 22 + * @tc.name: AnonRmapRwToRxTest + * @tc.desc: webview匿名映射的rw-权限内存重映射到r-x匿名内存 + * @tc.result: 重映射到r-x成功,webview匿名映射x权限内存(同debug_hap进程) + */ +HWTEST_F(XpmWebviewTest, AnonRmapRwToRxTest, TestSize.Level0) +{ + // 1. 匿名映射映射rw-内存 + void *addr1 = mmap(NULL, ANON_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(MAP_FAILED, addr1); + + // 2. 重映射匿名内存 + void *addr2 = mremap(addr1, ANON_SIZE, NEW_ANON_SIZE, MREMAP_MAYMOVE); + EXPECT_NE(MAP_FAILED, addr2); + + // 3. 修改匿名内存为r-x + int ret = mprotect(addr2, NEW_ANON_SIZE, PROT_READ | PROT_EXEC); + EXPECT_EQ(0, ret); + + munmap(addr2, ANON_SIZE); +} + +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/test/xpm_unit_test/xpm_webview_test.h b/test/xpm_unit_test/xpm_webview_test.h new file mode 100755 index 0000000000000000000000000000000000000000..b1c7e297f47651e19a3eed7a4bd1d7a28f35ac42 --- /dev/null +++ b/test/xpm_unit_test/xpm_webview_test.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef XPM_WEBVIEW_TEST +#define XPM_WEBVIEW_TEST + +#include + +namespace OHOS { +namespace Security { +namespace XpmUnitTest { +using namespace testing::ext; +class XpmWebviewTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; +} // namespace XpmUnitTest +} // namespace Security +} // namespace OHOS + +#endif // XPM_WEBVIEW_TEST \ No newline at end of file