You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
add: zygiskd C99 APatch support
This commit adds support for zygiskd C99 to recognize APatch rooted devices.
This commit is contained in:
@@ -14,7 +14,8 @@ fun getLatestNDKPath(): String {
|
||||
throw Exception("NDK not found at $ndkPath")
|
||||
}
|
||||
|
||||
val ndkVersion = ndkDir.toFile().listFiles().filter { it.isDirectory }.map { it.name }.sorted().last()
|
||||
// get 2nd latest version
|
||||
val ndkVersion = ndkDir.toFile().listFiles().filter { it.isDirectory }.map { it.name }.sorted().reversed().getOrNull(1)
|
||||
return ndkPath + "/" + ndkVersion
|
||||
}
|
||||
|
||||
@@ -26,6 +27,14 @@ val verCode: Int by rootProject.extra
|
||||
val verName: String by rootProject.extra
|
||||
val commitHash: String by rootProject.extra
|
||||
|
||||
val CStandardFlags = arrayOf(
|
||||
"-DMIN_APATCH_VERSION=$minAPatchVersion",
|
||||
"-DMIN_KSU_VERSION=$minKsuVersion",
|
||||
"-DMAX_KSU_VERSION=$maxKsuVersion",
|
||||
"-DMIN_MAGISK_VERSION=$minMagiskVersion",
|
||||
"-DZKSU_VERSION=\"$verName\""
|
||||
)
|
||||
|
||||
val CFlagsRelease = arrayOf(
|
||||
"-D_GNU_SOURCE", "-std=c99", "-Wpedantic", "-Wall", "-Wextra", "-Werror",
|
||||
"-Wformat", "-Wuninitialized", "-Wshadow", "-Wno-zero-length-array",
|
||||
@@ -41,6 +50,7 @@ val CFlagsDebug = arrayOf(
|
||||
)
|
||||
|
||||
val Files = arrayOf(
|
||||
"root_impl/apatch.c",
|
||||
"root_impl/common.c",
|
||||
"root_impl/kernelsu.c",
|
||||
"companion.c",
|
||||
@@ -94,7 +104,7 @@ task("buildAndStrip") {
|
||||
x86OutputDir.mkdirs()
|
||||
x86_64OutputDir.mkdirs()
|
||||
|
||||
val compileArgs = if (isDebug) CFlagsDebug else CFlagsRelease
|
||||
val compileArgs = (if (isDebug) CFlagsDebug else CFlagsRelease) + CStandardFlags
|
||||
|
||||
exec {
|
||||
commandLine(aarch64Compiler, "-o", Paths.get(aarch64OutputDir.toString(), "zygiskd").toString(), *compileArgs, *Files)
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
#include "dl.h"
|
||||
#include "utils.h"
|
||||
|
||||
typedef void (*ZygiskCompanionEntryFn)(int);
|
||||
typedef void (*zygisk_companion_entry_func)(int);
|
||||
|
||||
ZygiskCompanionEntryFn load_module(int fd) {
|
||||
zygisk_companion_entry_func load_module(int fd) {
|
||||
char path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
|
||||
|
||||
@@ -27,10 +27,10 @@ ZygiskCompanionEntryFn load_module(int fd) {
|
||||
void *entry = dlsym(handle, "zygisk_companion_entry");
|
||||
if (entry == NULL) return NULL;
|
||||
|
||||
return (ZygiskCompanionEntryFn)entry;
|
||||
return (zygisk_companion_entry_func)entry;
|
||||
}
|
||||
|
||||
void *ExecuteNew(void *arg) {
|
||||
void *call_entry(void *arg) {
|
||||
int fd = *((int *)arg);
|
||||
|
||||
struct stat st0;
|
||||
@@ -65,13 +65,10 @@ void *ExecuteNew(void *arg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void entry(int fd) {
|
||||
LOGI("companion entry fd: |%d|\n", fd);
|
||||
|
||||
char name[256 + 1];
|
||||
|
||||
/* INFO: Getting stuck here */
|
||||
ssize_t ret = read_string(fd, name, sizeof(name) - 1);
|
||||
if (ret == -1) return;
|
||||
|
||||
@@ -84,7 +81,7 @@ void entry(int fd) {
|
||||
|
||||
LOGI("Library fd: %d\n", library_fd);
|
||||
|
||||
ZygiskCompanionEntryFn entry = load_module(library_fd);
|
||||
zygisk_companion_entry_func entry = load_module(library_fd);
|
||||
|
||||
LOGI("Library loaded\n");
|
||||
|
||||
@@ -95,17 +92,28 @@ void entry(int fd) {
|
||||
if (entry == NULL) {
|
||||
LOGI("No companion entry for: %s\n", name);
|
||||
|
||||
write(fd, (void *)0, 1);
|
||||
uint8_t response[1] = { 0 };
|
||||
write(fd, &response, sizeof(response));
|
||||
|
||||
exit(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LOGI("Companion process created for: %s\n", name);
|
||||
|
||||
uint8_t response = 1;
|
||||
uint8_t response[1] = { 1 };
|
||||
write(fd, &response, sizeof(response));
|
||||
|
||||
while (1) {
|
||||
if (!check_unix_socket(fd, true)) {
|
||||
LOGI("Something went wrong. Bye!\n");
|
||||
|
||||
exit(0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
int client_fd;
|
||||
recv_fd(fd, &client_fd);
|
||||
|
||||
@@ -113,13 +121,14 @@ void entry(int fd) {
|
||||
|
||||
write(fd, &response, sizeof(response));
|
||||
|
||||
/* TODO: Do we really need to allocate this..? */
|
||||
int *client_fd_ptr = malloc(sizeof(int));
|
||||
*client_fd_ptr = client_fd;
|
||||
|
||||
LOGI("Creating new thread for companion request\n");
|
||||
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, ExecuteNew, (void *)client_fd_ptr);
|
||||
pthread_create(&thread, NULL, call_entry, (void *)client_fd_ptr);
|
||||
pthread_detach(thread);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,20 +7,6 @@
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
// #define MIN_APATCH_VERSION (atoi(getenv("MIN_APATCH_VERSION")))
|
||||
// #define MIN_KSU_VERSION (atoi(getenv("MIN_KSU_VERSION")))
|
||||
// #define MAX_KSU_VERSION (atoi(getenv("MAX_KSU_VERSION")))
|
||||
// #define MIN_MAGISK_VERSION (atoi(getenv("MIN_MAGISK_VERSION")))
|
||||
// #define ZKSU_VERSION (getenv("ZKSU_VERSION"))
|
||||
|
||||
#define MIN_APATCH_VERSION 0
|
||||
// val minKsudVersion by extra(11425)
|
||||
// val maxKsuVersion by extra(20000)
|
||||
#define MIN_KSU_VERSION 11425
|
||||
#define MAX_KSU_VERSION 20000
|
||||
#define MIN_MAGISK_VERSION 0
|
||||
#define ZKSU_VERSION "1.0.0"
|
||||
|
||||
#if DEBUG == false
|
||||
#define MAX_LOG_LEVEL ANDROID_LOG_VERBOSE
|
||||
#else
|
||||
@@ -64,6 +50,7 @@ enum ProcessFlags: uint32_t {
|
||||
enum RootImplState {
|
||||
Supported,
|
||||
TooOld,
|
||||
Inexistent,
|
||||
Abnormal
|
||||
};
|
||||
|
||||
|
||||
@@ -14,14 +14,7 @@
|
||||
int __android_log_print(int prio, const char *tag, const char *fmt, ...);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
errno = 0;
|
||||
/* Initialize android logger */
|
||||
LOGI("Initializing zygiskd\n");
|
||||
|
||||
LOGI("Argc: %d\n", argc);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
LOGI("argv[%d] = %s\n", i, argv[i]);
|
||||
}
|
||||
LOGI("Initializing zygiskd: %s\n", argv[0]);
|
||||
|
||||
if (argc > 1) {
|
||||
if (strcmp(argv[1], "companion") == 0) {
|
||||
@@ -63,10 +56,14 @@ int main(int argc, char *argv[]) {
|
||||
case KernelSU: {
|
||||
LOGI("KernelSU root implementation found.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
case APatch: {
|
||||
LOGI("APatch root implementation found.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
144
zygiskd/src/root_impl/apatch.c
Normal file
144
zygiskd/src/root_impl/apatch.c
Normal file
@@ -0,0 +1,144 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../constants.h"
|
||||
#include "../utils.h"
|
||||
|
||||
#include "apatch.h"
|
||||
|
||||
enum RootImplState apatch_get_existence(void) {
|
||||
struct stat s;
|
||||
if (stat("/data/adb/apd", &s) != 0) {
|
||||
LOGE("APATCH | Failed to stat /data/adb/apd: %s\n", strerror(errno));
|
||||
|
||||
return Inexistent;
|
||||
}
|
||||
|
||||
char apatch_version[32];
|
||||
char *const argv[] = { "apd", "-V", NULL };
|
||||
|
||||
LOGI("APATCH | Checking for apd existence\n");
|
||||
if (!exec_command(apatch_version, sizeof(apatch_version), "/data/adb/apd", argv)) {
|
||||
LOGE("APATCH | Failed to execute apd binary: %s\n", strerror(errno));
|
||||
errno = 0;
|
||||
|
||||
return Inexistent;
|
||||
}
|
||||
|
||||
int version = atoi(apatch_version + strlen("apd "));
|
||||
LOGI("APATCH | apd version: %d\n", version);
|
||||
if (version == 0) return Abnormal;
|
||||
|
||||
if (version >= MIN_APATCH_VERSION && version <= 999999) return Supported;
|
||||
if (version >= 1 && version <= MIN_APATCH_VERSION - 1) return TooOld;
|
||||
|
||||
return Inexistent;
|
||||
}
|
||||
|
||||
struct package_config {
|
||||
uid_t uid;
|
||||
bool root_granted;
|
||||
bool umount_needed;
|
||||
};
|
||||
|
||||
struct packages_config {
|
||||
struct package_config *configs;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
bool _apatch_get_package_config(struct packages_config *config) {
|
||||
FILE *fp = fopen("/data/adb/ap/package_config", "r");
|
||||
if (fp == NULL) {
|
||||
LOGE("APATCH | Failed to open package_config: %s\n", strerror(errno));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
char line[256];
|
||||
/* INFO: Skip the CSV header */
|
||||
fgets(line, sizeof(line), fp);
|
||||
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
config->configs = realloc(config, (config->size + 1) * sizeof(struct package_config));
|
||||
if (config->configs == NULL) {
|
||||
LOGE("APATCH | Failed to realloc package config: %s\n", strerror(errno));
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
strtok(line, ",");
|
||||
|
||||
char *exclude_str = strtok(NULL, ",");
|
||||
if (exclude_str == NULL) continue;
|
||||
|
||||
char *allow_str = strtok(NULL, ",");
|
||||
if (allow_str == NULL) continue;
|
||||
|
||||
char *uid_str = strtok(NULL, ",");
|
||||
if (uid_str == NULL) continue;
|
||||
|
||||
config->configs[config->size].uid = atoi(uid_str);
|
||||
config->configs[config->size].root_granted = strcmp(allow_str, "1") == 0;
|
||||
config->configs[config->size].umount_needed = strcmp(exclude_str, "1") == 0;
|
||||
|
||||
config->size++;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool apatch_uid_granted_root(uid_t uid) {
|
||||
struct packages_config *config = NULL;
|
||||
if (!_apatch_get_package_config(config)) {
|
||||
free(config);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < config->size; i++) {
|
||||
if (config->configs[i].uid == uid) {
|
||||
free(config);
|
||||
|
||||
return config->configs[i].root_granted;
|
||||
}
|
||||
}
|
||||
|
||||
free(config);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool apatch_uid_should_umount(uid_t uid) {
|
||||
struct packages_config *config = NULL;
|
||||
if (!_apatch_get_package_config(config)) {
|
||||
free(config);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < config->size; i++) {
|
||||
if (config->configs[i].uid == uid) {
|
||||
free(config);
|
||||
|
||||
return config->configs[i].umount_needed;
|
||||
}
|
||||
}
|
||||
|
||||
free(config);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool apatch_uid_is_manager(uid_t uid) {
|
||||
struct stat s;
|
||||
if (stat("/data/user_de/0/me.bmax.apatch", &s) == -1) return false;
|
||||
|
||||
return s.st_uid == uid;
|
||||
}
|
||||
14
zygiskd/src/root_impl/apatch.h
Normal file
14
zygiskd/src/root_impl/apatch.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef APATCH_H
|
||||
#define APATCH_H
|
||||
|
||||
#include "../constants.h"
|
||||
|
||||
enum RootImplState apatch_get_existence(void);
|
||||
|
||||
bool apatch_uid_granted_root(uid_t uid);
|
||||
|
||||
bool apatch_uid_should_umount(uid_t uid);
|
||||
|
||||
bool apatch_uid_is_manager(uid_t uid);
|
||||
|
||||
#endif
|
||||
@@ -1,19 +1,16 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "kernelsu.h"
|
||||
#include "apatch.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static enum RootImpl ROOT_IMPL = None;
|
||||
|
||||
void root_impls_setup(void) {
|
||||
enum RootImplState ksu_version = ksu_get_kernel_su();
|
||||
|
||||
enum RootImpl impl = None;
|
||||
|
||||
if (ksu_version == Supported) impl = KernelSU;
|
||||
|
||||
ROOT_IMPL = impl;
|
||||
if (ksu_get_existence() == Supported) ROOT_IMPL = KernelSU;
|
||||
else if (apatch_get_existence() == Supported) ROOT_IMPL = APatch;
|
||||
else ROOT_IMPL = None;
|
||||
}
|
||||
|
||||
enum RootImpl get_impl(void) {
|
||||
@@ -21,34 +18,43 @@ enum RootImpl get_impl(void) {
|
||||
}
|
||||
|
||||
bool uid_granted_root(uid_t uid) {
|
||||
switch (get_impl()) {
|
||||
case KernelSU: {
|
||||
// switch (get_impl()) {
|
||||
// case KernelSU: {
|
||||
return ksu_uid_granted_root(uid);
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// }
|
||||
// case APatch: {
|
||||
// return apatch_uid_granted_root(uid);
|
||||
// }
|
||||
// default: {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
bool uid_should_umount(uid_t uid) {
|
||||
switch (get_impl()) {
|
||||
case KernelSU: {
|
||||
// switch (get_impl()) {
|
||||
// case KernelSU: {
|
||||
return ksu_uid_should_umount(uid);
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// }
|
||||
// case APatch: {
|
||||
// return apatch_uid_should_umount(uid);
|
||||
// }
|
||||
// default: {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
bool uid_is_manager(uid_t uid) {
|
||||
switch (get_impl()) {
|
||||
case KernelSU: {
|
||||
// switch (get_impl()) {
|
||||
// case KernelSU: {
|
||||
return ksu_uid_is_manager(uid);
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// }
|
||||
// case APatch: {
|
||||
// return apatch_uid_is_manager(uid);
|
||||
// }
|
||||
// default: {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
|
||||
enum RootImpl {
|
||||
None,
|
||||
Multiple, /* INFO: I know. */
|
||||
KernelSU
|
||||
Multiple,
|
||||
KernelSU,
|
||||
APatch
|
||||
};
|
||||
|
||||
void root_impls_setup(void);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <errno.h>
|
||||
@@ -14,16 +15,12 @@
|
||||
#define CMD_UID_GRANTED_ROOT 12
|
||||
#define CMD_UID_SHOULD_UMOUNT 13
|
||||
|
||||
enum RootImplState ksu_get_kernel_su(void) {
|
||||
enum RootImplState ksu_get_existence(void) {
|
||||
int version = 0;
|
||||
prctl(KERNEL_SU_OPTION, CMD_GET_VERSION, &version, 0, 0);
|
||||
|
||||
errno = 0;
|
||||
|
||||
if (version == 0) return Abnormal;
|
||||
|
||||
if (version == 0) return Inexistent;
|
||||
if (version >= MIN_KSU_VERSION && version <= MAX_KSU_VERSION) return Supported;
|
||||
|
||||
if (version >= 1 && version <= MIN_KSU_VERSION - 1) return TooOld;
|
||||
|
||||
return Abnormal;
|
||||
@@ -34,8 +31,6 @@ bool ksu_uid_granted_root(uid_t uid) {
|
||||
bool granted = false;
|
||||
prctl(KERNEL_SU_OPTION, CMD_UID_GRANTED_ROOT, uid, &granted, &result);
|
||||
|
||||
LOGI("ksu_uid_granted_root: %d", granted);
|
||||
|
||||
if (result != KERNEL_SU_OPTION) return false;
|
||||
|
||||
return granted;
|
||||
@@ -46,23 +41,14 @@ bool ksu_uid_should_umount(uid_t uid) {
|
||||
bool umount = false;
|
||||
prctl(KERNEL_SU_OPTION, CMD_UID_SHOULD_UMOUNT, uid, &umount, &result);
|
||||
|
||||
LOGI("ksu_uid_should_umount: %d", umount);
|
||||
|
||||
if (result != KERNEL_SU_OPTION) return false;
|
||||
|
||||
return umount;
|
||||
}
|
||||
|
||||
bool ksu_uid_is_manager(uid_t uid) {
|
||||
|
||||
struct stat s;
|
||||
if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == 0) {
|
||||
LOGI("ksu_uid_is_manager: %d", uid);
|
||||
if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == -1) return false;
|
||||
|
||||
return s.st_uid == uid;
|
||||
}
|
||||
|
||||
LOGI("ksu_uid_is_manager: false");
|
||||
|
||||
return false;
|
||||
return s.st_uid == uid;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "../constants.h"
|
||||
|
||||
enum RootImplState ksu_get_kernel_su(void);
|
||||
enum RootImplState ksu_get_existence(void);
|
||||
|
||||
bool ksu_uid_granted_root(uid_t uid);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
|
||||
@@ -280,3 +281,37 @@ ssize_t read_string(int fd, char *str, size_t len) {
|
||||
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
bool exec_command(char *buf, size_t len, const char *file, char *const argv[]) {
|
||||
int link[2];
|
||||
pid_t pid;
|
||||
|
||||
if (pipe(link) == -1) {
|
||||
LOGE("pipe: %s\n", strerror(errno));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((pid = fork()) == -1) {
|
||||
LOGE("fork: %s\n", strerror(errno));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
dup2(link[1], STDOUT_FILENO);
|
||||
close(link[0]);
|
||||
close(link[1]);
|
||||
|
||||
execv(file, argv);
|
||||
} else {
|
||||
close(link[1]);
|
||||
|
||||
int nbytes = read(link[0], buf, len);
|
||||
buf[nbytes] = '\0';
|
||||
|
||||
wait(NULL);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5,13 +5,18 @@
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
#define CONCAT_(x,y) x##y
|
||||
#define CONCAT(x,y) CONCAT_(x,y)
|
||||
|
||||
#define LOGI(...) \
|
||||
__android_log_print(ANDROID_LOG_INFO, lp_select("zygiskd32", "zygiskd64"), __VA_ARGS__); \
|
||||
printf(__VA_ARGS__)
|
||||
printf(__VA_ARGS__); \
|
||||
FILE *CONCAT(fpl, __LINE__) = fopen("/data/local/tmp/zygiskd.log", "a"); fprintf(CONCAT(fpl, __LINE__), __VA_ARGS__); fclose(CONCAT(fpl, __LINE__))
|
||||
|
||||
#define LOGE(...) \
|
||||
__android_log_print(ANDROID_LOG_INFO , lp_select("zygiskd32", "zygiskd64"), __VA_ARGS__); \
|
||||
printf(__VA_ARGS__)
|
||||
printf(__VA_ARGS__); \
|
||||
FILE *CONCAT(fpl, __LINE__) = fopen("/data/local/tmp/zygiskd.log", "a"); fprintf(CONCAT(fpl, __LINE__), __VA_ARGS__); fclose(CONCAT(fpl, __LINE__))
|
||||
|
||||
bool switch_mount_namespace(pid_t pid);
|
||||
|
||||
@@ -33,4 +38,8 @@ ssize_t write_string(int fd, const char *str);
|
||||
|
||||
ssize_t read_string(int fd, char *str, size_t len);
|
||||
|
||||
bool exec_command(char *buf, size_t len, const char *file, char *const argv[]);
|
||||
|
||||
bool check_unix_socket(int fd, bool block);
|
||||
|
||||
#endif /* UTILS_H */
|
||||
|
||||
@@ -41,7 +41,7 @@ enum Architecture {
|
||||
#define TMP_PATH "/data/adb/rezygisk"
|
||||
#define CONTROLLER_SOCKET TMP_PATH "/init_monitor"
|
||||
#define PATH_CP_NAME TMP_PATH "/" lp_select("cp32.sock", "cp64.sock")
|
||||
#define ZYGISKD_FILE "zygiskd" lp_select("32", "64")
|
||||
#define ZYGISKD_FILE PATH_MODULES_DIR "/zygisksu/bin/zygiskd" lp_select("32", "64")
|
||||
#define ZYGISKD_PATH "/data/adb/modules/zygisksu/bin/zygiskd" lp_select("32", "64")
|
||||
|
||||
#define ASSURE_SIZE_WRITE(area_name, subarea_name, sent_size, expected_size) \
|
||||
@@ -100,30 +100,42 @@ static enum Architecture get_arch(void) {
|
||||
int create_library_fd(const char *so_path) {
|
||||
int memfd = memfd_create("jit-cache-zygisk", MFD_ALLOW_SEALING);
|
||||
if (memfd == -1) {
|
||||
perror("memfd_create");
|
||||
LOGE("Failed creating memfd: %s\n", strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int so_fd = open(so_path, O_RDONLY);
|
||||
if (so_fd == -1) {
|
||||
perror("open");
|
||||
LOGE("Failed opening so file: %s\n", strerror(errno));
|
||||
|
||||
close(memfd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (fstat(so_fd, &st) == -1) {
|
||||
perror("fstat");
|
||||
off_t so_size = lseek(so_fd, 0, SEEK_END);
|
||||
if (so_size == -1) {
|
||||
LOGE("Failed getting so file size: %s\n", strerror(errno));
|
||||
|
||||
close(so_fd);
|
||||
close(memfd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sendfile(memfd, so_fd, NULL, st.st_size) == -1) {
|
||||
perror("sendfile");
|
||||
if (lseek(so_fd, 0, SEEK_SET) == -1) {
|
||||
LOGE("Failed seeking so file: %s\n", strerror(errno));
|
||||
|
||||
close(so_fd);
|
||||
close(memfd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sendfile(memfd, so_fd, NULL, so_size) == -1) {
|
||||
LOGE("Failed copying so file to memfd: %s\n", strerror(errno));
|
||||
|
||||
close(so_fd);
|
||||
close(memfd);
|
||||
|
||||
@@ -133,7 +145,8 @@ int create_library_fd(const char *so_path) {
|
||||
close(so_fd);
|
||||
|
||||
if (fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) == -1) {
|
||||
perror("fcntl");
|
||||
LOGE("Failed sealing memfd: %s\n", strerror(errno));
|
||||
|
||||
close(memfd);
|
||||
|
||||
return -1;
|
||||
@@ -266,14 +279,21 @@ static int spawn_companion(char *name, int lib_fd) {
|
||||
LOGI("Waiting for companion to start (%d)\n", pid);
|
||||
|
||||
int status = 0;
|
||||
// waitpid(pid, &status, 0);
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
LOGI("Companion exited with status %d\n", status);
|
||||
|
||||
// if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
||||
if (write_string(daemon_fd, name) == -1) return -1;
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
||||
if (write_string(daemon_fd, name) == -1) {
|
||||
LOGE("Failed sending module name\n");
|
||||
|
||||
if (send_fd(daemon_fd, lib_fd) == -1) return -1;
|
||||
return -1;
|
||||
}
|
||||
if (send_fd(daemon_fd, lib_fd) == -1) {
|
||||
LOGE("Failed sending lib fd\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGI("Sent module name and lib fd\n");
|
||||
|
||||
@@ -281,20 +301,27 @@ static int spawn_companion(char *name, int lib_fd) {
|
||||
ssize_t ret = read(daemon_fd, &response_buf, sizeof(response_buf));
|
||||
ASSURE_SIZE_READ_WR("companion", "response", ret, sizeof(response_buf));
|
||||
|
||||
uint8_t response = response_buf[0];
|
||||
LOGI("Companion response: %hhu\n", response_buf[0]);
|
||||
|
||||
LOGI("Companion response: %hhu\n", response);
|
||||
if (response_buf[0] == 0) {
|
||||
close(daemon_fd);
|
||||
|
||||
if (response == 0) return -2;
|
||||
else if (response == 1) return daemon_fd;
|
||||
else return -2;
|
||||
// } else {
|
||||
// LOGE("Exited with status %d\n", status);
|
||||
return -1;
|
||||
} else if (response_buf[0] == 1) return daemon_fd;
|
||||
else {
|
||||
LOGE("Invalid response from companion: %hhu\n", response_buf[0]);
|
||||
|
||||
// close(daemon_fd);
|
||||
close(daemon_fd);
|
||||
|
||||
// return -1;
|
||||
// }
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
LOGE("Exited with status %d\n", status);
|
||||
|
||||
close(daemon_fd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
/* INFO: if pid == 0: */
|
||||
} else {
|
||||
LOGI("Companion started (%d)\n", pid);
|
||||
@@ -307,11 +334,11 @@ static int spawn_companion(char *name, int lib_fd) {
|
||||
|
||||
LOGI("Executing companion...\n");
|
||||
|
||||
char *argv[] = { ZYGISKD_FILE, "companion", companion_fd_str, NULL };
|
||||
if (execv(ZYGISKD_PATH, argv) == -1) {
|
||||
LOGE("Failed executing companion: %s\n", strerror(errno));
|
||||
char arg[sizeof(ZYGISKD_FILE) + sizeof(" companion ") + 32];
|
||||
snprintf(arg, sizeof(arg), "%s companion %d", ZYGISKD_FILE, companion_fd);
|
||||
|
||||
close(companion_fd);
|
||||
if (system(arg) == -1) {
|
||||
LOGE("Failed executing companion: %s\n", strerror(errno));
|
||||
|
||||
exit(1);
|
||||
}
|
||||
@@ -329,34 +356,60 @@ struct __attribute__((__packed__)) MsgHead {
|
||||
void zygiskd_start(void) {
|
||||
LOGI("Welcome to ReZygisk %s!", ZKSU_VERSION);
|
||||
|
||||
enum RootImpl impl = get_impl();
|
||||
if (impl == None) {
|
||||
struct MsgHead *msg = malloc(sizeof(struct MsgHead) + sizeof("No root implementation found."));
|
||||
msg->cmd = DAEMON_SET_ERROR_INFO;
|
||||
msg->length = sizeof("No root implementation found.");
|
||||
memcpy(msg->data, "No root implementation found.", msg->length);
|
||||
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead) + msg->length);
|
||||
|
||||
free(msg);
|
||||
} else if (impl == Multiple) {
|
||||
struct MsgHead *msg = malloc(sizeof(struct MsgHead) + sizeof("Multiple root implementations found. Not supported yet."));
|
||||
msg->cmd = DAEMON_SET_ERROR_INFO;
|
||||
msg->length = sizeof("Multiple root implementations found. Not supported yet.");
|
||||
memcpy(msg->data, "Multiple root implementations found. Not supported yet.", msg->length);
|
||||
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead) + msg->length);
|
||||
|
||||
free(msg);
|
||||
}
|
||||
|
||||
enum Architecture arch = get_arch();
|
||||
|
||||
struct Context context;
|
||||
load_modules(arch, &context);
|
||||
|
||||
struct MsgHead *msg = NULL;
|
||||
size_t msg_sz = 0;
|
||||
|
||||
switch (get_impl()) {
|
||||
case None: {
|
||||
/* INFO: Stop, compiler. */
|
||||
switch (impl) {
|
||||
case None: { break; }
|
||||
case Multiple: { break; }
|
||||
case KernelSU:
|
||||
case APatch: {
|
||||
size_t root_impl_len = strlen(impl == KernelSU ? "KernelSU" : "APatch");
|
||||
|
||||
break;
|
||||
}
|
||||
case Multiple: {
|
||||
/* INFO: Stop, compiler. */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case KernelSU: {
|
||||
if (context.len == 0) {
|
||||
msg_sz = sizeof(struct MsgHead) + strlen("Root: KernelSU, Modules: None") + 1;
|
||||
msg = malloc(msg_sz);
|
||||
|
||||
msg = malloc(sizeof(struct MsgHead) + strlen("Root: , Modules: None") + root_impl_len + 1);
|
||||
msg->cmd = DAEMON_SET_INFO;
|
||||
msg->length = strlen("Root: KernelSU, Modules: None") + 1;
|
||||
memcpy(msg->data, "Root: KernelSU, Modules: None", strlen("Root: KernelSU, Modules: None"));
|
||||
msg->length = strlen("Root: , Modules: None") + root_impl_len + 1;
|
||||
|
||||
switch (impl) {
|
||||
case None: { break; }
|
||||
case Multiple: { break; }
|
||||
case KernelSU: {
|
||||
memcpy(msg->data, "Root: KernelSU, Modules: None", strlen("Root: KernelSU, Modules: None"));
|
||||
|
||||
break;
|
||||
}
|
||||
case APatch: {
|
||||
memcpy(msg->data, "Root: APatch, Modules: None", strlen("Root: APatch, Modules: None"));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char *module_list = malloc(1);
|
||||
size_t module_list_len = 0;
|
||||
@@ -379,32 +432,34 @@ void zygiskd_start(void) {
|
||||
}
|
||||
}
|
||||
|
||||
msg_sz = sizeof(struct MsgHead) + strlen("Root: KernelSU, Modules: ") + module_list_len + 1;
|
||||
msg = malloc(msg_sz);
|
||||
|
||||
msg = malloc(sizeof(struct MsgHead) + strlen("Root: , Modules: ") + root_impl_len + module_list_len + 1);
|
||||
msg->cmd = DAEMON_SET_INFO;
|
||||
msg->length = strlen("Root: KernelSU, Modules: ") + module_list_len + 1;
|
||||
memcpy(msg->data, "Root: KernelSU, Modules: ", strlen("Root: KernelSU, Modules: "));
|
||||
memcpy(msg->data + strlen("Root: KernelSU, Modules: "), module_list, module_list_len);
|
||||
msg->length = strlen("Root: , Modules: ") + root_impl_len + module_list_len + 1;
|
||||
|
||||
switch (impl) {
|
||||
case None: { break; }
|
||||
case Multiple: { break; }
|
||||
case KernelSU: {
|
||||
memcpy(msg->data, "Root: KernelSU, Modules: ", strlen("Root: KernelSU, Modules: "));
|
||||
|
||||
break;
|
||||
}
|
||||
case APatch: {
|
||||
memcpy(msg->data, "Root: APatch, Modules: ", strlen("Root: APatch, Modules: "));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
memcpy(msg->data + strlen("Root: , Modules: ") + root_impl_len, module_list, module_list_len);
|
||||
|
||||
free(module_list);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
msg_sz = sizeof(struct MsgHead) + strlen("Invalid root implementation") + 1;
|
||||
msg = malloc(msg_sz);
|
||||
|
||||
msg->cmd = DAEMON_SET_ERROR_INFO;
|
||||
msg->length = strlen("Invalid root implementation") + 1;
|
||||
memcpy(msg->data, "Invalid root implementation", strlen("Invalid root implementation"));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, (void *)msg, msg_sz);
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, (void *)msg, sizeof(struct MsgHead) + msg->length);
|
||||
|
||||
free(msg);
|
||||
|
||||
@@ -425,7 +480,7 @@ void zygiskd_start(void) {
|
||||
|
||||
LOGI("Accepted client: %d\n", client_fd);
|
||||
|
||||
unsigned char buf[1];
|
||||
uint8_t buf[1];
|
||||
ssize_t len = read(client_fd, buf, sizeof(buf));
|
||||
if (len == -1) {
|
||||
LOGE("read: %s\n", strerror(errno));
|
||||
@@ -437,7 +492,7 @@ void zygiskd_start(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGI("Action: %hhu\n", (uint8_t)buf[0]);
|
||||
LOGI("Action: %hhu\n", buf[0]);
|
||||
enum DaemonSocketAction action = (enum DaemonSocketAction)buf[0];
|
||||
|
||||
switch (action) {
|
||||
@@ -448,8 +503,6 @@ void zygiskd_start(void) {
|
||||
break;
|
||||
}
|
||||
case ZygoteRestart: {
|
||||
LOGI("Zygote restart\n");
|
||||
|
||||
for (int i = 0; i < context.len; i++) {
|
||||
if (context.modules[i].companion != -1) {
|
||||
close(context.modules[i].companion);
|
||||
@@ -465,22 +518,31 @@ void zygiskd_start(void) {
|
||||
|
||||
break;
|
||||
}
|
||||
/* TODO: May need to move to another thread? :/ */
|
||||
case RequestLogcatFd: {
|
||||
char level_buf[1];
|
||||
uint8_t level_buf[1];
|
||||
ssize_t ret = read(client_fd, &level_buf, sizeof(level_buf));
|
||||
ASSURE_SIZE_READ_BREAK("RequestLogcatFd", "level", ret, sizeof(level_buf));
|
||||
|
||||
char level = level_buf[0];
|
||||
uint8_t level = level_buf[0];
|
||||
|
||||
char tag[128 + 1];
|
||||
ret = read_string(client_fd, tag, sizeof(tag) - 1);
|
||||
if (ret == -1) break;
|
||||
if (ret == -1) {
|
||||
LOGE("Failed reading tag\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
tag[ret] = '\0';
|
||||
|
||||
char message[1024];
|
||||
ret = read_string(client_fd, message, sizeof(message));
|
||||
if (ret == -1) break;
|
||||
if (ret == -1) {
|
||||
LOGE("Failed reading message\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
__android_log_print(level, tag, "%.*s", (int)ret, message);
|
||||
|
||||
@@ -489,13 +551,11 @@ void zygiskd_start(void) {
|
||||
case GetProcessFlags: {
|
||||
LOGI("Getting process flags\n");
|
||||
|
||||
uid_t uid_buf[1];
|
||||
uint32_t uid_buf[1];
|
||||
ssize_t ret = read(client_fd, &uid_buf, sizeof(uid_buf));
|
||||
ASSURE_SIZE_READ_BREAK("GetProcessFlags", "uid", ret, sizeof(uid_buf));
|
||||
|
||||
uid_t uid = uid_buf[0];
|
||||
|
||||
LOGI("Checking flags for uid: %d\n", uid);
|
||||
uint32_t uid = uid_buf[0];
|
||||
|
||||
uint32_t flags = 0;
|
||||
if (uid_is_manager(uid)) {
|
||||
@@ -512,23 +572,22 @@ void zygiskd_start(void) {
|
||||
LOGI("Flags for uid %d: %d\n", uid, flags);
|
||||
|
||||
switch (get_impl()) {
|
||||
case None: {
|
||||
break;
|
||||
}
|
||||
case Multiple: {
|
||||
break;
|
||||
}
|
||||
case None: { break; }
|
||||
case Multiple: { break; }
|
||||
case KernelSU: {
|
||||
flags |= PROCESS_ROOT_IS_KSU;
|
||||
|
||||
break;
|
||||
}
|
||||
case APatch: {
|
||||
flags |= PROCESS_ROOT_IS_APATCH;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// LOGI("Flags for uid %d: %d\n", uid, flags);
|
||||
|
||||
LOGI("Sending flags\n");
|
||||
|
||||
ret = write(client_fd, &flags, sizeof(flags));
|
||||
// ASSURE_SIZE_WRITE_BREAK("GetProcessFlags", "flags", ret, sizeof(flags));
|
||||
ASSURE_SIZE_WRITE_BREAK("GetProcessFlags", "flags", ret, sizeof(flags));
|
||||
|
||||
LOGI("Sent flags\n");
|
||||
|
||||
@@ -540,14 +599,17 @@ void zygiskd_start(void) {
|
||||
LOGI("Getting info\n");
|
||||
|
||||
switch (get_impl()) {
|
||||
case None: {
|
||||
break;
|
||||
}
|
||||
case Multiple: {
|
||||
break;
|
||||
}
|
||||
case None: { break; }
|
||||
case Multiple: { break; }
|
||||
case KernelSU: {
|
||||
flags |= PROCESS_ROOT_IS_KSU;
|
||||
|
||||
break;
|
||||
}
|
||||
case APatch: {
|
||||
flags |= PROCESS_ROOT_IS_APATCH;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,7 +618,7 @@ void zygiskd_start(void) {
|
||||
ssize_t ret = write(client_fd, &flags, sizeof(flags));
|
||||
ASSURE_SIZE_WRITE_BREAK("GetInfo", "flags", ret, sizeof(flags));
|
||||
|
||||
pid_t pid = getpid();
|
||||
uint32_t pid = getpid();
|
||||
|
||||
LOGI("Getting pid: %d\n", pid);
|
||||
|
||||
@@ -565,6 +627,13 @@ void zygiskd_start(void) {
|
||||
|
||||
LOGI("Sent pid\n");
|
||||
|
||||
size_t modules_len = context.len;
|
||||
ret = write(client_fd, &modules_len, sizeof(modules_len));
|
||||
|
||||
for (size_t i = 0; i < modules_len; i++) {
|
||||
write_string(client_fd, context.modules[i].name);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ReadModules: {
|
||||
@@ -574,23 +643,20 @@ void zygiskd_start(void) {
|
||||
ssize_t ret = write(client_fd, &clen, sizeof(clen));
|
||||
ASSURE_SIZE_WRITE_BREAK("ReadModules", "len", ret, sizeof(clen));
|
||||
|
||||
for (int i = 0; i < (int)clen; i++) {
|
||||
LOGI("Hey, we're talking about: %d\n", i);
|
||||
LOGI("Writing module `%s` to stream\n", context.modules[i].name);
|
||||
LOGI("Lib fd: %d\n", context.modules[i].lib_fd);
|
||||
for (size_t i = 0; i < clen; i++) {
|
||||
LOGI("Hey, we're talking about: %zu, with name and lib_fd: %s, %d\n", i, context.modules[i].name, context.modules[i].lib_fd);
|
||||
|
||||
size_t name_len = strlen(context.modules[i].name);
|
||||
if (write_string(client_fd, context.modules[i].name) == -1) {
|
||||
LOGE("Failed writing module name\n");
|
||||
|
||||
LOGI("Name length: %zu\n", name_len);
|
||||
ret = write(client_fd, &name_len, sizeof(name_len));
|
||||
ASSURE_SIZE_WRITE_BREAK("ReadModules", "name length", ret, sizeof(name_len));
|
||||
break;
|
||||
}
|
||||
|
||||
LOGI("Writing name: %s\n", context.modules[i].name);
|
||||
ret = write(client_fd, context.modules[i].name, name_len);
|
||||
ASSURE_SIZE_WRITE_BREAK("ReadModules", "name", ret, name_len);
|
||||
if (send_fd(client_fd, context.modules[i].lib_fd) == -1) {
|
||||
LOGE("Failed sending lib fd\n");
|
||||
|
||||
LOGI("Writing lib fd: %d\n", context.modules[i].lib_fd);
|
||||
if (send_fd(client_fd, context.modules[i].lib_fd) == -1) break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LOGI("Finished reading modules to stream\n");
|
||||
@@ -612,10 +678,10 @@ void zygiskd_start(void) {
|
||||
if (companion_fd != -1) {
|
||||
LOGI("Companion for module `%s` already exists\n", module->name);
|
||||
|
||||
if (fcntl(companion_fd, F_GETFD) == -1) {
|
||||
if (!check_unix_socket(companion_fd, false)) {
|
||||
LOGE("Poll companion for module `%s` crashed\n", module->name);
|
||||
close(companion_fd);
|
||||
|
||||
close(companion_fd);
|
||||
module->companion = -1;
|
||||
}
|
||||
}
|
||||
@@ -630,22 +696,26 @@ void zygiskd_start(void) {
|
||||
|
||||
module->companion = companion_fd;
|
||||
|
||||
if (send_fd(client_fd, companion_fd) == -1) break;
|
||||
} else if (companion_fd == -2) {
|
||||
LOGI("Could not spawn companion for `%s` as it has no entry\n", module->name);
|
||||
/* INFO: Reversed params, may fix issues */
|
||||
if (send_fd(companion_fd, client_fd) == -1) {
|
||||
LOGE("Failed sending companion fd\n");
|
||||
|
||||
/* TODO: Avoid duplicated code -- Merge this and the one below. */
|
||||
uint8_t response = 0;
|
||||
ret = write(client_fd, &response, sizeof(response));
|
||||
ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response));
|
||||
uint8_t response = 0;
|
||||
ret = write(client_fd, &response, sizeof(response));
|
||||
ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response));
|
||||
}
|
||||
} else {
|
||||
LOGE("Failed to spawn companion for `%s`\n", module->name);
|
||||
|
||||
uint8_t response = 0;
|
||||
ret = write(client_fd, &response, sizeof(response));
|
||||
ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response));
|
||||
if (companion_fd == -2) {
|
||||
LOGI("Could not spawn companion for `%s` as it has no entry\n", module->name);
|
||||
} else {
|
||||
LOGI("Could not spawn companion for `%s` due to failures.\n", module->name);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t response = 0;
|
||||
ret = write(client_fd, &response, sizeof(response));
|
||||
ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response));
|
||||
|
||||
LOGI("Companion fd: %d\n", companion_fd);
|
||||
}
|
||||
|
||||
@@ -666,19 +736,25 @@ void zygiskd_start(void) {
|
||||
snprintf(dir, PATH_MAX, "%s/%s", PATH_MODULES_DIR, context.modules[index].name);
|
||||
|
||||
LOGI("Module directory: %s\n", dir);
|
||||
/* INFO: Maybe not read only? */
|
||||
int dir_fd = open(dir, O_RDONLY);
|
||||
|
||||
LOGI("Module directory fd: %d\n", dir_fd);
|
||||
|
||||
if (send_fd(client_fd, dir_fd) == -1) break;
|
||||
if (send_fd(client_fd, dir_fd) == -1) {
|
||||
LOGE("Failed sending module directory fd\n");
|
||||
|
||||
close(dir_fd);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
LOGI("Sent module directory fd\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* INFO: Maybe we don't need to close? */
|
||||
close(client_fd);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user