From a9121fa28f4ed9a70c355150bdc25a0d7c2de929 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 12 Oct 2018 21:46:09 -0400 Subject: [PATCH] Reorganize libutils and cleanups --- native/jni/daemon/bootstages.c | 60 +++++++++++++- native/jni/daemon/daemon.c | 7 +- native/jni/include/daemon.h | 6 +- native/jni/magiskhide/hide_utils.c | 50 +++++++++++- native/jni/su/su.c | 11 +++ native/jni/utils/include/utils.h | 17 +--- native/jni/utils/misc.c | 124 +---------------------------- 7 files changed, 128 insertions(+), 147 deletions(-) diff --git a/native/jni/daemon/bootstages.c b/native/jni/daemon/bootstages.c index fd29288b5..5b0b1883b 100644 --- a/native/jni/daemon/bootstages.c +++ b/native/jni/daemon/bootstages.c @@ -462,7 +462,7 @@ static int prepare_img() { return 0; } -void install_apk(const char *apk) { +static void install_apk(const char *apk) { setfilecon(apk, "u:object_r:"SEPOL_FILE_DOMAIN":s0"); while (1) { sleep(5); @@ -486,6 +486,43 @@ void install_apk(const char *apk) { unlink(apk); } +static int check_data() { + struct vector v; + vec_init(&v); + file_to_vector("/proc/mounts", &v); + char *line; + int mnt = 0; + vec_for_each(&v, line) { + if (strstr(line, " /data ") && strstr(line, "tmpfs") == NULL) { + mnt = 1; + break; + } + } + vec_deep_destroy(&v); + int data = 0; + if (mnt) { + char *crypto = getprop("ro.crypto.state"); + if (crypto != NULL) { + if (strcmp(crypto, "unencrypted") == 0) { + // Unencrypted, we can directly access data + data = 1; + } else { + // Encrypted, check whether vold is started + char *vold = getprop("init.svc.vold"); + if (vold != NULL) { + free(vold); + data = 1; + } + } + free(crypto); + } else { + // ro.crypto.state is not set, assume it's unencrypted + data = 1; + } + } + return data; +} + static void *start_magisk_hide(void *args) { launch_magiskhide(-1); return NULL; @@ -503,6 +540,27 @@ static void auto_start_magiskhide() { free(hide_prop); } +void unlock_blocks() { + DIR *dir; + struct dirent *entry; + int fd, dev, OFF = 0; + + if ((dev = xopen("/dev/block", O_RDONLY | O_CLOEXEC)) < 0) + return; + dir = xfdopendir(dev); + + while((entry = readdir(dir))) { + if (entry->d_type == DT_BLK) { + if ((fd = openat(dev, entry->d_name, O_RDONLY)) < 0) + continue; + if (ioctl(fd, BLKROSET, &OFF) == -1) + PLOGE("unlock %s", entry->d_name); + close(fd); + } + } + close(dev); +} + /**************** * Entry points * ****************/ diff --git a/native/jni/daemon/daemon.c b/native/jni/daemon/daemon.c index c11c2a725..397ec1154 100644 --- a/native/jni/daemon/daemon.c +++ b/native/jni/daemon/daemon.c @@ -17,13 +17,18 @@ #include "magisk.h" #include "utils.h" #include "daemon.h" -#include "resetprop.h" #include "selinux.h" #include "flags.h" int setup_done = 0; int seperate_vendor = 0; +static void get_client_cred(int fd, struct ucred *cred) { + socklen_t ucred_length = sizeof(*cred); + if(getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &ucred_length)) + PLOGE("getsockopt"); +} + static void *request_handler(void *args) { int client = *((int *) args); free(args); diff --git a/native/jni/include/daemon.h b/native/jni/include/daemon.h index f1bce138c..6006219f0 100644 --- a/native/jni/include/daemon.h +++ b/native/jni/include/daemon.h @@ -41,11 +41,6 @@ enum { HIDE_ITEM_NOT_EXIST, }; -typedef enum { - MAIN_DAEMON, - LOG_DAEMON -} daemon_t; - // daemon.c int connect_daemon(); @@ -78,6 +73,7 @@ void write_key_token(int fd, const char *key, int tok); * Boot Stages * ***************/ +void unlock_blocks(); void startup(); void post_fs_data(int client); void late_start(int client); diff --git a/native/jni/magiskhide/hide_utils.c b/native/jni/magiskhide/hide_utils.c index 7caffaa3c..8b222b87e 100644 --- a/native/jni/magiskhide/hide_utils.c +++ b/native/jni/magiskhide/hide_utils.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -15,7 +16,6 @@ #include "resetprop.h" #include "magiskhide.h" #include "daemon.h" -#include "selinux.h" static char *prop_key[] = { "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked", "ro.boot.veritymode", @@ -63,6 +63,54 @@ static void rm_magisk_prop(const char *name, const char *value, void *v) { } } +/* Call func for each process */ +static void ps(void (*func)(int)) { + DIR *dir; + struct dirent *entry; + + if (!(dir = xopendir("/proc"))) + return; + + while ((entry = xreaddir(dir))) { + if (entry->d_type == DT_DIR) { + if (is_num(entry->d_name)) + func(atoi(entry->d_name)); + } + } + + closedir(dir); +} + +static int check_proc_name(int pid, const char *name) { + char buf[128]; + FILE *f; + sprintf(buf, "/proc/%d/comm", pid); + if ((f = fopen(buf, "r"))) { + fgets(buf, sizeof(buf), f); + if (strcmp(buf, name) == 0) + return 1; + } else { + // The PID is already killed + return 0; + } + fclose(f); + + sprintf(buf, "/proc/%d/cmdline", pid); + f = fopen(buf, "r"); + fgets(buf, sizeof(buf), f); + fclose(f); + if (strcmp(basename(buf), name) == 0) + return 1; + + sprintf(buf, "/proc/%d/exe", pid); + if (access(buf, F_OK) != 0) + return 0; + xreadlink(buf, buf, sizeof(buf)); + if (strcmp(basename(buf), name) == 0) + return 1; + return 0; +} + static void kill_proc_cb(int pid) { if (check_proc_name(pid, proc_name)) kill(pid, SIGTERM); diff --git a/native/jni/su/su.c b/native/jni/su/su.c index 0242adebb..051d3c243 100644 --- a/native/jni/su/su.c +++ b/native/jni/su/su.c @@ -29,6 +29,8 @@ #include "pts.h" #include "flags.h" +#define quit_signals ((int []) { SIGALRM, SIGABRT, SIGHUP, SIGPIPE, SIGQUIT, SIGTERM, SIGINT, 0 }) + static void usage(int status) { FILE *stream = (status == EXIT_SUCCESS) ? stdout : stderr; @@ -84,6 +86,15 @@ static void sighandler(int sig) { } } +static void setup_sighandlers(void (*handler)(int)) { + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_handler = handler; + for (int i = 0; quit_signals[i]; ++i) { + sigaction(quit_signals[i], &act, NULL); + } +} + /* * Connect daemon, send argc, argv, cwd, pts slave */ diff --git a/native/jni/utils/include/utils.h b/native/jni/utils/include/utils.h index 9387663f4..504040242 100644 --- a/native/jni/utils/include/utils.h +++ b/native/jni/utils/include/utils.h @@ -20,13 +20,6 @@ // xwrap.c -#ifndef SOCK_CLOEXEC -#define SOCK_CLOEXEC O_CLOEXEC -#endif -#ifndef SOCK_NONBLOCK -#define SOCK_NONBLOCK O_NONBLOCK -#endif - FILE *xfopen(const char *pathname, const char *mode); FILE *xfdopen(int fd, const char *mode); #define GET_MACRO(_1, _2, _3, NAME, ...) NAME @@ -83,24 +76,17 @@ int xpoll(struct pollfd *fds, nfds_t nfds, int timeout); // misc.c -#define quit_signals ((int []) { SIGALRM, SIGABRT, SIGHUP, SIGPIPE, SIGQUIT, SIGTERM, SIGINT, 0 }) - unsigned get_shell_uid(); unsigned get_system_uid(); unsigned get_radio_uid(); -int check_data(); int file_to_vector(const char* filename, struct vector *v); int vector_to_file(const char* filename, struct vector *v); ssize_t fdgets(char *buf, size_t size, int fd); -void ps(void (*func)(int)); -int check_proc_name(int pid, const char *filter); -void unlock_blocks(); -void setup_sighandlers(void (*handler)(int)); +int is_num(const char *s); int exec_array(int err, int *fd, void (*setenv)(struct vector *), char *const *argv); int exec_command(int err, int *fd, void (*setenv)(struct vector*), const char *argv0, ...); int exec_command_sync(char *const argv0, ...); int bind_mount(const char *from, const char *to); -void get_client_cred(int fd, struct ucred *cred); int switch_mnt_ns(int pid); int fork_dont_care(); void wait_till_exists(const char *target); @@ -146,7 +132,6 @@ int setattrat(int dirfd, const char *pathname, struct file_attr *a); int fsetattr(int fd, struct file_attr *a); void fclone_attr(const int sourcefd, const int targetfd); void clone_attr(const char *source, const char *target); - void mmap_ro(const char *filename, void **buf, size_t *size); void mmap_rw(const char *filename, void **buf, size_t *size); void fd_full_read(int fd, void **buf, size_t *size); diff --git a/native/jni/utils/misc.c b/native/jni/utils/misc.c index ae77938b5..328371fb8 100644 --- a/native/jni/utils/misc.c +++ b/native/jni/utils/misc.c @@ -22,7 +22,6 @@ #include "logging.h" #include "utils.h" -#include "resetprop.h" #include "flags.h" unsigned get_shell_uid() { @@ -49,43 +48,6 @@ unsigned get_radio_uid() { return ppwd->pw_uid; } -int check_data() { - struct vector v; - vec_init(&v); - file_to_vector("/proc/mounts", &v); - char *line; - int mnt = 0; - vec_for_each(&v, line) { - if (strstr(line, " /data ") && strstr(line, "tmpfs") == NULL) { - mnt = 1; - break; - } - } - vec_deep_destroy(&v); - int data = 0; - if (mnt) { - char *crypto = getprop("ro.crypto.state"); - if (crypto != NULL) { - if (strcmp(crypto, "unencrypted") == 0) { - // Unencrypted, we can directly access data - data = 1; - } else { - // Encrypted, check whether vold is started - char *vold = getprop("init.svc.vold"); - if (vold != NULL) { - free(vold); - data = 1; - } - } - free(crypto); - } else { - // ro.crypto.state is not set, assume it's unencrypted - data = 1; - } - } - return data; -} - /* All the string should be freed manually!! */ int file_to_vector(const char* filename, struct vector *v) { if (access(filename, R_OK) != 0) @@ -122,7 +84,7 @@ int vector_to_file(const char *filename, struct vector *v) { } /* Check if the string only contains digits */ -static int is_num(const char *s) { +int is_num(const char *s) { int len = strlen(s); for (int i = 0; i < len; ++i) if (s[i] < '0' || s[i] > '9') @@ -149,84 +111,6 @@ ssize_t fdgets(char *buf, const size_t size, int fd) { return len; } -/* Call func for each process */ -void ps(void (*func)(int)) { - DIR *dir; - struct dirent *entry; - - if (!(dir = xopendir("/proc"))) - return; - - while ((entry = xreaddir(dir))) { - if (entry->d_type == DT_DIR) { - if (is_num(entry->d_name)) - func(atoi(entry->d_name)); - } - } - - closedir(dir); -} - -int check_proc_name(int pid, const char *name) { - char buf[128]; - FILE *f; - sprintf(buf, "/proc/%d/comm", pid); - if ((f = fopen(buf, "r"))) { - fgets(buf, sizeof(buf), f); - if (strcmp(buf, name) == 0) - return 1; - } else { - // The PID is already killed - return 0; - } - fclose(f); - - sprintf(buf, "/proc/%d/cmdline", pid); - f = fopen(buf, "r"); - fgets(buf, sizeof(buf), f); - fclose(f); - if (strcmp(basename(buf), name) == 0) - return 1; - - sprintf(buf, "/proc/%d/exe", pid); - if (access(buf, F_OK) != 0) - return 0; - xreadlink(buf, buf, sizeof(buf)); - if (strcmp(basename(buf), name) == 0) - return 1; - return 0; -} - -void unlock_blocks() { - DIR *dir; - struct dirent *entry; - int fd, dev, OFF = 0; - - if ((dev = xopen("/dev/block", O_RDONLY | O_CLOEXEC)) < 0) - return; - dir = xfdopendir(dev); - - while((entry = readdir(dir))) { - if (entry->d_type == DT_BLK) { - if ((fd = openat(dev, entry->d_name, O_RDONLY)) < 0) - continue; - if (ioctl(fd, BLKROSET, &OFF) == -1) - PLOGE("unlock %s", entry->d_name); - close(fd); - } - } - close(dev); -} - -void setup_sighandlers(void (*handler)(int)) { - struct sigaction act; - memset(&act, 0, sizeof(act)); - act.sa_handler = handler; - for (int i = 0; quit_signals[i]; ++i) { - sigaction(quit_signals[i], &act, NULL); - } -} - /* fd == NULL -> Ignore output *fd < 0 -> Open pipe and set *fd to the read end @@ -324,12 +208,6 @@ int bind_mount(const char *from, const char *to) { return ret; } -void get_client_cred(int fd, struct ucred *cred) { - socklen_t ucred_length = sizeof(*cred); - if(getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &ucred_length)) - PLOGE("getsockopt"); -} - int switch_mnt_ns(int pid) { char mnt[32]; snprintf(mnt, sizeof(mnt), "/proc/%d/ns/mnt", pid);