Magisk/native/jni/core/log_monitor.c

179 lines
4.1 KiB
C
Raw Normal View History

2017-04-04 19:44:13 +00:00
/* log_monitor.c - New thread to monitor logcat
*
* A universal logcat monitor for many usages. Add listeners to the list,
* and the pointer of the new log line will be sent through pipes to trigger
* asynchronous events without polling
2017-04-04 19:44:13 +00:00
*/
#include <stdio.h>
#include <pthread.h>
2017-05-07 19:11:14 +00:00
#include <unistd.h>
2017-06-02 20:31:01 +00:00
#include <sys/wait.h>
2018-07-01 10:18:12 +00:00
#include <fcntl.h>
2017-04-04 19:44:13 +00:00
2017-04-05 22:12:29 +00:00
#include "magisk.h"
2017-04-04 19:44:13 +00:00
#include "utils.h"
2018-07-02 14:11:28 +00:00
#include "daemon.h"
2018-04-07 18:12:40 +00:00
int loggable = 1;
2018-07-02 14:11:28 +00:00
static int sockfd;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
enum {
HIDE_EVENT,
2018-07-02 14:48:26 +00:00
LOG_EVENT
2018-07-02 14:11:28 +00:00
};
struct log_listener {
int fd;
int (*filter) (const char*);
};
static int am_proc_start_filter(const char *log) {
return strstr(log, "am_proc_start") != NULL;
}
static int magisk_log_filter(const char *log) {
2018-07-02 14:48:26 +00:00
return !am_proc_start_filter(log);
}
2018-07-03 14:25:39 +00:00
static struct log_listener events[] = {
{ /* HIDE_EVENT */
.fd = -1,
.filter = am_proc_start_filter
},
{ /* LOG_EVENT */
.fd = -1,
.filter = magisk_log_filter
}
};
2018-07-03 14:25:39 +00:00
#define EVENT_NUM (sizeof(events) / sizeof(struct log_listener))
2017-04-04 19:44:13 +00:00
2018-04-07 18:12:40 +00:00
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;
2018-07-03 14:25:39 +00:00
LOGD("magisklogd: cannot read from logcat, disable logging");
2018-02-11 18:48:15 +00:00
}
2018-04-07 18:12:40 +00:00
kill(log_pid, SIGTERM);
waitpid(log_pid, NULL, 0);
2018-02-11 18:48:15 +00:00
}
2018-07-02 14:11:28 +00:00
static void sigpipe_handler(int sig) {
2018-07-03 14:25:39 +00:00
close(events[HIDE_EVENT].fd);
events[HIDE_EVENT].fd = -1;
2018-07-02 14:11:28 +00:00
}
static void *socket_thread(void *args) {
/* This would block, so separate thread */
while(1) {
2018-07-03 14:25:39 +00:00
int fd = xaccept4(sockfd, NULL, NULL, SOCK_CLOEXEC);
2018-07-02 14:11:28 +00:00
switch(read_int(fd)) {
case HIDE_CONNECT:
pthread_mutex_lock(&lock);
2018-07-03 14:25:39 +00:00
close(events[HIDE_EVENT].fd);
events[HIDE_EVENT].fd = fd;
2018-07-02 14:11:28 +00:00
pthread_mutex_unlock(&lock);
2018-07-03 14:25:39 +00:00
break;
2018-07-02 14:11:28 +00:00
default:
close(fd);
break;
}
}
}
static void *monitor_thread(void *args) {
// Block SIGPIPE to prevent interruption
sigset_t block_set;
sigemptyset(&block_set);
sigaddset(&block_set, SIGPIPE);
pthread_sigmask(SIG_SETMASK, &block_set, NULL);
// Give the main daemon some time before we monitor it
sleep(5);
int fd;
char b[1];
do {
fd = connect_daemon();
write_int(fd, MONITOR);
// This should hold unless the daemon is killed
read(fd, b, sizeof(b));
// The main daemon crashed, spawn a new one
close(fd);
} while (1);
}
2018-07-02 14:11:28 +00:00
void log_daemon() {
setsid();
struct sockaddr_un sun;
sockfd = setup_socket(&sun, LOG_DAEMON);
if (xbind(sockfd, (struct sockaddr*) &sun, sizeof(sun)))
exit(1);
2018-07-03 14:25:39 +00:00
xlisten(sockfd, 10);
2018-07-02 14:11:28 +00:00
LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") logger started\n");
2018-07-03 14:25:39 +00:00
strcpy(argv0, "magisklogd");
2018-07-02 14:11:28 +00:00
2018-07-03 14:25:39 +00:00
// Start worker threads
pthread_t t;
pthread_create(&t, NULL, monitor_thread, NULL);
pthread_detach(t);
2018-07-03 14:25:39 +00:00
xpthread_create(&t, NULL, socket_thread, NULL);
pthread_detach(t);
// Set SIGPIPE handler
2018-07-02 14:11:28 +00:00
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = sigpipe_handler;
sigaction(SIGPIPE, &act, NULL);
// Setup log dumps
rename(LOGFILE, LOGFILE ".bak");
2018-07-03 14:25:39 +00:00
events[LOG_EVENT].fd = xopen(LOGFILE, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0644);
2018-07-02 14:11:28 +00:00
int log_fd = -1, log_pid;
2018-07-01 10:18:12 +00:00
char line[PIPE_BUF];
2017-06-02 20:31:01 +00:00
while (1) {
// Start logcat
2018-07-01 10:18:12 +00:00
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);
FILE *logs = fdopen(log_fd, "r");
while (fgets(line, sizeof(line), logs)) {
if (line[0] == '-')
continue;
size_t len = strlen(line);
2018-07-02 14:11:28 +00:00
pthread_mutex_lock(&lock);
2018-07-01 10:18:12 +00:00
for (int i = 0; i < EVENT_NUM; ++i) {
2018-07-03 14:25:39 +00:00
if (events[i].fd > 0 && events[i].filter(line))
write(events[i].fd, line, len);
2018-07-02 14:11:28 +00:00
}
pthread_mutex_unlock(&lock);
}
2018-07-01 10:18:12 +00:00
fclose(logs);
log_fd = -1;
kill(log_pid, SIGTERM);
waitpid(log_pid, NULL, 0);
2018-07-03 14:25:39 +00:00
LOGI("magisklogd: logcat output EOF");
// Clear buffer
exec_command_sync("logcat", "-b", "events", "-b", "main", "-b", "crash", "-c", NULL);
2017-04-04 19:44:13 +00:00
}
}
/* Start new threads to monitor logcat and dump to logfile */
2017-04-04 19:44:13 +00:00
void monitor_logs() {
2018-04-07 18:12:40 +00:00
test_logcat();
if (loggable) {
2018-07-02 14:11:28 +00:00
int fd;
connect_daemon2(LOG_DAEMON, &fd);
write_int(fd, DO_NOTHING);
close(fd);
2018-02-11 18:48:15 +00:00
}
2017-04-17 08:36:49 +00:00
}