Integrate MagiskSU into Magisk daemon

This commit is contained in:
topjohnwu 2017-04-15 03:23:09 +08:00
parent 796c3009c7
commit 6ad993704c
12 changed files with 154 additions and 70 deletions

View File

@ -8,6 +8,7 @@ LOCAL_SHARED_LIBRARIES := libsqlite libselinux
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/utils \
$(LOCAL_PATH)/daemon \
$(LOCAL_PATH)/resetprop \
$(LOCAL_PATH)/selinux/libselinux/include \
$(LOCAL_PATH)/selinux/libsepol/include \
$(LOCAL_PATH)/sqlite3
@ -17,9 +18,9 @@ LOCAL_SRC_FILES := \
utils/misc.c \
utils/vector.c \
utils/xwrap.c \
utils/log_monitor.c \
daemon/daemon.c \
daemon/socket_trans.c \
daemon/log_monitor.c \
magiskhide/magiskhide.c \
magiskhide/hide_daemon.c \
magiskhide/proc_monitor.c \
@ -29,13 +30,14 @@ LOCAL_SRC_FILES := \
magiskpolicy/utils.c \
resetprop/resetprop.cpp \
resetprop/libc_logging.cpp \
resetprop/system_properties.cpp
# su/su.c \
# su/daemon.c \
# su/activity.c \
# su/db.c \
# su/utils.c \
# su/pts.c
resetprop/system_properties.cpp \
su/su.c \
su/activity.c \
su/db.c \
su/misc.c \
su/pts.c \
su/su_client.c \
su/su_socket.c
LOCAL_CFLAGS := -Wno-implicit-exception-spec-mismatch -DDEBUG
LOCAL_LDLIBS := -llog

View File

