You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
improve: companion handler fd closing; fix: PIPE signal handling (#103)
This commit improves how we decide to close the fd that connects the injected module with the companion, avoiding both double close and fd leaks.
This commit is contained in:
2
zygiskd/src/.gitignore
vendored
2
zygiskd/src/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
zygiskd64
|
|
||||||
zygiskd32
|
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
@@ -17,6 +18,9 @@
|
|||||||
#include "dl.h"
|
#include "dl.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#undef LOG_TAG
|
||||||
|
#define LOG_TAG lp_select("zygiskd-companion32", "zygiskd-companion64")
|
||||||
|
|
||||||
typedef void (*zygisk_companion_entry)(int);
|
typedef void (*zygisk_companion_entry)(int);
|
||||||
|
|
||||||
struct companion_module_thread_args {
|
struct companion_module_thread_args {
|
||||||
@@ -28,12 +32,23 @@ zygisk_companion_entry load_module(int fd) {
|
|||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
|
snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
|
||||||
|
|
||||||
void *handle = android_dlopen(path, RTLD_NOW);
|
void *handle = dlopen_ext(path, RTLD_NOW);
|
||||||
|
|
||||||
|
if (!handle) return NULL;
|
||||||
|
|
||||||
void *entry = dlsym(handle, "zygisk_companion_entry");
|
void *entry = dlsym(handle, "zygisk_companion_entry");
|
||||||
|
if (!entry) {
|
||||||
|
LOGE("Failed to dlsym zygisk_companion_entry: %s\n", dlerror());
|
||||||
|
|
||||||
|
dlclose(handle);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return (zygisk_companion_entry)entry;
|
return (zygisk_companion_entry)entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* WARNING: Dynamic memory based */
|
||||||
void *entry_thread(void *arg) {
|
void *entry_thread(void *arg) {
|
||||||
struct companion_module_thread_args *args = (struct companion_module_thread_args *)arg;
|
struct companion_module_thread_args *args = (struct companion_module_thread_args *)arg;
|
||||||
|
|
||||||
@@ -42,7 +57,7 @@ void *entry_thread(void *arg) {
|
|||||||
|
|
||||||
struct stat st0 = { 0 };
|
struct stat st0 = { 0 };
|
||||||
if (fstat(fd, &st0) == -1) {
|
if (fstat(fd, &st0) == -1) {
|
||||||
LOGE("Failed to get initial client fd stats: %s\n", strerror(errno));
|
LOGE(" - Failed to get initial client fd stats: %s\n", strerror(errno));
|
||||||
|
|
||||||
free(args);
|
free(args);
|
||||||
|
|
||||||
@@ -56,14 +71,10 @@ void *entry_thread(void *arg) {
|
|||||||
if the module companion already closed the fd.
|
if the module companion already closed the fd.
|
||||||
*/
|
*/
|
||||||
struct stat st1;
|
struct stat st1;
|
||||||
if (fstat(fd, &st1) == 0) {
|
if (fstat(fd, &st1) != -1 || st0.st_ino == st1.st_ino) {
|
||||||
if (st0.st_dev == st1.st_dev && st0.st_ino == st1.st_ino) {
|
LOGI(" - Client fd changed after module entry\n");
|
||||||
LOGI("Client fd stats unchanged. Closing.\n");
|
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
} else {
|
|
||||||
LOGI("Client fd stats changed, assuming module handled closing.\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(args);
|
free(args);
|
||||||
@@ -80,10 +91,7 @@ void companion_entry(int fd) {
|
|||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
LOGE("Failed to read module name\n");
|
LOGE("Failed to read module name\n");
|
||||||
|
|
||||||
/* TODO: Is that appropriate? */
|
goto cleanup;
|
||||||
close(fd);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGI(" - Module name: \"%s\"\n", name);
|
LOGI(" - Module name: \"%s\"\n", name);
|
||||||
@@ -92,10 +100,7 @@ void companion_entry(int fd) {
|
|||||||
if (library_fd == -1) {
|
if (library_fd == -1) {
|
||||||
LOGE("Failed to receive library fd\n");
|
LOGE("Failed to receive library fd\n");
|
||||||
|
|
||||||
/* TODO: Is that appropriate? */
|
goto cleanup;
|
||||||
close(fd);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGI(" - Library fd: %d\n", library_fd);
|
LOGI(" - Library fd: %d\n", library_fd);
|
||||||
@@ -109,7 +114,7 @@ void companion_entry(int fd) {
|
|||||||
ret = write_uint8_t(fd, 0);
|
ret = write_uint8_t(fd, 0);
|
||||||
ASSURE_SIZE_WRITE("ZygiskdCompanion", "module_entry", ret, sizeof(uint8_t));
|
ASSURE_SIZE_WRITE("ZygiskdCompanion", "module_entry", ret, sizeof(uint8_t));
|
||||||
|
|
||||||
exit(0);
|
goto cleanup;
|
||||||
} else {
|
} else {
|
||||||
LOGI(" - Module entry found\n");
|
LOGI(" - Module entry found\n");
|
||||||
|
|
||||||
@@ -117,18 +122,25 @@ void companion_entry(int fd) {
|
|||||||
ASSURE_SIZE_WRITE("ZygiskdCompanion", "module_entry", ret, sizeof(uint8_t));
|
ASSURE_SIZE_WRITE("ZygiskdCompanion", "module_entry", ret, sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct sigaction sa;
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_handler = SIG_IGN;
|
||||||
|
sigaction(SIGPIPE, &sa, NULL);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!check_unix_socket(fd, true)) {
|
if (!check_unix_socket(fd, true)) {
|
||||||
LOGE("Something went wrong in companion. Bye!\n");
|
LOGE("Something went wrong in companion. Bye!\n");
|
||||||
|
|
||||||
exit(0);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int client_fd = read_fd(fd);
|
int client_fd = read_fd(fd);
|
||||||
if (client_fd == -1) {
|
if (client_fd == -1) {
|
||||||
LOGE("Failed to receive client fd\n");
|
LOGE("Failed to receive client fd\n");
|
||||||
|
|
||||||
exit(0);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct companion_module_thread_args *args = malloc(sizeof(struct companion_module_thread_args));
|
struct companion_module_thread_args *args = malloc(sizeof(struct companion_module_thread_args));
|
||||||
@@ -137,7 +149,7 @@ void companion_entry(int fd) {
|
|||||||
|
|
||||||
close(client_fd);
|
close(client_fd);
|
||||||
|
|
||||||
exit(0);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
args->fd = client_fd;
|
args->fd = client_fd;
|
||||||
@@ -149,9 +161,20 @@ void companion_entry(int fd) {
|
|||||||
ASSURE_SIZE_WRITE("ZygiskdCompanion", "client_fd", ret, sizeof(uint8_t));
|
ASSURE_SIZE_WRITE("ZygiskdCompanion", "client_fd", ret, sizeof(uint8_t));
|
||||||
|
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
pthread_create(&thread, NULL, entry_thread, args);
|
if (pthread_create(&thread, NULL, entry_thread, (void *)args) == 0)
|
||||||
pthread_detach(thread);
|
continue;
|
||||||
|
|
||||||
LOGI(" - Spawned companion thread for client fd: %d\n", client_fd);
|
LOGE(" - Failed to create thread for companion module\n");
|
||||||
|
|
||||||
|
close(client_fd);
|
||||||
|
free(args);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
close(fd);
|
||||||
|
LOGE("Companion thread exited\n");
|
||||||
|
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,77 +11,47 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
#include <android/dlext.h>
|
||||||
|
|
||||||
#include "companion.h"
|
#include "companion.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define ANDROID_NAMESPACE_TYPE_SHARED 0x2
|
#define __LOADER_ANDROID_CREATE_NAMESPACE_TYPE(name) struct android_namespace_t *(*name)( \
|
||||||
#define ANDROID_DLEXT_USE_NAMESPACE 0x200
|
const char *name, \
|
||||||
|
const char *ld_library_path, \
|
||||||
|
const char *default_library_path, \
|
||||||
|
uint64_t type, \
|
||||||
|
const char *permitted_when_isolated_path, \
|
||||||
|
struct android_namespace_t *parent, \
|
||||||
|
const void *caller_addr)
|
||||||
|
|
||||||
typedef struct AndroidNamespace {
|
void *dlopen_ext(const char* path, int flags) {
|
||||||
uint8_t _unused[0];
|
android_dlextinfo info = { 0 };
|
||||||
} AndroidNamespace;
|
|
||||||
|
|
||||||
typedef struct AndroidDlextinfo {
|
|
||||||
uint64_t flags;
|
|
||||||
void *reserved_addr;
|
|
||||||
size_t reserved_size;
|
|
||||||
int relro_fd;
|
|
||||||
int library_fd;
|
|
||||||
off64_t library_fd_offset;
|
|
||||||
AndroidNamespace *library_namespace;
|
|
||||||
} AndroidDlextinfo;
|
|
||||||
|
|
||||||
extern void *android_dlopen_ext(const char *filename, int flags, const AndroidDlextinfo *extinfo);
|
|
||||||
|
|
||||||
typedef AndroidNamespace *(*AndroidCreateNamespaceFn)(
|
|
||||||
const char *name,
|
|
||||||
const char *ld_library_path,
|
|
||||||
const char *default_library_path,
|
|
||||||
uint64_t type,
|
|
||||||
const char *permitted_when_isolated_path,
|
|
||||||
AndroidNamespace *parent,
|
|
||||||
const void *caller_addr
|
|
||||||
);
|
|
||||||
|
|
||||||
void *android_dlopen(char *path, int flags) {
|
|
||||||
char *dir = dirname(path);
|
char *dir = dirname(path);
|
||||||
struct AndroidDlextinfo info = {
|
|
||||||
.flags = 0,
|
|
||||||
.reserved_addr = NULL,
|
|
||||||
.reserved_size = 0,
|
|
||||||
.relro_fd = 0,
|
|
||||||
.library_fd = 0,
|
|
||||||
.library_fd_offset = 0,
|
|
||||||
.library_namespace = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
void *handle = dlsym(RTLD_DEFAULT, "__loader_android_create_namespace");
|
__LOADER_ANDROID_CREATE_NAMESPACE_TYPE(__loader_android_create_namespace) = (__LOADER_ANDROID_CREATE_NAMESPACE_TYPE( ))dlsym(RTLD_DEFAULT, "__loader_android_create_namespace");
|
||||||
AndroidCreateNamespaceFn android_create_namespace_fn = (AndroidCreateNamespaceFn)handle;
|
|
||||||
|
|
||||||
AndroidNamespace *ns = android_create_namespace_fn(
|
struct android_namespace_t *ns = __loader_android_create_namespace == NULL ? NULL :
|
||||||
path,
|
__loader_android_create_namespace(path, dir, NULL,
|
||||||
dir,
|
2, /* ANDROID_NAMESPACE_TYPE_SHARED */
|
||||||
NULL,
|
NULL, NULL,
|
||||||
ANDROID_NAMESPACE_TYPE_SHARED,
|
(void *)&dlopen_ext);
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
(const void *)&android_dlopen
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ns != NULL) {
|
if (ns) {
|
||||||
info.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
info.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
||||||
info.library_namespace = ns;
|
info.library_namespace = ns;
|
||||||
|
|
||||||
LOGI("Open %s with namespace %p\n", path, (void *)ns);
|
LOGI("Open %s with namespace %p", path, (void *)ns);
|
||||||
} else {
|
} else {
|
||||||
LOGI("Cannot create namespace for %s\n", path);
|
LOGW("Cannot create namespace for %s", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *result = android_dlopen_ext(path, flags, &info);
|
void *handle = android_dlopen_ext(path, flags, &info);
|
||||||
if (result == NULL) {
|
if (handle) {
|
||||||
LOGE("Failed to dlopen %s: %s\n", path, dlerror());
|
LOGI("dlopen %s: %p", path, handle);
|
||||||
|
} else {
|
||||||
|
LOGE("dlopen %s: %s", path, dlerror());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#ifndef DL_H
|
#ifndef DL_H
|
||||||
#define DL_H
|
#define DL_H
|
||||||
|
|
||||||
void *android_dlopen(char *path, int flags);
|
void *dlopen_ext(char *path, int flags);
|
||||||
|
|
||||||
#endif /* DL_H */
|
#endif /* DL_H */
|
||||||
|
|||||||
@@ -228,11 +228,11 @@ ssize_t write_fd(int fd, int sendfd) {
|
|||||||
|
|
||||||
int read_fd(int fd) {
|
int read_fd(int fd) {
|
||||||
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
||||||
char buf[1] = { 0 };
|
|
||||||
|
int cnt = 1;
|
||||||
struct iovec iov = {
|
struct iovec iov = {
|
||||||
.iov_base = buf,
|
.iov_base = &cnt,
|
||||||
.iov_len = 1
|
.iov_len = sizeof(cnt)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msghdr msg = {
|
struct msghdr msg = {
|
||||||
@@ -242,7 +242,7 @@ int read_fd(int fd) {
|
|||||||
.msg_controllen = sizeof(cmsgbuf)
|
.msg_controllen = sizeof(cmsgbuf)
|
||||||
};
|
};
|
||||||
|
|
||||||
ssize_t ret = recvmsg(fd, &msg, 0);
|
ssize_t ret = recvmsg(fd, &msg, MSG_WAITALL);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
LOGE("recvmsg: %s\n", strerror(errno));
|
LOGE("recvmsg: %s\n", strerror(errno));
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,18 @@
|
|||||||
#define CONCAT_(x,y) x##y
|
#define CONCAT_(x,y) x##y
|
||||||
#define CONCAT(x,y) CONCAT_(x,y)
|
#define CONCAT(x,y) CONCAT_(x,y)
|
||||||
|
|
||||||
#define LOGI(...) \
|
#define LOG_TAG lp_select("zygiskd32", "zygiskd64")
|
||||||
__android_log_print(ANDROID_LOG_INFO, lp_select("zygiskd32", "zygiskd64"), __VA_ARGS__); \
|
|
||||||
|
#define LOGI(...) \
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); \
|
||||||
printf(__VA_ARGS__);
|
printf(__VA_ARGS__);
|
||||||
|
|
||||||
#define LOGE(...) \
|
#define LOGW(...) \
|
||||||
__android_log_print(ANDROID_LOG_ERROR , lp_select("zygiskd32", "zygiskd64"), __VA_ARGS__); \
|
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); \
|
||||||
|
printf(__VA_ARGS__);
|
||||||
|
|
||||||
|
#define LOGE(...) \
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR , LOG_TAG, __VA_ARGS__); \
|
||||||
printf(__VA_ARGS__);
|
printf(__VA_ARGS__);
|
||||||
|
|
||||||
#define ASSURE_SIZE_WRITE(area_name, subarea_name, sent_size, expected_size) \
|
#define ASSURE_SIZE_WRITE(area_name, subarea_name, sent_size, expected_size) \
|
||||||
|
|||||||
Reference in New Issue
Block a user