From e431fc2c6a6c6662e335ad73521190abaa030528 Mon Sep 17 00:00:00 2001 From: snake-4 <18491360+snake-4@users.noreply.github.com> Date: Sat, 27 Apr 2024 16:56:50 +0200 Subject: [PATCH] Added cache for parsers --- module/jni/include/map_parser.hpp | 2 +- module/jni/include/mount_parser.hpp | 2 +- module/jni/include/mountinfo_parser.hpp | 2 +- module/jni/map_parser.cpp | 21 +++++---- module/jni/modules.cpp | 57 ++++++++++++++----------- module/jni/mount_parser.cpp | 15 ++++--- module/jni/mountinfo_parser.cpp | 31 ++++++++------ module/jni/utils.cpp | 2 +- 8 files changed, 76 insertions(+), 56 deletions(-) diff --git a/module/jni/include/map_parser.hpp b/module/jni/include/map_parser.hpp index b663933..8858c97 100644 --- a/module/jni/include/map_parser.hpp +++ b/module/jni/include/map_parser.hpp @@ -25,4 +25,4 @@ private: ino_t inode; }; -std::vector parseMapsFromPath(const char *path); +const std::vector &parseSelfMaps(bool cached = true); diff --git a/module/jni/include/mount_parser.hpp b/module/jni/include/mount_parser.hpp index 8e12bdc..95150a1 100644 --- a/module/jni/include/mount_parser.hpp +++ b/module/jni/include/mount_parser.hpp @@ -22,5 +22,5 @@ private: int freq, passno; }; -std::vector parseMountsFromPath(const char *path); +const std::vector &parseSelfMounts(bool cached = true); std::unordered_map parseMountOptions(const std::string &input); diff --git a/module/jni/include/mountinfo_parser.hpp b/module/jni/include/mountinfo_parser.hpp index e41f919..de5ccce 100644 --- a/module/jni/include/mountinfo_parser.hpp +++ b/module/jni/include/mountinfo_parser.hpp @@ -30,4 +30,4 @@ private: std::unordered_map mount_options, super_options; }; -std::vector parseMountinfosFromPath(const char *path); +const std::vector &parseSelfMountinfo(bool cached = true); diff --git a/module/jni/map_parser.cpp b/module/jni/map_parser.cpp index e627a4d..db30060 100644 --- a/module/jni/map_parser.cpp +++ b/module/jni/map_parser.cpp @@ -19,15 +19,20 @@ dev_t map_entry_t::getDevice() const { return device; } ino_t map_entry_t::getInode() const { return inode; } const std::string &map_entry_t::getPathname() const { return pathname; } -std::vector parseMapsFromPath(const char *path) +const std::vector &parseSelfMaps(bool cached) { - std::vector ret; + static std::vector parser_cache; + if (cached && !parser_cache.empty()) + { + return parser_cache; + } + parser_cache.clear(); - std::ifstream ifs(path, std::ifstream::in); + std::ifstream ifs("/proc/self/maps", std::ifstream::in); if (!ifs) { - LOGE("parseMapsFromPath could not open file \"%s\"", path); - return ret; + LOGE("parseSelfMaps could not open /proc/self/maps"); + return parser_cache; } for (std::string line; std::getline(ifs, line);) @@ -45,15 +50,15 @@ std::vector parseMapsFromPath(const char *path) if (iss.fail()) { - LOGE("parseMapsFromPath failed to parse line: %s", line.c_str()); + LOGE("parseSelfMaps failed to parse line: %s", line.c_str()); continue; } // This operation can fail, it doesn't matter as it's an optional field. std::getline(iss >> std::ws, pathname); - ret.emplace_back(map_entry_t(address_start, address_end, offset, perms, pathname, makedev(dev_major, dev_minor), inode)); + parser_cache.emplace_back(map_entry_t(address_start, address_end, offset, perms, pathname, makedev(dev_major, dev_minor), inode)); } - return ret; + return parser_cache; } diff --git a/module/jni/modules.cpp b/module/jni/modules.cpp index a781132..897fcef 100644 --- a/module/jni/modules.cpp +++ b/module/jni/modules.cpp @@ -38,7 +38,7 @@ static bool shouldUnmount(const mount_entry_t &mount) const auto &options = mount.getOptions(); // Unmount everything mounted to /data/adb - if (mountPoint.rfind("/data/adb", 0) == 0) + if (mountPoint.starts_with("/data/adb")) return true; // Unmount all module overlayfs and tmpfs @@ -66,7 +66,7 @@ void doUnmount() std::vector mountPoints; // Check mounts first - for (auto &mount : parseMountsFromPath("/proc/self/mounts")) + for (const auto &mount : parseSelfMounts(false)) { if (shouldUnmount(mount)) { @@ -75,7 +75,7 @@ void doUnmount() } // Check mountinfos so that we can find bind mounts as well - for (auto &mount_info : parseMountinfosFromPath("/proc/self/mountinfo")) + for (const auto &mount_info : parseSelfMountinfo(false)) { if (shouldUnmount(mount_info)) { @@ -102,31 +102,33 @@ void doUnmount() void doRemount() { - std::vector mounts = parseMountsFromPath("/proc/self/mounts"); - auto data_mount_it = std::find_if(mounts.begin(), mounts.end(), [](const mount_entry_t &mount) - { return mount.getMountPoint() == "/data"; }); - if (data_mount_it != mounts.end()) + for (const auto &mount : parseSelfMounts(false)) { - const auto &options = data_mount_it->getOptions(); - - // If errors=remount-ro, remount it with errors=continue - if (options.contains("errors") && options.at("errors") == "remount-ro") + if (mount.getMountPoint() == "/data") { - unsigned long flags = MS_REMOUNT; - for (const auto &flagName : mount_flags_procfs) + const auto &options = mount.getOptions(); + + // If errors=remount-ro, remount it with errors=continue + if (options.contains("errors") && options.at("errors") == "remount-ro") { - if (options.contains(flagName.first)) - flags |= flagName.second; + unsigned long flags = MS_REMOUNT; + for (const auto &flagName : mount_flags_procfs) + { + if (options.contains(flagName.first)) + flags |= flagName.second; + } + + if (::mount(NULL, "/data", NULL, flags, "errors=continue") == 0) + { + LOGD("mount(NULL, \"/data\", NULL, 0x%lx, \"errors=continue\") returned 0", flags); + } + else + { + LOGW("mount(NULL, \"/data\", NULL, 0x%lx, \"errors=continue\") returned -1: %d (%s)", flags, errno, strerror(errno)); + } } - if (mount(NULL, "/data", NULL, flags, "errors=continue") == 0) - { - LOGD("mount(NULL, \"/data\", NULL, 0x%lx, \"errors=continue\") returned 0", flags); - } - else - { - LOGW("mount(NULL, \"/data\", NULL, 0x%lx, \"errors=continue\") returned -1: %d (%s)", flags, errno, strerror(errno)); - } + break; } } } @@ -144,7 +146,7 @@ void doHideZygisk() std::string filePath; uintptr_t startAddress = 0, bssAddress = 0; - for (const auto &map : parseMapsFromPath("/proc/self/maps")) + for (const auto &map : parseSelfMaps()) { if (map.getPathname().ends_with("/libnativebridge.so") && map.getPerms() == "r--p") { @@ -173,6 +175,9 @@ void doHideZygisk() LOGD("Found .bss for \"%s\" at 0x%" PRIxPTR " sized %" PRIuPTR " bytes.", filePath.c_str(), bssAddress, bssSize); uint8_t *pHadError = reinterpret_cast(memchr(reinterpret_cast(bssAddress), 0x01, bssSize)); - ASSERT_EXIT("doHideZygisk", pHadError != nullptr, return); - *pHadError = 0; + if (pHadError != nullptr) + { + *pHadError = 0; + LOGD("libnativebridge.so had_error was reset."); + } } diff --git a/module/jni/mount_parser.cpp b/module/jni/mount_parser.cpp index 651f06a..689399a 100644 --- a/module/jni/mount_parser.cpp +++ b/module/jni/mount_parser.cpp @@ -22,21 +22,26 @@ const std::unordered_map &mount_entry_t::getOptions() int mount_entry_t::getDumpFrequency() const { return freq; } int mount_entry_t::getPassNumber() const { return passno; } -std::vector parseMountsFromPath(const char *path) +const std::vector &parseSelfMounts(bool cached) { - std::vector result; + static std::vector parser_cache; + if (cached && !parser_cache.empty()) + { + return parser_cache; + } + parser_cache.clear(); FILE *file; - ASSERT_EXIT("parseMountsFromPath", (file = setmntent(path, "r")) != NULL, return result); + ASSERT_EXIT("parseSelfMounts", (file = setmntent("/proc/self/mounts", "r")) != NULL, return parser_cache); struct mntent *entry; while ((entry = getmntent(file)) != NULL) { - result.emplace_back(mount_entry_t(entry)); + parser_cache.emplace_back(mount_entry_t(entry)); } endmntent(file); - return result; + return parser_cache; } std::unordered_map parseMountOptions(const std::string &input) diff --git a/module/jni/mountinfo_parser.cpp b/module/jni/mountinfo_parser.cpp index 350b99e..ad71382 100644 --- a/module/jni/mountinfo_parser.cpp +++ b/module/jni/mountinfo_parser.cpp @@ -34,15 +34,20 @@ const std::string &mountinfo_entry_t::getFilesystemType() const { return filesys const std::string &mountinfo_entry_t::getMountSource() const { return mount_source; } const std::unordered_map &mountinfo_entry_t::getSuperOptions() const { return super_options; } -std::vector parseMountinfosFromPath(const char *path) +const std::vector &parseSelfMountinfo(bool cached) { - std::vector ret; + static std::vector parser_cache; + if (cached && !parser_cache.empty()) + { + return parser_cache; + } + parser_cache.clear(); - std::ifstream ifs(path, std::ifstream::in); + std::ifstream ifs("/proc/self/mountinfo", std::ifstream::in); if (!ifs) { - LOGE("parseMountinfosFromPath could not open file \"%s\"", path); - return ret; + LOGE("parseSelfMountinfo could not open /proc/self/mountinfo"); + return parser_cache; } for (std::string line; std::getline(ifs, line);) @@ -57,7 +62,7 @@ std::vector parseMountinfosFromPath(const char *path) iss >> mount_id >> parent_id >> major >> colon >> minor >> root >> mount_point >> mount_options; if (iss.fail()) { - LOGE("parseMountinfosFromPath failed to parse the first 6 fields of line: %s", line.c_str()); + LOGE("parseSelfMountinfo failed to parse the first 6 fields of line: %s", line.c_str()); continue; } @@ -69,22 +74,22 @@ std::vector parseMountinfosFromPath(const char *path) if (iss.fail()) { - LOGE("parseMountinfosFromPath failed to parse the optional fields of line: %s", line.c_str()); + LOGE("parseSelfMountinfo failed to parse the optional fields of line: %s", line.c_str()); continue; } iss >> filesystem_type >> mount_source >> super_options; if (iss.fail()) { - LOGE("parseMountinfosFromPath failed to parse the last 3 fields of line: %s", line.c_str()); + LOGE("parseSelfMountinfo failed to parse the last 3 fields of line: %s", line.c_str()); continue; } - ret.emplace_back(mountinfo_entry_t(mount_id, parent_id, major, minor, - root, mount_point, mount_options, - optional_fields, filesystem_type, mount_source, - super_options)); + parser_cache.emplace_back(mountinfo_entry_t(mount_id, parent_id, major, minor, + root, mount_point, mount_options, + optional_fields, filesystem_type, mount_source, + super_options)); } - return ret; + return parser_cache; } diff --git a/module/jni/utils.cpp b/module/jni/utils.cpp index 8ce6e5f..42d93c2 100644 --- a/module/jni/utils.cpp +++ b/module/jni/utils.cpp @@ -12,7 +12,7 @@ bool hookPLTByName(zygisk::Api *api, const std::string &libName, const std::string &symbolName, void *hookFunc, void **origFunc) { - for (const auto &map : parseMapsFromPath("/proc/self/maps")) + for (const auto &map : parseSelfMaps()) { if (map.getPathname().ends_with("/" + libName)) {