Skip to content

Commit

Permalink
restart zygote if needed
Browse files Browse the repository at this point in the history
  • Loading branch information
RikkaW committed Feb 18, 2019
1 parent 5709b4a commit 7930e98
Show file tree
Hide file tree
Showing 7 changed files with 508 additions and 4 deletions.
8 changes: 8 additions & 0 deletions riru-core/build.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
function copy_files {
cp $MODULE_NAME/template_override/config.sh $TMP_DIR_MAGISK
cp $MODULE_NAME/template_override/module.prop $TMP_DIR_MAGISK

mkdir -p $TMP_DIR_MAGISK/common
cp $MODULE_NAME/template_override/post-fs-data.sh $TMP_DIR_MAGISK/common/post-fs-data.sh

mv $TMP_DIR_MAGISK/system/lib/zygote_restart $TMP_DIR_MAGISK/zygote_restart_arm
mv $TMP_DIR_MAGISK/system/lib64/zygote_restart $TMP_DIR_MAGISK/zygote_restart_arm64
mv $TMP_DIR_MAGISK/system_x86/lib/zygote_restart $TMP_DIR_MAGISK/zygote_restart_x86
mv $TMP_DIR_MAGISK/system_x86/lib64/zygote_restart $TMP_DIR_MAGISK/zygote_restart_x64
}
12 changes: 12 additions & 0 deletions riru-core/jni/zygote_restart/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := zygote_restart
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)
LOCAL_LDLIBS += -ldl -llog
LOCAL_LDFLAGS := -Wl,--hash-style=both

LOCAL_SRC_FILES:= main.cpp pmparser.c

include $(BUILD_EXECUTABLE)
144 changes: 144 additions & 0 deletions riru-core/jni/zygote_restart/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#include <zconf.h>
#include <cstring>
#include <mntent.h>
#include <cerrno>
#include <android/log.h>
#include <sys/system_properties.h>
#include <dirent.h>

extern "C" {
#include "pmparser.h"
}

#ifdef __LP64__
#define CHECK_LIB_NAME "/system/lib64/libmemtrack_real.so"
#define ZYGOTE_NAME "zygote64"
#define RESTART_NAME "zygote_secondary"
#else
#define CHECK_LIB_NAME "/system/lib/libmemtrack_real.so"
#define ZYGOTE_NAME "zygote"
#define RESTART_NAME "zygote"
#endif

#define LOG_TAG "Riru"

#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))

static ssize_t fdgets(char *buf, const size_t size, int fd) {
ssize_t len = 0;
buf[0] = '\0';
while (len < size - 1) {
ssize_t ret = read(fd, buf + len, 1);
if (ret < 0)
return -1;
if (ret == 0)
break;
if (buf[len] == '\0' || buf[len++] == '\n') {
buf[len] = '\0';
break;
}
}
buf[len] = '\0';
buf[size - 1] = '\0';
return len;
}

static int is_proc_name_equals(int pid, const char *name) {
int fd;

char buf[1024];
snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
if (access(buf, R_OK) == -1 || (fd = open(buf, O_RDONLY)) == -1)
return 0;
if (fdgets(buf, sizeof(buf), fd) == 0) {
snprintf(buf, sizeof(buf), "/proc/%d/comm", pid);
close(fd);
if (access(buf, R_OK) == -1 || (fd = open(buf, O_RDONLY)) == -1)
return 0;
fdgets(buf, sizeof(buf), fd);
}
close(fd);

return strcmp(buf, name) == 0;
}

static int is_num(const char *s) {
size_t len = strlen(s);
for (size_t i = 0; i < len; ++i)
if (s[i] < '0' || s[i] > '9')
return 0;
return 1;
}

static pid_t get_pid_by_name_and_uid(const char *name, uid_t uid) {
DIR *dir;
struct dirent *entry;

if (!(dir = opendir("/proc")))
return -1;

struct stat st;
char path[32];

while ((entry = readdir(dir))) {
if (entry->d_type == DT_DIR) {
if (is_num(entry->d_name)) {
pid_t pid = atoi(entry->d_name);
if (is_proc_name_equals(pid, name)) {
sprintf(path, "/proc/%s", entry->d_name);
stat(path, &st);
if (uid == st.st_uid)
return pid;
}
}
}
}

closedir(dir);
return -1;
}

static int is_path_in_maps(int pid, const char *path) {
procmaps_iterator *maps = pmparser_parse(pid);
if (maps == nullptr) {
LOGE("[map]: cannot parse the memory map of %d", pid);
return false;
}

procmaps_struct *maps_tmp = nullptr;
while ((maps_tmp = pmparser_next(maps)) != nullptr) {
if (strstr(maps_tmp->pathname, path))
return true;
}
pmparser_free(maps);
return false;
}

int main(int argc, char **argv) {
if (fork() != 0)
return 1;

LOGV("sleep 10s");
sleep(10);

pid_t pid;
while ((pid = get_pid_by_name_and_uid(ZYGOTE_NAME, 0)) == -1) {
LOGV(ZYGOTE_NAME " not started, wait 1s");
sleep(1);
}

if (!is_path_in_maps(pid, CHECK_LIB_NAME)) {
LOGW("no Riru found in " ZYGOTE_NAME ", restart " RESTART_NAME);

// restart zygote_secondary will also restart zygote, see init.zygote64_32.rc
__system_property_get("ctl.restart", const_cast<char *>(RESTART_NAME));
} else {
LOGI("found Riru in " ZYGOTE_NAME);
}

return 0;
}
Loading

0 comments on commit 7930e98

Please sign in to comment.