mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-12 21:27:41 +02:00
Separate logging into its own daemon
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
for (int i = 0; i < size; ++i) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user