You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
fix: memory leak, unitialized memory access, FILE pointer leak bugs
This commit fixes numerous general code bugs, improving reliability and consistency of ReZygisk.
This commit is contained in:
@@ -108,43 +108,32 @@ void rezygiskd_get_info(struct rezygisk_info *info) {
|
||||
|
||||
read_uint32_t(fd, (uint32_t *)&info->pid);
|
||||
|
||||
read_size_t(fd, &info->modules->modules_count);
|
||||
if (info->modules->modules_count == 0) {
|
||||
info->modules->modules = NULL;
|
||||
read_size_t(fd, &info->modules.modules_count);
|
||||
if (info->modules.modules_count == 0) {
|
||||
info->modules.modules = NULL;
|
||||
|
||||
close(fd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
info->modules->modules = (char **)malloc(sizeof(char *) * info->modules->modules_count);
|
||||
if (info->modules->modules == NULL) {
|
||||
info->modules.modules = (char **)malloc(sizeof(char *) * info->modules.modules_count);
|
||||
if (!info->modules.modules) {
|
||||
PLOGE("allocating modules name memory");
|
||||
|
||||
free(info->modules);
|
||||
info->modules = NULL;
|
||||
info->modules->modules_count = 0;
|
||||
info->modules.modules_count = 0;
|
||||
|
||||
close(fd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < info->modules->modules_count; i++) {
|
||||
for (size_t i = 0; i < info->modules.modules_count; i++) {
|
||||
char *module_name = read_string(fd);
|
||||
if (module_name == NULL) {
|
||||
PLOGE("reading module name");
|
||||
|
||||
info->modules->modules_count = i;
|
||||
|
||||
free_rezygisk_info(info);
|
||||
|
||||
info->modules = NULL;
|
||||
info->modules->modules_count = 0;
|
||||
|
||||
close(fd);
|
||||
|
||||
return;
|
||||
goto info_cleanup;
|
||||
}
|
||||
|
||||
char module_path[PATH_MAX];
|
||||
@@ -156,43 +145,49 @@ void rezygiskd_get_info(struct rezygisk_info *info) {
|
||||
if (!module_prop) {
|
||||
PLOGE("failed to open module prop file %s", module_path);
|
||||
|
||||
info->modules->modules_count = i;
|
||||
|
||||
free_rezygisk_info(info);
|
||||
|
||||
info->modules = NULL;
|
||||
info->modules->modules_count = 0;
|
||||
|
||||
close(fd);
|
||||
|
||||
return;
|
||||
goto info_cleanup;
|
||||
}
|
||||
|
||||
info->modules.modules[i] = NULL;
|
||||
|
||||
char line[1024];
|
||||
while (fgets(line, sizeof(line), module_prop) != NULL) {
|
||||
if (strncmp(line, "name=", strlen("name=")) != 0) continue;
|
||||
|
||||
info->modules->modules[i] = strndup(line + 5, strlen(line) - 6);
|
||||
info->modules.modules[i] = strndup(line + 5, strlen(line) - 6);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (info->modules.modules[i] == NULL) {
|
||||
PLOGE("failed to read module name from %s", module_path);
|
||||
|
||||
fclose(module_prop);
|
||||
|
||||
goto info_cleanup;
|
||||
}
|
||||
|
||||
fclose(module_prop);
|
||||
|
||||
continue;
|
||||
|
||||
info_cleanup:
|
||||
info->modules.modules_count = i;
|
||||
free_rezygisk_info(info);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void free_rezygisk_info(struct rezygisk_info *info) {
|
||||
if (info->modules->modules) {
|
||||
for (size_t i = 0; i < info->modules->modules_count; i++) {
|
||||
free(info->modules->modules[i]);
|
||||
}
|
||||
|
||||
free(info->modules->modules);
|
||||
for (size_t i = 0; i < info->modules.modules_count; i++) {
|
||||
free(info->modules.modules[i]);
|
||||
}
|
||||
|
||||
free(info->modules);
|
||||
free(info->modules.modules);
|
||||
info->modules.modules = NULL;
|
||||
}
|
||||
|
||||
bool rezygiskd_read_modules(struct zygisk_modules *modules) {
|
||||
@@ -237,13 +232,11 @@ bool rezygiskd_read_modules(struct zygisk_modules *modules) {
|
||||
}
|
||||
|
||||
void free_modules(struct zygisk_modules *modules) {
|
||||
if (modules->modules) {
|
||||
for (size_t i = 0; i < modules->modules_count; i++) {
|
||||
free(modules->modules[i]);
|
||||
}
|
||||
|
||||
free(modules->modules);
|
||||
for (size_t i = 0; i < modules->modules_count; i++) {
|
||||
free(modules->modules[i]);
|
||||
}
|
||||
|
||||
free(modules->modules);
|
||||
}
|
||||
|
||||
int rezygiskd_connect_companion(size_t index) {
|
||||
|
||||
@@ -25,7 +25,7 @@ int read_fd(int fd) {
|
||||
.msg_controllen = sizeof(cmsgbuf)
|
||||
};
|
||||
|
||||
ssize_t ret = recvmsg(fd, &msg, MSG_WAITALL);
|
||||
ssize_t ret = TEMP_FAILURE_RETRY(recvmsg(fd, &msg, MSG_WAITALL));
|
||||
if (ret == -1) {
|
||||
PLOGE("recvmsg");
|
||||
|
||||
@@ -47,14 +47,14 @@ int read_fd(int fd) {
|
||||
|
||||
ssize_t write_string(int fd, const char *str) {
|
||||
size_t str_len = strlen(str);
|
||||
ssize_t write_bytes = write(fd, &str_len, sizeof(size_t));
|
||||
ssize_t write_bytes = TEMP_FAILURE_RETRY(write(fd, &str_len, sizeof(size_t)));
|
||||
if (write_bytes != (ssize_t)sizeof(size_t)) {
|
||||
LOGE("Failed to write string length: Not all bytes were written (%zd != %zu).\n", write_bytes, sizeof(size_t));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
write_bytes = write(fd, str, str_len);
|
||||
write_bytes = TEMP_FAILURE_RETRY(write(fd, str, str_len));
|
||||
if (write_bytes != (ssize_t)str_len) {
|
||||
LOGE("Failed to write string: Promised bytes doesn't exist (%zd != %zu).\n", write_bytes, str_len);
|
||||
|
||||
@@ -66,7 +66,7 @@ ssize_t write_string(int fd, const char *str) {
|
||||
|
||||
char *read_string(int fd) {
|
||||
size_t str_len = 0;
|
||||
ssize_t read_bytes = read(fd, &str_len, sizeof(size_t));
|
||||
ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, &str_len, sizeof(size_t)));
|
||||
if (read_bytes != (ssize_t)sizeof(size_t)) {
|
||||
LOGE("Failed to read string length: Not all bytes were read (%zd != %zu).\n", read_bytes, sizeof(size_t));
|
||||
|
||||
@@ -80,7 +80,7 @@ char *read_string(int fd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
read_bytes = read(fd, buf, str_len);
|
||||
read_bytes = TEMP_FAILURE_RETRY(read(fd, buf, str_len));
|
||||
if (read_bytes != (ssize_t)str_len) {
|
||||
LOGE("Failed to read string: Promised bytes doesn't exist (%zd != %zu).\n", read_bytes, str_len);
|
||||
|
||||
@@ -94,14 +94,14 @@ char *read_string(int fd) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define write_func(type) \
|
||||
ssize_t write_## type(int fd, type val) { \
|
||||
return write(fd, &val, sizeof(type)); \
|
||||
#define write_func(type) \
|
||||
ssize_t write_## type(int fd, type val) { \
|
||||
return TEMP_FAILURE_RETRY(write(fd, &val, sizeof(type))); \
|
||||
}
|
||||
|
||||
#define read_func(type) \
|
||||
ssize_t read_## type(int fd, type *val) { \
|
||||
return read(fd, val, sizeof(type)); \
|
||||
#define read_func(type) \
|
||||
ssize_t read_## type(int fd, type *val) { \
|
||||
return TEMP_FAILURE_RETRY(read(fd, val, sizeof(type))); \
|
||||
}
|
||||
|
||||
write_func(uint8_t)
|
||||
|
||||
@@ -42,7 +42,7 @@ enum root_impl {
|
||||
};
|
||||
|
||||
struct rezygisk_info {
|
||||
struct zygisk_modules *modules;
|
||||
struct zygisk_modules modules;
|
||||
enum root_impl root_impl;
|
||||
pid_t pid;
|
||||
bool running;
|
||||
|
||||
@@ -77,11 +77,11 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (info.modules->modules_count != 0) {
|
||||
printf("Modules: %zu\n", info.modules->modules_count);
|
||||
if (info.modules.modules_count != 0) {
|
||||
printf("Modules: %zu\n", info.modules.modules_count);
|
||||
|
||||
for (size_t i = 0; i < info.modules->modules_count; i++) {
|
||||
printf(" - %s\n", info.modules->modules[i]);
|
||||
for (size_t i = 0; i < info.modules.modules_count; i++) {
|
||||
printf(" - %s\n", info.modules.modules[i]);
|
||||
}
|
||||
} else {
|
||||
printf("Modules: N/A\n");
|
||||
|
||||
@@ -66,6 +66,7 @@ struct rezygiskd_status status32 = {
|
||||
|
||||
int monitor_epoll_fd;
|
||||
bool monitor_events_running = true;
|
||||
typedef void (*monitor_event_callback_t)();
|
||||
|
||||
bool monitor_events_init() {
|
||||
monitor_epoll_fd = epoll_create(1);
|
||||
@@ -78,14 +79,9 @@ bool monitor_events_init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
struct monitor_event_cbs {
|
||||
void (*callback)();
|
||||
void (*stop_callback)();
|
||||
};
|
||||
|
||||
bool monitor_events_register_event(struct monitor_event_cbs *event_cbs, int fd, uint32_t events) {
|
||||
bool monitor_events_register_event(monitor_event_callback_t event_cb, int fd, uint32_t events) {
|
||||
struct epoll_event ev = {
|
||||
.data.ptr = event_cbs,
|
||||
.data.ptr = (void *)event_cb,
|
||||
.events = events
|
||||
};
|
||||
|
||||
@@ -116,15 +112,16 @@ void monitor_events_loop() {
|
||||
struct epoll_event events[2];
|
||||
while (monitor_events_running) {
|
||||
int nfds = epoll_wait(monitor_epoll_fd, events, 2, -1);
|
||||
if (nfds == -1) {
|
||||
if (errno != EINTR) PLOGE("epoll_wait");
|
||||
if (nfds == -1 && errno != EINTR) {
|
||||
PLOGE("epoll_wait");
|
||||
|
||||
continue;
|
||||
monitor_events_running = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nfds; i++) {
|
||||
struct monitor_event_cbs *event_cbs = (struct monitor_event_cbs *)events[i].data.ptr;
|
||||
event_cbs->callback();
|
||||
for (int i = 0; i < nfds; i++) {
|
||||
((monitor_event_callback_t)events[i].data.ptr)();
|
||||
|
||||
if (!monitor_events_running) break;
|
||||
}
|
||||
@@ -132,11 +129,6 @@ void monitor_events_loop() {
|
||||
|
||||
if (monitor_epoll_fd >= 0) close(monitor_epoll_fd);
|
||||
monitor_epoll_fd = -1;
|
||||
|
||||
for (int i = 0; i < (int)(sizeof(events) / sizeof(events[0])); i++) {
|
||||
struct monitor_event_cbs *event_cbs = (struct monitor_event_cbs *)events[i].data.ptr;
|
||||
event_cbs->stop_callback();
|
||||
}
|
||||
}
|
||||
|
||||
int monitor_sock_fd;
|
||||
@@ -272,15 +264,13 @@ void rezygiskd_listener_callback() {
|
||||
status64.daemon_info = NULL;
|
||||
}
|
||||
|
||||
status64.daemon_info = (char *)malloc(msg.length);
|
||||
status64.daemon_info = strdup(msg_data);
|
||||
if (!status64.daemon_info) {
|
||||
PLOGE("malloc daemon64 info");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(status64.daemon_info, msg_data);
|
||||
|
||||
update_status(NULL);
|
||||
|
||||
break;
|
||||
@@ -293,15 +283,13 @@ void rezygiskd_listener_callback() {
|
||||
status32.daemon_info = NULL;
|
||||
}
|
||||
|
||||
status32.daemon_info = (char *)malloc(msg.length);
|
||||
status32.daemon_info = strdup(msg_data);
|
||||
if (!status32.daemon_info) {
|
||||
PLOGE("malloc daemon32 info");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(status32.daemon_info, msg_data);
|
||||
|
||||
update_status(NULL);
|
||||
|
||||
break;
|
||||
@@ -316,15 +304,13 @@ void rezygiskd_listener_callback() {
|
||||
status64.daemon_error_info = NULL;
|
||||
}
|
||||
|
||||
status64.daemon_error_info = (char *)malloc(msg.length);
|
||||
status64.daemon_error_info = strdup(msg_data);
|
||||
if (!status64.daemon_error_info) {
|
||||
PLOGE("malloc daemon64 error info");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(status64.daemon_error_info, msg_data);
|
||||
|
||||
update_status(NULL);
|
||||
|
||||
break;
|
||||
@@ -339,15 +325,13 @@ void rezygiskd_listener_callback() {
|
||||
status32.daemon_error_info = NULL;
|
||||
}
|
||||
|
||||
status32.daemon_error_info = (char *)malloc(msg.length);
|
||||
status32.daemon_error_info = strdup(msg_data);
|
||||
if (!status32.daemon_error_info) {
|
||||
PLOGE("malloc daemon32 error info");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(status32.daemon_error_info, msg_data);
|
||||
|
||||
update_status(NULL);
|
||||
|
||||
break;
|
||||
@@ -847,10 +831,6 @@ void init_monitor() {
|
||||
|
||||
monitor_events_init();
|
||||
|
||||
struct monitor_event_cbs listener_cbs = {
|
||||
.callback = rezygiskd_listener_callback,
|
||||
.stop_callback = rezygiskd_listener_stop
|
||||
};
|
||||
if (!rezygiskd_listener_init()) {
|
||||
LOGE("failed to create socket");
|
||||
|
||||
@@ -859,12 +839,8 @@ void init_monitor() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
monitor_events_register_event(&listener_cbs, monitor_sock_fd, EPOLLIN | EPOLLET);
|
||||
monitor_events_register_event(rezygiskd_listener_callback, monitor_sock_fd, EPOLLIN | EPOLLET);
|
||||
|
||||
struct monitor_event_cbs sigchld_cbs = {
|
||||
.callback = sigchld_listener_callback,
|
||||
.stop_callback = sigchld_listener_stop
|
||||
};
|
||||
if (sigchld_listener_init() == false) {
|
||||
LOGE("failed to create signalfd");
|
||||
|
||||
@@ -874,10 +850,15 @@ void init_monitor() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
monitor_events_register_event(&sigchld_cbs, sigchld_signal_fd, EPOLLIN | EPOLLET);
|
||||
monitor_events_register_event(sigchld_listener_callback, sigchld_signal_fd, EPOLLIN | EPOLLET);
|
||||
|
||||
monitor_events_loop();
|
||||
|
||||
/* INFO: Once it stops the loop, we cannot access the epool data, so we
|
||||
either manually call the stops or save to a structure. */
|
||||
rezygiskd_listener_stop();
|
||||
sigchld_listener_stop();
|
||||
|
||||
if (status64.daemon_info) free(status64.daemon_info);
|
||||
if (status64.daemon_error_info) free(status64.daemon_error_info);
|
||||
if (status32.daemon_info) free(status32.daemon_info);
|
||||
|
||||
@@ -119,8 +119,8 @@ struct maps *parse_maps(const char *filename) {
|
||||
path_offset++;
|
||||
}
|
||||
|
||||
maps->maps = (struct map *)realloc(maps->maps, (i + 1) * sizeof(struct map));
|
||||
if (!maps->maps) {
|
||||
struct map *tmp_maps = (struct map *)realloc(maps->maps, (i + 1) * sizeof(struct map));
|
||||
if (!tmp_maps) {
|
||||
LOGE("Failed to allocate memory for maps->maps");
|
||||
|
||||
maps->size = i;
|
||||
@@ -130,6 +130,7 @@ struct maps *parse_maps(const char *filename) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
maps->maps = tmp_maps;
|
||||
|
||||
maps->maps[i].start = addr_start;
|
||||
maps->maps[i].end = addr_end;
|
||||
|
||||
Reference in New Issue
Block a user