From 6c3896079d47dae893f9cb5a02bd5699141f94df Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Mon, 4 Mar 2019 16:45:18 -0500 Subject: [PATCH] Add zygote server notifier --- native/jni/core/applets.cpp | 4 +++- native/jni/core/bootstages.cpp | 21 ++++++++++++++++++- native/jni/core/daemon.cpp | 10 +++++---- native/jni/core/db.cpp | 1 + native/jni/core/magisk.cpp | 35 +++++++++++++++++++++++++++---- native/jni/include/daemon.h | 4 +++- native/jni/include/magisk.h | 5 +++-- native/jni/magiskpolicy/rules.cpp | 1 + 8 files changed, 68 insertions(+), 13 deletions(-) diff --git a/native/jni/core/applets.cpp b/native/jni/core/applets.cpp index 9ba625245..c4d1ad1e5 100644 --- a/native/jni/core/applets.cpp +++ b/native/jni/core/applets.cpp @@ -11,13 +11,15 @@ static int (*applet_main[]) (int, char *[]) = { magisk_main, su_client_main, resetprop_main, magiskhide_main, nullptr }; -__attribute__((noreturn)) static void call_applets(int argc, char *argv[]) { +[[noreturn]] static void call_applets(int argc, char *argv[]) { // Applets for (int i = 0; applet_names[i]; ++i) { if (strcmp(basename(argv[0]), applet_names[i]) == 0) { exit((*applet_main[i])(argc, argv)); } } + if (strncmp(basename(argv[0]), "app_process", 11) == 0) + exit(app_process_main(argc, argv)); fprintf(stderr, "%s: applet not found\n", argv[0]); exit(1); } diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 0f6ec30ad..40871ad7a 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -575,11 +575,30 @@ static void dump_logs() { pthread_exit(nullptr); } -[[noreturn]] static inline void core_only() { +[[noreturn]] static void core_only() { auto_start_magiskhide(); + cp_afc("/sbin/magisk", MAGISKTMP "/app_process"); + struct stat st; + for (const char *app : { "app_process", "app_process32", "app_process64" }) { + sprintf(buf, "/system/bin/%s", app); + if (lstat(buf, &st) == 0 && S_ISREG(st.st_mode)) { + clone_attr(buf, MAGISKTMP "/app_process"); + bind_mount(MAGISKTMP "/app_process", buf); + } + } unblock_boot_process(); } +void zygote_notify(int client, struct ucred *cred) { + /* TODO: notify services that need zygote PIDs */ + char *path = read_string(client); + LOGD("%s PID=[%d]\n", path, cred->pid); + close(client); + usleep(100000); + bind_mount(MAGISKTMP "/app_process", path); + free(path); +} + void post_fs_data(int client) { // ack write_int(client, 0); diff --git a/native/jni/core/daemon.cpp b/native/jni/core/daemon.cpp index 589f7a324..ae444f930 100644 --- a/native/jni/core/daemon.cpp +++ b/native/jni/core/daemon.cpp @@ -88,7 +88,9 @@ static void *request_handler(void *args) { break; case SQLITE_CMD: exec_sql(client); - close(client); + break; + case ZYGOTE_NOTIFY: + zygote_notify(client, &credential); break; default: close(client); @@ -161,13 +163,13 @@ int switch_mnt_ns(int pid) { return ret; } -int connect_daemon() { +int connect_daemon(bool create) { struct sockaddr_un sun; socklen_t len = setup_sockaddr(&sun, MAIN_SOCKET); int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); if (connect(fd, (struct sockaddr*) &sun, len)) { - if (getuid() != UID_ROOT || getgid() != UID_ROOT) { - fprintf(stderr, "No daemon is currently running!\n"); + if (!create || getuid() != UID_ROOT || getgid() != UID_ROOT) { + LOGE("No daemon is currently running!\n"); exit(1); } diff --git a/native/jni/core/db.cpp b/native/jni/core/db.cpp index 80af679c7..b2770f241 100644 --- a/native/jni/core/db.cpp +++ b/native/jni/core/db.cpp @@ -320,4 +320,5 @@ void exec_sql(int client) { return; ); write_int(client, 0); + close(client); } diff --git a/native/jni/core/magisk.cpp b/native/jni/core/magisk.cpp index 979bb5381..d97f22231 100644 --- a/native/jni/core/magisk.cpp +++ b/native/jni/core/magisk.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -81,19 +82,19 @@ int magisk_main(int argc, char *argv[]) { cp_afc(argv[2], argv[3]); return 0; } else if (strcmp(argv[1], "--daemon") == 0) { - int fd = connect_daemon(); + int fd = connect_daemon(true); write_int(fd, DO_NOTHING); return 0; } else if (strcmp(argv[1], "--post-fs-data") == 0) { - int fd = connect_daemon(); + int fd = connect_daemon(true); write_int(fd, POST_FS_DATA); return read_int(fd); } else if (strcmp(argv[1], "--service") == 0) { - int fd = connect_daemon(); + int fd = connect_daemon(true); write_int(fd, LATE_START); return read_int(fd); } else if (strcmp(argv[1], "--boot-complete") == 0) { - int fd = connect_daemon(); + int fd = connect_daemon(true); write_int(fd, BOOT_COMPLETE); return read_int(fd); } else if (strcmp(argv[1], "--sqlite") == 0) { @@ -111,3 +112,29 @@ int magisk_main(int argc, char *argv[]) { #endif usage(); } + +int app_process_main(int argc, char *argv[]) { + char path[512]; + bool zygote = false; + for (int i = 0; i < argc; ++i) { + if (strcmp(argv[i], "--zygote") == 0) { + zygote = true; + break; + } + } + if (zygote) { + // Notify main daemon + sprintf(path, "/system/bin/%s", basename(argv[0])); + umount2(path, MNT_DETACH); + int fd = connect_daemon(); + write_int(fd, ZYGOTE_NOTIFY); + write_string(fd, path); + close(fd); + } else { + // Redirect to system mirror + sprintf(path, MIRRDIR "/system/bin/%s", basename(argv[0])); + } + argv[0] = path; + execve(path, argv, environ); + return -1; +} diff --git a/native/jni/include/daemon.h b/native/jni/include/daemon.h index 85df78c9b..e47cfbc74 100644 --- a/native/jni/include/daemon.h +++ b/native/jni/include/daemon.h @@ -21,6 +21,7 @@ enum { BOOT_COMPLETE, MAGISKHIDE, SQLITE_CMD, + ZYGOTE_NOTIFY, }; // Return codes for daemon @@ -33,7 +34,7 @@ enum { // daemon.c -int connect_daemon(); +int connect_daemon(bool create = false); int switch_mnt_ns(int pid); // socket.c @@ -60,6 +61,7 @@ void write_key_token(int fd, const char *key, int tok); ***************/ void unlock_blocks(); +void zygote_notify(int client, struct ucred *cred); void post_fs_data(int client); void late_start(int client); void boot_complete(int client); diff --git a/native/jni/include/magisk.h b/native/jni/include/magisk.h index 54f24d88c..af9dd113d 100644 --- a/native/jni/include/magisk.h +++ b/native/jni/include/magisk.h @@ -41,8 +41,8 @@ extern int SDK_INT; -#define applet_names ((const char *[]) { "magisk", "su", "resetprop", "magiskhide", nullptr }) -#define init_applet ((const char *[]) { "magiskpolicy", "supolicy", nullptr }) +constexpr const char *applet_names[] = { "magisk", "su", "resetprop", "magiskhide", nullptr }; +constexpr const char *init_applet[] = { "magiskpolicy", "supolicy", nullptr }; // Multi-call entrypoints int magisk_main(int argc, char *argv[]); @@ -50,5 +50,6 @@ int magiskhide_main(int argc, char *argv[]); int magiskpolicy_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[]); #endif diff --git a/native/jni/magiskpolicy/rules.cpp b/native/jni/magiskpolicy/rules.cpp index e9907a104..38b886c09 100644 --- a/native/jni/magiskpolicy/rules.cpp +++ b/native/jni/magiskpolicy/rules.cpp @@ -78,6 +78,7 @@ void sepol_magisk_rules() { allowSuClient("untrusted_app_25"); allowSuClient("untrusted_app_27"); allowSuClient("update_engine"); + allowSuClient("zygote"); // suRights sepol_allow("servicemanager", SEPOL_PROC_DOMAIN, "dir", "search");