mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 16:07:39 +00:00
Use bitflags
This commit is contained in:
parent
977c981265
commit
6d6f14fcb3
@ -37,7 +37,7 @@ static bool should_unmap_zygisk = false;
|
|||||||
ret (*old_##func)(__VA_ARGS__); \
|
ret (*old_##func)(__VA_ARGS__); \
|
||||||
ret new_##func(__VA_ARGS__)
|
ret new_##func(__VA_ARGS__)
|
||||||
|
|
||||||
DCL_HOOK_FUNC(void, androidSetCreateThreadFunc, void *func) {
|
DCL_HOOK_FUNC(static void, androidSetCreateThreadFunc, void *func) {
|
||||||
ZLOGD("androidSetCreateThreadFunc\n");
|
ZLOGD("androidSetCreateThreadFunc\n");
|
||||||
hook_jni_env();
|
hook_jni_env();
|
||||||
old_androidSetCreateThreadFunc(func);
|
old_androidSetCreateThreadFunc(func);
|
||||||
@ -49,14 +49,14 @@ DCL_HOOK_FUNC(int, fork) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unmount stuffs in the process's private mount namespace
|
// Unmount stuffs in the process's private mount namespace
|
||||||
DCL_HOOK_FUNC(int, unshare, int flags) {
|
DCL_HOOK_FUNC(static int, unshare, int flags) {
|
||||||
int res = old_unshare(flags);
|
int res = old_unshare(flags);
|
||||||
if (g_ctx && (flags & CLONE_NEWNS) != 0 && res == 0 &&
|
if (g_ctx && (flags & CLONE_NEWNS) != 0 && res == 0 &&
|
||||||
// For some unknown reason, unmounting app_process in SysUI can break.
|
// For some unknown reason, unmounting app_process in SysUI can break.
|
||||||
// This is reproducible on the official AVD running API 26 and 27.
|
// This is reproducible on the official AVD running API 26 and 27.
|
||||||
// Simply avoid doing any unmounts for SysUI to avoid potential issues.
|
// Simply avoid doing any unmounts for SysUI to avoid potential issues.
|
||||||
(g_ctx->info_flags & PROCESS_IS_SYS_UI) == 0) {
|
(g_ctx->info_flags & PROCESS_IS_SYS_UI) == 0) {
|
||||||
if (g_ctx->flags[DO_REVERT_UNMOUNT]) {
|
if (g_ctx->flags & DO_REVERT_UNMOUNT) {
|
||||||
revert_unmount();
|
revert_unmount();
|
||||||
}
|
}
|
||||||
// Restore errno back to 0
|
// Restore errno back to 0
|
||||||
@ -66,7 +66,7 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is the last moment before the secontext of the process changes
|
// This is the last moment before the secontext of the process changes
|
||||||
DCL_HOOK_FUNC(int, selinux_android_setcontext,
|
DCL_HOOK_FUNC(static int, selinux_android_setcontext,
|
||||||
uid_t uid, bool isSystemServer, const char *seinfo, const char *pkgname) {
|
uid_t uid, bool isSystemServer, const char *seinfo, const char *pkgname) {
|
||||||
// Pre-fetch logd before secontext transition
|
// Pre-fetch logd before secontext transition
|
||||||
zygisk_get_logd();
|
zygisk_get_logd();
|
||||||
@ -74,8 +74,8 @@ DCL_HOOK_FUNC(int, selinux_android_setcontext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Close file descriptors to prevent crashing
|
// Close file descriptors to prevent crashing
|
||||||
DCL_HOOK_FUNC(void, android_log_close) {
|
DCL_HOOK_FUNC(static void, android_log_close) {
|
||||||
if (g_ctx == nullptr || !g_ctx->flags[SKIP_CLOSE_LOG_PIPE]) {
|
if (g_ctx == nullptr || !(g_ctx->flags & SKIP_CLOSE_LOG_PIPE)) {
|
||||||
// This happens during forks like nativeForkApp, nativeForkUsap,
|
// This happens during forks like nativeForkApp, nativeForkUsap,
|
||||||
// nativeForkSystemServer, and nativeForkAndSpecialize.
|
// nativeForkSystemServer, and nativeForkAndSpecialize.
|
||||||
zygisk_close_logd();
|
zygisk_close_logd();
|
||||||
@ -86,7 +86,7 @@ DCL_HOOK_FUNC(void, android_log_close) {
|
|||||||
// We cannot directly call `dlclose` to unload ourselves, otherwise when `dlclose` returns,
|
// 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.
|
// it will return to our code which has been unmapped, causing segmentation fault.
|
||||||
// Instead, we hook `pthread_attr_destroy` which will be called when VM daemon threads start.
|
// Instead, we hook `pthread_attr_destroy` which will be called when VM daemon threads start.
|
||||||
DCL_HOOK_FUNC(int, pthread_attr_destroy, void *target) {
|
DCL_HOOK_FUNC(static int, pthread_attr_destroy, void *target) {
|
||||||
int res = old_pthread_attr_destroy((pthread_attr_t *)target);
|
int res = old_pthread_attr_destroy((pthread_attr_t *)target);
|
||||||
|
|
||||||
// Only perform unloading on the main thread
|
// Only perform unloading on the main thread
|
||||||
@ -111,7 +111,7 @@ DCL_HOOK_FUNC(int, pthread_attr_destroy, void *target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// it should be safe to assume all dlclose's in libnativebridge are for zygisk_loader
|
// it should be safe to assume all dlclose's in libnativebridge are for zygisk_loader
|
||||||
DCL_HOOK_FUNC(int, dlclose, void *handle) {
|
DCL_HOOK_FUNC(static int, dlclose, void *handle) {
|
||||||
static bool kDone = false;
|
static bool kDone = false;
|
||||||
if (!kDone) {
|
if (!kDone) {
|
||||||
ZLOGV("dlclose zygisk_loader\n");
|
ZLOGV("dlclose zygisk_loader\n");
|
||||||
@ -126,7 +126,7 @@ DCL_HOOK_FUNC(int, dlclose, void *handle) {
|
|||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
HookContext::HookContext(JNIEnv *env, void *args) :
|
HookContext::HookContext(JNIEnv *env, void *args) :
|
||||||
env(env), args{args}, process(nullptr), pid(-1), info_flags(0),
|
env(env), args{args}, process(nullptr), pid(-1), flags(0), info_flags(0),
|
||||||
hook_info_lock(PTHREAD_MUTEX_INITIALIZER) { g_ctx = this; }
|
hook_info_lock(PTHREAD_MUTEX_INITIALIZER) { g_ctx = this; }
|
||||||
|
|
||||||
HookContext::~HookContext() {
|
HookContext::~HookContext() {
|
||||||
|
@ -98,7 +98,7 @@ void ZygiskModule::setOption(zygisk::Option opt) {
|
|||||||
return;
|
return;
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case zygisk::FORCE_DENYLIST_UNMOUNT:
|
case zygisk::FORCE_DENYLIST_UNMOUNT:
|
||||||
g_ctx->flags[DO_REVERT_UNMOUNT] = true;
|
g_ctx->flags |= DO_REVERT_UNMOUNT;
|
||||||
break;
|
break;
|
||||||
case zygisk::DLCLOSE_MODULE_LIBRARY:
|
case zygisk::DLCLOSE_MODULE_LIBRARY:
|
||||||
unload = true;
|
unload = true;
|
||||||
@ -203,45 +203,6 @@ bool HookContext::plt_hook_commit() {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
static int sigmask(int how, int signum) {
|
|
||||||
sigset_t set;
|
|
||||||
sigemptyset(&set);
|
|
||||||
sigaddset(&set, signum);
|
|
||||||
return sigprocmask(how, &set, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HookContext::fork_pre() {
|
|
||||||
// Do our own fork before loading any 3rd party code
|
|
||||||
// First block SIGCHLD, unblock after original fork is done
|
|
||||||
sigmask(SIG_BLOCK, SIGCHLD);
|
|
||||||
pid = old_fork();
|
|
||||||
|
|
||||||
if (!is_child())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Record all open fds
|
|
||||||
auto dir = xopen_dir("/proc/self/fd");
|
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
|
||||||
int fd = parse_int(entry->d_name);
|
|
||||||
if (fd < 0 || fd >= MAX_FD_SIZE) {
|
|
||||||
close(fd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
allowed_fds[fd] = true;
|
|
||||||
}
|
|
||||||
// The dirfd will be closed once out of scope
|
|
||||||
allowed_fds[dirfd(dir.get())] = false;
|
|
||||||
// logd_fd should be handled separately
|
|
||||||
if (int fd = zygisk_get_logd(); fd >= 0) {
|
|
||||||
allowed_fds[fd] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HookContext::fork_post() {
|
|
||||||
// Unblock SIGCHLD in case the original method didn't
|
|
||||||
sigmask(SIG_UNBLOCK, SIGCHLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HookContext::sanitize_fds() {
|
void HookContext::sanitize_fds() {
|
||||||
zygisk_close_logd();
|
zygisk_close_logd();
|
||||||
|
|
||||||
@ -296,7 +257,7 @@ void HookContext::sanitize_fds() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool HookContext::exempt_fd(int fd) {
|
bool HookContext::exempt_fd(int fd) {
|
||||||
if (flags[POST_SPECIALIZE] || flags[SKIP_CLOSE_LOG_PIPE])
|
if ((flags & POST_SPECIALIZE) || (flags & SKIP_CLOSE_LOG_PIPE))
|
||||||
return true;
|
return true;
|
||||||
if (!can_exempt_fd())
|
if (!can_exempt_fd())
|
||||||
return false;
|
return false;
|
||||||
@ -304,6 +265,49 @@ bool HookContext::exempt_fd(int fd) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HookContext::can_exempt_fd() const {
|
||||||
|
return (flags & APP_FORK_AND_SPECIALIZE) && args.app->fds_to_ignore;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sigmask(int how, int signum) {
|
||||||
|
sigset_t set;
|
||||||
|
sigemptyset(&set);
|
||||||
|
sigaddset(&set, signum);
|
||||||
|
return sigprocmask(how, &set, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HookContext::fork_pre() {
|
||||||
|
// Do our own fork before loading any 3rd party code
|
||||||
|
// First block SIGCHLD, unblock after original fork is done
|
||||||
|
sigmask(SIG_BLOCK, SIGCHLD);
|
||||||
|
pid = old_fork();
|
||||||
|
|
||||||
|
if (!is_child())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Record all open fds
|
||||||
|
auto dir = xopen_dir("/proc/self/fd");
|
||||||
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||||
|
int fd = parse_int(entry->d_name);
|
||||||
|
if (fd < 0 || fd >= MAX_FD_SIZE) {
|
||||||
|
close(fd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
allowed_fds[fd] = true;
|
||||||
|
}
|
||||||
|
// The dirfd will be closed once out of scope
|
||||||
|
allowed_fds[dirfd(dir.get())] = false;
|
||||||
|
// logd_fd should be handled separately
|
||||||
|
if (int fd = zygisk_get_logd(); fd >= 0) {
|
||||||
|
allowed_fds[fd] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HookContext::fork_post() {
|
||||||
|
// Unblock SIGCHLD in case the original method didn't
|
||||||
|
sigmask(SIG_UNBLOCK, SIGCHLD);
|
||||||
|
}
|
||||||
|
|
||||||
void HookContext::run_modules_pre(const vector<int> &fds) {
|
void HookContext::run_modules_pre(const vector<int> &fds) {
|
||||||
for (int i = 0; i < fds.size(); ++i) {
|
for (int i = 0; i < fds.size(); ++i) {
|
||||||
struct stat s{};
|
struct stat s{};
|
||||||
@ -319,7 +323,7 @@ void HookContext::run_modules_pre(const vector<int> &fds) {
|
|||||||
if (void *e = dlsym(h, "zygisk_module_entry")) {
|
if (void *e = dlsym(h, "zygisk_module_entry")) {
|
||||||
modules.emplace_back(i, h, e);
|
modules.emplace_back(i, h, e);
|
||||||
}
|
}
|
||||||
} else if (g_ctx->flags[SERVER_FORK_AND_SPECIALIZE]) {
|
} else if (flags & SERVER_FORK_AND_SPECIALIZE) {
|
||||||
ZLOGW("Failed to dlopen zygisk module: %s\n", dlerror());
|
ZLOGW("Failed to dlopen zygisk module: %s\n", dlerror());
|
||||||
}
|
}
|
||||||
close(fds[i]);
|
close(fds[i]);
|
||||||
@ -335,20 +339,20 @@ void HookContext::run_modules_pre(const vector<int> &fds) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto &m : modules) {
|
for (auto &m : modules) {
|
||||||
if (flags[APP_SPECIALIZE]) {
|
if (flags & APP_SPECIALIZE) {
|
||||||
m.preAppSpecialize(args.app);
|
m.preAppSpecialize(args.app);
|
||||||
} else if (flags[SERVER_FORK_AND_SPECIALIZE]) {
|
} else if (flags & SERVER_FORK_AND_SPECIALIZE) {
|
||||||
m.preServerSpecialize(args.server);
|
m.preServerSpecialize(args.server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HookContext::run_modules_post() {
|
void HookContext::run_modules_post() {
|
||||||
flags[POST_SPECIALIZE] = true;
|
flags |= POST_SPECIALIZE;
|
||||||
for (const auto &m : modules) {
|
for (const auto &m : modules) {
|
||||||
if (flags[APP_SPECIALIZE]) {
|
if (flags & APP_SPECIALIZE) {
|
||||||
m.postAppSpecialize(args.app);
|
m.postAppSpecialize(args.app);
|
||||||
} else if (flags[SERVER_FORK_AND_SPECIALIZE]) {
|
} else if (flags & SERVER_FORK_AND_SPECIALIZE) {
|
||||||
m.postServerSpecialize(args.server);
|
m.postServerSpecialize(args.server);
|
||||||
}
|
}
|
||||||
m.tryUnload();
|
m.tryUnload();
|
||||||
@ -356,7 +360,7 @@ void HookContext::run_modules_post() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HookContext::app_specialize_pre() {
|
void HookContext::app_specialize_pre() {
|
||||||
flags[APP_SPECIALIZE] = true;
|
flags |= APP_SPECIALIZE;
|
||||||
|
|
||||||
vector<int> module_fds;
|
vector<int> module_fds;
|
||||||
int fd = remote_get_info(args.app->uid, process, &info_flags, module_fds);
|
int fd = remote_get_info(args.app->uid, process, &info_flags, module_fds);
|
||||||
@ -369,7 +373,7 @@ void HookContext::app_specialize_pre() {
|
|||||||
}
|
}
|
||||||
if ((info_flags & UNMOUNT_MASK) == UNMOUNT_MASK) {
|
if ((info_flags & UNMOUNT_MASK) == UNMOUNT_MASK) {
|
||||||
ZLOGI("[%s] is on the denylist\n", process);
|
ZLOGI("[%s] is on the denylist\n", process);
|
||||||
flags[DO_REVERT_UNMOUNT] = true;
|
flags |= DO_REVERT_UNMOUNT;
|
||||||
} else if (fd >= 0) {
|
} else if (fd >= 0) {
|
||||||
run_modules_pre(module_fds);
|
run_modules_pre(module_fds);
|
||||||
}
|
}
|
||||||
@ -419,7 +423,7 @@ void HookContext::nativeSpecializeAppProcess_pre() {
|
|||||||
process = env->GetStringUTFChars(args.app->nice_name, nullptr);
|
process = env->GetStringUTFChars(args.app->nice_name, nullptr);
|
||||||
ZLOGV("pre specialize [%s]\n", process);
|
ZLOGV("pre specialize [%s]\n", process);
|
||||||
// App specialize does not check FD
|
// App specialize does not check FD
|
||||||
flags[SKIP_CLOSE_LOG_PIPE] = true;
|
flags |= SKIP_CLOSE_LOG_PIPE;
|
||||||
app_specialize_pre();
|
app_specialize_pre();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +434,7 @@ void HookContext::nativeSpecializeAppProcess_post() {
|
|||||||
|
|
||||||
void HookContext::nativeForkSystemServer_pre() {
|
void HookContext::nativeForkSystemServer_pre() {
|
||||||
ZLOGV("pre forkSystemServer\n");
|
ZLOGV("pre forkSystemServer\n");
|
||||||
flags[SERVER_FORK_AND_SPECIALIZE] = true;
|
flags |= SERVER_FORK_AND_SPECIALIZE;
|
||||||
|
|
||||||
fork_pre();
|
fork_pre();
|
||||||
if (is_child()) {
|
if (is_child()) {
|
||||||
@ -450,7 +454,7 @@ void HookContext::nativeForkSystemServer_post() {
|
|||||||
void HookContext::nativeForkAndSpecialize_pre() {
|
void HookContext::nativeForkAndSpecialize_pre() {
|
||||||
process = env->GetStringUTFChars(args.app->nice_name, nullptr);
|
process = env->GetStringUTFChars(args.app->nice_name, nullptr);
|
||||||
ZLOGV("pre forkAndSpecialize [%s]\n", process);
|
ZLOGV("pre forkAndSpecialize [%s]\n", process);
|
||||||
flags[APP_FORK_AND_SPECIALIZE] = true;
|
flags |= APP_FORK_AND_SPECIALIZE;
|
||||||
|
|
||||||
fork_pre();
|
fork_pre();
|
||||||
if (is_child()) {
|
if (is_child()) {
|
||||||
|
@ -202,15 +202,13 @@ private:
|
|||||||
extern HookContext *g_ctx;
|
extern HookContext *g_ctx;
|
||||||
extern int (*old_fork)(void);
|
extern int (*old_fork)(void);
|
||||||
|
|
||||||
enum {
|
enum : uint32_t {
|
||||||
POST_SPECIALIZE,
|
POST_SPECIALIZE = (1u << 0),
|
||||||
APP_FORK_AND_SPECIALIZE,
|
APP_FORK_AND_SPECIALIZE = (1u << 1),
|
||||||
APP_SPECIALIZE,
|
APP_SPECIALIZE = (1u << 2),
|
||||||
SERVER_FORK_AND_SPECIALIZE,
|
SERVER_FORK_AND_SPECIALIZE = (1u << 3),
|
||||||
DO_REVERT_UNMOUNT,
|
DO_REVERT_UNMOUNT = (1u << 4),
|
||||||
SKIP_CLOSE_LOG_PIPE,
|
SKIP_CLOSE_LOG_PIPE = (1u << 5),
|
||||||
|
|
||||||
FLAG_MAX
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_FD_SIZE 1024
|
#define MAX_FD_SIZE 1024
|
||||||
@ -231,7 +229,7 @@ struct HookContext {
|
|||||||
std::list<ZygiskModule> modules;
|
std::list<ZygiskModule> modules;
|
||||||
|
|
||||||
int pid;
|
int pid;
|
||||||
std::bitset<FLAG_MAX> flags;
|
uint32_t flags;
|
||||||
uint32_t info_flags;
|
uint32_t info_flags;
|
||||||
std::bitset<MAX_FD_SIZE> allowed_fds;
|
std::bitset<MAX_FD_SIZE> allowed_fds;
|
||||||
std::vector<int> exempted_fds;
|
std::vector<int> exempted_fds;
|
||||||
@ -266,8 +264,8 @@ struct HookContext {
|
|||||||
|
|
||||||
void sanitize_fds();
|
void sanitize_fds();
|
||||||
bool exempt_fd(int fd);
|
bool exempt_fd(int fd);
|
||||||
|
bool can_exempt_fd() const;
|
||||||
bool is_child() const { return pid <= 0; }
|
bool is_child() const { return pid <= 0; }
|
||||||
bool can_exempt_fd() const { return flags[APP_FORK_AND_SPECIALIZE] && args.app->fds_to_ignore; }
|
|
||||||
|
|
||||||
// Compatibility shim
|
// Compatibility shim
|
||||||
void plt_hook_register(const char *regex, const char *symbol, void *fn, void **backup);
|
void plt_hook_register(const char *regex, const char *symbol, void *fn, void **backup);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user