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:
LoveSy
2023-11-06 17:19:12 -08:00
committed by topjohnwu
parent 42eb928054
commit 9fbd079560
17 changed files with 183 additions and 347 deletions

View File

@ -31,11 +31,6 @@ int main(int argc, char *argv[]) {
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);
if (argv[0][0] == '\0') {

View File

@ -416,6 +416,8 @@ static void boot_complete() {
// Ensure manager exists
check_pkg_refresh();
get_manager(0, nullptr, true);
reset_zygisk(true);
}
void boot_stage_handler(int client, int code) {

View File

@ -144,6 +144,7 @@ static void handle_request_async(int client, int code, const sock_cred &cred) {
LOGI("** zygote restarted\n");
pkg_xml_ino = 0;
prune_su_access();
reset_zygisk(false);
close(client);
break;
case MainRequest::SQLITE_CMD:
@ -158,7 +159,6 @@ static void handle_request_async(int client, int code, const sock_cred &cred) {
break;
}
case MainRequest::ZYGISK:
case MainRequest::ZYGISK_PASSTHROUGH:
zygisk_handler(client, &cred);
break;
default:

View File

@ -15,6 +15,8 @@ using namespace std;
#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) {
int ret = xmount(from, to, nullptr, MS_BIND | MS_REC, nullptr);
if (ret == 0)
@ -22,9 +24,6 @@ static int bind_mount(const char *reason, const char *from, const char *to) {
return ret;
}
string node_entry::module_mnt;
string node_entry::mirror_dir;
/*************************
* 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) {
auto bin = system->get_child<inter_node>("bin");
if (!bin) {
@ -228,24 +242,28 @@ static void inject_magisk_bins(root_node *system) {
delete bin->extract("supolicy");
}
vector<module_info> *module_list;
int app_process_32 = -1;
int app_process_64 = -1;
static void inject_zygisk_libs(root_node *system) {
if (access("/system/bin/linker", F_OK) == 0) {
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/app_process" #bit, F_OK) == 0) { \
app_process_##bit = xopen("/system/bin/app_process" #bit, O_RDONLY | O_CLOEXEC); \
string zbin = zygisk_bin + "/app_process" #bit; \
string mbin = get_magisk_tmp() + "/magisk"s #bit; \
int src = xopen(mbin.data(), O_RDONLY | O_CLOEXEC); \
int out = xopen(zbin.data(), O_CREAT | O_WRONLY | O_CLOEXEC, 0); \
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); \
if (access("/system/bin/linker64", F_OK) == 0) {
auto lib64 = system->get_child<inter_node>("lib64");
if (!lib64) {
lib64 = new inter_node("lib64");
system->insert(lib64);
}
lib64->insert(new zygisk_node(native_bridge.data(), true));
}
}
vector<module_info> *module_list;
void load_modules() {
node_entry::mirror_dir = get_magisk_tmp() + "/"s MIRRDIR;
node_entry::module_mnt = get_magisk_tmp() + "/"s MODULEMNT "/";
@ -289,6 +307,22 @@ void load_modules() {
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()) {
// Handle special read-only partitions
for (const char *part : { "/vendor", "/product", "/system_ext" }) {
@ -304,14 +338,6 @@ void load_modules() {
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());
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; });
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);
}
}

View File

@ -49,8 +49,8 @@ public:
virtual void mount() = 0;
static string module_mnt;
static string mirror_dir;
inline static string module_mnt;
inline static string mirror_dir;
protected:
template<class T>

View File

@ -10,11 +10,11 @@
using namespace std;
#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
#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", \
"-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,
const shared_ptr<su_info> &info, bool provider = true) {
char exe[128];
char target[128];
char user[4];
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
if (provider) {
ssprintf(target, sizeof(target), "content://%s.provider", info->mgr_pkg.data());