You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
improve: mounting system, compatibility; remove: logging on release (#111)
This commit adds numerous improvements to the state of hidden'ility of ReZygisk, and also for compatibility. Recommended to check #111 for more information.
This commit is contained in:
@@ -63,19 +63,6 @@ namespace zygiskd {
|
||||
return true;
|
||||
}
|
||||
|
||||
int RequestLogcatFd() {
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
PLOGE("RequestLogcatFd");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket_utils::write_u8(fd, (uint8_t) SocketAction::RequestLogcatFd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
uint32_t GetProcessFlags(uid_t uid) {
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
@@ -94,8 +81,8 @@ namespace zygiskd {
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<Module> ReadModules() {
|
||||
std::vector<Module> modules;
|
||||
std::vector<ModuleInfo> ReadModules() {
|
||||
std::vector<ModuleInfo> modules;
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
PLOGE("ReadModules");
|
||||
@@ -260,4 +247,34 @@ namespace zygiskd {
|
||||
close(fd);
|
||||
} else info->running = false;
|
||||
}
|
||||
|
||||
std::string UpdateMountNamespace(enum mount_namespace_state nms_state) {
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
PLOGE("UpdateMountNamespace");
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
socket_utils::write_u8(fd, (uint8_t) SocketAction::UpdateMountNamespace);
|
||||
socket_utils::write_u32(fd, getpid());
|
||||
socket_utils::write_u8(fd, (uint8_t)nms_state);
|
||||
|
||||
uint32_t target_pid = socket_utils::read_u32(fd);
|
||||
int target_fd = 0;
|
||||
|
||||
if (target_pid == 0) goto error;
|
||||
|
||||
target_fd = (int)socket_utils::read_u32(fd);
|
||||
if (target_fd == 0) goto error;
|
||||
|
||||
close(fd);
|
||||
|
||||
return "/proc/" + std::to_string(target_pid) + "/fd/" + std::to_string(target_fd);
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,9 +46,14 @@ void* DlopenExt(const char* path, int flags) {
|
||||
}
|
||||
|
||||
void* DlopenMem(int fd, int flags) {
|
||||
auto info = android_dlextinfo{
|
||||
auto info = android_dlextinfo {
|
||||
.flags = ANDROID_DLEXT_USE_LIBRARY_FD,
|
||||
.library_fd = fd
|
||||
.reserved_addr = NULL,
|
||||
.reserved_size = 0,
|
||||
.relro_fd = 0,
|
||||
.library_fd = fd,
|
||||
.library_fd_offset = 0,
|
||||
.library_namespace = NULL
|
||||
};
|
||||
|
||||
/* INFO: We need to find the path of the fd since passing "" to android_dlopen_ext
|
||||
|
||||
@@ -187,7 +187,7 @@ ElfW(Addr) ElfImg::LinearLookup(std::string_view name) const {
|
||||
}
|
||||
}
|
||||
|
||||
std::string_view ElfImg::LinearLookupByPrefix(std::string_view name) const {
|
||||
ElfW(Addr) ElfImg::LinearLookupByPrefix(std::string_view name) const {
|
||||
if (symtabs_.empty()) {
|
||||
symtabs_.reserve(symtab_count);
|
||||
if (symtab_start != nullptr && symstr_offset_for_symtab != 0) {
|
||||
@@ -207,11 +207,11 @@ std::string_view ElfImg::LinearLookupByPrefix(std::string_view name) const {
|
||||
if (symtab.first.size() < size) continue;
|
||||
|
||||
if (symtab.first.substr(0, size) == name) {
|
||||
return symtab.first;
|
||||
return symtab.second->st_value;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#include <android/log.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "socket_utils.h"
|
||||
|
||||
namespace logging {
|
||||
static int logfd = -1;
|
||||
|
||||
void setfd(int fd) {
|
||||
close(logfd);
|
||||
logfd = fd;
|
||||
}
|
||||
|
||||
int getfd() {
|
||||
return logfd;
|
||||
}
|
||||
|
||||
void log(int prio, const char* tag, const char* fmt, ...) {
|
||||
if (logfd == -1) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
__android_log_vprint(prio, tag, fmt, ap);
|
||||
va_end(ap);
|
||||
} else {
|
||||
char buf[BUFSIZ];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
socket_utils::write_u8(logfd, prio);
|
||||
socket_utils::write_string(logfd, tag);
|
||||
socket_utils::write_string(logfd, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,18 +61,23 @@ struct zygote_info {
|
||||
bool running;
|
||||
};
|
||||
|
||||
enum mount_namespace_state {
|
||||
Clean,
|
||||
Rooted,
|
||||
Module
|
||||
};
|
||||
|
||||
namespace zygiskd {
|
||||
|
||||
struct Module {
|
||||
struct ModuleInfo {
|
||||
std::string name;
|
||||
UniqueFd memfd;
|
||||
|
||||
inline explicit Module(std::string name, int memfd) : name(name), memfd(memfd) {}
|
||||
inline explicit ModuleInfo(std::string name, int memfd) : name(name), memfd(memfd) {}
|
||||
};
|
||||
|
||||
enum class SocketAction {
|
||||
PingHeartBeat,
|
||||
RequestLogcatFd,
|
||||
GetProcessFlags,
|
||||
GetInfo,
|
||||
ReadModules,
|
||||
@@ -80,6 +85,7 @@ namespace zygiskd {
|
||||
GetModuleDir,
|
||||
ZygoteRestart,
|
||||
SystemServerStarted,
|
||||
UpdateMountNamespace
|
||||
};
|
||||
|
||||
void Init(const char *path);
|
||||
@@ -88,9 +94,7 @@ namespace zygiskd {
|
||||
|
||||
bool PingHeartbeat();
|
||||
|
||||
int RequestLogcatFd();
|
||||
|
||||
std::vector<Module> ReadModules();
|
||||
std::vector<ModuleInfo> ReadModules();
|
||||
|
||||
uint32_t GetProcessFlags(uid_t uid);
|
||||
|
||||
@@ -103,4 +107,6 @@ namespace zygiskd {
|
||||
void SystemServerStarted();
|
||||
|
||||
void GetInfo(struct zygote_info *info);
|
||||
|
||||
std::string UpdateMountNamespace(enum mount_namespace_state mns_state);
|
||||
}
|
||||
|
||||
@@ -48,8 +48,13 @@ namespace SandHook {
|
||||
}
|
||||
}
|
||||
|
||||
std::string_view findSymbolNameByPrefix(std::string_view prefix) const {
|
||||
return LinearLookupByPrefix(prefix);
|
||||
constexpr ElfW(Addr) getSymbAddressByPrefix(std::string_view prefix) const {
|
||||
ElfW(Addr) offset = LinearLookupByPrefix(prefix);
|
||||
if (offset > 0 && base != nullptr) {
|
||||
return static_cast<ElfW(Addr)>((uintptr_t) base + offset - bias);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -57,6 +62,11 @@ namespace SandHook {
|
||||
return reinterpret_cast<T>(getSymbAddress(name));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T getSymbAddressByPrefix(std::string_view prefix) const {
|
||||
return reinterpret_cast<T>(getSymbAddressByPrefix(prefix));
|
||||
}
|
||||
|
||||
bool isValid() const {
|
||||
return base != nullptr;
|
||||
}
|
||||
@@ -76,7 +86,7 @@ namespace SandHook {
|
||||
|
||||
ElfW(Addr) LinearLookup(std::string_view name) const;
|
||||
|
||||
std::string_view LinearLookupByPrefix(std::string_view name) const;
|
||||
ElfW(Addr) LinearLookupByPrefix(std::string_view name) const;
|
||||
|
||||
constexpr static uint32_t ElfHash(std::string_view name);
|
||||
|
||||
|
||||
@@ -1,35 +1,30 @@
|
||||
#pragma once
|
||||
#ifndef LOGGING_H
|
||||
#define LOGGING_H
|
||||
|
||||
#include <android/log.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#if defined(__LP64__)
|
||||
# define LOG_TAG "zygisk-core64"
|
||||
#else
|
||||
# define LOG_TAG "zygisk-core32"
|
||||
#endif
|
||||
#ifdef __LP64__
|
||||
#define LOG_TAG "zygisk-core64"
|
||||
#else
|
||||
#define LOG_TAG "zygisk-core32"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define LOGD(...) logging::log(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGV(...) logging::log(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define LOGD(...)
|
||||
#define LOGV(...)
|
||||
#define LOGD(...)
|
||||
#define LOGV(...)
|
||||
#endif
|
||||
#define LOGI(...) logging::log(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGW(...) logging::log(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGE(...) logging::log(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGF(...) logging::log(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__)
|
||||
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__)
|
||||
#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
|
||||
|
||||
namespace logging {
|
||||
void setfd(int fd);
|
||||
|
||||
int getfd();
|
||||
|
||||
[[gnu::format(printf, 3, 4)]]
|
||||
void log(int prio, const char* tag, const char* fmt, ...);
|
||||
}
|
||||
#endif /* LOGGING_H */
|
||||
@@ -21,7 +21,6 @@ namespace SoList {
|
||||
#endif
|
||||
|
||||
inline static const char *(*get_realpath_sym)(SoInfo *) = NULL;
|
||||
inline static const char *(*get_soname_sym)(SoInfo *) = NULL;
|
||||
inline static void (*soinfo_free)(SoInfo *) = NULL;
|
||||
|
||||
inline SoInfo *get_next() {
|
||||
@@ -38,12 +37,6 @@ namespace SoList {
|
||||
return ((std::string *) ((uintptr_t) this + solist_realpath_offset))->c_str();
|
||||
}
|
||||
|
||||
inline const char *get_name() {
|
||||
if (get_soname_sym) return get_soname_sym(this);
|
||||
|
||||
return ((std::string *) ((uintptr_t) this + solist_realpath_offset - sizeof(void *)))->c_str();
|
||||
}
|
||||
|
||||
void set_next(SoInfo *si) {
|
||||
*(SoInfo **) ((uintptr_t) this + solist_next_offset) = si;
|
||||
}
|
||||
@@ -110,6 +103,13 @@ namespace SoList {
|
||||
return addr == NULL ? NULL : *addr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T *getStaticPointerByPrefix(const SandHook::ElfImg &linker, const char *name) {
|
||||
auto *addr = reinterpret_cast<T **>(linker.getSymbAddressByPrefix(name));
|
||||
|
||||
return addr == NULL ? NULL : *addr;
|
||||
}
|
||||
|
||||
static bool DropSoPath(const char* target_path) {
|
||||
bool path_found = false;
|
||||
if (solist == NULL && !Initialize()) {
|
||||
@@ -117,9 +117,9 @@ namespace SoList {
|
||||
return path_found;
|
||||
}
|
||||
for (auto iter = solist; iter; iter = iter->get_next()) {
|
||||
if (iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_path)) {
|
||||
if (iter->get_path() && strstr(iter->get_path(), target_path)) {
|
||||
SoList::ProtectedDataGuard guard;
|
||||
LOGI("dropping solist record for %s loaded at %s with size %zu", iter->get_name(), iter->get_path(), iter->get_size());
|
||||
LOGV("dropping solist record loaded at %s with size %zu", iter->get_path(), iter->get_size());
|
||||
if (iter->get_size() > 0) {
|
||||
iter->set_size(0);
|
||||
SoInfo::soinfo_free(iter);
|
||||
@@ -136,7 +136,7 @@ namespace SoList {
|
||||
return;
|
||||
}
|
||||
if (g_module_load_counter == NULL || g_module_unload_counter == NULL) {
|
||||
LOGI("g_module counters not defined, skip reseting them");
|
||||
LOGD("g_module counters not defined, skip reseting them");
|
||||
return;
|
||||
}
|
||||
auto loaded_modules = *g_module_load_counter;
|
||||
@@ -163,57 +163,26 @@ namespace SoList {
|
||||
|
||||
See #63 for more information.
|
||||
*/
|
||||
|
||||
std::string_view solist_sym_name = linker.findSymbolNameByPrefix("__dl__ZL6solist");
|
||||
if (solist_sym_name.empty()) return false;
|
||||
LOGD("found symbol name %s", solist_sym_name.data());
|
||||
|
||||
std::string_view soinfo_free_name = linker.findSymbolNameByPrefix("__dl__ZL11soinfo_freeP6soinfo");
|
||||
if (soinfo_free_name.empty()) return false;
|
||||
LOGD("found symbol name %s", soinfo_free_name.data());
|
||||
|
||||
/* INFO: The size isn't a magic number, it's the size for the string: .llvm.7690929523238822858 */
|
||||
char llvm_sufix[25 + 1];
|
||||
|
||||
if (solist_sym_name.length() != strlen("__dl__ZL6solist")) {
|
||||
strncpy(llvm_sufix, solist_sym_name.data() + strlen("__dl__ZL6solist"), sizeof(llvm_sufix));
|
||||
} else {
|
||||
llvm_sufix[0] = '\0';
|
||||
}
|
||||
|
||||
solist = getStaticPointer<SoInfo>(linker, solist_sym_name.data());
|
||||
solist = getStaticPointerByPrefix<SoInfo>(linker, "__dl__ZL6solist");
|
||||
if (solist == NULL) return false;
|
||||
LOGD("found symbol solist");
|
||||
|
||||
char somain_sym_name[sizeof("__dl__ZL6somain") + sizeof(llvm_sufix)];
|
||||
snprintf(somain_sym_name, sizeof(somain_sym_name), "__dl__ZL6somain%s", llvm_sufix);
|
||||
|
||||
char sonext_sym_name[sizeof("__dl__ZL6sonext") + sizeof(llvm_sufix)];
|
||||
snprintf(sonext_sym_name, sizeof(somain_sym_name), "__dl__ZL6sonext%s", llvm_sufix);
|
||||
|
||||
char vdso_sym_name[sizeof("__dl__ZL4vdso") + sizeof(llvm_sufix)];
|
||||
snprintf(vdso_sym_name, sizeof(vdso_sym_name), "__dl__ZL4vdso%s", llvm_sufix);
|
||||
|
||||
somain = getStaticPointer<SoInfo>(linker, somain_sym_name);
|
||||
somain = getStaticPointerByPrefix<SoInfo>(linker, "__dl__ZL6somain");
|
||||
if (somain == NULL) return false;
|
||||
LOGD("found symbol somain");
|
||||
|
||||
sonext = linker.getSymbAddress<SoInfo **>(sonext_sym_name);
|
||||
sonext = linker.getSymbAddressByPrefix<SoInfo **>("__dl__ZL6sonext");
|
||||
if (sonext == NULL) return false;
|
||||
LOGD("found symbol sonext");
|
||||
|
||||
SoInfo *vdso = getStaticPointer<SoInfo>(linker, vdso_sym_name);
|
||||
SoInfo *vdso = getStaticPointerByPrefix<SoInfo>(linker, "__dl__ZL4vdso");
|
||||
if (vdso != NULL) LOGD("found symbol vdso");
|
||||
|
||||
SoInfo::get_realpath_sym = reinterpret_cast<decltype(SoInfo::get_realpath_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo12get_realpathEv"));
|
||||
if (SoInfo::get_realpath_sym == NULL) return false;
|
||||
LOGD("found symbol get_realpath_sym");
|
||||
|
||||
SoInfo::get_soname_sym = reinterpret_cast<decltype(SoInfo::get_soname_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo10get_sonameEv"));
|
||||
if (SoInfo::get_soname_sym == NULL) return false;
|
||||
LOGD("found symbol get_soname_sym");
|
||||
|
||||
SoInfo::soinfo_free = reinterpret_cast<decltype(SoInfo::soinfo_free)>(linker.getSymbAddress(soinfo_free_name));
|
||||
SoInfo::soinfo_free = reinterpret_cast<decltype(SoInfo::soinfo_free)>(linker.getSymbAddressByPrefix("__dl__ZL11soinfo_freeP6soinfo"));
|
||||
if (SoInfo::soinfo_free == NULL) return false;
|
||||
LOGD("found symbol soinfo_free");
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ size_t block_size = 0;
|
||||
|
||||
extern "C" [[gnu::visibility("default")]]
|
||||
void entry(void* addr, size_t size, const char* path) {
|
||||
LOGI("Zygisk library injected, version %s", ZKSU_VERSION);
|
||||
LOGD("Zygisk library injected, version %s", ZKSU_VERSION);
|
||||
start_addr = addr;
|
||||
block_size = size;
|
||||
zygiskd::Init(path);
|
||||
@@ -19,11 +19,7 @@ void entry(void* addr, size_t size, const char* path) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
logging::setfd(zygiskd::RequestLogcatFd());
|
||||
#endif
|
||||
|
||||
LOGI("start plt hooking");
|
||||
LOGD("start plt hooking");
|
||||
hook_functions();
|
||||
clean_trace(path, 1, 0, false);
|
||||
}
|
||||
|
||||
@@ -137,6 +137,36 @@ DCL_HOOK_FUNC(int, fork) {
|
||||
return (g_ctx && g_ctx->pid >= 0) ? g_ctx->pid : old_fork();
|
||||
}
|
||||
|
||||
bool update_mnt_ns(enum mount_namespace_state mns_state, bool dry_run) {
|
||||
std::string ns_path = zygiskd::UpdateMountNamespace(mns_state);
|
||||
if (ns_path.empty()) {
|
||||
PLOGE("Failed to update mount namespace");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dry_run) return true;
|
||||
|
||||
int updated_ns = open(ns_path.data(), O_RDONLY);
|
||||
if (updated_ns == -1) {
|
||||
PLOGE("Failed to open mount namespace [%s]", ns_path.data());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGD("set mount namespace to [%s] fd=[%d]\n", ns_path.data(), updated_ns);
|
||||
if (setns(updated_ns, CLONE_NEWNS) == -1) {
|
||||
PLOGE("Failed to set mount namespace [%s]", ns_path.data());
|
||||
close(updated_ns);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
close(updated_ns);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Unmount stuffs in the process's private mount namespace
|
||||
DCL_HOOK_FUNC(int, unshare, int flags) {
|
||||
int res = old_unshare(flags);
|
||||
@@ -144,37 +174,22 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
|
||||
// For some unknown reason, unmounting app_process in SysUI can break.
|
||||
// This is reproducible on the official AVD running API 26 and 27.
|
||||
// Simply avoid doing any unmounts for SysUI to avoid potential issues.
|
||||
(g_ctx->info_flags & PROCESS_IS_SYS_UI) == 0) {
|
||||
if (g_ctx->flags[DO_REVERT_UNMOUNT]) {
|
||||
if (g_ctx->info_flags & PROCESS_ROOT_IS_KSU) {
|
||||
revert_unmount_ksu();
|
||||
} else if (g_ctx->info_flags & PROCESS_ROOT_IS_APATCH){
|
||||
revert_unmount_apatch();
|
||||
} else if (g_ctx->info_flags & PROCESS_ROOT_IS_MAGISK) {
|
||||
revert_unmount_magisk();
|
||||
}
|
||||
!g_ctx->flags[SERVER_FORK_AND_SPECIALIZE] && !(g_ctx->info_flags & PROCESS_IS_FIRST_STARTED)) {
|
||||
if (g_ctx->info_flags & (PROCESS_IS_MANAGER | PROCESS_GRANTED_ROOT)) {
|
||||
update_mnt_ns(Rooted, false);
|
||||
} else if (!(g_ctx->flags[DO_REVERT_UNMOUNT])) {
|
||||
update_mnt_ns(Module, false);
|
||||
}
|
||||
|
||||
/* Zygisksu changed: No umount app_process */
|
||||
|
||||
// Restore errno back to 0
|
||||
errno = 0;
|
||||
old_unshare(CLONE_NEWNS);
|
||||
}
|
||||
|
||||
/* INFO: To spoof the errno value */
|
||||
errno = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// Close logd_fd if necessary to prevent crashing
|
||||
// For more info, check comments in zygisk_log_write
|
||||
DCL_HOOK_FUNC(void, android_log_close) {
|
||||
if (g_ctx == nullptr) {
|
||||
// Happens during un-managed fork like nativeForkApp, nativeForkUsap
|
||||
logging::setfd(-1);
|
||||
} else if (!g_ctx->flags[SKIP_FD_SANITIZATION]) {
|
||||
logging::setfd(-1);
|
||||
}
|
||||
old_android_log_close();
|
||||
}
|
||||
|
||||
// We cannot directly call `dlclose` to unload ourselves, otherwise when `dlclose` returns,
|
||||
// it will return to our code which has been unmapped, causing segmentation fault.
|
||||
// Instead, we hook `pthread_attr_setstacksize` which will be called when VM daemon threads start.
|
||||
@@ -189,11 +204,13 @@ DCL_HOOK_FUNC(int, pthread_attr_setstacksize, void *target, size_t size) {
|
||||
if (should_unmap_zygisk) {
|
||||
unhook_functions();
|
||||
cached_map_infos.clear();
|
||||
|
||||
if (should_unmap_zygisk) {
|
||||
// Because both `pthread_attr_setstacksize` and `dlclose` have the same function signature,
|
||||
// we can use `musttail` to let the compiler reuse our stack frame and thus
|
||||
// `dlclose` will directly return to the caller of `pthread_attr_setstacksize`.
|
||||
LOGI("unmap libzygisk.so loaded at %p with size %zu", start_addr, block_size);
|
||||
LOGD("unmap libzygisk.so loaded at %p with size %zu", start_addr, block_size);
|
||||
|
||||
[[clang::musttail]] return munmap(start_addr, block_size);
|
||||
}
|
||||
}
|
||||
@@ -598,14 +615,18 @@ void ZygiskContext::run_modules_post() {
|
||||
/* Zygisksu changed: Load module fds */
|
||||
void ZygiskContext::app_specialize_pre() {
|
||||
flags[APP_SPECIALIZE] = true;
|
||||
|
||||
info_flags = zygiskd::GetProcessFlags(g_ctx->args.app->uid);
|
||||
if (info_flags & PROCESS_IS_FIRST_STARTED) {
|
||||
update_mnt_ns(Clean, true);
|
||||
}
|
||||
|
||||
if ((info_flags & PROCESS_ON_DENYLIST) == PROCESS_ON_DENYLIST) {
|
||||
flags[DO_REVERT_UNMOUNT] = true;
|
||||
flags[DO_REVERT_UNMOUNT] = true;
|
||||
}
|
||||
|
||||
if ((info_flags & (PROCESS_IS_MANAGER | PROCESS_ROOT_IS_MAGISK)) == (PROCESS_IS_MANAGER | PROCESS_ROOT_IS_MAGISK)) {
|
||||
LOGI("Manager process detected. Notifying that Zygisk has been enabled.");
|
||||
LOGD("Manager process detected. Notifying that Zygisk has been enabled.");
|
||||
|
||||
setenv("ZYGISK_ENABLED", "1", 1);
|
||||
} else {
|
||||
@@ -620,7 +641,6 @@ void ZygiskContext::app_specialize_post() {
|
||||
// Cleanups
|
||||
env->ReleaseStringUTFChars(args.app->nice_name, process);
|
||||
g_ctx = nullptr;
|
||||
logging::setfd(-1);
|
||||
}
|
||||
|
||||
bool ZygiskContext::exempt_fd(int fd) {
|
||||
@@ -653,11 +673,10 @@ void ZygiskContext::nativeForkSystemServer_pre() {
|
||||
flags[SERVER_FORK_AND_SPECIALIZE] = true;
|
||||
|
||||
fork_pre();
|
||||
if (pid != 0)
|
||||
return;
|
||||
|
||||
run_modules_pre();
|
||||
zygiskd::SystemServerStarted();
|
||||
if (is_child()) {
|
||||
run_modules_pre();
|
||||
zygiskd::SystemServerStarted();
|
||||
}
|
||||
|
||||
sanitize_fds();
|
||||
}
|
||||
@@ -673,12 +692,9 @@ void ZygiskContext::nativeForkSystemServer_post() {
|
||||
void ZygiskContext::nativeForkAndSpecialize_pre() {
|
||||
process = env->GetStringUTFChars(args.app->nice_name, nullptr);
|
||||
LOGV("pre forkAndSpecialize [%s]", process);
|
||||
|
||||
flags[APP_FORK_AND_SPECIALIZE] = true;
|
||||
/* Zygisksu changed: No args.app->fds_to_ignore check since we are Android 10+ */
|
||||
if (logging::getfd() != -1) {
|
||||
exempted_fds.push_back(logging::getfd());
|
||||
}
|
||||
|
||||
update_mnt_ns(Clean, false);
|
||||
|
||||
fork_pre();
|
||||
if (pid == 0) {
|
||||
@@ -805,7 +821,6 @@ void hook_functions() {
|
||||
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, fork);
|
||||
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, unshare);
|
||||
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, strdup);
|
||||
PLT_HOOK_REGISTER_SYM(android_runtime_dev, android_runtime_inode, "__android_log_close", android_log_close);
|
||||
hook_commit();
|
||||
|
||||
// Remove unhooked methods
|
||||
|
||||
@@ -126,13 +126,13 @@ namespace {
|
||||
PROCESS_GRANTED_ROOT = zygisk::StateFlag::PROCESS_GRANTED_ROOT,
|
||||
PROCESS_ON_DENYLIST = zygisk::StateFlag::PROCESS_ON_DENYLIST,
|
||||
|
||||
PROCESS_IS_MANAGER = (1u << 28),
|
||||
PROCESS_ROOT_IS_APATCH = (1u << 27),
|
||||
PROCESS_IS_MANAGER = (1u << 27),
|
||||
PROCESS_ROOT_IS_APATCH = (1u << 28),
|
||||
PROCESS_ROOT_IS_KSU = (1u << 29),
|
||||
PROCESS_ROOT_IS_MAGISK = (1u << 30),
|
||||
PROCESS_IS_SYS_UI = (1u << 31),
|
||||
PROCESS_IS_FIRST_STARTED = (1u << 31),
|
||||
|
||||
PRIVATE_MASK = PROCESS_IS_SYS_UI
|
||||
PRIVATE_MASK = PROCESS_IS_FIRST_STARTED
|
||||
};
|
||||
|
||||
struct api_abi_base {
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
#include <mntent.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include "files.hpp"
|
||||
#include "logging.h"
|
||||
#include "misc.hpp"
|
||||
#include "zygisk.hpp"
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
namespace {
|
||||
constexpr auto MODULE_DIR = "/data/adb/modules";
|
||||
constexpr auto KSU_OVERLAY_SOURCE = "KSU";
|
||||
constexpr auto AP_OVERLAY_SOURCE = "APatch";
|
||||
const std::vector<std::string> DEVICE_PARTITIONS{"/system", "/vendor", "/product", "/system_ext", "/odm", "/oem"};
|
||||
|
||||
void lazy_unmount(const char* mountpoint) {
|
||||
if (umount2(mountpoint, MNT_DETACH) != -1) {
|
||||
LOGD("Unmounted (%s)", mountpoint);
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
PLOGE("Unmount (%s)", mountpoint);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void revert_unmount_ksu() {
|
||||
std::string ksu_loop;
|
||||
std::vector<std::string> targets;
|
||||
|
||||
// Unmount ksu module dir last
|
||||
targets.emplace_back(MODULE_DIR);
|
||||
|
||||
for (auto& info: parse_mount_info("self")) {
|
||||
if (info.target == MODULE_DIR) {
|
||||
ksu_loop = info.source;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Unmount everything mounted to /data/adb
|
||||
if (info.target.starts_with("/data/adb")) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
|
||||
// Unmount everything mounted to /data/adb
|
||||
if (info.root.starts_with("/adb/modules")) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
|
||||
// Unmount ksu overlays
|
||||
if (info.type == "overlay"
|
||||
&& info.source == KSU_OVERLAY_SOURCE
|
||||
&& std::find(DEVICE_PARTITIONS.begin(), DEVICE_PARTITIONS.end(), info.target) != DEVICE_PARTITIONS.end()) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
|
||||
// Unmount temp dir
|
||||
if (info.type == "tmpfs" && info.source == KSU_OVERLAY_SOURCE) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& info: parse_mount_info("self")) {
|
||||
// Unmount everything from ksu loop except ksu module dir
|
||||
if (info.source == ksu_loop && info.target != MODULE_DIR) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
}
|
||||
|
||||
// Do unmount
|
||||
for (auto& s: reversed(targets)) {
|
||||
lazy_unmount(s.data());
|
||||
}
|
||||
}
|
||||
|
||||
void revert_unmount_magisk() {
|
||||
std::vector<std::string> targets;
|
||||
|
||||
// Unmount dummy skeletons and MAGISKTMP
|
||||
// since mirror nodes are always mounted under skeleton, we don't have to specifically unmount
|
||||
for (auto& info: parse_mount_info("self")) {
|
||||
if (info.source == "magisk" || info.source == "worker" || // magisktmp tmpfs
|
||||
info.root.starts_with("/adb/modules")) { // bind mount from data partition
|
||||
targets.push_back(info.target);
|
||||
}
|
||||
// Unmount everything mounted to /data/adb
|
||||
if (info.target.starts_with("/data/adb")) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& s: reversed(targets)) {
|
||||
lazy_unmount(s.data());
|
||||
}
|
||||
}
|
||||
|
||||
void revert_unmount_apatch() {
|
||||
std::string ap_loop;
|
||||
std::vector<std::string> targets;
|
||||
|
||||
// Unmount ksu module dir last
|
||||
targets.emplace_back(MODULE_DIR);
|
||||
|
||||
for (auto& info: parse_mount_info("self")) {
|
||||
if (info.target == MODULE_DIR) {
|
||||
ap_loop = info.source;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Unmount everything mounted to /data/adb
|
||||
if (info.target.starts_with("/data/adb")) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
|
||||
// Unmount everything mounted to /data/adb
|
||||
if (info.root.starts_with("/adb/modules")) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
|
||||
// Unmount ksu overlays
|
||||
if (info.type == "overlay"
|
||||
&& info.source == AP_OVERLAY_SOURCE
|
||||
&& std::find(DEVICE_PARTITIONS.begin(), DEVICE_PARTITIONS.end(), info.target) != DEVICE_PARTITIONS.end()) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
|
||||
// Unmount temp dir
|
||||
if (info.type == "tmpfs" && info.source == AP_OVERLAY_SOURCE) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& info: parse_mount_info("self")) {
|
||||
// Unmount everything from ksu loop except ksu module dir
|
||||
if (info.source == ap_loop && info.target != MODULE_DIR) {
|
||||
targets.emplace_back(info.target);
|
||||
}
|
||||
}
|
||||
|
||||
// Do unmount
|
||||
for (auto& s: reversed(targets)) {
|
||||
lazy_unmount(s.data());
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,3 @@ extern size_t block_size;
|
||||
void hook_functions();
|
||||
|
||||
void clean_trace(const char* path, size_t load = 1, size_t unload = 0, bool spoof_maps = false);
|
||||
|
||||
void revert_unmount_ksu();
|
||||
|
||||
void revert_unmount_magisk();
|
||||
|
||||
void revert_unmount_apatch();
|
||||
|
||||
Reference in New Issue
Block a user