Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor zygisk to use native bridge to inject #6659

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ def run_ndk_build(flags):
error("Build binary failed!")
os.chdir("..")
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)
target = op.join("native", "out", arch, tgt)
mv(source, target)
Expand Down Expand Up @@ -342,9 +342,6 @@ def dump_bin_header(args):
preload = op.join("native", "out", arch, "libinit-ld.so")
with open(preload, "rb") as src:
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)


Expand Down Expand Up @@ -395,8 +392,9 @@ def build_binary(args):
flag = ""
clean = False

if "magisk" in args.target or "magiskinit" in args.target:
flag += " B_PRELOAD=1"
if "magisk" in args.target:
flag += " B_MAGISK=1"
clean = True

if "magiskpolicy" in args.target:
flag += " B_POLICY=1"
Expand All @@ -417,14 +415,10 @@ def build_binary(args):
if flag:
run_ndk_build(flag)

# magiskinit and magisk embeds preload.so
# magiskinit embeds preload.so

flag = ""

if "magisk" in args.target:
flag += " B_MAGISK=1"
clean = True

if "magiskinit" in args.target:
flag += " B_INIT=1"

Expand Down
9 changes: 1 addition & 8 deletions native/src/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ LOCAL_SRC_FILES := \
core/su/su_daemon.cpp \
zygisk/entry.cpp \
zygisk/main.cpp \
zygisk/utils.cpp \
zygisk/hook.cpp \
zygisk/memory.cpp \
zygisk/native_bridge.cpp \
zygisk/deny/cli.cpp \
zygisk/deny/utils.cpp \
zygisk/deny/revert.cpp
Expand All @@ -57,12 +56,6 @@ LOCAL_SRC_FILES := init/preload.c
LOCAL_STRIP_MODE := --strip-all
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

ifdef B_INIT
Expand Down
1 change: 0 additions & 1 deletion native/src/base/include/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "../files.hpp"
#include "../misc.hpp"
#include "../logging.hpp"
#include "../missing.hpp"
#include "../base-rs.hpp"

using rust::xpipe2;
Expand Down
17 changes: 0 additions & 17 deletions native/src/base/missing.hpp

This file was deleted.

1 change: 1 addition & 0 deletions native/src/base/xwrap.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <unistd.h>
#include <dirent.h>
#include <stdio.h>
#include <poll.h>
Expand Down
5 changes: 0 additions & 5 deletions native/src/core/applets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand Down
2 changes: 2 additions & 0 deletions native/src/core/bootstages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,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) {
Expand Down
4 changes: 2 additions & 2 deletions native/src/core/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,11 @@ static void handle_request_async(int client, int code, const sock_cred &cred) {
su_daemon_handler(client, &cred);
break;
case MainRequest::ZYGOTE_RESTART:
close(client);
LOGI("** zygote restarted\n");
pkg_xml_ino = 0;
prune_su_access();
reset_zygisk(false);
close(client);
break;
case MainRequest::SQLITE_CMD:
exec_sql(client);
Expand All @@ -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:
Expand Down
101 changes: 74 additions & 27 deletions native/src/core/module.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/mount.h>
#include <map>
#include <utility>
Expand All @@ -15,16 +16,15 @@ 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)
VLOGD(reason, from, to);
return ret;
}

string node_entry::module_mnt;
string node_entry::mirror_dir;

/*************************
* Node Tree Construction
*************************/
Expand Down Expand Up @@ -211,6 +211,21 @@ class magisk_node : public node_entry {
}
};

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) {
Expand All @@ -228,24 +243,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;

#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); \
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));
}

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 "/";
Expand Down Expand Up @@ -289,6 +308,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" }) {
Expand All @@ -304,14 +339,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);
}
Expand Down Expand Up @@ -491,3 +518,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);
}
}
4 changes: 2 additions & 2 deletions native/src/core/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class node_entry {

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>
Expand Down
15 changes: 2 additions & 13 deletions native/src/core/su/connect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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());
Expand Down
2 changes: 1 addition & 1 deletion native/src/exported_sym.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
zygisk_inject_entry;
unload_first_stage;
NativeBridgeItf;
};
4 changes: 1 addition & 3 deletions native/src/include/daemon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ enum : int {
SQLITE_CMD,
REMOVE_MODULES,
ZYGISK,
ZYGISK_PASSTHROUGH,

_STAGE_BARRIER_,

Expand Down Expand Up @@ -67,9 +66,8 @@ struct module_info {
};

extern bool zygisk_enabled;
extern int app_process_32;
extern int app_process_64;
extern std::vector<module_info> *module_list;
void reset_zygisk(bool restore);

extern "C" const char *get_magisk_tmp();
int connect_daemon(int req, bool create = false);
Expand Down
3 changes: 2 additions & 1 deletion native/src/include/magisk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <string>

#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
#define ZYGISKLDR "libzygisk.so"
#define NBPROP "ro.dalvik.vm.native.bridge"
#define SECURE_DIR "/data/adb"
#define MODULEROOT SECURE_DIR "/modules"
#define MODULEUPGRADE SECURE_DIR "/modules_update"
Expand Down Expand Up @@ -49,5 +51,4 @@ extern int SDK_INT;
int magisk_main(int argc, char *argv[]);
int su_client_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[]);
Loading