Separate logging into its own daemon

This commit is contained in:
topjohnwu 2018-07-02 22:11:28 +08:00
parent 7243b9e72f
commit a8030c39b1
9 changed files with 153 additions and 81 deletions

View File

@ -84,6 +84,7 @@ static void *request_handler(void *args) {
late_start(client);
break;
default:
close(client);
break;
}
return NULL;
@ -105,14 +106,16 @@ void auto_start_magiskhide() {
free(hide_prop);
}
void start_daemon() {
void main_daemon() {
setsid();
setcon("u:r:"SEPOL_PROC_DOMAIN":s0");
int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
xdup2(fd, STDIN_FILENO);
xdup2(fd, STDOUT_FILENO);
xdup2(fd, STDERR_FILENO);
close(fd);
fd = xopen("/dev/zero", O_RDWR | O_CLOEXEC);
xdup2(fd, STDIN_FILENO);
close(fd);
// Block user signals
sigset_t block_set;
@ -121,16 +124,15 @@ void start_daemon() {
sigaddset(&block_set, SIGUSR2);
pthread_sigmask(SIG_SETMASK, &block_set, NULL);
// Start the log monitor
monitor_logs();
struct sockaddr_un sun;
fd = setup_socket(&sun);
fd = setup_socket(&sun, MAIN_DAEMON);
if (xbind(fd, (struct sockaddr*) &sun, sizeof(sun)))
exit(1);
xlisten(fd, 10);
// Start the log monitor
monitor_logs();
LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n");
// Change process name
@ -147,13 +149,11 @@ void start_daemon() {
}
}
/* Connect the daemon, and return a socketfd */
int connect_daemon() {
/* Connect the daemon, set sockfd, and return if new daemon is spawned */
int connect_daemon2(daemon_t d, int *sockfd) {
struct sockaddr_un sun;
int fd = setup_socket(&sun);
if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) {
// If we cannot access the daemon, we start a daemon in the child process if possible
*sockfd = setup_socket(&sun, d);
if (connect(*sockfd, (struct sockaddr*) &sun, sizeof(sun))) {
if (getuid() != UID_ROOT || getgid() != UID_ROOT) {
fprintf(stderr, "No daemon is currently running!\n");
exit(1);
@ -161,12 +161,26 @@ int connect_daemon() {
if (fork_dont_care() == 0) {
LOGD("client: connect fail, try launching new daemon process\n");
close(fd);
start_daemon();
close(*sockfd);
switch (d) {
case MAIN_DAEMON:
main_daemon();
break;
case LOG_DAEMON:
log_daemon();
break;
}
}
while (connect(fd, (struct sockaddr*) &sun, sizeof(sun)))
while (connect(*sockfd, (struct sockaddr*) &sun, sizeof(sun)))
usleep(10000);
return 1;
}
return 0;
}
int connect_daemon() {
int fd;
connect_daemon2(MAIN_DAEMON, &fd);
return fd;
}

View File

@ -13,9 +13,23 @@
#include "magisk.h"
#include "utils.h"
#include "resetprop.h"
#include "daemon.h"
int loggable = 1;
static int sockfd;
static pthread_t thread = -1;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
enum {
HIDE_EVENT,
LOG_EVENT,
DEBUG_EVENT
};
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;
@ -30,7 +44,7 @@ static int magisk_debug_log_filter(const char *log) {
return strstr(log, "am_proc_start") == NULL;
}
struct log_listener log_events[] = {
static struct log_listener log_events[] = {
{ /* HIDE_EVENT */
.fd = -1,
.filter = am_proc_start_filter
@ -58,12 +72,55 @@ static void test_logcat() {
waitpid(log_pid, NULL, 0);
}
static void *logger_thread(void *args) {
static void sigpipe_handler(int sig) {
close(log_events[HIDE_EVENT].fd);
log_events[HIDE_EVENT].fd = -1;
}
static void *socket_thread(void *args) {
/* This would block, so separate thread */
while(1) {
int fd = accept4(sockfd, NULL, NULL, SOCK_CLOEXEC);
switch(read_int(fd)) {
case HIDE_CONNECT:
pthread_mutex_lock(&lock);
log_events[HIDE_EVENT].fd = fd;
pthread_mutex_unlock(&lock);
thread = -1;
return NULL;
default:
close(fd);
break;
}
}
}
void log_daemon() {
setsid();
strcpy(argv0, "magisklogd");
struct sockaddr_un sun;
sockfd = setup_socket(&sun, LOG_DAEMON);
if (xbind(sockfd, (struct sockaddr*) &sun, sizeof(sun)))
exit(1);
xlisten(sockfd, 1);
LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") logger started\n");
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = sigpipe_handler;
sigaction(SIGPIPE, &act, NULL);
// Setup log dumps
rename(LOGFILE, LOGFILE ".bak");
log_events[LOG_EVENT].fd = xopen(LOGFILE, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0644);
#ifdef MAGISK_DEBUG
log_events[DEBUG_EVENT].fd = xopen(DEBUG_LOG, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0644);
#endif
int log_fd = -1, log_pid;
char line[PIPE_BUF];
LOGD("log_monitor: logger start");
while (1) {
if (!loggable) {
// Disable all services
@ -71,7 +128,7 @@ static void *logger_thread(void *args) {
close(log_events[i].fd);
log_events[i].fd = -1;
}
return NULL;
return;
}
// Start logcat
@ -86,10 +143,17 @@ static void *logger_thread(void *args) {
if (line[0] == '-')
continue;
size_t len = strlen(line);
pthread_mutex_lock(&lock);
for (int i = 0; i < EVENT_NUM; ++i) {
if (log_events[i].fd > 0 && log_events[i].filter(line))
xwrite(log_events[i].fd, line, len);
write(log_events[i].fd, line, len);
}
if (thread < 0 && log_events[HIDE_EVENT].fd < 0) {
// New thread to handle connection to main daemon
xpthread_create(&thread, NULL, socket_thread, NULL);
pthread_detach(thread);
}
pthread_mutex_unlock(&lock);
if (kill(log_pid, 0))
break;
}
@ -101,26 +165,15 @@ static void *logger_thread(void *args) {
waitpid(log_pid, NULL, 0);
test_logcat();
}
// Should never be here, but well...
return NULL;
}
/* Start new threads to monitor logcat and dump to logfile */
void monitor_logs() {
pthread_t thread;
test_logcat();
if (loggable) {
rename(LOGFILE, LOGFILE ".bak");
log_events[LOG_EVENT].fd = creat(LOGFILE, 0644);
#ifdef MAGISK_DEBUG
log_events[DEBUG_EVENT].fd = creat(DEBUG_LOG, 0644);
#endif
// Start logcat monitor
xpthread_create(&thread, NULL, logger_thread, NULL);
pthread_detach(thread);
int fd;
connect_daemon2(LOG_DAEMON, &fd);
write_int(fd, DO_NOTHING);
close(fd);
}
}

View File

@ -98,7 +98,7 @@ int magisk_main(int argc, char *argv[]) {
return 0;
} else if (strcmp(argv[1], "--daemon") == 0) {
int fd = connect_daemon();
close(fd);
write_int(fd, DO_NOTHING);
return 0;
} else if (strcmp(argv[1], "--startup") == 0) {
startup();

View File

@ -57,8 +57,6 @@
extern policydb_t *policydb;
int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_main, NULL };
static char RAND_SOCKET_NAME[sizeof(SOCKET_NAME)];
static int SOCKET_OFF = -1;
struct cmdline {
char skip_initramfs;
@ -345,18 +343,21 @@ static int dump_magiskrc(const char *path, mode_t mode) {
static void patch_socket_name(const char *path) {
void *buf;
char name[sizeof(MAIN_SOCKET)];
size_t size;
mmap_rw(path, &buf, &size);
if (SOCKET_OFF < 0) {
for (int i = 0; i < size; ++i) {
if (memcmp(buf + i, SOCKET_NAME, sizeof(SOCKET_NAME)) == 0) {
SOCKET_OFF = i;
break;
if (memcmp(buf + i, MAIN_SOCKET, sizeof(MAIN_SOCKET)) == 0) {
gen_rand_str(name, sizeof(name));
memcpy(buf + i, name, sizeof(name));
i += sizeof(name);
}
if (memcmp(buf + i, LOG_SOCKET, sizeof(LOG_SOCKET)) == 0) {
gen_rand_str(name, sizeof(name));
memcpy(buf + i, name, sizeof(name));
i += sizeof(name);
}
}
}
gen_rand_str(RAND_SOCKET_NAME, sizeof(SOCKET_NAME));
memcpy(buf + SOCKET_OFF, RAND_SOCKET_NAME, sizeof(SOCKET_NAME));
munmap(buf, size);
}

View File

@ -8,19 +8,25 @@
#include "utils.h"
#include "magisk.h"
static char socket_name[] = SOCKET_NAME; /* Workaround compiler bug pre NDK r13 */
/* Setup the address and return socket fd */
int setup_socket(struct sockaddr_un *sun) {
int setup_socket(struct sockaddr_un *sun, daemon_t d) {
int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
memset(sun, 0, sizeof(*sun));
sun->sun_family = AF_LOCAL;
sun->sun_path[0] = '\0';
memcpy(sun->sun_path + 1, socket_name, sizeof(SOCKET_NAME));
const char *name;
switch (d) {
case MAIN_DAEMON:
name = MAIN_SOCKET;
break;
case LOG_DAEMON:
name = LOG_SOCKET;
break;
}
strcpy(sun->sun_path + 1, name);
return fd;
}
/*
* Receive a file descriptor from a Unix socket.
* Contributed by @mkasick

View File

@ -24,7 +24,8 @@ enum {
STOP_MAGISKHIDE,
ADD_HIDELIST,
RM_HIDELIST,
LS_HIDELIST
LS_HIDELIST,
HIDE_CONNECT
};
// Return codes for daemon
@ -39,15 +40,25 @@ enum {
HIDE_ITEM_NOT_EXIST,
};
typedef enum {
MAIN_DAEMON,
LOG_DAEMON
} daemon_t;
// daemon.c
void start_daemon();
void main_daemon();
int connect_daemon();
int connect_daemon2(daemon_t d, int *sockfd);
void auto_start_magiskhide();
// log_monitor.c
void log_daemon();
// socket.c
int setup_socket(struct sockaddr_un *sun);
int setup_socket(struct sockaddr_un *sun, daemon_t d);
int recv_fd(int sockfd);
void send_fd(int sockfd, int fd);
int read_int(int fd);

View File

@ -46,18 +46,6 @@
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
enum {
HIDE_EVENT,
LOG_EVENT,
DEBUG_EVENT
};
struct log_listener {
int fd;
int (*filter) (const char*);
};
extern struct log_listener log_events[];
extern int loggable;
void monitor_logs();

View File

@ -7,7 +7,8 @@
#include "logging.h"
#define MAGISK_VER_STR xstr(MAGISK_VERSION) ":MAGISK"
#define SOCKET_NAME "d30138f2310a9fb9c54a3e0c21f58591"
#define MAIN_SOCKET "d30138f2310a9fb9c54a3e0c21f58591"
#define LOG_SOCKET "5864cd77f2f8c59b3882e2d35dbf51e4"
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
#ifndef ARG_MAX

View File

@ -16,21 +16,19 @@
#include <sys/mount.h>
#include "magisk.h"
#include "daemon.h"
#include "utils.h"
#include "magiskhide.h"
static int pipefd[2] = { -1, -1 };
static int sockfd = -1;
// Workaround for the lack of pthread_cancel
static void term_thread(int sig) {
LOGD("proc_monitor: running cleanup\n");
destroy_list();
hideEnabled = 0;
// Unregister listener
log_events[HIDE_EVENT].fd = -1;
close(pipefd[0]);
close(pipefd[1]);
pipefd[0] = pipefd[1] = -1;
close(sockfd);
sockfd = -1;
pthread_mutex_destroy(&hide_lock);
pthread_mutex_destroy(&file_lock);
LOGD("proc_monitor: terminating...\n");
@ -128,12 +126,12 @@ void proc_monitor() {
term_thread(TERM_THREAD);
}
// Register our listener to logcat monitor
xpipe2(pipefd, O_CLOEXEC);
log_events[HIDE_EVENT].fd = pipefd[1];
// Connect to the log daemon
connect_daemon2(LOG_DAEMON, &sockfd);
write_int(sockfd, HIDE_CONNECT);
FILE *logs = fdopen(pipefd[0], "r");
char log[PIPE_BUF], *line;
FILE *logs = fdopen(sockfd, "r");
char log[4096], *line;
while (1) {
/* It might be interrupted */
if (fgets(log, sizeof(log), logs) == NULL)