Test the log buffers before running command

This commit is contained in:
topjohnwu 2018-07-06 07:32:16 +08:00
parent c3a6179a21
commit 5d5ec08566
5 changed files with 64 additions and 49 deletions

View File

@ -16,6 +16,7 @@
#include "daemon.h" #include "daemon.h"
int loggable = 1; int loggable = 1;
static struct vector log_cmd, clear_cmd;
static int sockfd; static int sockfd;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 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)) #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) { static void sigpipe_handler(int sig) {
close(events[HIDE_EVENT].fd); close(events[HIDE_EVENT].fd);
events[HIDE_EVENT].fd = -1; 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 // Give the main daemon some time before we monitor it
sleep(5); sleep(5);
int fd; int fd;
char b[1]; char b;
do { do {
fd = connect_daemon(); fd = connect_daemon();
write_int(fd, MONITOR); write_int(fd, MONITOR);
// This should hold unless the daemon is killed // 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 // The main daemon crashed, spawn a new one
close(fd); close(fd);
} while (1); } while (1);
@ -131,17 +120,27 @@ void log_daemon() {
rename(LOGFILE, LOGFILE ".bak"); rename(LOGFILE, LOGFILE ".bak");
events[LOG_EVENT].fd = xopen(LOGFILE, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC | O_APPEND, 0644); 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; int log_fd = -1, log_pid;
char line[PIPE_BUF]; char line[PIPE_BUF];
while (1) { while (1) {
// Start logcat // Start logcat
log_pid = exec_command(0, &log_fd, NULL, log_pid = exec_array(0, &log_fd, NULL, (char **) vec_entry(&log_cmd));
"/system/bin/logcat",
"-b", "events", "-b", "main", "-b", "crash",
"-v", "threadtime",
"-s", "am_proc_start", "Magisk", "*:F",
NULL);
FILE *logs = fdopen(log_fd, "r"); FILE *logs = fdopen(log_fd, "r");
while (fgets(line, sizeof(line), logs)) { while (fgets(line, sizeof(line), logs)) {
if (line[0] == '-') if (line[0] == '-')
@ -162,13 +161,14 @@ void log_daemon() {
LOGI("magisklogd: logcat output EOF"); LOGI("magisklogd: logcat output EOF");
// Clear buffer // 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 */ /* Start new threads to monitor logcat and dump to logfile */
void monitor_logs() { void monitor_logs() {
test_logcat(); loggable = exec_command_sync("/system/bin/logcat", "-d", "-f", "/dev/null", NULL) == 0;
if (loggable) { if (loggable) {
int fd; int fd;
connect_daemon2(LOG_DAEMON, &fd); connect_daemon2(LOG_DAEMON, &fd);

View File

@ -83,7 +83,8 @@ void ps(void (*func)(int));
void ps_filter_proc_name(const char *filter, void (*func)(int)); void ps_filter_proc_name(const char *filter, void (*func)(int));
void unlock_blocks(); void unlock_blocks();
void setup_sighandlers(void (*handler)(int)); 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 exec_command_sync(char *const argv0, ...);
int bind_mount(const char *from, const char *to); int bind_mount(const char *from, const char *to);
void get_client_cred(int fd, struct ucred *cred); void get_client_cred(int fd, struct ucred *cred);

View File

@ -14,11 +14,12 @@ struct vector {
void vec_init(struct vector *v); void vec_init(struct vector *v);
void vec_push_back(struct vector *v, void *p); 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_pop_back(struct vector *v);
void vec_sort(struct vector *v, int (*compar)(const void *, const void *)); void vec_sort(struct vector *v, int (*compar)(const void *, const void *));
void vec_destroy(struct vector *v); void vec_destroy(struct vector *v);
void vec_deep_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_size(v) (v)->size
#define vec_cap(v) (v)->cap #define vec_cap(v) (v)->cap

View File

@ -245,9 +245,9 @@ void setup_sighandlers(void (*handler)(int)) {
fd == NULL -> Ignore output fd == NULL -> Ignore output
*fd < 0 -> Open pipe and set *fd to the read end *fd < 0 -> Open pipe and set *fd to the read end
*fd >= 0 -> STDOUT (or STDERR) will be redirected to *fd *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; int pipefd[2], writeEnd = -1;
if (fd) { 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 // Setup environment
char *const *envp; char *const *envp;
struct vector env; struct vector env;
vec_init(&env); vec_init(&env);
if (setupenv) { if (setenv) {
setupenv(&env); setenv(&env);
envp = (char **) vec_entry(&env); envp = (char **) vec_entry(&env);
} else { } else {
extern char **environ; extern char **environ;
@ -287,21 +279,34 @@ static int v_exec_command(int err, int *fd, void (*setupenv)(struct vector*), co
*fd = pipefd[0]; *fd = pipefd[0];
close(pipefd[1]); close(pipefd[1]);
} }
vec_deep_destroy(&args);
vec_deep_destroy(&env); vec_deep_destroy(&env);
return pid; return pid;
} }
if (fd) { if (fd) {
xdup2(writeEnd, STDOUT_FILENO); xdup2(writeEnd, STDOUT_FILENO);
if (err) xdup2(writeEnd, STDERR_FILENO); if (err)
xdup2(writeEnd, STDERR_FILENO);
} }
execvpe(argv0, (char **) vec_entry(&args), envp); execvpe(argv[0], argv, envp);
PLOGE("execvpe %s", argv0); PLOGE("execvpe %s", argv[0]);
return -1; 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, ...) { int exec_command_sync(char *const argv0, ...) {
va_list argv; va_list argv;
va_start(argv, argv0); va_start(argv, argv0);
@ -314,10 +319,10 @@ int exec_command_sync(char *const argv0, ...) {
return WEXITSTATUS(status); 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_list argv;
va_start(argv, argv0); 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); va_end(argv);
return pid; return pid;
} }

View File

@ -3,6 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdarg.h>
#include "vector.h" #include "vector.h"
@ -23,6 +24,15 @@ void vec_push_back(struct vector *v, void *p) {
++vec_size(v); ++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 *vec_pop_back(struct vector *v) {
void *ret = vec_entry(v)[vec_size(v) - 1]; void *ret = vec_entry(v)[vec_size(v) - 1];
--vec_size(v); --vec_size(v);
@ -73,11 +83,9 @@ void vec_deep_destroy(struct vector *v) {
vec_destroy(v); vec_destroy(v);
} }
struct vector *vec_dup(struct vector *v) { void vec_dup(struct vector *v, struct vector *vv) {
struct vector *ret = malloc(sizeof(*ret)); vec_size(vv) = vec_size(v);
vec_size(ret) = vec_size(v); vec_cap(vv) = vec_cap(v);
vec_cap(ret) = vec_cap(v); vec_entry(vv) = malloc(sizeof(void*) * vec_cap(v));
vec_entry(v) = malloc(sizeof(void*) * vec_cap(ret)); memcpy(vec_entry(vv), vec_entry(v), sizeof(void*) * vec_cap(v));
memcpy(vec_entry(ret), vec_entry(v), sizeof(void*) * vec_cap(ret));
return ret;
} }