You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
This commit adds the first base for C99 zygiskd, that is not fully working or code-ready.
723 lines
21 KiB
C
723 lines
21 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <dirent.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/sendfile.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
#include <linux/limits.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include "root_impl/common.h"
|
|
#include "constants.h"
|
|
#include "utils.h"
|
|
|
|
struct Module {
|
|
char *name;
|
|
int lib_fd;
|
|
int companion;
|
|
};
|
|
|
|
struct Context {
|
|
struct Module *modules;
|
|
int len;
|
|
};
|
|
|
|
enum Architecture {
|
|
ARM32,
|
|
ARM64,
|
|
X86,
|
|
X86_64,
|
|
};
|
|
|
|
#define PATH_MODULES_DIR "/data/adb/modules"
|
|
#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_PATH "/data/adb/modules/zygisksu/bin/zygiskd" lp_select("32", "64")
|
|
|
|
#define ASSURE_SIZE_WRITE(area_name, subarea_name, sent_size, expected_size) \
|
|
if (sent_size != (ssize_t)(expected_size)) { \
|
|
LOGE("Failed to sent " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \
|
|
\
|
|
return; \
|
|
}
|
|
|
|
#define ASSURE_SIZE_READ(area_name, subarea_name, sent_size, expected_size) \
|
|
if (sent_size != (ssize_t)(expected_size)) { \
|
|
LOGE("Failed to read " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \
|
|
\
|
|
return; \
|
|
}
|
|
|
|
#define ASSURE_SIZE_WRITE_BREAK(area_name, subarea_name, sent_size, expected_size) \
|
|
if (sent_size != (ssize_t)(expected_size)) { \
|
|
LOGE("Failed to sent " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \
|
|
\
|
|
break; \
|
|
}
|
|
|
|
#define ASSURE_SIZE_READ_BREAK(area_name, subarea_name, sent_size, expected_size) \
|
|
if (sent_size != (ssize_t)(expected_size)) { \
|
|
LOGE("Failed to read " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \
|
|
\
|
|
break; \
|
|
}
|
|
|
|
#define ASSURE_SIZE_WRITE_WR(area_name, subarea_name, sent_size, expected_size) \
|
|
if (sent_size != (ssize_t)(expected_size)) { \
|
|
LOGE("Failed to sent " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \
|
|
\
|
|
return -1; \
|
|
}
|
|
|
|
#define ASSURE_SIZE_READ_WR(area_name, subarea_name, sent_size, expected_size) \
|
|
if (sent_size != (ssize_t)(expected_size)) { \
|
|
LOGE("Failed to read " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \
|
|
\
|
|
return -1; \
|
|
}
|
|
|
|
static enum Architecture get_arch(void) {
|
|
char system_arch[32];
|
|
get_property("ro.product.cpu.abi", system_arch);
|
|
|
|
if (strstr(system_arch, "arm") != NULL) return lp_select(ARM32, ARM64);
|
|
if (strstr(system_arch, "x86") != NULL) return lp_select(X86, X86_64);
|
|
|
|
LOGE("Unsupported system architecture: %s\n", system_arch);
|
|
exit(1);
|
|
}
|
|
|
|
int create_library_fd(const char *so_path) {
|
|
int memfd = memfd_create("jit-cache-zygisk", MFD_ALLOW_SEALING);
|
|
if (memfd == -1) {
|
|
perror("memfd_create");
|
|
|
|
return -1;
|
|
}
|
|
|
|
int so_fd = open(so_path, O_RDONLY);
|
|
if (so_fd == -1) {
|
|
perror("open");
|
|
close(memfd);
|
|
|
|
return -1;
|
|
}
|
|
|
|
struct stat st;
|
|
if (fstat(so_fd, &st) == -1) {
|
|
perror("fstat");
|
|
close(so_fd);
|
|
close(memfd);
|
|
|
|
return -1;
|
|
}
|
|
|
|
if (sendfile(memfd, so_fd, NULL, st.st_size) == -1) {
|
|
perror("sendfile");
|
|
close(so_fd);
|
|
close(memfd);
|
|
|
|
return -1;
|
|
}
|
|
|
|
close(so_fd);
|
|
|
|
if (fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) == -1) {
|
|
perror("fcntl");
|
|
close(memfd);
|
|
|
|
return -1;
|
|
}
|
|
|
|
return memfd;
|
|
}
|
|
|
|
|
|
/* WARNING: Dynamic memory based */
|
|
static void load_modules(enum Architecture arch, struct Context *context) {
|
|
context->len = 0;
|
|
context->modules = malloc(1);
|
|
|
|
// LOGI("Previous error{25}: %s\n", strerror(errno));
|
|
|
|
DIR *dir = opendir(PATH_MODULES_DIR);
|
|
if (dir == NULL) {
|
|
LOGE("Failed opening modules directory: %s.", PATH_MODULES_DIR);
|
|
|
|
return;
|
|
}
|
|
|
|
// LOGI("Previous error{27}: %s\n", strerror(errno));
|
|
|
|
char arch_str[32];
|
|
switch (arch) {
|
|
case ARM32: {
|
|
strcpy(arch_str, "armeabi-v7a");
|
|
|
|
break;
|
|
}
|
|
case ARM64: {
|
|
strcpy(arch_str, "arm64-v8a");
|
|
|
|
break;
|
|
}
|
|
case X86: {
|
|
strcpy(arch_str, "x86");
|
|
|
|
break;
|
|
}
|
|
case X86_64: {
|
|
strcpy(arch_str, "x86_64");
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
LOGI("Loading modules for architecture: %s\n", arch_str);
|
|
// LOGI("Previous error{28}: %s\n", strerror(errno));
|
|
|
|
struct dirent *entry;
|
|
while ((entry = readdir(dir)) != NULL) {
|
|
// LOGI("Previous error{29}: %s\n", strerror(errno));
|
|
if (entry->d_type != DT_DIR) continue; /* INFO: Only directories */
|
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 || strcmp(entry->d_name, "zygisksu") == 0) continue;
|
|
|
|
char *name = entry->d_name;
|
|
char so_path[PATH_MAX];
|
|
snprintf(so_path, PATH_MAX, "/data/adb/modules/%s/zygisk/%s.so", name, arch_str);
|
|
|
|
struct stat st;
|
|
if (stat(so_path, &st) == -1) {
|
|
errno = 0;
|
|
|
|
continue;
|
|
}
|
|
|
|
char disabled[PATH_MAX];
|
|
snprintf(disabled, PATH_MAX, "/data/adb/modules/%s/disable", name);
|
|
|
|
if (stat(disabled, &st) != -1) {
|
|
errno = 0;
|
|
|
|
continue;
|
|
}
|
|
|
|
LOGI("Loading module `%s`...\n", name);
|
|
int lib_fd = create_library_fd(so_path);
|
|
if (lib_fd == -1) {
|
|
LOGE("Failed loading module `%s`\n", name);
|
|
|
|
continue;
|
|
}
|
|
|
|
LOGI("Loaded module lib fd: %d\n", lib_fd);
|
|
|
|
context->modules = realloc(context->modules, ((context->len + 1) * sizeof(struct Module)));
|
|
context->modules[context->len].name = strdup(name);
|
|
context->modules[context->len].lib_fd = lib_fd;
|
|
context->modules[context->len].companion = -1;
|
|
context->len++;
|
|
}
|
|
}
|
|
|
|
static void free_modules(struct Context *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);
|
|
}
|
|
}
|
|
|
|
static int create_daemon_socket(void) {
|
|
set_socket_create_context("u:r:zygote:s0");
|
|
|
|
return unix_listener_from_path(PATH_CP_NAME);
|
|
}
|
|
|
|
static int spawn_companion(char *name, int lib_fd) {
|
|
// LOGI("Previous error{15}: %s\n", strerror(errno));
|
|
|
|
int sockets[2];
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
|
|
LOGE("Failed creating socket pair.\n");
|
|
|
|
return -1;
|
|
}
|
|
|
|
int daemon_fd = sockets[0];
|
|
int companion_fd = sockets[1];
|
|
|
|
LOGI("Companion fd: %d\n", companion_fd);
|
|
LOGI("Daemon fd: %d\n", daemon_fd);
|
|
|
|
// LOGI("Previous error{13}: %s\n", strerror(errno));
|
|
|
|
pid_t pid = fork();
|
|
LOGI("Forked: %d\n", pid);
|
|
if (pid < 0) {
|
|
LOGE("Failed forking companion: %s\n", strerror(errno));
|
|
|
|
close(companion_fd);
|
|
close(daemon_fd);
|
|
|
|
exit(1);
|
|
} else if (pid > 0) {
|
|
// LOGI("Previous error{11}: %s\n", strerror(errno));
|
|
|
|
close(companion_fd);
|
|
|
|
LOGI("Waiting for companion to start (%d)\n", pid);
|
|
// LOGI("Previous error{8}: %s\n", strerror(errno));
|
|
|
|
int status;
|
|
waitpid(pid, &status, 0);
|
|
|
|
LOGI("Companion exited with status %d\n", status);
|
|
// LOGI("Previous error{9}: %s\n", strerror(errno));
|
|
|
|
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
|
if (write_string(daemon_fd, name) == -1) return -1;
|
|
|
|
if (send_fd(daemon_fd, lib_fd) == -1) return -1;
|
|
|
|
LOGI("Sent module name and lib fd\n");
|
|
|
|
uint8_t response_buf[1];
|
|
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);
|
|
|
|
if (response == 0) return -2;
|
|
else if (response == 1) return daemon_fd;
|
|
else return -2;
|
|
} else {
|
|
LOGE("Exited with status %d\n", status);
|
|
|
|
close(daemon_fd);
|
|
|
|
return -1;
|
|
}
|
|
/* INFO: if pid == 0: */
|
|
} else {
|
|
LOGI("Companion started (%d)\n", pid);
|
|
/* INFO: There is no case where this will fail with a valid fd. */
|
|
fcntl(companion_fd, F_SETFD, 0);
|
|
}
|
|
|
|
char companion_fd_str[32];
|
|
snprintf(companion_fd_str, 32, "%d", companion_fd);
|
|
|
|
LOGI("Executing companion...\n");
|
|
// LOGI("Previous error{10}: %s\n", strerror(errno));
|
|
|
|
char *argv[] = { ZYGISKD_FILE, "companion", companion_fd_str, NULL };
|
|
if (execv(ZYGISKD_PATH, argv) == -1) {
|
|
LOGE("Failed executing companion: %s\n", strerror(errno));
|
|
|
|
close(companion_fd);
|
|
|
|
exit(1);
|
|
}
|
|
|
|
exit(0);
|
|
}
|
|
|
|
/* TODO: Is packed attribute really necessary? */
|
|
struct __attribute__((__packed__)) MsgHead {
|
|
unsigned int cmd;
|
|
int length;
|
|
char data[0];
|
|
};
|
|
|
|
void zygiskd_start(void) {
|
|
LOGI("Welcome to ReZygisk %s!", ZKSU_VERSION);
|
|
|
|
// LOGI("Previous error{26}: %s\n", strerror(errno));
|
|
|
|
enum Architecture arch = get_arch();
|
|
|
|
// LOGI("Previous error{25}: %s\n", strerror(errno));
|
|
|
|
struct Context context;
|
|
load_modules(arch, &context);
|
|
|
|
struct MsgHead *msg = NULL;
|
|
size_t msg_sz = 0;
|
|
|
|
// LOGI("Previous error{24}: %s\n", strerror(errno));
|
|
|
|
switch (get_impl()) {
|
|
case None: {
|
|
/* INFO: Stop, compiler. */
|
|
|
|
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->cmd = DAEMON_SET_INFO;
|
|
msg->length = strlen("Root: KernelSU, Modules: None") + 1;
|
|
memcpy(msg->data, "Root: KernelSU, Modules: None", strlen("Root: KernelSU, Modules: None"));
|
|
} else {
|
|
char *module_list = malloc(1);
|
|
size_t module_list_len = 0;
|
|
|
|
for (int i = 0; i < context.len; i++) {
|
|
if (i != context.len - 1) {
|
|
module_list = realloc(module_list, module_list_len + strlen(context.modules[i].name) + strlen(", ") + 1);
|
|
memcpy(module_list + module_list_len, context.modules[i].name, strlen(context.modules[i].name));
|
|
|
|
module_list_len += strlen(context.modules[i].name);
|
|
|
|
memcpy(module_list + module_list_len, ", ", strlen(", "));
|
|
|
|
module_list_len += strlen(", ");
|
|
} else {
|
|
module_list = realloc(module_list, module_list_len + strlen(context.modules[i].name) + 1);
|
|
memcpy(module_list + module_list_len, context.modules[i].name, strlen(context.modules[i].name));
|
|
|
|
module_list_len += strlen(context.modules[i].name);
|
|
}
|
|
}
|
|
|
|
msg_sz = sizeof(struct MsgHead) + strlen("Root: KernelSU, Modules: ") + module_list_len + 1;
|
|
msg = malloc(msg_sz);
|
|
|
|
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);
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
// LOGI("Previous error{22}: %s\n", strerror(errno));
|
|
|
|
unix_datagram_sendto(CONTROLLER_SOCKET, (void *)msg, msg_sz);
|
|
|
|
free(msg);
|
|
|
|
// LOGI("Previous error{21}: %s\n", strerror(errno));
|
|
|
|
int socket_fd = create_daemon_socket();
|
|
if (socket_fd == -1) {
|
|
LOGE("Failed creating daemon socket\n");
|
|
|
|
return;
|
|
}
|
|
|
|
while (1) {
|
|
// LOGI("Previous error{20}: %s\n", strerror(errno));
|
|
int client_fd = accept(socket_fd, NULL, NULL);
|
|
if (client_fd == -1) {
|
|
LOGE("accept: %s\n", strerror(errno));
|
|
|
|
return;
|
|
}
|
|
|
|
LOGI("Accepted client: %d\n", client_fd);
|
|
|
|
// LOGI("Previous error{19}: %s\n", strerror(errno));
|
|
|
|
unsigned char buf[1];
|
|
ssize_t len = read(client_fd, buf, sizeof(buf));
|
|
if (len == -1) {
|
|
LOGE("read: %s\n", strerror(errno));
|
|
|
|
return;
|
|
} else if (len == 0) {
|
|
LOGI("Client disconnected\n");
|
|
|
|
return;
|
|
}
|
|
|
|
LOGI("Action: %hhu\n", (uint8_t)buf[0]);
|
|
enum DaemonSocketAction action = (enum DaemonSocketAction)buf[0];
|
|
|
|
switch (action) {
|
|
case PingHeartbeat: {
|
|
enum DaemonSocketAction msgr = ZYGOTE_INJECTED;
|
|
unix_datagram_sendto(CONTROLLER_SOCKET, &msgr, sizeof(enum DaemonSocketAction));
|
|
|
|
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);
|
|
context.modules[i].companion = -1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case SystemServerStarted: {
|
|
enum DaemonSocketAction msgr = SYSTEM_SERVER_STARTED;
|
|
unix_datagram_sendto(CONTROLLER_SOCKET, &msgr, sizeof(enum DaemonSocketAction));
|
|
|
|
break;
|
|
}
|
|
case RequestLogcatFd: {
|
|
char 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];
|
|
|
|
char tag[128 + 1];
|
|
ret = read_string(client_fd, tag, sizeof(tag) - 1);
|
|
if (ret == -1) break;
|
|
|
|
tag[ret] = '\0';
|
|
|
|
char message[1024];
|
|
ret = read_string(client_fd, message, sizeof(message));
|
|
if (ret == -1) break;
|
|
|
|
__android_log_print(level, tag, "%.*s", (int)ret, message);
|
|
|
|
break;
|
|
}
|
|
case GetProcessFlags: {
|
|
LOGI("Getting process flags\n");
|
|
|
|
uid_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 flags = 0;
|
|
if (uid_is_manager(uid)) {
|
|
flags |= PROCESS_IS_MANAGER;
|
|
} else {
|
|
if (uid_granted_root(uid)) {
|
|
flags |= PROCESS_GRANTED_ROOT;
|
|
}
|
|
if (uid_should_umount(uid)) {
|
|
flags |= PROCESS_ON_DENYLIST;
|
|
}
|
|
}
|
|
|
|
LOGI("Flags for uid %d: %d\n", uid, flags);
|
|
|
|
switch (get_impl()) {
|
|
case None: {
|
|
break;
|
|
}
|
|
case Multiple: {
|
|
break;
|
|
}
|
|
case KernelSU: {
|
|
flags |= PROCESS_ROOT_IS_KSU;
|
|
}
|
|
}
|
|
|
|
// 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));
|
|
|
|
LOGI("Sent flags\n");
|
|
|
|
break;
|
|
}
|
|
case GetInfo: {
|
|
uint32_t flags = 0;
|
|
|
|
LOGI("Getting info\n");
|
|
|
|
switch (get_impl()) {
|
|
case None: {
|
|
break;
|
|
}
|
|
case Multiple: {
|
|
break;
|
|
}
|
|
case KernelSU: {
|
|
flags |= PROCESS_ROOT_IS_KSU;
|
|
}
|
|
}
|
|
|
|
LOGI("Flags: %d\n", flags);
|
|
|
|
ssize_t ret = write(client_fd, &flags, sizeof(flags));
|
|
ASSURE_SIZE_WRITE_BREAK("GetInfo", "flags", ret, sizeof(flags));
|
|
|
|
pid_t pid = getpid();
|
|
|
|
LOGI("Getting pid: %d\n", pid);
|
|
|
|
ret = write(client_fd, &pid, sizeof(pid));
|
|
ASSURE_SIZE_WRITE_BREAK("GetInfo", "pid", ret, sizeof(pid));
|
|
|
|
LOGI("Sent pid\n");
|
|
|
|
break;
|
|
}
|
|
case ReadModules: {
|
|
LOGI("Reading modules to stream\n");
|
|
|
|
size_t clen = context.len;
|
|
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);
|
|
|
|
size_t name_len = strlen(context.modules[i].name);
|
|
|
|
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));
|
|
|
|
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);
|
|
|
|
LOGI("Writing lib fd: %d\n", context.modules[i].lib_fd);
|
|
if (send_fd(client_fd, context.modules[i].lib_fd) == -1) break;
|
|
}
|
|
|
|
LOGI("Finished reading modules to stream\n");
|
|
|
|
break;
|
|
}
|
|
case RequestCompanionSocket: {
|
|
LOGI("Requesting companion socket\n");
|
|
|
|
// LOGI("Previous error{17}: %s\n", strerror(errno));
|
|
|
|
size_t index_buf[1];
|
|
ssize_t ret = read(client_fd, &index_buf, sizeof(index_buf));
|
|
ASSURE_SIZE_READ_BREAK("RequestCompanionSocket", "index", ret, sizeof(index_buf));
|
|
|
|
// LOGI("Previous error{16}: %s\n", strerror(errno));
|
|
|
|
size_t index = index_buf[0];
|
|
|
|
struct Module *module = &context.modules[index];
|
|
int companion_fd = module->companion;
|
|
|
|
if (companion_fd != -1) {
|
|
LOGI("Companion for module `%s` already exists\n", module->name);
|
|
|
|
if (fcntl(companion_fd, F_GETFD) == -1) {
|
|
LOGE("Poll companion for module `%s` crashed\n", module->name);
|
|
close(companion_fd);
|
|
|
|
module->companion = -1;
|
|
}
|
|
}
|
|
|
|
if (companion_fd == -1) {
|
|
LOGI("Spawning companion for `%s`\n", module->name);
|
|
|
|
companion_fd = spawn_companion(module->name, module->lib_fd);
|
|
|
|
if (companion_fd != -1) {
|
|
LOGI("Spawned companion for `%s`\n", module->name);
|
|
|
|
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);
|
|
|
|
/* 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));
|
|
} 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));
|
|
}
|
|
|
|
LOGI("Companion fd: %d\n", companion_fd);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GetModuleDir: {
|
|
LOGI("Getting module directory\n");
|
|
|
|
size_t index_buf[1];
|
|
ssize_t ret = read(client_fd, &index_buf, sizeof(index_buf));
|
|
ASSURE_SIZE_READ_BREAK("GetModuleDir", "index", ret, sizeof(index_buf));
|
|
|
|
size_t index = index_buf[0];
|
|
|
|
LOGI("Index: %zu\n", index);
|
|
|
|
char dir[PATH_MAX];
|
|
snprintf(dir, PATH_MAX, "%s/%s", PATH_MODULES_DIR, context.modules[index].name);
|
|
|
|
LOGI("Module directory: %s\n", dir);
|
|
int dir_fd = open(dir, O_RDONLY);
|
|
|
|
LOGI("Module directory fd: %d\n", dir_fd);
|
|
|
|
if (send_fd(client_fd, dir_fd) == -1) break;
|
|
|
|
LOGI("Sent module directory fd\n");
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
close(client_fd);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
close(socket_fd);
|
|
free_modules(&context);
|
|
}
|