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

View File

@ -36,16 +36,24 @@ static void request_handler(int client) {
// TODO: Remove hidelist // TODO: Remove hidelist
break; break;
case SUPERUSER: 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; break;
case TEST: case TEST:
s = read_string(client); s = read_string(client);
LOGI("%s\n", s); LOGI("%s\n", s);
free(s); free(s);
write_int(client, 0); write_int(client, 0);
close(client);
break; break;
} }
close(client);
} }
/* Setup the address and return socket fd */ /* Setup the address and return socket fd */
@ -66,7 +74,7 @@ static void do_nothing() {}
void start_daemon() { void start_daemon() {
// Launch the daemon, create new session, set proper context // 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)); fprintf(stderr, "Starting daemon requires root: %s\n", strerror(errno));
PLOGE("start daemon"); PLOGE("start daemon");
} }
@ -90,7 +98,7 @@ void start_daemon() {
// Change process name // Change process name
strcpy(argv0, "magisk_daemon"); strcpy(argv0, "magisk_daemon");
// The root daemon should not do anything if an error occurs // 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; err_handler = do_nothing;
// Start log monitor // Start log monitor

View File

@ -1,6 +1,9 @@
/* daemon.h - Utility functions for daemon-client communication /* daemon.h - Utility functions for daemon-client communication
*/ */
#ifndef _DAEMON_H_
#define _DAEMON_H_
// Commands require connecting to daemon // Commands require connecting to daemon
typedef enum { typedef enum {
@ -9,6 +12,8 @@ typedef enum {
ADD_HIDELIST, ADD_HIDELIST,
RM_HIDELIST, RM_HIDELIST,
SUPERUSER, SUPERUSER,
CHECK_VERSION,
CHECK_VERSION_CODE,
TEST TEST
} client_request; } client_request;
@ -25,3 +30,9 @@ int read_int(int fd);
void write_int(int fd, int val); void write_int(int fd, int val);
char* read_string(int fd); char* read_string(int fd);
void write_string(int fd, const char* val); 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 <stdio.h>
#include <limits.h>
#include <pthread.h> #include <pthread.h>
#include "magisk.h" #include "magisk.h"
#include "utils.h" #include "utils.h"
#include "daemon.h"
static void *logger_thread(void *args) { static void *logger_thread(void *args) {
char buffer[PATH_MAX];
// rename("/cache/magisk.log", "/cache/last_magisk.log"); // rename("/cache/magisk.log", "/cache/last_magisk.log");
FILE *logfile = xfopen("/cache/magisk_test.log", "w"); FILE *logfile = xfopen("/cache/magisk_test.log", "w");
// Disable buffering // Disable buffering
setbuf(logfile, NULL); setbuf(logfile, NULL);
// Start logcat // Start logcat
FILE *p = popen("logcat -s Magisk", "r"); FILE *p = popen("logcat -s Magisk", "r");
while (fgets(magiskbuf, BUF_SIZE, p)) { while (fgets(buffer, sizeof(buffer), p)) {
fprintf(logfile, "%s", magiskbuf); fprintf(logfile, "%s", buffer);
} }
return NULL; return NULL;
} }

View File

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

View File

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

View File

@ -83,9 +83,11 @@ void launch_magiskhide(int client) {
isEnabled = 1; isEnabled = 1;
write_int(client, 0); write_int(client, 0);
close(client);
return; return;
error: error:
write_int(client, 1); write_int(client, 1);
close(client);
return; return;
} }
@ -106,6 +108,7 @@ void stop_magiskhide(int client) {
isEnabled = 0; isEnabled = 0;
write_int(client, 0); write_int(client, 0);
close(client);
} }
int magiskhide_main(int argc, char *argv[]) { int magiskhide_main(int argc, char *argv[]) {
@ -123,8 +126,9 @@ int magiskhide_main(int argc, char *argv[]) {
req = RM_HIDELIST; req = RM_HIDELIST;
} else if (strcmp(argv[1], "--ls") == 0) { } else if (strcmp(argv[1], "--ls") == 0) {
FILE *fp = xfopen(HIDELIST, "r"); FILE *fp = xfopen(HIDELIST, "r");
while (fgets(magiskbuf, BUF_SIZE, fp)) { char buffer[512];
printf("%s", magiskbuf); while (fgets(buffer, sizeof(buffer), fp)) {
printf("%s", buffer);
} }
fclose(fp); fclose(fp);
return 0; 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 <stdlib.h>
#include <pthread.h>
#include "utils.h" #include "utils.h"
#include "magisk.h" #include "magisk.h"
#include "daemon.h" #include "daemon.h"
char magiskbuf[BUF_SIZE];
char *argv0; char *argv0;
void stub(const char *fmt, ...) {}
// Global error hander function // Global error hander function
// Should be changed each thread/process // Should be changed each thread/process
__thread void (*err_handler)(void); __thread void (*err_handler)(void);
void exit_proc() {
exit(-1);
}
void exit_thread() {
pthread_exit(NULL);
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
argv0 = argv[0]; argv0 = argv[0];
// Exit the whole app if error occurs by default // Exit the whole app if error occurs by default
@ -32,12 +20,28 @@ int main(int argc, char *argv[]) {
char * arg = strrchr(argv[0], '/'); char * arg = strrchr(argv[0], '/');
if (arg) ++arg; if (arg) ++arg;
if (strcmp(arg, "magisk") == 0) { 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 // TODO: post-fs mode
return 0; return 0;
} else if (strcmp(argv[1], "--post-fs-data") == 0) { } else if (strcmp(argv[1], "--post-fs-data") == 0) {
// TODO: post-fs-data mode // TODO: post-fs-data mode
return 0; return 0;
} else if (strcmp(argv[1], "--service") == 0) {
// TODO: late_start service mode
return 0;
} else if (strcmp(argv[1], "--install") == 0) { } else if (strcmp(argv[1], "--install") == 0) {
// TODO: Install symlinks // TODO: Install symlinks
return 0; return 0;
@ -57,7 +61,7 @@ int main(int argc, char *argv[]) {
// Applets // Applets
if (strcmp(arg, "su") == 0) { if (strcmp(arg, "su") == 0) {
// return su_main(argc, argv); return su_client_main(argc, argv);
} else if (strcmp(arg, "magiskpolicy") == 0) { } else if (strcmp(arg, "magiskpolicy") == 0) {
return magiskpolicy_main(argc, argv); return magiskpolicy_main(argc, argv);
} else if (strcmp(arg, "resetprop") == 0) { } else if (strcmp(arg, "resetprop") == 0) {

2
jni/su

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

View File

@ -7,17 +7,42 @@
#include <dirent.h> #include <dirent.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <pwd.h>
#include <sys/types.h> #include <sys/types.h>
#include "magisk.h" #include "magisk.h"
#include "utils.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() { int check_data() {
char buffer[4096];
FILE *fp = xfopen("/proc/mounts", "r"); FILE *fp = xfopen("/proc/mounts", "r");
while (fgets(magiskbuf, BUF_SIZE, fp)) { while (fgets(buffer, sizeof(buffer), fp)) {
if (strstr(magiskbuf, " /data ")) { if (strstr(buffer, " /data ")) {
if (strstr(magiskbuf, "tmpfs")) if (strstr(buffer, "tmpfs"))
return 0; return 0;
else else
return 1; return 1;

View File

@ -9,9 +9,15 @@
#include <pthread.h> #include <pthread.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h>
#include "vector.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 // xwrap.c
FILE *xfopen(const char *pathname, const char *mode); 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, int xpthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg); void *(*start_routine) (void *), void *arg);
int xsocketpair(int domain, int type, int protocol, int sv[2]); int xsocketpair(int domain, int type, int protocol, int sv[2]);
int xstat(const char *pathname, struct stat *buf);
// log_monitor.c int xdup2(int oldfd, int newfd);
void monitor_logs();
// misc.c // misc.c
unsigned get_shell_uid();
unsigned get_system_uid();
unsigned get_radio_uid();
int check_data(); int check_data();
void file_to_vector(struct vector *v, FILE *fp); void file_to_vector(struct vector *v, FILE *fp);
int isNum(const char *s); int isNum(const char *s);

View File

@ -210,4 +210,20 @@ int xsocketpair(int domain, int type, int protocol, int sv[2]) {
return ret; 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;
}