add: zygiskd C99 APatch support

This commit adds support for zygiskd C99 to recognize APatch rooted devices.
This commit is contained in:
ThePedroo
2024-08-15 22:42:47 -03:00
parent 19d2a1758e
commit c1e45e9af6
13 changed files with 484 additions and 210 deletions

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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
};

View File

@@ -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;
}

View 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;
}

View 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

View File

@@ -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;
// }
// }
}

View File

@@ -5,8 +5,9 @@
enum RootImpl {
None,
Multiple, /* INFO: I know. */
KernelSU
Multiple,
KernelSU,
APatch
};
void root_impls_setup(void);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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);
}