diff --git a/loader/src/common/daemon.cpp b/loader/src/common/daemon.cpp index 97b0dcf..4ba297b 100644 --- a/loader/src/common/daemon.cpp +++ b/loader/src/common/daemon.cpp @@ -58,6 +58,17 @@ namespace zygiskd { return socket_utils::read_string(fd); } + uint32_t GetProcessFlags(uid_t uid) { + UniqueFd fd = Connect(1); + if (fd == -1) { + PLOGE("GetProcessFlags"); + return 0; + } + socket_utils::write_u8(fd, (uint8_t) SocketAction::GetProcessFlags); + socket_utils::write_u32(fd, uid); + return socket_utils::read_u32(fd); + } + std::vector ReadModules() { std::vector modules; UniqueFd fd = Connect(1); diff --git a/loader/src/common/socket_utils.cpp b/loader/src/common/socket_utils.cpp index a889d90..73dd1d2 100644 --- a/loader/src/common/socket_utils.cpp +++ b/loader/src/common/socket_utils.cpp @@ -90,6 +90,10 @@ namespace socket_utils { return read_exact_or(fd, 0); } + uint32_t read_u32(int fd) { + return read_exact_or(fd, 0); + } + size_t read_usize(int fd) { return read_exact_or(fd, 0); } @@ -110,6 +114,10 @@ namespace socket_utils { return write_exact(fd, val); } + bool write_u32(int fd, uint32_t val) { + return write_exact(fd, val); + } + bool write_string(int fd, std::string_view str) { return write_usize(fd, str.size()) && str.size() == xwrite(fd, str.data(), str.size()); } diff --git a/loader/src/include/daemon.h b/loader/src/include/daemon.h index 65b0a81..ddf7247 100644 --- a/loader/src/include/daemon.h +++ b/loader/src/include/daemon.h @@ -54,6 +54,7 @@ namespace zygiskd { PingHeartBeat, RequestLogcatFd, ReadNativeBridge, + GetProcessFlags, ReadModules, RequestCompanionSocket, GetModuleDir, @@ -67,6 +68,8 @@ namespace zygiskd { std::vector ReadModules(); + uint32_t GetProcessFlags(uid_t uid); + int ConnectCompanion(size_t index); int GetModuleDir(size_t index); diff --git a/loader/src/include/socket_utils.h b/loader/src/include/socket_utils.h index 76f692e..b2775d7 100644 --- a/loader/src/include/socket_utils.h +++ b/loader/src/include/socket_utils.h @@ -13,12 +13,16 @@ namespace socket_utils { uint8_t read_u8(int fd); + uint32_t read_u32(int fd); + size_t read_usize(int fd); std::string read_string(int fd); bool write_u8(int fd, uint8_t val); + bool write_u32(int fd, uint32_t val); + int recv_fd(int fd); bool write_usize(int fd, size_t val); diff --git a/loader/src/injector/hide.cpp b/loader/src/injector/hide.cpp deleted file mode 100644 index a85ce90..0000000 --- a/loader/src/injector/hide.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include - -#include "logging.h" -#include "misc.hpp" -#include "zygisk.hpp" - -using namespace std::string_view_literals; - -static void lazy_unmount(const char* mountpoint) { - if (umount2(mountpoint, MNT_DETACH) != -1) - LOGD("Unmounted (%s)", mountpoint); -} - -void revert_unmount() { - parse_mnt("/proc/self/mounts", [](mntent* mentry) { - if (mentry->mnt_fsname == "/data/adb/ksu/modules"sv || - std::string_view(mentry->mnt_opts).find("/data/adb/ksu/modules") != std::string_view::npos) { - lazy_unmount(mentry->mnt_fsname); - } - return true; - }); -} diff --git a/loader/src/injector/hook.cpp b/loader/src/injector/hook.cpp index 7f9cf30..516a782 100644 --- a/loader/src/injector/hook.cpp +++ b/loader/src/injector/hook.cpp @@ -566,15 +566,13 @@ void HookContext::run_modules_post() { /* Zygisksu changed: Load module fds */ void HookContext::app_specialize_pre() { flags[APP_SPECIALIZE] = true; + info_flags = zygiskd::GetProcessFlags(g_ctx->args.app->uid); run_modules_pre(); } void HookContext::app_specialize_post() { run_modules_post(); - if (info_flags & PROCESS_IS_MAGISK_APP) { - setenv("ZYGISK_ENABLED", "1", 1); - } // Cleanups env->ReleaseStringUTFChars(args.app->nice_name, process); diff --git a/loader/src/injector/misc.cpp b/loader/src/injector/misc.cpp index d7b5131..dee9f9e 100644 --- a/loader/src/injector/misc.cpp +++ b/loader/src/injector/misc.cpp @@ -35,6 +35,31 @@ void parse_mnt(const char* file, const std::function& fn) { } } +std::list split_str(std::string_view s, std::string_view delimiter) { + std::list ret; + size_t pos = 0; + while (pos < s.size()) { + auto next = s.find(delimiter, pos); + if (next == std::string_view::npos) { + ret.emplace_back(s.substr(pos)); + break; + } + ret.emplace_back(s.substr(pos, next - pos)); + pos = next + delimiter.size(); + } + return ret; +} + +std::string join_str(const std::list& list, std::string_view delimiter) { + std::string ret; + for (auto& s : list) { + if (!ret.empty()) + ret += delimiter; + ret += s; + } + return ret; +} + sDIR make_dir(DIR *dp) { return sDIR(dp, [](DIR *dp){ return dp ? closedir(dp) : 1; }); } diff --git a/loader/src/injector/misc.hpp b/loader/src/injector/misc.hpp index 6d09dce..083414a 100644 --- a/loader/src/injector/misc.hpp +++ b/loader/src/injector/misc.hpp @@ -2,10 +2,12 @@ #include #include +#include #include #include #include #include +#include #include #include "logging.h" @@ -34,6 +36,16 @@ private: using thread_entry = void *(*)(void *); int new_daemon_thread(thread_entry entry, void *arg); +static inline bool str_contains(std::string_view s, std::string_view ss) { + return s.find(ss) != std::string_view::npos; +} +static inline bool str_starts(std::string_view s, std::string_view ss) { + return s.size() >= ss.size() && s.compare(0, ss.size(), ss) == 0; +} +static inline bool str_ends(std::string_view s, std::string_view ss) { + return s.size() >= ss.size() && s.compare(s.size() - ss.size(), std::string_view::npos, ss) == 0; +} + template class stateless_allocator { public: @@ -78,6 +90,25 @@ static inline sFILE xopen_file(int fd, const char *mode) { return make_file(fdopen(fd, mode)); } +template +class reversed_container { +public: + reversed_container(T &base) : base(base) {} + decltype(std::declval().rbegin()) begin() { return base.rbegin(); } + decltype(std::declval().crbegin()) begin() const { return base.crbegin(); } + decltype(std::declval().crbegin()) cbegin() const { return base.crbegin(); } + decltype(std::declval().rend()) end() { return base.rend(); } + decltype(std::declval().crend()) end() const { return base.crend(); } + decltype(std::declval().crend()) cend() const { return base.crend(); } +private: + T &base; +}; + +template +reversed_container reversed(T &base) { + return reversed_container(base); +} + template static inline void default_new(T *&p) { p = new T(); } @@ -97,6 +128,10 @@ int parse_int(std::string_view s); void parse_mnt(const char* file, const std::function& fn); +std::list split_str(std::string_view s, std::string_view delimiter); + +std::string join_str(const std::list& list, std::string_view delimiter); + template static inline T align_to(T v, int a) { static_assert(std::is_integral::value); diff --git a/loader/src/injector/module.hpp b/loader/src/injector/module.hpp index e1d13bc..a21982c 100644 --- a/loader/src/injector/module.hpp +++ b/loader/src/injector/module.hpp @@ -111,12 +111,10 @@ namespace { PROCESS_GRANTED_ROOT = zygisk::StateFlag::PROCESS_GRANTED_ROOT, PROCESS_ON_DENYLIST = zygisk::StateFlag::PROCESS_ON_DENYLIST, - PROCESS_IS_SYS_UI = (1u << 29), - DENYLIST_ENFORCING = (1u << 30), - PROCESS_IS_MAGISK_APP = (1u << 31), + PROCESS_IS_SYS_UI = (1u << 30), + PROCESS_IS_KSU_APP = (1u << 31), - UNMOUNT_MASK = (PROCESS_ON_DENYLIST | DENYLIST_ENFORCING), - PRIVATE_MASK = (PROCESS_IS_SYS_UI | DENYLIST_ENFORCING | PROCESS_IS_MAGISK_APP) + PRIVATE_MASK = (PROCESS_IS_SYS_UI | PROCESS_IS_KSU_APP) }; struct api_abi_base { diff --git a/loader/src/injector/unmount.cpp b/loader/src/injector/unmount.cpp new file mode 100644 index 0000000..77dc3dc --- /dev/null +++ b/loader/src/injector/unmount.cpp @@ -0,0 +1,73 @@ +#include + +#include "logging.h" +#include "misc.hpp" +#include "zygisk.hpp" + +using namespace std::string_view_literals; + +static void lazy_unmount(const char* mountpoint) { + if (umount2(mountpoint, MNT_DETACH) != -1) { + LOGD("Unmounted (%s)", mountpoint); + } else { + PLOGE("Failed to unmount: %s (%s)", strerror(errno), mountpoint); + } +} + +#define PARSE_OPT(name, flag) \ + if (opt == name) { \ + flags |= (flag); \ + return true; \ + } + +void revert_unmount() { + std::vector targets; + std::list> backups; + + targets.emplace_back("/data/adb/ksu/modules"); + parse_mnt("/proc/self/mounts", [&](mntent* mentry) { + if (str_starts(mentry->mnt_fsname, "/data/adb/")) { + targets.emplace_back(mentry->mnt_dir); + } + if (mentry->mnt_type == "overlay"sv) { + if (str_contains(mentry->mnt_opts, "/data/adb/ksu/modules")) { + targets.emplace_back(mentry->mnt_dir); + } else { + backups.emplace_back(mentry->mnt_dir, mentry->mnt_opts); + } + } + return true; + }); + + for (auto& s: reversed(targets)) { + lazy_unmount(s.data()); + } + + parse_mnt("/proc/self/mounts", [&](mntent* mentry) { + if (mentry->mnt_type == "overlay"sv) { + for (auto it = backups.begin(); it != backups.end(); it++) { + backups.remove_if([&](auto& mnt) { + return mnt.first == mentry->mnt_dir && mnt.second == mentry->mnt_opts; + }); + } + } + return true; + }); + + for (auto& mnt: backups) { + auto opts = split_str(mnt.second, ","); + unsigned long flags = 0; + opts.remove_if([&](auto& opt) { + PARSE_OPT(MNTOPT_RO, MS_RDONLY) + PARSE_OPT(MNTOPT_NOSUID, MS_NOSUID) + PARSE_OPT("relatime", MS_RELATIME) + return false; + }); + auto mnt_data = join_str(opts, ","); + if (mount("overlay", mnt.first.data(), "overlay", flags, mnt_data.data()) != -1) { + LOGD("Remounted (%s)", mnt.first.data()); + } else { + LOGW("Failed to remount: %s (%s, %s)", strerror(errno), mnt.first.data(), mnt_data.data()); + } + } +} diff --git a/module/src/customize.sh b/module/src/customize.sh index 9ed74a2..aa120b1 100644 --- a/module/src/customize.sh +++ b/module/src/customize.sh @@ -72,10 +72,8 @@ ui_print "- Extracting module files" extract "$ZIPFILE" 'daemon.sh' "$MODPATH" extract "$ZIPFILE" 'module.prop' "$MODPATH" extract "$ZIPFILE" 'post-fs-data.sh' "$MODPATH" +extract "$ZIPFILE" 'sepolicy.rule' "$MODPATH" extract "$ZIPFILE" 'service.sh' "$MODPATH" -if [ "$KSU" ]; then - extract "$ZIPFILE" 'sepolicy.rule' "$MODPATH" -fi HAS32BIT=false && [ -d "/system/lib" ] && HAS32BIT=true HAS64BIT=false && [ -d "/system/lib64" ] && HAS64BIT=true diff --git a/module/src/post-fs-data.sh b/module/src/post-fs-data.sh index dd9beee..f19ef2d 100644 --- a/module/src/post-fs-data.sh +++ b/module/src/post-fs-data.sh @@ -21,4 +21,4 @@ if [ $(which magisk) ] && [ ".." -ef "/data/adb/modules" ]; then done fi -unshare -m sh -c "./daemon.sh $@&" +sh -c "./daemon.sh $@&" diff --git a/module/src/sepolicy.rule b/module/src/sepolicy.rule index 810ab0d..95b3aa7 100644 --- a/module/src/sepolicy.rule +++ b/module/src/sepolicy.rule @@ -10,3 +10,6 @@ allow * magisk_file lnk_file * allow * magisk_file sock_file * allow system_server system_server process execmem +allow zygote mnt_vendor_file dir search +allow zygote system_file dir mounton +allow zygote labeledfs filesystem mount