diff --git a/jni/daemon/bootstages.c b/jni/daemon/bootstages.c index 01b619ddc..6f7101471 100644 --- a/jni/daemon/bootstages.c +++ b/jni/daemon/bootstages.c @@ -136,8 +136,7 @@ static void exec_common_script(const char* stage) { if (access(buf2, X_OK) == -1) continue; LOGI("%s.d: exec [%s]\n", stage, entry->d_name); - char *const command[] = { "sh", buf2, NULL }; - int pid = run_command2(0, NULL, bb_setenv, command); + int pid = exec_command(0, NULL, bb_setenv, "sh", buf2, NULL); if (pid != -1) waitpid(pid, NULL, 0); } @@ -154,8 +153,7 @@ static void exec_module_script(const char* stage) { if (access(buf2, F_OK) == -1 || access(buf, F_OK) == 0) continue; LOGI("%s: exec [%s.sh]\n", module, stage); - char *const command[] = { "sh", buf2, NULL }; - int pid = run_command2(0, NULL, bb_setenv, command); + int pid = exec_command(0, NULL, bb_setenv, "sh", buf2, NULL); if (pid != -1) waitpid(pid, NULL, 0); } @@ -402,8 +400,7 @@ static void mount_mirrors() { static void link_busybox() { mkdir_p(BBPATH, 0755); - char *const command[] = { MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL}; - run_command(command); + exec_command_sync(MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL); symlink(MIRRDIR "/bin/busybox", BBPATH "/busybox"); } @@ -442,7 +439,7 @@ static int prepare_img() { snprintf(buf, PATH_MAX, "%s/%s/remove", MOUNTPOINT, entry->d_name); if (access(buf, F_OK) == 0) { snprintf(buf, PATH_MAX, "%s/%s", MOUNTPOINT, entry->d_name); - rm_rf(buf); + exec_command_sync(BBPATH "/rm", "-rf", buf, NULL); continue; } snprintf(buf, PATH_MAX, "%s/%s/disable", MOUNTPOINT, entry->d_name); @@ -520,8 +517,7 @@ void post_fs_data(int client) { #ifdef MAGISK_DEBUG // Start debug logs in new process debug_log_fd = xopen(DEBUG_LOG, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, 0644); - char *const command[] = { "logcat", "-v", "brief", NULL }; - debug_log_pid = run_command2(0, &debug_log_fd, NULL, command); + debug_log_pid = exec_command(0, &debug_log_fd, NULL, "logcat", "-v", "brief", NULL); close(debug_log_fd); #endif @@ -531,20 +527,25 @@ void post_fs_data(int client) { if (buf == NULL) buf = xmalloc(PATH_MAX); if (buf2 == NULL) buf2 = xmalloc(PATH_MAX); - // Cache support - if (access("/cache/data_bin", F_OK) == 0) { - rm_rf(DATABIN); - rename("/cache/data_bin", DATABIN); + // Magisk binaries + char *bin_path = NULL; + if (access("/cache/data_bin", F_OK) == 0) + bin_path = "/cache/data_bin"; + else if (access("/data/local/tmp/magisk_inject", F_OK) == 0) + bin_path = "/data/local/tmp/magisk_inject"; + if (bin_path) { + exec_command_sync("rm", "-rf", DATABIN, NULL); + exec_command_sync("cp", "-r", bin_path, DATABIN, NULL); + exec_command_sync("rm", "-rf", bin_path, NULL); + exec_command_sync("chmod", "-R", "755", bin_path, NULL); } - // Magisk Manual Injector support - if (access("/data/local/tmp/magisk_inject", F_OK) == 0) { - rm_rf(DATABIN); - rename("/data/local/tmp/magisk_inject", DATABIN); - } + // Lazy.... use shell blob to match files + exec_command_sync("sh", "-c", "mv /data/magisk/stock_boot* /data", NULL); - // Lazy.... use shell blob - system("mv /data/magisk/stock_boot* /data;"); + // Link busybox + mount_mirrors(); + link_busybox(); // Merge images if (merge_img("/cache/magisk.img", MAINIMG)) { @@ -556,15 +557,12 @@ void post_fs_data(int client) { goto unblock; } - // Link busybox - mount_mirrors(); - link_busybox(); - // uninstaller if (access(UNINSTALLER, F_OK) == 0) { close(open(UNBLOCKFILE, O_RDONLY | O_CREAT)); bb_setenv(); - system("(BOOTMODE=true sh " UNINSTALLER ") &"); + setenv("BOOTMODE", "true", 1); + exec_command(0, NULL, NULL, "sh", UNINSTALLER, NULL); return; } @@ -704,11 +702,11 @@ core_only: if (access(MANAGERAPK, F_OK) == 0) { while (1) { sleep(5); - char *const command[] = { "app_process", - "/system/bin", "com.android.commands.pm.Pm", - "install", "-r", MANAGERAPK, NULL }; int apk_res = -1, pid; - pid = run_command2(1, &apk_res, pm_setenv, command); + pid = exec_command(1, &apk_res, pm_setenv, + "app_process", + "/system/bin", "com.android.commands.pm.Pm", + "install", "-r", MANAGERAPK, NULL); if (pid != -1) { waitpid(pid, NULL, 0); fdgets(buf, PATH_MAX, apk_res); diff --git a/jni/daemon/log_monitor.c b/jni/daemon/log_monitor.c index 832ed5622..bb5616e4c 100644 --- a/jni/daemon/log_monitor.c +++ b/jni/daemon/log_monitor.c @@ -26,13 +26,11 @@ static void *logger_thread(void *args) { while (1) { // Start logcat - char *const command[] = { "logcat", "-s", "Magisk", "-v", "thread", NULL }; - log_pid = run_command2(0, &log_fd, NULL, command); + log_pid = exec_command(0, &log_fd, NULL, "logcat", "-s", "Magisk", "-v", "thread", NULL); if (log_pid > 0) waitpid(log_pid, NULL, 0); // For some reason it went here, clear buffer and restart - char *const restart[] = { "logcat", "-c", NULL }; - run_command(restart); + exec_command_sync("logcat", "-c", NULL); } // Should never be here, but well... diff --git a/jni/include/utils.h b/jni/include/utils.h index 52ff6066c..97901dea4 100644 --- a/jni/include/utils.h +++ b/jni/include/utils.h @@ -75,21 +75,18 @@ unsigned get_radio_uid(); int check_data(); int file_to_vector(const char* filename, struct vector *v); int vector_to_file(const char* filename, struct vector *v); -int isNum(const char *s); ssize_t fdgets(char *buf, size_t size, int fd); void ps(void (*func)(int)); void ps_filter_proc_name(const char *filter, void (*func)(int)); int create_links(const char *bin, const char *path); void unlock_blocks(); void setup_sighandlers(void (*handler)(int)); -int run_command(char *const argv[]); -int run_command2(int err, int *fd, void (*cb)(void), char *const argv[]); +int exec_command(int err, int *fd, void (*cb)(void), const char *argv0, ...); +int exec_command_sync(char *const argv0, ...); int mkdir_p(const char *pathname, mode_t mode); int bind_mount(const char *from, const char *to); int open_new(const char *filename); int cp_afc(const char *source, const char *target); -int clone_dir(const char *source, const char *target); -void rm_rf(const char *target); void fclone_attr(const int sourcefd, const int targetfd); void clone_attr(const char *source, const char *target); void get_client_cred(int fd, struct ucred *cred); diff --git a/jni/include/vector.h b/jni/include/vector.h index 3d74902c2..1774c749c 100644 --- a/jni/include/vector.h +++ b/jni/include/vector.h @@ -32,4 +32,4 @@ struct vector *vec_dup(struct vector *v); e = v ? (v)->data[(v)->size - 1] : NULL; \ for (size_t _ = (v)->size; v && _ > 0; --_, e = (v)->data[_ - 1]) -#endif \ No newline at end of file +#endif diff --git a/jni/magiskhide/proc_monitor.c b/jni/magiskhide/proc_monitor.c index cf5a36bd4..ea335c664 100644 --- a/jni/magiskhide/proc_monitor.c +++ b/jni/magiskhide/proc_monitor.c @@ -181,13 +181,11 @@ void proc_monitor() { while (1) { // Clear previous logcat buffer - char *const restart[] = { "logcat", "-b", "events", "-c", NULL }; - run_command(restart); + exec_command_sync("logcat", "-b", "events", "-c", NULL); // Monitor am_proc_start - char *const command[] = { "logcat", "-b", "events", "-v", "raw", "-s", "am_proc_start", NULL }; log_fd = -1; - log_pid = run_command2(0, &log_fd, NULL, command); + log_pid = exec_command(0, &log_fd, NULL, "logcat", "-b", "events", "-v", "raw", "-s", "am_proc_start", NULL); if (log_pid < 0) continue; if (kill(log_pid, 0)) continue; diff --git a/jni/utils/img.c b/jni/utils/img.c index 2d0ae6490..b38f1187f 100644 --- a/jni/utils/img.c +++ b/jni/utils/img.c @@ -14,8 +14,7 @@ static int e2fsck(const char *img) { // Check and repair ext4 image char buffer[128]; int pid, fd = -1; - char *const command[] = { "e2fsck", "-yf", (char *) img, NULL }; - pid = run_command2(1, &fd, NULL, command); + pid = exec_command(1, &fd, NULL, "e2fsck", "-yf", img, NULL); if (pid < 0) return 1; while (fdgets(buffer, sizeof(buffer), fd)) @@ -56,19 +55,17 @@ int create_img(const char *img, int size) { char file_contexts[] = "/magisk(/.*)? u:object_r:system_file:s0\n"; // If not root, attempt to create in current diretory char *filename = getuid() == UID_ROOT ? "/dev/file_contexts_image" : "file_contexts_image"; - int pid, status, fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + int ret, fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); xwrite(fd, file_contexts, sizeof(file_contexts)); close(fd); char buffer[16]; snprintf(buffer, sizeof(buffer), "%dM", size); - char *const command[] = { "make_ext4fs", "-l", buffer, "-a", "/magisk", "-S", filename, (char *) img, NULL }; - pid = run_command2(0, NULL, NULL, command); - if (pid < 0) + ret = exec_command_sync("make_ext4fs", "-l", buffer, "-a", "/magisk", "-S", filename, img, NULL); + if (ret < 0) return 1; - waitpid(pid, &status, 0); unlink(filename); - return WEXITSTATUS(status); + return ret; } int get_img_size(const char *img, int *used, int *total) { @@ -76,8 +73,7 @@ int get_img_size(const char *img, int *used, int *total) { return 1; char buffer[PATH_MAX]; int pid, fd = -1, status = 1; - char *const command[] = { "e2fsck", "-n", (char *) img, NULL }; - pid = run_command2(1, &fd, NULL, command); + pid = exec_command(1, &fd, NULL, "e2fsck", "-n", img, NULL); if (pid < 0) return 1; while (fdgets(buffer, sizeof(buffer), fd)) { @@ -109,8 +105,7 @@ int resize_img(const char *img, int size) { char buffer[128]; int pid, status, fd = -1; snprintf(buffer, sizeof(buffer), "%dM", size); - char *const command[] = { "resize2fs", (char *) img, buffer, NULL }; - pid = run_command2(1, &fd, NULL, command); + pid = exec_command(1, &fd, NULL, "resize2fs", img, buffer, NULL); if (pid < 0) return 1; while (fdgets(buffer, sizeof(buffer), fd)) @@ -188,14 +183,14 @@ int merge_img(const char *source, const char *target) { snprintf(buffer, sizeof(buffer), "%s/%s", TARGET_TMP, entry->d_name); if (access(buffer, F_OK) == 0) { LOGI("Upgrade module: %s\n", entry->d_name); - rm_rf(buffer); + exec_command_sync(BBPATH "/rm", "-rf", buffer, NULL); } else { LOGI("New module: %s\n", entry->d_name); } } } closedir(dir); - clone_dir(SOURCE_TMP, TARGET_TMP); + cp_afc(SOURCE_TMP, TARGET_TMP); // Unmount all loop devices umount_image(SOURCE_TMP, s_loop); diff --git a/jni/utils/misc.c b/jni/utils/misc.c index 5f843094f..c0af9d58e 100644 --- a/jni/utils/misc.c +++ b/jni/utils/misc.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -97,7 +98,7 @@ int vector_to_file(const char *filename, struct vector *v) { } /* Check if the string only contains digits */ -int isNum(const char *s) { +static int is_num(const char *s) { int len = strlen(s); for (int i = 0; i < len; ++i) if (s[i] < '0' || s[i] > '9') @@ -129,7 +130,7 @@ void ps(void (*func)(int)) { while ((entry = xreaddir(dir))) { if (entry->d_type == DT_DIR) { - if (isNum(entry->d_name)) + if (is_num(entry->d_name)) func(atoi(entry->d_name)); } } @@ -219,22 +220,13 @@ void setup_sighandlers(void (*handler)(int)) { } } -int run_command(char *const argv[]) { - int pid = run_command2(0, NULL, NULL, argv); - if (pid != -1) - waitpid(pid, NULL, 0); - else - return 1; - return 0; -} - /* fd == NULL -> Ignore output *fd < 0 -> Open pipe and set *fd to the read end *fd >= 0 -> STDOUT (or STDERR) will be redirected to *fd *cb -> A callback function which runs after fork */ -int run_command2(int err, int *fd, void (*cb)(void), char *const argv[]) { +static int v_exec_command(int err, int *fd, void (*cb)(void), const char *argv0, va_list argv) { int pipefd[2], writeEnd = -1; if (fd) { @@ -257,6 +249,9 @@ int run_command2(int err, int *fd, void (*cb)(void), char *const argv[]) { return pid; } + // Don't affect the daemon if anything wrong happens + err_handler = do_nothing; + if (cb) cb(); if (fd) { @@ -264,11 +259,39 @@ int run_command2(int err, int *fd, void (*cb)(void), char *const argv[]) { if (err) xdup2(writeEnd, STDERR_FILENO); } - execvp(argv[0], argv); - PLOGE("execv"); + // Collect va_list into vector + struct vector v; + vec_init(&v); + vec_push_back(&v, (void *) argv0); + for (void *arg = va_arg(argv, void*); arg; arg = va_arg(argv, void*)) + vec_push_back(&v, arg); + vec_push_back(&v, NULL); + + execvp(argv0, (char **) vec_entry(&v)); + PLOGE("execvp"); return -1; } +int exec_command_sync(char *const argv0, ...) { + va_list argv; + va_start(argv, argv0); + int pid, status; + pid = v_exec_command(0, NULL, NULL, argv0, argv); + va_end(argv); + if (pid < 0) + return pid; + waitpid(pid, &status, 0); + return WEXITSTATUS(status); +} + +int exec_command(int err, int *fd, void (*cb)(void), const char *argv0, ...) { + va_list argv; + va_start(argv, argv0); + int pid = v_exec_command(err, fd, cb, argv0, argv); + va_end(argv); + return pid; +} + int mkdir_p(const char *pathname, mode_t mode) { char *path = strdup(pathname), *p; errno = 0; @@ -304,78 +327,57 @@ int open_new(const char *filename) { return xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); } -// file/link -> file/link only!! int cp_afc(const char *source, const char *target) { struct stat buf; xlstat(source, &buf); - unlink(target); - char *con; - if (S_ISREG(buf.st_mode)) { - int sfd, tfd; - sfd = xopen(source, O_RDONLY); - tfd = xopen(target, O_WRONLY | O_CREAT | O_TRUNC); - xsendfile(tfd, sfd, NULL, buf.st_size); - fclone_attr(sfd, tfd); - close(sfd); - close(tfd); - } else if (S_ISLNK(buf.st_mode)) { - char buffer[PATH_MAX]; - xreadlink(source, buffer, sizeof(buffer)); - xsymlink(buffer, target); - lchown(target, buf.st_uid, buf.st_gid); - lgetfilecon(source, &con); - lsetfilecon(target, con); - free(con); - } else { - return 1; - } - return 0; -} -int clone_dir(const char *source, const char *target) { - DIR *dir; - struct dirent *entry; - char *s_path, *t_path; + if (S_ISDIR(buf.st_mode)) { + DIR *dir; + struct dirent *entry; + char *s_path, *t_path; - if (!(dir = xopendir(source))) - return 1; + if (!(dir = xopendir(source))) + return 1; - s_path = xmalloc(PATH_MAX); - t_path = xmalloc(PATH_MAX); + s_path = xmalloc(PATH_MAX); + t_path = xmalloc(PATH_MAX); - mkdir_p(target, 0755); - clone_attr(source, target); + mkdir_p(target, 0755); + clone_attr(source, target); - while ((entry = xreaddir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - snprintf(s_path, PATH_MAX, "%s/%s", source, entry->d_name); - snprintf(t_path, PATH_MAX, "%s/%s", target, entry->d_name); - switch (entry->d_type) { - case DT_DIR: - clone_dir(s_path, t_path); - break; - case DT_REG: - case DT_LNK: + while ((entry = xreaddir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + snprintf(s_path, PATH_MAX, "%s/%s", source, entry->d_name); + snprintf(t_path, PATH_MAX, "%s/%s", target, entry->d_name); cp_afc(s_path, t_path); - break; + } + free(s_path); + free(t_path); + + closedir(dir); + } else{ + unlink(target); + if (S_ISREG(buf.st_mode)) { + int sfd, tfd; + sfd = xopen(source, O_RDONLY); + tfd = xopen(target, O_WRONLY | O_CREAT | O_TRUNC); + xsendfile(tfd, sfd, NULL, buf.st_size); + fclone_attr(sfd, tfd); + close(sfd); + close(tfd); + } else if (S_ISLNK(buf.st_mode)) { + char buffer[PATH_MAX]; + xreadlink(source, buffer, sizeof(buffer)); + xsymlink(buffer, target); + clone_attr(source, target); + } else { + return 1; } } - free(s_path); - free(t_path); - - closedir(dir); return 0; } -void rm_rf(const char *target) { - if (access(target, F_OK) == -1) - return; - // Use external rm command, saves a lot of headache and issues - char *const command[] = { "rm", "-rf", (char*) target, NULL }; - run_command(command); -} - void clone_attr(const char *source, const char *target) { int sourcefd, targetfd; sourcefd = xopen(source, O_RDONLY);