diff --git a/native/jni/core/log_monitor.c b/native/jni/core/log_monitor.c index 8d081192a..b6f1663ce 100644 --- a/native/jni/core/log_monitor.c +++ b/native/jni/core/log_monitor.c @@ -16,6 +16,7 @@ #include "daemon.h" int loggable = 1; +static struct vector log_cmd, clear_cmd; static int sockfd; static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; @@ -49,18 +50,6 @@ static struct log_listener events[] = { }; #define EVENT_NUM (sizeof(events) / sizeof(struct log_listener)) -static void test_logcat() { - int log_fd = -1, log_pid; - char buf[1]; - log_pid = exec_command(0, &log_fd, NULL, "logcat", NULL); - if (read(log_fd, buf, sizeof(buf)) != sizeof(buf)) { - loggable = 0; - LOGD("magisklogd: cannot read from logcat, disable logging"); - } - kill(log_pid, SIGTERM); - waitpid(log_pid, NULL, 0); -} - static void sigpipe_handler(int sig) { close(events[HIDE_EVENT].fd); events[HIDE_EVENT].fd = -1; @@ -93,12 +82,12 @@ static void *monitor_thread(void *args) { // Give the main daemon some time before we monitor it sleep(5); int fd; - char b[1]; + char b; do { fd = connect_daemon(); write_int(fd, MONITOR); // This should hold unless the daemon is killed - read(fd, b, sizeof(b)); + read(fd, &b, sizeof(b)); // The main daemon crashed, spawn a new one close(fd); } while (1); @@ -131,17 +120,27 @@ void log_daemon() { rename(LOGFILE, LOGFILE ".bak"); events[LOG_EVENT].fd = xopen(LOGFILE, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC | O_APPEND, 0644); + // Construct cmdline + vec_init(&log_cmd); + vec_push_back(&log_cmd, "/system/bin/logcat"); + // Test whether these buffers actually works + const char* b[] = { "main", "events", "crash" }; + for (int i = 0; i < 3; ++i) { + if (exec_command_sync("/system/bin/logcat", "-b", b[i], "-d", "-f", "/dev/null", NULL) == 0) + vec_push_back_all(&log_cmd, "-b", b[i], NULL); + } + vec_dup(&log_cmd, &clear_cmd); + vec_push_back_all(&log_cmd, "-v", "threadtime", "-s", "am_proc_start", "Magisk", "*:F", NULL); + vec_push_back(&log_cmd, NULL); + vec_push_back(&clear_cmd, "-c"); + vec_push_back(&clear_cmd, NULL); + int log_fd = -1, log_pid; char line[PIPE_BUF]; while (1) { // Start logcat - log_pid = exec_command(0, &log_fd, NULL, - "/system/bin/logcat", - "-b", "events", "-b", "main", "-b", "crash", - "-v", "threadtime", - "-s", "am_proc_start", "Magisk", "*:F", - NULL); + log_pid = exec_array(0, &log_fd, NULL, (char **) vec_entry(&log_cmd)); FILE *logs = fdopen(log_fd, "r"); while (fgets(line, sizeof(line), logs)) { if (line[0] == '-') @@ -162,13 +161,14 @@ void log_daemon() { LOGI("magisklogd: logcat output EOF"); // Clear buffer - exec_command_sync("logcat", "-b", "events", "-b", "main", "-b", "crash", "-c", NULL); + log_pid = exec_array(0, NULL, NULL, (char **) vec_entry(&clear_cmd)); + waitpid(log_pid, NULL, 0); } } /* Start new threads to monitor logcat and dump to logfile */ void monitor_logs() { - test_logcat(); + loggable = exec_command_sync("/system/bin/logcat", "-d", "-f", "/dev/null", NULL) == 0; if (loggable) { int fd; connect_daemon2(LOG_DAEMON, &fd); diff --git a/native/jni/include/utils.h b/native/jni/include/utils.h index c43242b15..0880a8bed 100644 --- a/native/jni/include/utils.h +++ b/native/jni/include/utils.h @@ -83,7 +83,8 @@ void ps(void (*func)(int)); void ps_filter_proc_name(const char *filter, void (*func)(int)); void unlock_blocks(); void setup_sighandlers(void (*handler)(int)); -int exec_command(int err, int *fd, void (*setupenv)(struct vector*), const char *argv0, ...); +int exec_array(int err, int *fd, void (*setenv)(struct vector *), char *const *argv); +int exec_command(int err, int *fd, void (*setenv)(struct vector*), const char *argv0, ...); int exec_command_sync(char *const argv0, ...); int bind_mount(const char *from, const char *to); void get_client_cred(int fd, struct ucred *cred); diff --git a/native/jni/include/vector.h b/native/jni/include/vector.h index 9984734af..8b1136e58 100644 --- a/native/jni/include/vector.h +++ b/native/jni/include/vector.h @@ -14,11 +14,12 @@ struct vector { void vec_init(struct vector *v); void vec_push_back(struct vector *v, void *p); +void vec_push_back_all(struct vector *v, void *p, ...); void *vec_pop_back(struct vector *v); void vec_sort(struct vector *v, int (*compar)(const void *, const void *)); void vec_destroy(struct vector *v); void vec_deep_destroy(struct vector *v); -struct vector *vec_dup(struct vector *v); +void vec_dup(struct vector *v, struct vector *vv); #define vec_size(v) (v)->size #define vec_cap(v) (v)->cap diff --git a/native/jni/utils/misc.c b/native/jni/utils/misc.c index c830bc84d..4b9efda92 100644 --- a/native/jni/utils/misc.c +++ b/native/jni/utils/misc.c @@ -245,9 +245,9 @@ void setup_sighandlers(void (*handler)(int)) { 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 + *setenv -> A callback function which sets up a vector of environment variables */ -static int v_exec_command(int err, int *fd, void (*setupenv)(struct vector*), const char *argv0, va_list argv) { +int exec_array(int err, int *fd, void (*setenv)(struct vector *), char *const *argv) { int pipefd[2], writeEnd = -1; if (fd) { @@ -260,20 +260,12 @@ static int v_exec_command(int err, int *fd, void (*setupenv)(struct vector*), co } } - // Collect va_list into vector - struct vector args; - vec_init(&args); - vec_push_back(&args, strdup(argv0)); - for (void *arg = va_arg(argv, void*); arg; arg = va_arg(argv, void*)) - vec_push_back(&args, strdup(arg)); - vec_push_back(&args, NULL); - // Setup environment char *const *envp; struct vector env; vec_init(&env); - if (setupenv) { - setupenv(&env); + if (setenv) { + setenv(&env); envp = (char **) vec_entry(&env); } else { extern char **environ; @@ -287,21 +279,34 @@ static int v_exec_command(int err, int *fd, void (*setupenv)(struct vector*), co *fd = pipefd[0]; close(pipefd[1]); } - vec_deep_destroy(&args); vec_deep_destroy(&env); return pid; } if (fd) { xdup2(writeEnd, STDOUT_FILENO); - if (err) xdup2(writeEnd, STDERR_FILENO); + if (err) + xdup2(writeEnd, STDERR_FILENO); } - execvpe(argv0, (char **) vec_entry(&args), envp); - PLOGE("execvpe %s", argv0); + execvpe(argv[0], argv, envp); + PLOGE("execvpe %s", argv[0]); return -1; } +static int v_exec_command(int err, int *fd, void (*setenv)(struct vector*), const char *argv0, va_list argv) { + // Collect va_list into vector + struct vector args; + vec_init(&args); + vec_push_back(&args, strdup(argv0)); + for (void *arg = va_arg(argv, void*); arg; arg = va_arg(argv, void*)) + vec_push_back(&args, strdup(arg)); + vec_push_back(&args, NULL); + int pid = exec_array(err, fd, setenv, (char **) vec_entry(&args)); + vec_deep_destroy(&args); + return pid; +} + int exec_command_sync(char *const argv0, ...) { va_list argv; va_start(argv, argv0); @@ -314,10 +319,10 @@ int exec_command_sync(char *const argv0, ...) { return WEXITSTATUS(status); } -int exec_command(int err, int *fd, void (*setupenv)(struct vector*), const char *argv0, ...) { +int exec_command(int err, int *fd, void (*setenv)(struct vector*), const char *argv0, ...) { va_list argv; va_start(argv, argv0); - int pid = v_exec_command(err, fd, setupenv, argv0, argv); + int pid = v_exec_command(err, fd, setenv, argv0, argv); va_end(argv); return pid; } diff --git a/native/jni/utils/vector.c b/native/jni/utils/vector.c index 4fcb28beb..70411a17f 100644 --- a/native/jni/utils/vector.c +++ b/native/jni/utils/vector.c @@ -3,6 +3,7 @@ #include #include +#include #include "vector.h" @@ -23,6 +24,15 @@ void vec_push_back(struct vector *v, void *p) { ++vec_size(v); } +void vec_push_back_all(struct vector *v, void *p, ...) { + va_list argv; + va_start(argv, p); + vec_push_back(v, p); + for (void *arg = va_arg(argv, char*); arg; arg = va_arg(argv, char*)) + vec_push_back(v, arg); + va_end(argv); +} + void *vec_pop_back(struct vector *v) { void *ret = vec_entry(v)[vec_size(v) - 1]; --vec_size(v); @@ -73,11 +83,9 @@ void vec_deep_destroy(struct vector *v) { vec_destroy(v); } -struct vector *vec_dup(struct vector *v) { - struct vector *ret = malloc(sizeof(*ret)); - vec_size(ret) = vec_size(v); - vec_cap(ret) = vec_cap(v); - vec_entry(v) = malloc(sizeof(void*) * vec_cap(ret)); - memcpy(vec_entry(ret), vec_entry(v), sizeof(void*) * vec_cap(ret)); - return ret; +void vec_dup(struct vector *v, struct vector *vv) { + vec_size(vv) = vec_size(v); + vec_cap(vv) = vec_cap(v); + vec_entry(vv) = malloc(sizeof(void*) * vec_cap(v)); + memcpy(vec_entry(vv), vec_entry(v), sizeof(void*) * vec_cap(v)); }