mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-02 12:02:15 +00:00
Refactor zygisk to use native bridge to inject
Co-authored-by: vvb2060 <vvb2060@gmail.com> Co-authored-by: topjohnwu <topjohnwu@gmail.com>
This commit is contained in:
parent
42eb928054
commit
9fbd079560
16
build.py
16
build.py
@ -246,7 +246,7 @@ def run_ndk_build(flags):
|
|||||||
error("Build binary failed!")
|
error("Build binary failed!")
|
||||||
os.chdir("..")
|
os.chdir("..")
|
||||||
for arch in archs:
|
for arch in archs:
|
||||||
for tgt in support_targets + ["libinit-ld.so", "libzygisk-ld.so"]:
|
for tgt in support_targets + ["libinit-ld.so"]:
|
||||||
source = op.join("native", "libs", arch, tgt)
|
source = op.join("native", "libs", arch, tgt)
|
||||||
target = op.join("native", "out", arch, tgt)
|
target = op.join("native", "out", arch, tgt)
|
||||||
mv(source, target)
|
mv(source, target)
|
||||||
@ -342,9 +342,6 @@ def dump_bin_header(args):
|
|||||||
preload = op.join("native", "out", arch, "libinit-ld.so")
|
preload = op.join("native", "out", arch, "libinit-ld.so")
|
||||||
with open(preload, "rb") as src:
|
with open(preload, "rb") as src:
|
||||||
text = binary_dump(src, "init_ld_xz")
|
text = binary_dump(src, "init_ld_xz")
|
||||||
preload = op.join("native", "out", arch, "libzygisk-ld.so")
|
|
||||||
with open(preload, "rb") as src:
|
|
||||||
text += binary_dump(src, "zygisk_ld", compressor=lambda x: x)
|
|
||||||
write_if_diff(op.join(native_gen_path, f"{arch}_binaries.h"), text)
|
write_if_diff(op.join(native_gen_path, f"{arch}_binaries.h"), text)
|
||||||
|
|
||||||
|
|
||||||
@ -395,8 +392,9 @@ def build_binary(args):
|
|||||||
flag = ""
|
flag = ""
|
||||||
clean = False
|
clean = False
|
||||||
|
|
||||||
if "magisk" in args.target or "magiskinit" in args.target:
|
if "magisk" in args.target:
|
||||||
flag += " B_PRELOAD=1"
|
flag += " B_MAGISK=1"
|
||||||
|
clean = True
|
||||||
|
|
||||||
if "magiskpolicy" in args.target:
|
if "magiskpolicy" in args.target:
|
||||||
flag += " B_POLICY=1"
|
flag += " B_POLICY=1"
|
||||||
@ -417,14 +415,10 @@ def build_binary(args):
|
|||||||
if flag:
|
if flag:
|
||||||
run_ndk_build(flag)
|
run_ndk_build(flag)
|
||||||
|
|
||||||
# magiskinit and magisk embeds preload.so
|
# magiskinit embeds preload.so
|
||||||
|
|
||||||
flag = ""
|
flag = ""
|
||||||
|
|
||||||
if "magisk" in args.target:
|
|
||||||
flag += " B_MAGISK=1"
|
|
||||||
clean = True
|
|
||||||
|
|
||||||
if "magiskinit" in args.target:
|
if "magiskinit" in args.target:
|
||||||
flag += " B_INIT=1"
|
flag += " B_INIT=1"
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ LOCAL_SRC_FILES := \
|
|||||||
zygisk/utils.cpp \
|
zygisk/utils.cpp \
|
||||||
zygisk/hook.cpp \
|
zygisk/hook.cpp \
|
||||||
zygisk/memory.cpp \
|
zygisk/memory.cpp \
|
||||||
|
zygisk/native_bridge.cpp \
|
||||||
zygisk/deny/cli.cpp \
|
zygisk/deny/cli.cpp \
|
||||||
zygisk/deny/utils.cpp \
|
zygisk/deny/utils.cpp \
|
||||||
zygisk/deny/revert.cpp
|
zygisk/deny/revert.cpp
|
||||||
@ -57,12 +58,6 @@ LOCAL_SRC_FILES := init/preload.c
|
|||||||
LOCAL_STRIP_MODE := --strip-all
|
LOCAL_STRIP_MODE := --strip-all
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := zygisk-ld
|
|
||||||
LOCAL_SRC_FILES := zygisk/loader.c
|
|
||||||
LOCAL_STRIP_MODE := --strip-all
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef B_INIT
|
ifdef B_INIT
|
||||||
|
@ -31,11 +31,6 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
string_view argv0 = basename(argv[0]);
|
string_view argv0 = basename(argv[0]);
|
||||||
|
|
||||||
// app_process is actually not an applet
|
|
||||||
if (argv0.starts_with("app_process")) {
|
|
||||||
return app_process_main(argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
umask(0);
|
umask(0);
|
||||||
|
|
||||||
if (argv[0][0] == '\0') {
|
if (argv[0][0] == '\0') {
|
||||||
|
@ -416,6 +416,8 @@ static void boot_complete() {
|
|||||||
// Ensure manager exists
|
// Ensure manager exists
|
||||||
check_pkg_refresh();
|
check_pkg_refresh();
|
||||||
get_manager(0, nullptr, true);
|
get_manager(0, nullptr, true);
|
||||||
|
|
||||||
|
reset_zygisk(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void boot_stage_handler(int client, int code) {
|
void boot_stage_handler(int client, int code) {
|
||||||
|
@ -144,6 +144,7 @@ static void handle_request_async(int client, int code, const sock_cred &cred) {
|
|||||||
LOGI("** zygote restarted\n");
|
LOGI("** zygote restarted\n");
|
||||||
pkg_xml_ino = 0;
|
pkg_xml_ino = 0;
|
||||||
prune_su_access();
|
prune_su_access();
|
||||||
|
reset_zygisk(false);
|
||||||
close(client);
|
close(client);
|
||||||
break;
|
break;
|
||||||
case MainRequest::SQLITE_CMD:
|
case MainRequest::SQLITE_CMD:
|
||||||
@ -158,7 +159,6 @@ static void handle_request_async(int client, int code, const sock_cred &cred) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MainRequest::ZYGISK:
|
case MainRequest::ZYGISK:
|
||||||
case MainRequest::ZYGISK_PASSTHROUGH:
|
|
||||||
zygisk_handler(client, &cred);
|
zygisk_handler(client, &cred);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -15,6 +15,8 @@ using namespace std;
|
|||||||
|
|
||||||
#define VLOGD(tag, from, to) LOGD("%-8s: %s <- %s\n", tag, to, from)
|
#define VLOGD(tag, from, to) LOGD("%-8s: %s <- %s\n", tag, to, from)
|
||||||
|
|
||||||
|
static string native_bridge = "0";
|
||||||
|
|
||||||
static int bind_mount(const char *reason, const char *from, const char *to) {
|
static int bind_mount(const char *reason, const char *from, const char *to) {
|
||||||
int ret = xmount(from, to, nullptr, MS_BIND | MS_REC, nullptr);
|
int ret = xmount(from, to, nullptr, MS_BIND | MS_REC, nullptr);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
@ -22,9 +24,6 @@ static int bind_mount(const char *reason, const char *from, const char *to) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
string node_entry::module_mnt;
|
|
||||||
string node_entry::mirror_dir;
|
|
||||||
|
|
||||||
/*************************
|
/*************************
|
||||||
* Node Tree Construction
|
* Node Tree Construction
|
||||||
*************************/
|
*************************/
|
||||||
@ -211,6 +210,21 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class zygisk_node : public node_entry {
|
||||||
|
public:
|
||||||
|
explicit zygisk_node(const char *name, bool is64bit) : node_entry(name, DT_REG, this),
|
||||||
|
is64bit(is64bit) {}
|
||||||
|
|
||||||
|
void mount() override {
|
||||||
|
const string src = get_magisk_tmp() + "/magisk"s + (is64bit ? "64" : "32");
|
||||||
|
create_and_mount("zygisk", src);
|
||||||
|
xmount(nullptr, node_path().data(), nullptr, MS_REMOUNT | MS_BIND | MS_RDONLY, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is64bit;
|
||||||
|
};
|
||||||
|
|
||||||
static void inject_magisk_bins(root_node *system) {
|
static void inject_magisk_bins(root_node *system) {
|
||||||
auto bin = system->get_child<inter_node>("bin");
|
auto bin = system->get_child<inter_node>("bin");
|
||||||
if (!bin) {
|
if (!bin) {
|
||||||
@ -228,24 +242,28 @@ static void inject_magisk_bins(root_node *system) {
|
|||||||
delete bin->extract("supolicy");
|
delete bin->extract("supolicy");
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<module_info> *module_list;
|
static void inject_zygisk_libs(root_node *system) {
|
||||||
int app_process_32 = -1;
|
if (access("/system/bin/linker", F_OK) == 0) {
|
||||||
int app_process_64 = -1;
|
auto lib = system->get_child<inter_node>("lib");
|
||||||
|
if (!lib) {
|
||||||
|
lib = new inter_node("lib");
|
||||||
|
system->insert(lib);
|
||||||
|
}
|
||||||
|
lib->insert(new zygisk_node(native_bridge.data(), false));
|
||||||
|
}
|
||||||
|
|
||||||
#define mount_zygisk(bit) \
|
if (access("/system/bin/linker64", F_OK) == 0) {
|
||||||
if (access("/system/bin/app_process" #bit, F_OK) == 0) { \
|
auto lib64 = system->get_child<inter_node>("lib64");
|
||||||
app_process_##bit = xopen("/system/bin/app_process" #bit, O_RDONLY | O_CLOEXEC); \
|
if (!lib64) {
|
||||||
string zbin = zygisk_bin + "/app_process" #bit; \
|
lib64 = new inter_node("lib64");
|
||||||
string mbin = get_magisk_tmp() + "/magisk"s #bit; \
|
system->insert(lib64);
|
||||||
int src = xopen(mbin.data(), O_RDONLY | O_CLOEXEC); \
|
}
|
||||||
int out = xopen(zbin.data(), O_CREAT | O_WRONLY | O_CLOEXEC, 0); \
|
lib64->insert(new zygisk_node(native_bridge.data(), true));
|
||||||
xsendfile(out, src, nullptr, INT_MAX); \
|
}
|
||||||
close(out); \
|
|
||||||
close(src); \
|
|
||||||
clone_attr("/system/bin/app_process" #bit, zbin.data()); \
|
|
||||||
bind_mount("zygisk", zbin.data(), "/system/bin/app_process" #bit); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<module_info> *module_list;
|
||||||
|
|
||||||
void load_modules() {
|
void load_modules() {
|
||||||
node_entry::mirror_dir = get_magisk_tmp() + "/"s MIRRDIR;
|
node_entry::mirror_dir = get_magisk_tmp() + "/"s MIRRDIR;
|
||||||
node_entry::module_mnt = get_magisk_tmp() + "/"s MODULEMNT "/";
|
node_entry::module_mnt = get_magisk_tmp() + "/"s MODULEMNT "/";
|
||||||
@ -289,6 +307,22 @@ void load_modules() {
|
|||||||
inject_magisk_bins(system);
|
inject_magisk_bins(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (zygisk_enabled) {
|
||||||
|
string native_bridge_orig = get_prop(NBPROP);
|
||||||
|
if (native_bridge_orig.empty()) {
|
||||||
|
native_bridge_orig = "0";
|
||||||
|
}
|
||||||
|
native_bridge = native_bridge_orig != "0" ? ZYGISKLDR + native_bridge_orig : ZYGISKLDR;
|
||||||
|
set_prop(NBPROP, native_bridge.data(), true);
|
||||||
|
// Weather Huawei's Maple compiler is enabled.
|
||||||
|
// If so, system server will be created by a special Zygote which ignores the native bridge
|
||||||
|
// and make system server out of our control. Avoid it by disabling.
|
||||||
|
if (get_prop("ro.maple.enable") == "1") {
|
||||||
|
set_prop("ro.maple.enable", "0", true);
|
||||||
|
}
|
||||||
|
inject_zygisk_libs(system);
|
||||||
|
}
|
||||||
|
|
||||||
if (!system->is_empty()) {
|
if (!system->is_empty()) {
|
||||||
// Handle special read-only partitions
|
// Handle special read-only partitions
|
||||||
for (const char *part : { "/vendor", "/product", "/system_ext" }) {
|
for (const char *part : { "/vendor", "/product", "/system_ext" }) {
|
||||||
@ -304,14 +338,6 @@ void load_modules() {
|
|||||||
root->mount();
|
root->mount();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount on top of modules to enable zygisk
|
|
||||||
if (zygisk_enabled) {
|
|
||||||
string zygisk_bin = get_magisk_tmp() + "/"s ZYGISKBIN;
|
|
||||||
mkdir(zygisk_bin.data(), 0);
|
|
||||||
mount_zygisk(32)
|
|
||||||
mount_zygisk(64)
|
|
||||||
}
|
|
||||||
|
|
||||||
ssprintf(buf, sizeof(buf), "%s/" WORKERDIR, get_magisk_tmp());
|
ssprintf(buf, sizeof(buf), "%s/" WORKERDIR, get_magisk_tmp());
|
||||||
xmount(nullptr, buf, nullptr, MS_REMOUNT | MS_RDONLY, nullptr);
|
xmount(nullptr, buf, nullptr, MS_REMOUNT | MS_RDONLY, nullptr);
|
||||||
}
|
}
|
||||||
@ -491,3 +517,23 @@ void exec_module_scripts(const char *stage) {
|
|||||||
[](const module_info &info) -> string_view { return info.name; });
|
[](const module_info &info) -> string_view { return info.name; });
|
||||||
exec_module_scripts(stage, module_names);
|
exec_module_scripts(stage, module_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reset_zygisk(bool restore) {
|
||||||
|
if (!zygisk_enabled) return;
|
||||||
|
static atomic_uint zygote_start_count{1};
|
||||||
|
if (restore) {
|
||||||
|
zygote_start_count = 1;
|
||||||
|
} else if (zygote_start_count.fetch_add(1) > 3) {
|
||||||
|
LOGW("zygote crashes too many times, rolling-back\n");
|
||||||
|
restore = true;
|
||||||
|
}
|
||||||
|
if (restore) {
|
||||||
|
string native_bridge_orig = "0";
|
||||||
|
if (native_bridge.length() > strlen(ZYGISKLDR)) {
|
||||||
|
native_bridge_orig = native_bridge.substr(strlen(ZYGISKLDR));
|
||||||
|
}
|
||||||
|
set_prop(NBPROP, native_bridge_orig.data(), true);
|
||||||
|
} else {
|
||||||
|
set_prop(NBPROP, native_bridge.data(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -49,8 +49,8 @@ public:
|
|||||||
|
|
||||||
virtual void mount() = 0;
|
virtual void mount() = 0;
|
||||||
|
|
||||||
static string module_mnt;
|
inline static string module_mnt;
|
||||||
static string mirror_dir;
|
inline static string mirror_dir;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<class T>
|
template<class T>
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#define CALL_PROVIDER \
|
#define CALL_PROVIDER \
|
||||||
exe, "/system/bin", "com.android.commands.content.Content", \
|
"/system/bin/app_process", "/system/bin", "com.android.commands.content.Content", \
|
||||||
"call", "--uri", target, "--user", user, "--method", action
|
"call", "--uri", target, "--user", user, "--method", action
|
||||||
|
|
||||||
#define START_ACTIVITY \
|
#define START_ACTIVITY \
|
||||||
exe, "/system/bin", "com.android.commands.am.Am", \
|
"/system/bin/app_process", "/system/bin", "com.android.commands.am.Am", \
|
||||||
"start", "-p", target, "--user", user, "-a", "android.intent.action.VIEW", \
|
"start", "-p", target, "--user", user, "-a", "android.intent.action.VIEW", \
|
||||||
"-f", "0x58800020", "--es", "action", action
|
"-f", "0x58800020", "--es", "action", action
|
||||||
|
|
||||||
@ -130,21 +130,10 @@ static bool check_no_error(int fd) {
|
|||||||
|
|
||||||
static void exec_cmd(const char *action, vector<Extra> &data,
|
static void exec_cmd(const char *action, vector<Extra> &data,
|
||||||
const shared_ptr<su_info> &info, bool provider = true) {
|
const shared_ptr<su_info> &info, bool provider = true) {
|
||||||
char exe[128];
|
|
||||||
char target[128];
|
char target[128];
|
||||||
char user[4];
|
char user[4];
|
||||||
ssprintf(user, sizeof(user), "%d", to_user_id(info->eval_uid));
|
ssprintf(user, sizeof(user), "%d", to_user_id(info->eval_uid));
|
||||||
|
|
||||||
if (zygisk_enabled) {
|
|
||||||
#if defined(__LP64__)
|
|
||||||
ssprintf(exe, sizeof(exe), "/proc/self/fd/%d", app_process_64);
|
|
||||||
#else
|
|
||||||
ssprintf(exe, sizeof(exe), "/proc/self/fd/%d", app_process_32);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
strscpy(exe, "/system/bin/app_process", sizeof(exe));
|
|
||||||
}
|
|
||||||
|
|
||||||
// First try content provider call method
|
// First try content provider call method
|
||||||
if (provider) {
|
if (provider) {
|
||||||
ssprintf(target, sizeof(target), "content://%s.provider", info->mgr_pkg.data());
|
ssprintf(target, sizeof(target), "content://%s.provider", info->mgr_pkg.data());
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
zygisk_inject_entry;
|
zygisk_inject_entry;
|
||||||
unload_first_stage;
|
NativeBridgeItf;
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,6 @@ enum : int {
|
|||||||
SQLITE_CMD,
|
SQLITE_CMD,
|
||||||
REMOVE_MODULES,
|
REMOVE_MODULES,
|
||||||
ZYGISK,
|
ZYGISK,
|
||||||
ZYGISK_PASSTHROUGH,
|
|
||||||
|
|
||||||
_STAGE_BARRIER_,
|
_STAGE_BARRIER_,
|
||||||
|
|
||||||
@ -67,9 +66,8 @@ struct module_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern bool zygisk_enabled;
|
extern bool zygisk_enabled;
|
||||||
extern int app_process_32;
|
|
||||||
extern int app_process_64;
|
|
||||||
extern std::vector<module_info> *module_list;
|
extern std::vector<module_info> *module_list;
|
||||||
|
void reset_zygisk(bool restore);
|
||||||
|
|
||||||
extern "C" const char *get_magisk_tmp();
|
extern "C" const char *get_magisk_tmp();
|
||||||
int connect_daemon(int req, bool create = false);
|
int connect_daemon(int req, bool create = false);
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
|
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
|
||||||
|
#define ZYGISKLDR "libzygisk.so"
|
||||||
|
#define NBPROP "ro.dalvik.vm.native.bridge"
|
||||||
#define SECURE_DIR "/data/adb"
|
#define SECURE_DIR "/data/adb"
|
||||||
#define MODULEROOT SECURE_DIR "/modules"
|
#define MODULEROOT SECURE_DIR "/modules"
|
||||||
#define MODULEUPGRADE SECURE_DIR "/modules_update"
|
#define MODULEUPGRADE SECURE_DIR "/modules_update"
|
||||||
@ -49,5 +51,4 @@ extern int SDK_INT;
|
|||||||
int magisk_main(int argc, char *argv[]);
|
int magisk_main(int argc, char *argv[]);
|
||||||
int su_client_main(int argc, char *argv[]);
|
int su_client_main(int argc, char *argv[]);
|
||||||
int resetprop_main(int argc, char *argv[]);
|
int resetprop_main(int argc, char *argv[]);
|
||||||
int app_process_main(int argc, char *argv[]);
|
|
||||||
int zygisk_main(int argc, char *argv[]);
|
int zygisk_main(int argc, char *argv[]);
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
#include <android/dlext.h>
|
#include <android/dlext.h>
|
||||||
|
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
#include <daemon.hpp>
|
|
||||||
#include <magisk.hpp>
|
#include <magisk.hpp>
|
||||||
#include <selinux.hpp>
|
|
||||||
|
|
||||||
#include "zygisk.hpp"
|
#include "zygisk.hpp"
|
||||||
#include "module.hpp"
|
#include "module.hpp"
|
||||||
@ -18,43 +16,11 @@ using namespace std;
|
|||||||
|
|
||||||
void *self_handle = nullptr;
|
void *self_handle = nullptr;
|
||||||
|
|
||||||
// Make sure /proc/self/environ is sanitized
|
extern "C" [[maybe_unused]] void zygisk_inject_entry(void *handle) {
|
||||||
// Filter env and reset MM_ENV_END
|
|
||||||
static void sanitize_environ() {
|
|
||||||
char *cur = environ[0];
|
|
||||||
|
|
||||||
for (int i = 0; environ[i]; ++i) {
|
|
||||||
// Copy all env onto the original stack
|
|
||||||
size_t len = strlen(environ[i]);
|
|
||||||
memmove(cur, environ[i], len + 1);
|
|
||||||
environ[i] = cur;
|
|
||||||
cur += len + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
prctl(PR_SET_MM, PR_SET_MM_ENV_END, cur, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void unload_first_stage() {
|
|
||||||
ZLOGD("unloading first stage\n");
|
|
||||||
unmap_all(HIJACK_BIN);
|
|
||||||
xumount2(HIJACK_BIN, MNT_DETACH);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void zygisk_inject_entry(void *handle) {
|
|
||||||
zygisk_logging();
|
|
||||||
ZLOGD("load success\n");
|
|
||||||
|
|
||||||
char *ld = getenv("LD_PRELOAD");
|
|
||||||
if (char *c = strrchr(ld, ':')) {
|
|
||||||
*c = '\0';
|
|
||||||
setenv("LD_PRELOAD", ld, 1); // Restore original LD_PRELOAD
|
|
||||||
} else {
|
|
||||||
unsetenv("LD_PRELOAD");
|
|
||||||
}
|
|
||||||
|
|
||||||
self_handle = handle;
|
self_handle = handle;
|
||||||
sanitize_environ();
|
zygisk_logging();
|
||||||
hook_functions();
|
hook_functions();
|
||||||
|
ZLOGD("load success\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following code runs in zygote/app process
|
// The following code runs in zygote/app process
|
||||||
@ -146,88 +112,6 @@ static void connect_companion(int client, bool is_64_bit) {
|
|||||||
send_fd(zygiskd_socket, client);
|
send_fd(zygiskd_socket, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
static timespec last_zygote_start;
|
|
||||||
static int zygote_start_counts[] = { 0, 0 };
|
|
||||||
#define zygote_start_count zygote_start_counts[is_64_bit]
|
|
||||||
#define zygote_started (zygote_start_counts[0] + zygote_start_counts[1])
|
|
||||||
#define zygote_start_reset(val) { zygote_start_counts[0] = val; zygote_start_counts[1] = val; }
|
|
||||||
|
|
||||||
static void setup_files(int client, const sock_cred *cred) {
|
|
||||||
LOGD("zygisk: setup files for pid=[%d]\n", cred->pid);
|
|
||||||
|
|
||||||
char buf[4096];
|
|
||||||
if (!get_exe(cred->pid, buf, sizeof(buf))) {
|
|
||||||
write_int(client, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hijack some binary in /system/bin to host loader
|
|
||||||
const char *hbin;
|
|
||||||
string mbin;
|
|
||||||
int app_fd;
|
|
||||||
bool is_64_bit = str_ends(buf, "64");
|
|
||||||
if (is_64_bit) {
|
|
||||||
hbin = HIJACK_BIN64;
|
|
||||||
mbin = get_magisk_tmp() + "/"s ZYGISKBIN "/loader64.so";
|
|
||||||
app_fd = app_process_64;
|
|
||||||
} else {
|
|
||||||
hbin = HIJACK_BIN32;
|
|
||||||
mbin = get_magisk_tmp() + "/"s ZYGISKBIN "/loader32.so";
|
|
||||||
app_fd = app_process_32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!zygote_started) {
|
|
||||||
// First zygote launch, record time
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &last_zygote_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zygote_start_count) {
|
|
||||||
// This zygote ABI had started before, kill existing zygiskd
|
|
||||||
close(zygiskd_sockets[0]);
|
|
||||||
close(zygiskd_sockets[1]);
|
|
||||||
zygiskd_sockets[0] = -1;
|
|
||||||
zygiskd_sockets[1] = -1;
|
|
||||||
xumount2(hbin, MNT_DETACH);
|
|
||||||
}
|
|
||||||
++zygote_start_count;
|
|
||||||
|
|
||||||
if (zygote_start_count >= 5) {
|
|
||||||
// Bootloop prevention
|
|
||||||
timespec ts;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
||||||
if (ts.tv_sec - last_zygote_start.tv_sec > 60) {
|
|
||||||
// This is very likely manual soft reboot
|
|
||||||
memcpy(&last_zygote_start, &ts, sizeof(ts));
|
|
||||||
zygote_start_reset(1);
|
|
||||||
} else {
|
|
||||||
// If any zygote relaunched more than 5 times within a minute,
|
|
||||||
// don't do any setups further to prevent bootloop.
|
|
||||||
zygote_start_reset(999);
|
|
||||||
write_int(client, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ack
|
|
||||||
write_int(client, 0);
|
|
||||||
|
|
||||||
// Receive and bind mount loader
|
|
||||||
int ld_fd = xopen(mbin.data(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0755);
|
|
||||||
string ld_data = read_string(client);
|
|
||||||
xwrite(ld_fd, ld_data.data(), ld_data.size());
|
|
||||||
close(ld_fd);
|
|
||||||
setfilecon(mbin.data(), MAGISK_FILE_CON);
|
|
||||||
xmount(mbin.data(), hbin, nullptr, MS_BIND, nullptr);
|
|
||||||
|
|
||||||
send_fd(client, app_fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void magiskd_passthrough(int client) {
|
|
||||||
bool is_64_bit = read_int(client);
|
|
||||||
write_int(client, 0);
|
|
||||||
send_fd(client, is_64_bit ? app_process_64 : app_process_32);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern bool uid_granted_root(int uid);
|
extern bool uid_granted_root(int uid);
|
||||||
static void get_process_info(int client, const sock_cred *cred) {
|
static void get_process_info(int client, const sock_cred *cred) {
|
||||||
int uid = read_int(client);
|
int uid = read_int(client);
|
||||||
@ -301,12 +185,6 @@ void zygisk_handler(int client, const sock_cred *cred) {
|
|||||||
int code = read_int(client);
|
int code = read_int(client);
|
||||||
char buf[256];
|
char buf[256];
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case ZygiskRequest::SETUP:
|
|
||||||
setup_files(client, cred);
|
|
||||||
break;
|
|
||||||
case ZygiskRequest::PASSTHROUGH:
|
|
||||||
magiskd_passthrough(client);
|
|
||||||
break;
|
|
||||||
case ZygiskRequest::GET_INFO:
|
case ZygiskRequest::GET_INFO:
|
||||||
get_process_info(client, cred);
|
get_process_info(client, cred);
|
||||||
break;
|
break;
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
#include <unwind.h>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include <lsplt.hpp>
|
#include <lsplt.hpp>
|
||||||
|
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
#include <flags.h>
|
#include <magisk.hpp>
|
||||||
#include <daemon.hpp>
|
|
||||||
|
|
||||||
#include "zygisk.hpp"
|
#include "zygisk.hpp"
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
@ -29,6 +29,7 @@ static void hook_unloader();
|
|||||||
static void unhook_functions();
|
static void unhook_functions();
|
||||||
static void hook_jni_env();
|
static void hook_jni_env();
|
||||||
static void restore_jni_env(JNIEnv *env);
|
static void restore_jni_env(JNIEnv *env);
|
||||||
|
static void ReloadNativeBridge(const string &nb);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -157,9 +158,6 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
|
|||||||
(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();
|
||||||
} else {
|
|
||||||
umount2("/system/bin/app_process64", MNT_DETACH);
|
|
||||||
umount2("/system/bin/app_process32", MNT_DETACH);
|
|
||||||
}
|
}
|
||||||
// Restore errno back to 0
|
// Restore errno back to 0
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@ -209,6 +207,21 @@ DCL_HOOK_FUNC(int, pthread_attr_destroy, void *target) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// it should be safe to assume all dlclose's in libnativebridge are for zygisk_loader
|
||||||
|
DCL_HOOK_FUNC(int, dlclose, void *handle) {
|
||||||
|
static bool kDone = false;
|
||||||
|
if (!kDone) {
|
||||||
|
ZLOGV("dlclose zygisk_loader\n");
|
||||||
|
kDone = true;
|
||||||
|
string nb = get_prop(NBPROP);
|
||||||
|
if (nb != ZYGISKLDR) {
|
||||||
|
auto orig_nb_path = nb.substr(sizeof(ZYGISKLDR) - 1);
|
||||||
|
ReloadNativeBridge(orig_nb_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[[clang::musttail]] return old_dlclose(handle);
|
||||||
|
}
|
||||||
|
|
||||||
#undef DCL_HOOK_FUNC
|
#undef DCL_HOOK_FUNC
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
@ -714,6 +727,37 @@ void HookContext::nativeForkAndSpecialize_post() {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
inline void *unwind_get_region_start(_Unwind_Context *ctx) {
|
||||||
|
auto fp = _Unwind_GetRegionStart(ctx);
|
||||||
|
#if defined(__arm__)
|
||||||
|
auto pc = _Unwind_GetGR(ctx, 15); // r15 is pc
|
||||||
|
if (pc & 1) {
|
||||||
|
// Thumb mode
|
||||||
|
fp |= 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return reinterpret_cast<void *>(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReloadNativeBridge(const string &nb) {
|
||||||
|
// Use unwind to find the address of LoadNativeBridge
|
||||||
|
// and call it to get NativeBridgeRuntimeCallbacks
|
||||||
|
void *load_native_bridge = nullptr;
|
||||||
|
_Unwind_Backtrace(+[](struct _Unwind_Context *ctx, void *arg) -> _Unwind_Reason_Code {
|
||||||
|
void *fp = unwind_get_region_start(ctx);
|
||||||
|
Dl_info info{};
|
||||||
|
dladdr(fp, &info);
|
||||||
|
ZLOGV("backtrace: %p %s\n", fp, info.dli_fname ? info.dli_fname : "???");
|
||||||
|
if (info.dli_fname && std::string_view(info.dli_fname).ends_with("/libart.so")) {
|
||||||
|
ZLOGV("LoadNativeBridge: %p\n", fp);
|
||||||
|
*reinterpret_cast<void **>(arg) = fp;
|
||||||
|
return _URC_END_OF_STACK;
|
||||||
|
}
|
||||||
|
return _URC_NO_REASON;
|
||||||
|
}, &load_native_bridge);
|
||||||
|
reinterpret_cast<bool (*)(const string &)>(load_native_bridge)(nb);
|
||||||
|
}
|
||||||
|
|
||||||
static void hook_register(dev_t dev, ino_t inode, const char *symbol, void *new_func, void **old_func) {
|
static void hook_register(dev_t dev, ino_t inode, const char *symbol, void *new_func, void **old_func) {
|
||||||
if (!lsplt::RegisterHook(dev, inode, symbol, new_func, old_func)) {
|
if (!lsplt::RegisterHook(dev, inode, symbol, new_func, old_func)) {
|
||||||
ZLOGE("Failed to register plt_hook \"%s\"\n", symbol);
|
ZLOGE("Failed to register plt_hook \"%s\"\n", symbol);
|
||||||
@ -741,15 +785,20 @@ void hook_functions() {
|
|||||||
|
|
||||||
ino_t android_runtime_inode = 0;
|
ino_t android_runtime_inode = 0;
|
||||||
dev_t android_runtime_dev = 0;
|
dev_t android_runtime_dev = 0;
|
||||||
|
ino_t native_bridge_inode = 0;
|
||||||
|
dev_t native_bridge_dev = 0;
|
||||||
|
|
||||||
for (auto &map : lsplt::MapInfo::Scan()) {
|
for (auto &map : lsplt::MapInfo::Scan()) {
|
||||||
if (map.path.ends_with("libandroid_runtime.so")) {
|
if (map.path.ends_with("/libandroid_runtime.so")) {
|
||||||
android_runtime_inode = map.inode;
|
android_runtime_inode = map.inode;
|
||||||
android_runtime_dev = map.dev;
|
android_runtime_dev = map.dev;
|
||||||
break;
|
} else if (map.path.ends_with("/libnativebridge.so")) {
|
||||||
|
native_bridge_inode = map.inode;
|
||||||
|
native_bridge_dev = map.dev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PLT_HOOK_REGISTER(native_bridge_dev, native_bridge_inode, dlclose);
|
||||||
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, fork);
|
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, unshare);
|
||||||
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, androidSetCreateThreadFunc);
|
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, androidSetCreateThreadFunc);
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
#include <dlfcn.h>
|
|
||||||
#include <android/dlext.h>
|
|
||||||
|
|
||||||
#if defined(__LP64__)
|
|
||||||
// Use symlink to workaround linker bug on old broken Android
|
|
||||||
// https://issuetracker.google.com/issues/36914295
|
|
||||||
#define SECOND_STAGE_PATH "/system/bin/app_process"
|
|
||||||
#else
|
|
||||||
#define SECOND_STAGE_PATH "/system/bin/app_process32"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__attribute__((constructor))
|
|
||||||
static void zygisk_loader(void) {
|
|
||||||
android_dlextinfo info = {
|
|
||||||
.flags = ANDROID_DLEXT_FORCE_LOAD
|
|
||||||
};
|
|
||||||
void *handle = android_dlopen_ext(SECOND_STAGE_PATH, RTLD_LAZY, &info);
|
|
||||||
if (handle) {
|
|
||||||
void(*entry)(void*) = dlsym(handle, "zygisk_inject_entry");
|
|
||||||
if (entry) {
|
|
||||||
entry(handle);
|
|
||||||
}
|
|
||||||
void (*unload)(void) = dlsym(handle, "unload_first_stage");
|
|
||||||
if (unload) {
|
|
||||||
__attribute__((musttail)) return unload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,98 +7,11 @@
|
|||||||
#include <socket.hpp>
|
#include <socket.hpp>
|
||||||
#include <daemon.hpp>
|
#include <daemon.hpp>
|
||||||
#include <selinux.hpp>
|
#include <selinux.hpp>
|
||||||
#include <embed.hpp>
|
|
||||||
|
|
||||||
#include "zygisk.hpp"
|
#include "zygisk.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// Entrypoint for app_process overlay
|
|
||||||
int app_process_main(int argc, char *argv[]) {
|
|
||||||
android_logging();
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
|
|
||||||
bool zygote = false;
|
|
||||||
if (auto fp = open_file("/proc/self/attr/current", "r")) {
|
|
||||||
fscanf(fp.get(), "%s", buf);
|
|
||||||
zygote = (buf == "u:r:zygote:s0"sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!zygote) {
|
|
||||||
// For the non zygote case, we need to get real app_process via passthrough
|
|
||||||
// We have to connect magiskd via exec-ing magisk due to SELinux restrictions
|
|
||||||
|
|
||||||
// This is actually only relevant for calling app_process via ADB shell
|
|
||||||
// because zygisk shall already have the app_process overlays unmounted
|
|
||||||
// during app process specialization within its private mount namespace.
|
|
||||||
|
|
||||||
int fds[2];
|
|
||||||
socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds);
|
|
||||||
if (fork_dont_care() == 0) {
|
|
||||||
// This fd has to survive exec
|
|
||||||
fcntl(fds[1], F_SETFD, 0);
|
|
||||||
ssprintf(buf, sizeof(buf), "%d", fds[1]);
|
|
||||||
#if defined(__LP64__)
|
|
||||||
execlp("magisk", "", "zygisk", "passthrough", buf, "1", (char *) nullptr);
|
|
||||||
#else
|
|
||||||
execlp("magisk", "", "zygisk", "passthrough", buf, "0", (char *) nullptr);
|
|
||||||
#endif
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fds[1]);
|
|
||||||
if (read_int(fds[0]) != 0) {
|
|
||||||
fprintf(stderr, "Failed to connect magiskd, try umount %s or reboot.\n", argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int app_proc_fd = recv_fd(fds[0]);
|
|
||||||
if (app_proc_fd < 0)
|
|
||||||
return 1;
|
|
||||||
close(fds[0]);
|
|
||||||
|
|
||||||
fcntl(app_proc_fd, F_SETFD, FD_CLOEXEC);
|
|
||||||
fexecve(app_proc_fd, argv, environ);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (int socket = zygisk_request(ZygiskRequest::SETUP); socket >= 0) {
|
|
||||||
do {
|
|
||||||
if (read_int(socket) != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Send over zygisk loader
|
|
||||||
write_int(socket, sizeof(zygisk_ld));
|
|
||||||
xwrite(socket, zygisk_ld, sizeof(zygisk_ld));
|
|
||||||
|
|
||||||
int app_proc_fd = recv_fd(socket);
|
|
||||||
if (app_proc_fd < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (char *ld = getenv("LD_PRELOAD")) {
|
|
||||||
string env = ld;
|
|
||||||
env += ':';
|
|
||||||
env += HIJACK_BIN;
|
|
||||||
setenv("LD_PRELOAD", env.data(), 1);
|
|
||||||
} else {
|
|
||||||
setenv("LD_PRELOAD", HIJACK_BIN, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(socket);
|
|
||||||
|
|
||||||
fcntl(app_proc_fd, F_SETFD, FD_CLOEXEC);
|
|
||||||
fexecve(app_proc_fd, argv, environ);
|
|
||||||
} while (false);
|
|
||||||
|
|
||||||
close(socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If encountering any errors, unmount and execute the original app_process
|
|
||||||
xreadlink("/proc/self/exe", buf, sizeof(buf));
|
|
||||||
xumount2("/proc/self/exe", MNT_DETACH);
|
|
||||||
execve(buf, argv, environ);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void zygiskd(int socket) {
|
static void zygiskd(int socket) {
|
||||||
if (getuid() != 0 || fcntl(socket, F_GETFD) < 0)
|
if (getuid() != 0 || fcntl(socket, F_GETFD) < 0)
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@ -177,30 +90,8 @@ static void zygiskd(int socket) {
|
|||||||
// This should only ever be called internally
|
// This should only ever be called internally
|
||||||
int zygisk_main(int argc, char *argv[]) {
|
int zygisk_main(int argc, char *argv[]) {
|
||||||
android_logging();
|
android_logging();
|
||||||
|
|
||||||
if (argc == 3 && argv[1] == "companion"sv) {
|
if (argc == 3 && argv[1] == "companion"sv) {
|
||||||
zygiskd(parse_int(argv[2]));
|
zygiskd(parse_int(argv[2]));
|
||||||
} else if (argc == 4 && argv[1] == "passthrough"sv) {
|
|
||||||
int client = parse_int(argv[2]);
|
|
||||||
int is_64_bit = parse_int(argv[3]);
|
|
||||||
if (fcntl(client, F_GETFD) < 0)
|
|
||||||
return 1;
|
|
||||||
if (int magiskd = connect_daemon(MainRequest::ZYGISK_PASSTHROUGH); magiskd >= 0) {
|
|
||||||
write_int(magiskd, ZygiskRequest::PASSTHROUGH);
|
|
||||||
write_int(magiskd, is_64_bit);
|
|
||||||
|
|
||||||
if (read_int(magiskd) != 0) {
|
|
||||||
write_int(client, 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_int(client, 0);
|
|
||||||
int real_app_fd = recv_fd(magiskd);
|
|
||||||
send_fd(client, real_app_fd);
|
|
||||||
} else {
|
|
||||||
write_int(client, 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
35
native/src/zygisk/native_bridge.cpp
Normal file
35
native/src/zygisk/native_bridge.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include <android/dlext.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <unwind.h>
|
||||||
|
|
||||||
|
#include <magisk.hpp>
|
||||||
|
#include "../core/core.hpp"
|
||||||
|
|
||||||
|
// The reference layout of this struct
|
||||||
|
// https://cs.android.com/android/platform/superproject/main/+/main:art/libnativebridge/include/nativebridge/native_bridge.h
|
||||||
|
struct NativeBridgeCallbacks {
|
||||||
|
uint32_t version;
|
||||||
|
void *padding[5];
|
||||||
|
bool (*isCompatibleWith)(uint32_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool is_compatible_with(uint32_t) {
|
||||||
|
auto name = get_prop(NBPROP);
|
||||||
|
android_dlextinfo info = {
|
||||||
|
.flags = ANDROID_DLEXT_FORCE_LOAD
|
||||||
|
};
|
||||||
|
void *handle = android_dlopen_ext(name.data(), RTLD_LAZY, &info);
|
||||||
|
if (handle) {
|
||||||
|
auto entry = reinterpret_cast<void (*)(void *)>(dlsym(handle, "zygisk_inject_entry"));
|
||||||
|
if (entry) {
|
||||||
|
entry(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" [[maybe_unused]] NativeBridgeCallbacks NativeBridgeItf{
|
||||||
|
.version = 2,
|
||||||
|
.padding = {},
|
||||||
|
.isCompatibleWith = &is_compatible_with,
|
||||||
|
};
|
@ -6,18 +6,11 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <daemon.hpp>
|
#include <daemon.hpp>
|
||||||
|
|
||||||
#define MAGISKTMP_ENV "MAGISKTMP"
|
|
||||||
|
|
||||||
#define HIJACK_BIN64 "/system/bin/appwidget"
|
|
||||||
#define HIJACK_BIN32 "/system/bin/bu"
|
|
||||||
|
|
||||||
namespace ZygiskRequest {
|
namespace ZygiskRequest {
|
||||||
enum : int {
|
enum : int {
|
||||||
SETUP,
|
|
||||||
GET_INFO,
|
GET_INFO,
|
||||||
CONNECT_COMPANION,
|
CONNECT_COMPANION,
|
||||||
GET_MODDIR,
|
GET_MODDIR,
|
||||||
PASSTHROUGH,
|
|
||||||
END
|
END
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -27,13 +20,11 @@ enum : int {
|
|||||||
#define ZLOGE(...) LOGE("zygisk64: " __VA_ARGS__)
|
#define ZLOGE(...) LOGE("zygisk64: " __VA_ARGS__)
|
||||||
#define ZLOGI(...) LOGI("zygisk64: " __VA_ARGS__)
|
#define ZLOGI(...) LOGI("zygisk64: " __VA_ARGS__)
|
||||||
#define ZLOGW(...) LOGW("zygisk64: " __VA_ARGS__)
|
#define ZLOGW(...) LOGW("zygisk64: " __VA_ARGS__)
|
||||||
#define HIJACK_BIN HIJACK_BIN64
|
|
||||||
#else
|
#else
|
||||||
#define ZLOGD(...) LOGD("zygisk32: " __VA_ARGS__)
|
#define ZLOGD(...) LOGD("zygisk32: " __VA_ARGS__)
|
||||||
#define ZLOGE(...) LOGE("zygisk32: " __VA_ARGS__)
|
#define ZLOGE(...) LOGE("zygisk32: " __VA_ARGS__)
|
||||||
#define ZLOGI(...) LOGI("zygisk32: " __VA_ARGS__)
|
#define ZLOGI(...) LOGI("zygisk32: " __VA_ARGS__)
|
||||||
#define ZLOGW(...) LOGW("zygisk32: " __VA_ARGS__)
|
#define ZLOGW(...) LOGW("zygisk32: " __VA_ARGS__)
|
||||||
#define HIJACK_BIN HIJACK_BIN32
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Unmap all pages matching the name
|
// Unmap all pages matching the name
|
||||||
|
Loading…
x
Reference in New Issue
Block a user