@ -36,23 +36,31 @@ static void request_handler(int client) {
// TODO: Remove hidelist
break;
case SUPERUSER:
// TODO: Run su
su_daemon_receiver(client);
break;
case CHECK_VERSION:
write_string(client, VERSION_STR);
close(client);
break;
case CHECK_VERSION_CODE:
write_int(client, VERSION_CODE);
close(client);
break;
case TEST:
s = read_string(client);
LOGI("%s\n", s);
free(s);
write_int(client, 0);
close(client);
break;
}
close(client);
}
/* Setup the address and return socket fd */
static int setup_socket(struct sockaddr_un *sun) {
int fd = xsocket(AF_LOCAL, SOCK_STREAM, 0);
if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
PLOGE("fcntl FD_CLOEXEC");
PLOGE("fcntl FD_CLOEXEC");
}
memset(sun, 0, sizeof(*sun));
@ -66,7 +74,7 @@ static void do_nothing() {}
void start_daemon() {
// Launch the daemon, create new session, set proper context
if (getuid() != AID_ROOT || getgid() != AID_ROOT) {
if (getuid() != UID_ROOT || getgid() != UID_ROOT) {
fprintf(stderr, "Starting daemon requires root: %s\n", strerror(errno));
PLOGE("start daemon");
}
@ -90,7 +98,7 @@ void start_daemon() {
// Change process name
strcpy(argv0, "magisk_daemon");
// The root daemon should not do anything if an error occurs
// It should stay intact in any circumstances
// It should stay intact under any circumstances
err_handler = do_nothing;
// Start log monitor

View File

@ -1,6 +1,9 @@
/* daemon.h - Utility functions for daemon-client communication
*/
#ifndef _DAEMON_H_
#define _DAEMON_H_
// Commands require connecting to daemon
typedef enum {
@ -9,6 +12,8 @@ typedef enum {
ADD_HIDELIST,
RM_HIDELIST,
SUPERUSER,
CHECK_VERSION,
CHECK_VERSION_CODE,
TEST
} client_request;
@ -25,3 +30,9 @@ int read_int(int fd);
void write_int(int fd, int val);
char* read_string(int fd);
void write_string(int fd, const char* val);
// log_monitor.c
void monitor_logs();
#endif

View File

@ -6,20 +6,23 @@
*/
#include <stdio.h>
#include <limits.h>
#include <pthread.h>
#include "magisk.h"
#include "utils.h"
#include "daemon.h"
static void *logger_thread(void *args) {
char buffer[PATH_MAX];
// rename("/cache/magisk.log", "/cache/last_magisk.log");
FILE *logfile = xfopen("/cache/magisk_test.log", "w");
// Disable buffering
setbuf(logfile, NULL);
// Start logcat
FILE *p = popen("logcat -s Magisk", "r");
while (fgets(magiskbuf, BUF_SIZE, p)) {
fprintf(logfile, "%s", magiskbuf);
while (fgets(buffer, sizeof(buffer), p)) {
fprintf(logfile, "%s", buffer);
}
return NULL;
}

View File

@ -1,23 +1,24 @@
/* magisk.h - Top header
*
* Contain global functions like logging,
* and entrypoint for main
*/
#ifndef _MAGISK_H_
#define _MAGISK_H_
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <android/log.h>
#define AID_SHELL (get_shell_uid())
#define AID_ROOT 0
#define AID_SYSTEM (get_system_uid())
#define AID_RADIO (get_radio_uid())
#define REQUESTOR_DAEMON_PATH "\0MAGISK"
#define VERSION_CODE 130
#define VERSION 13.0
#define VERSION_STR xstr(VERSION) ":MAGISK"
#define str(a) #a
#define xstr(a) str(a)
#define REQUESTOR_DAEMON_PATH "\0MAGISK"
#define REQUESTOR_DAEMON_PATH_LEN 7
#define LOG_TAG "Magisk"
@ -26,8 +27,11 @@
extern __thread void (*err_handler)(void);
// Two common error handlers
void exit_proc();
void exit_thread();
static inline void exit_proc() { exit(1); }
static inline void exit_thread() { pthread_exit(NULL); }
// Dummy function to depress debug message
static inline void stub(const char *fmt, ...) {}
#ifdef DEBUG
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
@ -38,20 +42,14 @@ void exit_thread();
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#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)); err_handler()
void stub(const char *fmt, ...);
// Global buffer (only for main thread!!)
#define BUF_SIZE 4096
extern char magiskbuf[BUF_SIZE];
#define PLOGE(fmt, args...) { LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno)); err_handler(); }
extern char *argv0; /* For changing process name */
// Multi-call entrypoints
int magiskhide_main(int argc, char *argv[]);
int magiskpolicy_main(int argc, char *argv[]);
// int su_main(int argc, char *argv[]);
int su_client_main(int argc, char *argv[]);
#ifdef __cplusplus
extern "C" {
@ -68,5 +66,11 @@ int resetprop_main(int argc, char *argv[]);
void launch_magiskhide(int client);
void stop_magiskhide(int client);
/*************
* Superuser *
*************/
void su_daemon_receiver(int client);
#endif

View File

@ -74,7 +74,7 @@ int hide_daemon() {
int fd;
FILE *fp;
char cache_block[256], *line;
char buffer[4096], cache_block[256], *line;
struct vector mount_list;
cache_block[0] = '\0';
@ -87,18 +87,18 @@ int hide_daemon() {
_exit(0);
}
snprintf(magiskbuf, BUF_SIZE, "/proc/%d/ns/mnt", pid);
if(access(magiskbuf, F_OK) == -1) continue; // Maybe process died..
snprintf(buffer, sizeof(buffer), "/proc/%d/ns/mnt", pid);
if(access(buffer, F_OK) == -1) continue; // Maybe process died..
fd = xopen(magiskbuf, O_RDONLY);
fd = xopen(buffer, O_RDONLY);
// Switch to its namespace
xsetns(fd, 0);
close(fd);
manage_selinux();
snprintf(magiskbuf, BUF_SIZE, "/proc/%d/mounts", pid);
fp = xfopen(magiskbuf, "r");
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
fp = xfopen(buffer, "r");
vec_init(&mount_list);
file_to_vector(&mount_list, fp);
@ -116,8 +116,8 @@ int hide_daemon() {
vec_for_each_r(&mount_list, line) {
if (strstr(line, "tmpfs /system") || strstr(line, "tmpfs /vendor") || strstr(line, "tmpfs /sbin")
|| (strstr(line, cache_block) && strstr(line, "/system/")) ) {
sscanf(line, "%*s %512s", magiskbuf);
lazy_unmount(magiskbuf);
sscanf(line, "%*s %512s", buffer);
lazy_unmount(buffer);
}
free(line);
}
@ -132,8 +132,8 @@ int hide_daemon() {
// Unmount loop mounts
vec_for_each_r(&mount_list, line) {
if (strstr(line, "/dev/block/loop") && !strstr(line, DUMMYPATH)) {
sscanf(line, "%*s %512s", magiskbuf);
lazy_unmount(magiskbuf);
sscanf(line, "%*s %512s", buffer);
lazy_unmount(buffer);
}
free(line);
}

View File

@ -83,9 +83,11 @@ void launch_magiskhide(int client) {
isEnabled = 1;
write_int(client, 0);
close(client);
return;
error:
write_int(client, 1);
close(client);
return;
}
@ -106,6 +108,7 @@ void stop_magiskhide(int client) {
isEnabled = 0;
write_int(client, 0);
close(client);
}
int magiskhide_main(int argc, char *argv[]) {
@ -123,8 +126,9 @@ int magiskhide_main(int argc, char *argv[]) {
req = RM_HIDELIST;
} else if (strcmp(argv[1], "--ls") == 0) {
FILE *fp = xfopen(HIDELIST, "r");
while (fgets(magiskbuf, BUF_SIZE, fp)) {
printf("%s", magiskbuf);
char buffer[512];
while (fgets(buffer, sizeof(buffer), fp)) {
printf("%s", buffer);
}
fclose(fp);
return 0;

View File

@ -1,30 +1,18 @@
/* main.c - The entry point, should be multi-call
/* main.c - The multicall entry point
*/
#include <stdlib.h>
#include <pthread.h>
#include "utils.h"
#include "magisk.h"
#include "daemon.h"
char magiskbuf[BUF_SIZE];
char *argv0;
void stub(const char *fmt, ...) {}
// Global error hander function
// Should be changed each thread/process
__thread void (*err_handler)(void);
void exit_proc() {
exit(-1);
}
void exit_thread() {
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
argv0 = argv[0];
// Exit the whole app if error occurs by default
@ -32,12 +20,28 @@ int main(int argc, char *argv[]) {
char * arg = strrchr(argv[0], '/');
if (arg) ++arg;
if (strcmp(arg, "magisk") == 0) {
if (strcmp(argv[1], "--post-fs") == 0) {
if (strcmp(argv[1], "-v") == 0) {
printf("Client: %s\n", VERSION_STR);
int fd = connect_daemon();
write_int(fd, CHECK_VERSION);
char *v = read_string(fd);
printf("Daemon: %s\n", v);
free(v);
return 0;
} else if (strcmp(argv[1], "-V") == 0) {
int fd = connect_daemon();
write_int(fd, CHECK_VERSION_CODE);
printf("%d\n", read_int(fd));
return 0;
} else if (strcmp(argv[1], "--post-fs") == 0) {
// TODO: post-fs mode
return 0;
} else if (strcmp(argv[1], "--post-fs-data") == 0) {
// TODO: post-fs-data mode
return 0;
} else if (strcmp(argv[1], "--service") == 0) {
// TODO: late_start service mode
return 0;
} else if (strcmp(argv[1], "--install") == 0) {
// TODO: Install symlinks
return 0;
@ -57,7 +61,7 @@ int main(int argc, char *argv[]) {
// Applets
if (strcmp(arg, "su") == 0) {
// return su_main(argc, argv);
return su_client_main(argc, argv);
} else if (strcmp(arg, "magiskpolicy") == 0) {
return magiskpolicy_main(argc, argv);
} else if (strcmp(arg, "resetprop") == 0) {
@ -68,4 +72,4 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "Applet \'%s\' not found\n", arg);
}
return 1;
}
}

2
jni/su

@ -1 +1 @@
Subproject commit 8770e8fb88a5688a1635ea384085b6d09b4242c6
Subproject commit c42c44a55254416fc2ccdb89395f42e8a580a67f

View File

@ -7,17 +7,42 @@
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
#include <pwd.h>
#include <sys/types.h>
#include "magisk.h"
#include "utils.h"
unsigned get_shell_uid() {
struct passwd* ppwd = getpwnam("shell");
if (NULL == ppwd)
return 2000;
return ppwd->pw_uid;
}
unsigned get_system_uid() {
struct passwd* ppwd = getpwnam("system");
if (NULL == ppwd)
return 1000;
return ppwd->pw_uid;
}
unsigned get_radio_uid() {
struct passwd* ppwd = getpwnam("radio");
if (NULL == ppwd)
return 1001;
return ppwd->pw_uid;
}
int check_data() {
char buffer[4096];
FILE *fp = xfopen("/proc/mounts", "r");
while (fgets(magiskbuf, BUF_SIZE, fp)) {
if (strstr(magiskbuf, " /data ")) {
if (strstr(magiskbuf, "tmpfs"))
while (fgets(buffer, sizeof(buffer), fp)) {
if (strstr(buffer, " /data ")) {
if (strstr(buffer, "tmpfs"))
return 0;
else
return 1;

View File

@ -9,9 +9,15 @@
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include "vector.h"
#define UID_SHELL (get_shell_uid())
#define UID_ROOT 0
#define UID_SYSTEM (get_system_uid())
#define UID_RADIO (get_radio_uid())
// xwrap.c
FILE *xfopen(const char *pathname, const char *mode);
@ -38,13 +44,14 @@ ssize_t xrecvmsg(int sockfd, struct msghdr *msg, int flags);
int xpthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
int xsocketpair(int domain, int type, int protocol, int sv[2]);
// log_monitor.c
void monitor_logs();
int xstat(const char *pathname, struct stat *buf);
int xdup2(int oldfd, int newfd);
// misc.c
unsigned get_shell_uid();
unsigned get_system_uid();
unsigned get_radio_uid();
int check_data();
void file_to_vector(struct vector *v, FILE *fp);
int isNum(const char *s);

View File

@ -210,4 +210,20 @@ int xsocketpair(int domain, int type, int protocol, int sv[2]) {
return ret;
}
int xstat(const char *pathname, struct stat *buf) {
int ret = stat(pathname, buf);
if (ret == -1) {
PLOGE("stat %s", pathname);
}
return ret;
}
int xdup2(int oldfd, int newfd) {
int ret = dup2(oldfd, newfd);
if (ret == -1) {
PLOGE("dup2");
}
return ret;
}