You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
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:
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ enum RootImpl {
|
||||
None,
|
||||
Multiple,
|
||||
KernelSU,
|
||||
APatch
|
||||
APatch,
|
||||
Magisk
|
||||
};
|
||||
|
||||
void root_impls_setup(void);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
190
zygiskd/src/root_impl/magisk.c
Normal file
190
zygiskd/src/root_impl/magisk.c
Normal 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;
|
||||
}
|
||||
}
|
||||
19
zygiskd/src/root_impl/magisk.h
Normal file
19
zygiskd/src/root_impl/magisk.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user