add: Magisk support; fix: (some) zygiskd code issues

This commit adds Magisk support to Zygiskd C99, and also fixes some code issues of it.
This commit is contained in:
ThePedroo
2024-08-20 19:16:12 -03:00
parent c1e45e9af6
commit a549f0e5ae
14 changed files with 520 additions and 126 deletions

View File

@@ -53,6 +53,7 @@ val Files = arrayOf(
"root_impl/apatch.c",
"root_impl/common.c",
"root_impl/kernelsu.c",
"root_impl/magisk.c",
"companion.c",
"dl.c",
"main.c",

View File

@@ -30,7 +30,7 @@ zygisk_companion_entry_func load_module(int fd) {
return (zygisk_companion_entry_func)entry;
}
void *call_entry(void *arg) {
void *call_entry(void *restrict arg) {
int fd = *((int *)arg);
struct stat st0;
@@ -92,7 +92,7 @@ void entry(int fd) {
if (entry == NULL) {
LOGI("No companion entry for: %s\n", name);
uint8_t response[1] = { 0 };
uint8_t response = 0;
write(fd, &response, sizeof(response));
exit(0);
@@ -102,7 +102,7 @@ void entry(int fd) {
LOGI("Companion process created for: %s\n", name);
uint8_t response[1] = { 1 };
uint8_t response = 1;
write(fd, &response, sizeof(response));
while (1) {
@@ -114,21 +114,17 @@ void entry(int fd) {
break;
}
int client_fd;
recv_fd(fd, &client_fd);
int *client_fd = malloc(sizeof(int));
recv_fd(fd, client_fd);
LOGI("New companion request from module \"%s\" with fd \"%d\"\n", name, client_fd);
LOGI("New companion request from module \"%s\" with fd \"%d\"\n", name, *client_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, call_entry, (void *)client_fd_ptr);
pthread_create(&thread, NULL, call_entry, (void *)client_fd);
pthread_detach(thread);
}
}

View File

@@ -23,7 +23,7 @@ struct AndroidDlextinfo {
void *android_dlopen_ext(const char *filename, int flags, const struct AndroidDlextinfo *extinfo);
void *android_dlopen(char *path, u_int32_t flags) {
void *android_dlopen(char *restrict path, uint32_t flags) {
char *dir = dirname(path);
struct AndroidDlextinfo info = {
.flags = 0,

View File

@@ -1,6 +1,6 @@
#ifndef DL_H
#define DL_H
void *android_dlopen(char *path, u_int32_t flags);
void *android_dlopen(char *restrict path, u_int32_t flags);
#endif /* DL_H */

View File

@@ -11,7 +11,7 @@
#include "utils.h"
int __android_log_print(int prio, const char *tag, const char *fmt, ...);
int __android_log_print(int prio, const char *tag, const char *fmt, ...);
int main(int argc, char *argv[]) {
LOGI("Initializing zygiskd: %s\n", argv[0]);
@@ -61,6 +61,11 @@ int main(int argc, char *argv[]) {
case APatch: {
LOGI("APatch root implementation found.\n");
return 0;
}
case Magisk: {
LOGI("Magisk root implementation found.\n");
return 0;
}
}

View File

@@ -12,7 +12,8 @@
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));
if (errno != ENOENT) LOGE("Failed to stat APatch apd binary: %s\n", strerror(errno));
errno = 0;
return Inexistent;
}
@@ -20,18 +21,16 @@ enum RootImplState apatch_get_existence(void) {
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));
LOGE("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 == 0) return Abnormal;
if (version >= MIN_APATCH_VERSION && version <= 999999) return Supported;
if (version >= 1 && version <= MIN_APATCH_VERSION - 1) return TooOld;
@@ -49,38 +48,54 @@ struct packages_config {
size_t size;
};
bool _apatch_get_package_config(struct packages_config *config) {
/* WARNING: Dynamic memory based */
bool _apatch_get_package_config(struct packages_config *restrict config) {
FILE *fp = fopen("/data/adb/ap/package_config", "r");
if (fp == NULL) {
LOGE("APATCH | Failed to open package_config: %s\n", strerror(errno));
LOGE("Failed to open APatch's package_config: %s\n", strerror(errno));
return false;
}
char line[256];
char line[1024];
/* INFO: Skip the CSV header */
fgets(line, sizeof(line), fp);
LOGI("meow meow: %s\n", line);
config->size = 0;
while (fgets(line, sizeof(line), fp) != NULL) {
config->configs = realloc(config, (config->size + 1) * sizeof(struct package_config));
LOGI("meow meow\n");
config->configs = realloc(config->configs, (config->size + 1) * sizeof(struct package_config));
if (config->configs == NULL) {
LOGE("APATCH | Failed to realloc package config: %s\n", strerror(errno));
LOGE("Failed to realloc APatch config struct: %s\n", strerror(errno));
fclose(fp);
return false;
}
LOGI("meow meow (1): %s\n", line);
strtok(line, ",");
LOGI("meow meow (2)\n");
char *exclude_str = strtok(NULL, ",");
if (exclude_str == NULL) continue;
LOGI("meow meow: %s\n", exclude_str);
char *allow_str = strtok(NULL, ",");
if (allow_str == NULL) continue;
LOGI("meow meow: %s\n", allow_str);
char *uid_str = strtok(NULL, ",");
if (uid_str == NULL) continue;
if (uid_str == NULL) continue;
LOGI("meow meow: %s\n", uid_str);
config->configs[config->size].uid = atoi(uid_str);
config->configs[config->size].root_granted = strcmp(allow_str, "1") == 0;
@@ -138,7 +153,12 @@ bool apatch_uid_should_umount(uid_t uid) {
bool apatch_uid_is_manager(uid_t uid) {
struct stat s;
if (stat("/data/user_de/0/me.bmax.apatch", &s) == -1) return false;
if (stat("/data/user_de/0/me.bmax.apatch", &s) == -1) {
if (errno != ENOENT) LOGE("Failed to stat APatch manager data directory: %s\n", strerror(errno));
errno = 0;
return false;
}
return s.st_uid == uid;
}

View File

@@ -1,7 +1,11 @@
#include <stdio.h>
#include <sys/types.h>
#include "../utils.h"
#include "kernelsu.h"
#include "apatch.h"
#include "magisk.h"
#include "common.h"
@@ -10,7 +14,36 @@ static enum RootImpl ROOT_IMPL = None;
void root_impls_setup(void) {
if (ksu_get_existence() == Supported) ROOT_IMPL = KernelSU;
else if (apatch_get_existence() == Supported) ROOT_IMPL = APatch;
else if (magisk_get_existence() == Supported) ROOT_IMPL = Magisk;
else ROOT_IMPL = None;
switch (ROOT_IMPL) {
case None: {
LOGI("No root implementation found.\n");
break;
}
case Multiple: {
LOGI("Multiple root implementations found.\n");
break;
}
case KernelSU: {
LOGI("KernelSU root implementation found.\n");
break;
}
case APatch: {
LOGI("APatch root implementation found.\n");
break;
}
case Magisk: {
LOGI("Magisk root implementation found.\n");
break;
}
}
}
enum RootImpl get_impl(void) {
@@ -18,43 +51,52 @@ 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);
// }
// case APatch: {
// return apatch_uid_granted_root(uid);
// }
// default: {
// return false;
// }
// }
}
case APatch: {
return apatch_uid_granted_root(uid);
}
case Magisk: {
return magisk_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);
// }
// case APatch: {
// return apatch_uid_should_umount(uid);
// }
// default: {
// return false;
// }
// }
}
case APatch: {
return apatch_uid_should_umount(uid);
}
case Magisk: {
return magisk_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);
// }
// case APatch: {
// return apatch_uid_is_manager(uid);
// }
// default: {
// return false;
// }
// }
}
case APatch: {
return apatch_uid_is_manager(uid);
}
case Magisk: {
return magisk_uid_is_manager(uid);
}
default: {
return false;
}
}
}

View File

@@ -7,7 +7,8 @@ enum RootImpl {
None,
Multiple,
KernelSU,
APatch
APatch,
Magisk
};
void root_impls_setup(void);

View File

@@ -48,7 +48,12 @@ bool ksu_uid_should_umount(uid_t uid) {
bool ksu_uid_is_manager(uid_t uid) {
struct stat s;
if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == -1) return false;
if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == -1) {
if (errno != ENOENT) LOGE("Failed to stat KSU manager data directory: %s\n", strerror(errno));
errno = 0;
return false;
}
return s.st_uid == uid;
}

View File

@@ -0,0 +1,190 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/prctl.h>
#include <errno.h>
#include <unistd.h>
#include "../constants.h"
#include "../utils.h"
#include "magisk.h"
char *supported_variants[] = {
"kitsune"
};
char *magisk_managers[] = {
"com.topjohnwu.magisk",
"io.github.huskydg.magisk"
};
enum magisk_variants variant = Official;
enum RootImplState magisk_get_existence(void) {
char *argv[] = { "magisk", "-v", NULL };
char magisk_info[32];
if (!exec_command(magisk_info, sizeof(magisk_info), "/sbin/magisk", argv)) {
LOGE("Failed to execute magisk binary: %s\n", strerror(errno));
errno = 0;
return Inexistent;
}
for (unsigned long i = 0; i < sizeof(supported_variants) / sizeof(char *); i++) {
if (strstr(magisk_info, supported_variants[i])) variant = (enum magisk_variants)(i + 1);
}
argv[1] = "-V";
char magisk_version[32];
if (!exec_command(magisk_version, sizeof(magisk_version), "/sbin/magisk", argv)) {
LOGE("Failed to execute magisk binary: %s\n", strerror(errno));
errno = 0;
return Abnormal;
}
if (atoi(magisk_version) >= MIN_MAGISK_VERSION) return Supported;
else return TooOld;
}
bool magisk_uid_granted_root(uid_t uid) {
char sqlite_cmd[256];
snprintf(sqlite_cmd, sizeof(sqlite_cmd), "select 1 from policies where uid=%d and policy=2 limit 1", uid);
char *const argv[] = { "magisk", "--sqlite", sqlite_cmd, NULL };
char result[32];
if (!exec_command(result, sizeof(result), "/sbin/magisk", argv)) {
LOGE("Failed to execute magisk binary: %s\n", strerror(errno));
errno = 0;
return false;
}
return result[0] != '\0';
}
bool magisk_uid_should_umount(uid_t uid) {
struct dirent *entry;
DIR *proc = opendir("/proc");
if (!proc) {
LOGE("Failed to open /proc: %s\n", strerror(errno));
errno = 0;
return false;
}
while ((entry = readdir(proc))) {
if (entry->d_type != DT_DIR) continue;
if (atoi(entry->d_name) == 0) continue;
char stat_path[32];
snprintf(stat_path, sizeof(stat_path), "/proc/%s/stat", entry->d_name);
struct stat s;
if (stat(stat_path, &s) == -1) continue;
if (s.st_uid != uid) continue;
char package_name[255 + 1];
char cmdline_path[32];
snprintf(cmdline_path, sizeof(cmdline_path), "/proc/%s/cmdline", entry->d_name);
int cmdline = open(cmdline_path, O_RDONLY);
if (cmdline == -1) {
LOGE("Failed to open %s: %s\n", cmdline_path, strerror(errno));
errno = 0;
closedir(proc);
continue;
}
ssize_t read_bytes = read(cmdline, package_name, sizeof(package_name) - 1);
if (read_bytes == -1) {
LOGE("Failed to read from %s: %s\n", cmdline_path, strerror(errno));
errno = 0;
close(cmdline);
closedir(proc);
continue;
}
close(cmdline);
closedir(proc);
package_name[read_bytes] = '\0';
char sqlite_cmd[256];
snprintf(sqlite_cmd, sizeof(sqlite_cmd), "select 1 from denylist where package_name=\"%s\" limit 1", package_name);
char *const argv[] = { "magisk", "--sqlite", sqlite_cmd, NULL };
char result[32];
if (!exec_command(result, sizeof(result), "/sbin/magisk", argv)) {
LOGE("Failed to execute magisk binary: %s\n", strerror(errno));
errno = 0;
return false;
}
return result[0] != '\0';
}
return false;
}
bool magisk_uid_is_manager(uid_t uid) {
char sqlite_cmd[256];
snprintf(sqlite_cmd, sizeof(sqlite_cmd), "select value from strings where key=\"requester\" limit 1");
char *const argv[] = { "magisk", "--sqlite", sqlite_cmd, NULL };
char output[32];
if (!exec_command(output, sizeof(output), "/sbin/magisk", argv)) {
LOGE("Failed to execute magisk binary: %s\n", strerror(errno));
errno = 0;
return false;
}
if (output[0] == '\0') {
char stat_path[PATH_MAX];
snprintf(stat_path, sizeof(stat_path), "/data/user_de/0/%s", magisk_managers[(int)variant]);
struct stat s;
if (stat(stat_path, &s) == -1) {
LOGE("Failed to stat %s: %s\n", stat_path, strerror(errno));
errno = 0;
return false;
}
return s.st_uid == uid;
} else {
char stat_path[PATH_MAX];
snprintf(stat_path, sizeof(stat_path), "/data/user_de/0/%s", output + strlen("value="));
LOGI("Checking |%s|\n", stat_path);
struct stat s;
if (stat(stat_path, &s) == -1) {
LOGE("Failed to stat %s: %s\n", stat_path, strerror(errno));
LOGE("???\n");
errno = 0;
return false;
}
return s.st_uid == uid;
}
}

View File

@@ -0,0 +1,19 @@
#ifndef MAGISK_H
#define MAGISK_H
#include "../constants.h"
enum magisk_variants {
Official,
Kitsune
};
enum RootImplState magisk_get_existence(void);
bool magisk_uid_granted_root(uid_t uid);
bool magisk_uid_should_umount(uid_t uid);
bool magisk_uid_is_manager(uid_t uid);
#endif

View File

@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
@@ -43,31 +44,53 @@ bool switch_mount_namespace(pid_t pid) {
int __system_property_get(const char *, char *);
void get_property(const char *name, char *output) {
void get_property(const char *restrict name, char *restrict output) {
__system_property_get(name, output);
}
void set_socket_create_context(const char *context) {
void set_socket_create_context(const char *restrict context) {
char path[PATH_MAX];
snprintf(path, PATH_MAX, "/proc/thread-self/attr/sockcreate");
FILE *sockcreate = fopen(path, "w");
if (sockcreate == NULL) {
LOGE("Failed to open /proc/thread-self/attr/sockcreate: %s\n", strerror(errno));
LOGE("Failed to open /proc/thread-self/attr/sockcreate: %s Now trying to via gettid().\n", strerror(errno));
return;
goto fail;
}
if (fwrite(context, 1, strlen(context), sockcreate) != strlen(context)) {
LOGE("Failed to write to /proc/thread-self/attr/sockcreate: %s\n", strerror(errno));
LOGE("Failed to write to /proc/thread-self/attr/sockcreate: %s Now trying to via gettid().\n", strerror(errno));
return;
fclose(sockcreate);
goto fail;
}
fclose(sockcreate);
return;
fail:
snprintf(path, PATH_MAX, "/proc/self/task/%d/attr/sockcreate", gettid());
sockcreate = fopen(path, "w");
if (sockcreate == NULL) {
LOGE("Failed to open %s: %s\n", path, strerror(errno));
return;
}
if (fwrite(context, 1, strlen(context), sockcreate) != strlen(context)) {
LOGE("Failed to write to %s: %s\n", path, strerror(errno));
return;
}
fclose(sockcreate);
}
static void get_current_attr(char *output) {
static void get_current_attr(char *restrict output, size_t size) {
char path[PATH_MAX];
snprintf(path, PATH_MAX, "/proc/self/attr/current");
@@ -78,8 +101,8 @@ static void get_current_attr(char *output) {
return;
}
if (fgets(output, PATH_MAX, current) == NULL) {
LOGE("fgets: %s\n", strerror(errno));
if (fread(output, 1, size, current) == 0) {
LOGE("fread: %s\n", strerror(errno));
return;
}
@@ -87,9 +110,9 @@ static void get_current_attr(char *output) {
fclose(current);
}
void unix_datagram_sendto(const char *path, void *buf, size_t len) {
void unix_datagram_sendto(const char *restrict path, void *restrict buf, size_t len) {
char current_attr[PATH_MAX];
get_current_attr(current_attr);
get_current_attr(current_attr, sizeof(current_attr));
set_socket_create_context(current_attr);
@@ -122,14 +145,14 @@ void unix_datagram_sendto(const char *path, void *buf, size_t len) {
close(socket_fd);
}
int chcon(const char *path, const char *context) {
int chcon(const char *restrict path, const char *context) {
char command[PATH_MAX];
snprintf(command, PATH_MAX, "chcon %s %s", context, path);
return system(command);
}
int unix_listener_from_path(char *path) {
int unix_listener_from_path(char *restrict path) {
if (remove(path) == -1 && errno != ENOENT) {
LOGE("remove: %s\n", strerror(errno));
@@ -143,10 +166,9 @@ int unix_listener_from_path(char *path) {
return -1;
}
struct sockaddr_un addr;
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
struct sockaddr_un addr = {
.sun_family = AF_UNIX
};
strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
@@ -204,7 +226,7 @@ ssize_t send_fd(int sockfd, int fd) {
return sent_bytes;
}
ssize_t recv_fd(int sockfd, int *fd) {
ssize_t recv_fd(int sockfd, int *restrict fd) {
char control_buf[CMSG_SPACE(sizeof(int))];
memset(control_buf, 0, sizeof(control_buf));
@@ -234,7 +256,7 @@ ssize_t recv_fd(int sockfd, int *fd) {
return received_bytes;
}
ssize_t write_string(int fd, const char *str) {
ssize_t write_string(int fd, const char *restrict str) {
size_t len = strlen(str);
ssize_t written_bytes = write(fd, &len, sizeof(len));
@@ -254,7 +276,7 @@ ssize_t write_string(int fd, const char *str) {
return written_bytes;
}
ssize_t read_string(int fd, char *str, size_t len) {
ssize_t read_string(int fd, char *restrict str, size_t len) {
size_t str_len_buf[1];
ssize_t read_bytes = read(fd, &str_len_buf, sizeof(str_len_buf));
@@ -282,7 +304,8 @@ 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[]) {
/* INFO: Cannot use restrict here as execv does not have restrict */
bool exec_command(char *restrict buf, size_t len, const char *restrict file, char *const argv[]) {
int link[2];
pid_t pid;
@@ -308,10 +331,55 @@ bool exec_command(char *buf, size_t len, const char *file, char *const argv[]) {
close(link[1]);
int nbytes = read(link[0], buf, len);
buf[nbytes] = '\0';
buf[nbytes - 1] = '\0';
wait(NULL);
}
return true;
}
bool check_unix_socket(int fd, bool block) {
struct pollfd pfd = {
.fd = fd,
.events = POLLIN,
.revents = 0
};
int timeout = block ? -1 : 0;
poll(&pfd, 1, timeout);
return (pfd.revents & !POLLIN) != 0 ? false : true;
}
/* INFO: Cannot use restrict here as execv does not have restrict */
int non_blocking_execv(const char *restrict file, char *const argv[]) {
int link[2];
pid_t pid;
if (pipe(link) == -1) {
LOGE("pipe: %s\n", strerror(errno));
return -1;
}
if ((pid = fork()) == -1) {
LOGE("fork: %s\n", strerror(errno));
return -1;
}
if (pid == 0) {
dup2(link[1], STDOUT_FILENO);
close(link[0]);
close(link[1]);
execv(file, argv);
} else {
close(link[1]);
return link[0];
}
return -1;
}

View File

@@ -8,38 +8,40 @@
#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__); \
#define LOGI(...) \
__android_log_print(ANDROID_LOG_INFO, lp_select("zygiskd32", "zygiskd64"), __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);
void get_property(const char *name, char *output);
void get_property(const char *name, char *restrict output);
void set_socket_create_context(const char *context);
void set_socket_create_context(const char *restrict context);
void unix_datagram_sendto(const char *path, void *buf, size_t len);
void unix_datagram_sendto(const char *restrict path, void *restrict buf, size_t len);
int chcon(const char *path, const char *context);
int chcon(const char *path, const char *restrict context);
int unix_listener_from_path(char *path);
ssize_t send_fd(int sockfd, int fd);
ssize_t recv_fd(int sockfd, int *fd);
ssize_t recv_fd(int sockfd, int *restrict fd);
ssize_t write_string(int fd, const char *str);
ssize_t write_string(int fd, const char *restrict str);
ssize_t read_string(int fd, char *str, size_t len);
ssize_t read_string(int fd, char *restrict str, size_t len);
bool exec_command(char *buf, size_t len, const char *file, char *const argv[]);
bool exec_command(char *restrict buf, size_t len, const char *restrict file, char *const argv[]);
bool check_unix_socket(int fd, bool block);
int non_blocking_execv(const char *restrict file, char *const argv[]);
#endif /* UTILS_H */

View File

@@ -12,6 +12,8 @@
#include <unistd.h>
#include <linux/limits.h>
#include <sys/syscall.h>
#include <linux/memfd.h>
#include <pthread.h>
@@ -97,8 +99,10 @@ static enum Architecture get_arch(void) {
exit(1);
}
int create_library_fd(const char *so_path) {
int memfd = memfd_create("jit-cache-zygisk", MFD_ALLOW_SEALING);
int create_library_fd(const char *restrict so_path) {
/* INFO: This is required as older implementations of glibc may not
have the memfd_create function call, causing a crash. */
int memfd = syscall(SYS_memfd_create, "jit-cache-zygisk", MFD_ALLOW_SEALING);
if (memfd == -1) {
LOGE("Failed creating memfd: %s\n", strerror(errno));
@@ -155,9 +159,8 @@ int create_library_fd(const char *so_path) {
return memfd;
}
/* WARNING: Dynamic memory based */
static void load_modules(enum Architecture arch, struct Context *context) {
static void load_modules(enum Architecture arch, struct Context *restrict context) {
context->len = 0;
context->modules = malloc(1);
@@ -213,11 +216,16 @@ static void load_modules(enum Architecture arch, struct Context *context) {
char disabled[PATH_MAX];
snprintf(disabled, PATH_MAX, "/data/adb/modules/%s/disable", name);
if (stat(disabled, &st) != -1) {
errno = 0;
if (stat(disabled, &st) == -1) {
if (errno != ENOENT) {
LOGE("Failed checking if module `%s` is disabled: %s\n", name, strerror(errno));
errno = 0;
continue;
}
continue;
}
errno = 0;
} else continue;
LOGI("Loading module `%s`...\n", name);
int lib_fd = create_library_fd(so_path);
@@ -237,7 +245,7 @@ static void load_modules(enum Architecture arch, struct Context *context) {
}
}
static void free_modules(struct Context *context) {
static void free_modules(struct Context *restrict context) {
for (int i = 0; i < context->len; i++) {
free(context->modules[i].name);
if (context->modules[i].companion != -1) close(context->modules[i].companion);
@@ -250,7 +258,7 @@ static int create_daemon_socket(void) {
return unix_listener_from_path(PATH_CP_NAME);
}
static int spawn_companion(char *name, int lib_fd) {
static int spawn_companion(char *restrict name, int lib_fd) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
LOGE("Failed creating socket pair.\n");
@@ -324,7 +332,7 @@ static int spawn_companion(char *name, int lib_fd) {
}
/* INFO: if pid == 0: */
} else {
LOGI("Companion started (%d)\n", pid);
LOGI("Companion started\n");
/* INFO: There is no case where this will fail with a valid fd. */
fcntl(companion_fd, F_SETFD, 0);
}
@@ -334,19 +342,20 @@ static int spawn_companion(char *name, int lib_fd) {
LOGI("Executing companion...\n");
char arg[sizeof(ZYGISKD_FILE) + sizeof(" companion ") + 32];
snprintf(arg, sizeof(arg), "%s companion %d", ZYGISKD_FILE, companion_fd);
if (system(arg) == -1) {
char *argv[] = { ZYGISKD_FILE, "companion", companion_fd_str, NULL };
if (non_blocking_execv(ZYGISKD_PATH, argv) == -1) {
LOGE("Failed executing companion: %s\n", strerror(errno));
close(companion_fd);
exit(1);
}
LOGI("Bye bye!\n");
exit(0);
}
/* TODO: Is packed attribute really necessary? */
struct __attribute__((__packed__)) MsgHead {
unsigned int cmd;
int length;
@@ -354,7 +363,7 @@ struct __attribute__((__packed__)) MsgHead {
};
void zygiskd_start(void) {
LOGI("Welcome to ReZygisk %s!", ZKSU_VERSION);
LOGI("Welcome to ReZygisk %s!\n", ZKSU_VERSION);
enum RootImpl impl = get_impl();
if (impl == None) {
@@ -388,8 +397,28 @@ void zygiskd_start(void) {
case None: { break; }
case Multiple: { break; }
case KernelSU:
case APatch: {
size_t root_impl_len = strlen(impl == KernelSU ? "KernelSU" : "APatch");
case APatch:
case Magisk: {
size_t root_impl_len = 0;
switch (impl) {
case None: { break; }
case Multiple: { break; }
case KernelSU: {
root_impl_len = strlen("KernelSU");
break;
}
case APatch: {
root_impl_len = strlen("APatch");
break;
}
case Magisk: {
root_impl_len = strlen("Magisk");
break;
}
}
if (context.len == 0) {
msg = malloc(sizeof(struct MsgHead) + strlen("Root: , Modules: None") + root_impl_len + 1);
@@ -407,6 +436,11 @@ void zygiskd_start(void) {
case APatch: {
memcpy(msg->data, "Root: APatch, Modules: None", strlen("Root: APatch, Modules: None"));
break;
}
case Magisk: {
memcpy(msg->data, "Root: Magisk, Modules: None", strlen("Root: Magisk, Modules: None"));
break;
}
}
@@ -447,6 +481,11 @@ void zygiskd_start(void) {
case APatch: {
memcpy(msg->data, "Root: APatch, Modules: ", strlen("Root: APatch, Modules: "));
break;
}
case Magisk: {
memcpy(msg->data, "Root: Magisk, Modules: ", strlen("Root: Magisk, Modules: "));
break;
}
}
@@ -582,6 +621,11 @@ void zygiskd_start(void) {
case APatch: {
flags |= PROCESS_ROOT_IS_APATCH;
break;
}
case Magisk: {
flags |= PROCESS_ROOT_IS_MAGISK;
break;
}
}
@@ -609,6 +653,11 @@ void zygiskd_start(void) {
case APatch: {
flags |= PROCESS_ROOT_IS_APATCH;
break;
}
case Magisk: {
flags |= PROCESS_ROOT_IS_MAGISK;
break;
}
}
@@ -673,31 +722,28 @@ void zygiskd_start(void) {
size_t index = index_buf[0];
struct Module *module = &context.modules[index];
int companion_fd = module->companion;
if (companion_fd != -1) {
if (module->companion != -1) {
LOGI("Companion for module `%s` already exists\n", module->name);
if (!check_unix_socket(companion_fd, false)) {
if (!check_unix_socket(module->companion, false)) {
LOGE("Poll companion for module `%s` crashed\n", module->name);
close(companion_fd);
close(module->companion);
module->companion = -1;
}
}
if (companion_fd == -1) {
if (module->companion == -1) {
LOGI("Spawning companion for `%s`\n", module->name);
companion_fd = spawn_companion(module->name, module->lib_fd);
module->companion = spawn_companion(module->name, module->lib_fd);
if (companion_fd != -1) {
if (module->companion != -1) {
LOGI("Spawned companion for `%s`\n", module->name);
module->companion = companion_fd;
/* INFO: Reversed params, may fix issues */
if (send_fd(companion_fd, client_fd) == -1) {
if (send_fd(module->companion, client_fd) == -1) {
LOGE("Failed sending companion fd\n");
uint8_t response = 0;
@@ -705,7 +751,7 @@ void zygiskd_start(void) {
ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response));
}
} else {
if (companion_fd == -2) {
if (module->companion == -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);
@@ -716,7 +762,7 @@ void zygiskd_start(void) {
ret = write(client_fd, &response, sizeof(response));
ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response));
LOGI("Companion fd: %d\n", companion_fd);
LOGI("Companion fd: %d\n", module->companion);
}
break;
@@ -753,11 +799,10 @@ void zygiskd_start(void) {
break;
}
/* INFO: Maybe we don't need to close? */
close(client_fd);
}
close(client_fd);
continue;
}