Magisk/native/jni/daemon/log_daemon.cpp

210 lines
5.1 KiB
C++
Raw Normal View History

2018-07-06 01:57:18 +02:00
/* log_daemon.c - A dedicated daemon to monitor logcat
2017-04-04 21:44:13 +02:00
*
* A universal logcat monitor for many usages. Add listeners to the list,
2018-07-06 01:57:18 +02:00
* and the new log line will be sent through sockets to trigger
* asynchronous events without polling
2017-04-04 21:44:13 +02:00
*/
#include <stdio.h>
#include <pthread.h>
2017-05-07 21:11:14 +02:00
#include <unistd.h>
2018-09-27 09:11:10 +02:00
#include <string.h>
#include <stdlib.h>
2017-06-02 22:31:01 +02:00
#include <sys/wait.h>
2018-07-01 12:18:12 +02:00
#include <fcntl.h>
2017-04-04 21:44:13 +02:00
2017-04-06 00:12:29 +02:00
#include "magisk.h"
2017-04-04 21:44:13 +02:00
#include "utils.h"
2018-07-02 16:11:28 +02:00
#include "daemon.h"
2018-09-27 09:56:56 +02:00
#include "flags.h"
2018-11-04 23:23:08 +01:00
bool log_daemon_started = false;
static Vector<const char *> log_cmd, clear_cmd;
2018-07-02 16:11:28 +02:00
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
enum {
HIDE_EVENT,
2018-07-02 16:48:26 +02:00
LOG_EVENT
2018-07-02 16:11:28 +02:00
};
2018-11-04 23:23:08 +01:00
#define EVENT_NUM 2
2018-07-02 16:11:28 +02:00
struct log_listener {
int fd;
2018-11-04 23:23:08 +01:00
bool (*filter)(const char *);
2018-07-02 16:11:28 +02:00
};
2018-11-04 23:23:08 +01:00
static bool am_proc_start_filter(const char *log) {
2018-11-04 09:38:06 +01:00
return strstr(log, "am_proc_start") != nullptr;
}
2018-11-04 23:23:08 +01:00
static bool magisk_log_filter(const char *log) {
2018-07-02 16:48:26 +02:00
return !am_proc_start_filter(log);
}
2018-07-03 16:25:39 +02:00
static struct log_listener events[] = {
{ /* HIDE_EVENT */
.fd = -1,
.filter = am_proc_start_filter
},
{ /* LOG_EVENT */
.fd = -1,
.filter = magisk_log_filter
}
};
2017-04-04 21:44:13 +02:00
2018-11-04 09:38:06 +01:00
static void sigpipe_handler(int) {
2018-07-03 16:25:39 +02:00
close(events[HIDE_EVENT].fd);
events[HIDE_EVENT].fd = -1;
2018-07-02 16:11:28 +02:00
}
2018-11-04 09:38:06 +01:00
static void *monitor_thread(void *) {
// Block SIGPIPE to prevent interruption
sigset_t block_set;
sigemptyset(&block_set);
sigaddset(&block_set, SIGPIPE);
2018-11-04 09:38:06 +01:00
pthread_sigmask(SIG_SETMASK, &block_set, nullptr);
// Give the main daemon some time before we monitor it
sleep(5);
int fd;
char b;
while (1) {
fd = connect_daemon();
write_int(fd, HANDSHAKE);
// This should hold unless the daemon is killed
read(fd, &b, sizeof(b));
// The main daemon crashed, spawn a new one
close(fd);
}
}
2018-11-04 09:38:06 +01:00
static void *logcat_thread(void *) {
int log_fd = -1, log_pid;
char line[4096];
while (1) {
// Start logcat
2018-11-04 09:38:06 +01:00
log_pid = exec_array(0, &log_fd, nullptr, log_cmd.data());
FILE *logs = fdopen(log_fd, "r");
while (fgets(line, sizeof(line), logs)) {
if (line[0] == '-')
continue;
size_t len = strlen(line);
pthread_mutex_lock(&lock);
for (int i = 0; i < EVENT_NUM; ++i) {
if (events[i].fd > 0 && events[i].filter(line))
write(events[i].fd, line, len);
}
pthread_mutex_unlock(&lock);
}
fclose(logs);
log_fd = -1;
kill(log_pid, SIGTERM);
2018-11-04 09:38:06 +01:00
waitpid(log_pid, nullptr, 0);
LOGI("magisklogd: logcat output EOF");
// Clear buffer
2018-11-04 09:38:06 +01:00
log_pid = exec_array(0, nullptr, nullptr, clear_cmd.data());
waitpid(log_pid, nullptr, 0);
}
}
2018-10-12 06:50:47 +02:00
static void log_daemon() {
2018-07-02 16:11:28 +02:00
setsid();
LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") logger started\n");
2018-07-03 16:25:39 +02:00
strcpy(argv0, "magisklogd");
2018-07-02 16:11:28 +02:00
// Set SIGPIPE handler
2018-07-02 16:11:28 +02:00
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = sigpipe_handler;
2018-11-04 09:38:06 +01:00
sigaction(SIGPIPE, &act, nullptr);
2018-07-02 16:11:28 +02:00
// Setup log dumps
rename(LOGFILE, LOGFILE ".bak");
2018-07-04 17:46:40 +02:00
events[LOG_EVENT].fd = xopen(LOGFILE, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC | O_APPEND, 0644);
2018-07-02 16:11:28 +02:00
// Construct cmdline
2018-11-04 09:38:06 +01:00
log_cmd.push_back(MIRRDIR "/system/bin/logcat");
// Test whether these buffers actually works
2018-11-04 23:23:08 +01:00
const char *b[] = { "main", "events", "crash" };
for (int i = 0; i < 3; ++i) {
2018-11-04 09:38:06 +01:00
if (exec_command_sync(MIRRDIR "/system/bin/logcat", "-b", b[i], "-d", "-f", "/dev/null", nullptr) == 0) {
log_cmd.push_back("-b");
log_cmd.push_back(b[i]);
}
}
chmod("/dev/null", 0666);
2018-11-04 09:38:06 +01:00
clear_cmd = log_cmd;
log_cmd.push_back("-v");
log_cmd.push_back("threadtime");
log_cmd.push_back("-s");
log_cmd.push_back("am_proc_start");
log_cmd.push_back("Magisk");
2018-07-17 21:25:36 +02:00
#ifdef MAGISK_DEBUG
2018-11-04 09:38:06 +01:00
log_cmd.push_back("*:F");
2018-07-17 21:25:36 +02:00
#endif
2018-11-04 09:38:06 +01:00
log_cmd.push_back(nullptr);
clear_cmd.push_back("-c");
clear_cmd.push_back(nullptr);
// Start worker threads
pthread_t thread;
2018-11-04 09:38:06 +01:00
pthread_create(&thread, nullptr, monitor_thread, nullptr);
pthread_detach(thread);
2018-11-04 09:38:06 +01:00
xpthread_create(&thread, nullptr, logcat_thread, nullptr);
pthread_detach(thread);
2017-06-02 22:31:01 +02:00
// Handle socket requests
struct sockaddr_un sun;
socklen_t len = setup_sockaddr(&sun, LOG_SOCKET);
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (xbind(sockfd, (struct sockaddr*) &sun, len))
exit(1);
xlisten(sockfd, 10);
while(1) {
2018-11-04 09:38:06 +01:00
int fd = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC);
switch(read_int(fd)) {
case HIDE_CONNECT:
pthread_mutex_lock(&lock);
close(events[HIDE_EVENT].fd);
events[HIDE_EVENT].fd = fd;
pthread_mutex_unlock(&lock);
break;
case HANDSHAKE:
write_int(fd, HANDSHAKE);
default:
close(fd);
}
2018-02-11 19:48:15 +01:00
}
2017-04-17 10:36:49 +02:00
}
2018-10-12 06:50:47 +02:00
2018-11-04 23:23:08 +01:00
bool start_log_daemon() {
2018-10-12 06:50:47 +02:00
if (!log_daemon_started) {
2018-11-04 09:38:06 +01:00
if (exec_command_sync(MIRRDIR "/system/bin/logcat", "-d", "-f", "/dev/null", nullptr) == 0) {
2018-10-12 06:50:47 +02:00
if (fork_dont_care() == 0)
log_daemon();
2018-11-04 23:23:08 +01:00
log_daemon_started = true;
// Wait till we can connect to log_daemon and receive ack
2018-10-12 06:50:47 +02:00
int fd = connect_log_daemon();
write_int(fd, HANDSHAKE);
read_int(fd);
2018-10-12 06:50:47 +02:00
close(fd);
}
chmod("/dev/null", 0666);
}
return log_daemon_started;
}
int connect_log_daemon() {
if (!log_daemon_started)
return -1;
struct sockaddr_un sun;
socklen_t len = setup_sockaddr(&sun, LOG_SOCKET);
int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
while (connect(fd, (struct sockaddr*) &sun, len))
usleep(10000);
return fd;
}