Merge remote-tracking branch 'john/master' into development

This commit is contained in:
Viktor De Pasquale 2019-04-24 20:39:27 +02:00
commit a25dace7e0
12 changed files with 160 additions and 150 deletions

View File

@ -77,6 +77,7 @@ post_ota() {
cat << EOF > post-fs-data.d/post_ota.sh
${1}/bootctl mark-boot-successful
rm -f ${1}/bootctl
rm -f ${1}/post-fs-data.d/post_ota.sh
EOF
chmod 755 post-fs-data.d/post_ota.sh
cd /

View File

@ -101,6 +101,8 @@ static void main_daemon() {
android_logging();
setsid();
setcon("u:r:" SEPOL_PROC_DOMAIN ":s0");
restore_rootcon();
int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
xdup2(fd, STDOUT_FILENO);
xdup2(fd, STDERR_FILENO);

View File

@ -46,7 +46,8 @@ static int vprintk(const char *fmt, va_list ap) {
static void setup_klog() {
mknod("/kmsg", S_IFCHR | 0666, makedev(1, 11));
kmsg = xfopen("/kmsg", "ae");
int fd = xopen("/kmsg", O_WRONLY | O_CLOEXEC);
kmsg = fdopen(fd, "w");
setbuf(kmsg, nullptr);
unlink("/kmsg");
log_cb.d = log_cb.i = log_cb.w = log_cb.e = vprintk;
@ -156,11 +157,10 @@ private:
bool read_dt_fstab(const char *name, char *partname, char *partfs);
bool patch_sepolicy();
void cleanup();
void re_exec_init();
public:
explicit MagiskInit(char *argv[]) : argv(argv) {}
void setup_overlay();
void re_exec_init();
void start();
void test();
};
@ -460,6 +460,27 @@ void MagiskInit::early_mount() {
mount_root(odm);
}
static void patch_socket_name(const char *path) {
uint8_t *buf;
char name[sizeof(MAIN_SOCKET)];
size_t size;
mmap_rw(path, buf, size);
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);
}
}
munmap(buf, size);
}
constexpr const char wrapper[] =
"#!/system/bin/sh\n"
"export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH:/apex/com.android.runtime/" LIBNAME "\"\n"
"exec /sbin/magisk.bin \"$0\" \"$@\"\n"
;
void MagiskInit::setup_rootfs() {
bool patch_init = patch_sepolicy();
@ -531,6 +552,7 @@ void MagiskInit::setup_rootfs() {
gen_rand_str(pfd_svc + 1, sizeof(pfd_svc) - 1);
gen_rand_str(ls_svc + 1, sizeof(ls_svc) - 1);
gen_rand_str(bc_svc + 1, sizeof(bc_svc) - 1);
LOGD("Inject magisk services: [%s] [%s] [%s]\n", pfd_svc, ls_svc, bc_svc);
fprintf(rc, magiskrc, pfd_svc, pfd_svc, ls_svc, bc_svc, bc_svc);
fclose(rc);
clone_attr("/init.rc", "/init.p.rc");
@ -545,6 +567,56 @@ void MagiskInit::setup_rootfs() {
int rootdir = xopen("/root", O_RDONLY | O_CLOEXEC);
int sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
link_dir(sbin, rootdir);
close(sbin);
LOGD("Mount /sbin tmpfs overlay\n");
xmount("tmpfs", "/sbin", "tmpfs", 0, "mode=755");
sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
char path[64];
// Create symlinks pointing back to /root
DIR *dir = xfdopendir(rootdir);
struct dirent *entry;
while((entry = xreaddir(dir))) {
if (entry->d_name == "."sv || entry->d_name == ".."sv)
continue;
sprintf(path, "/root/%s", entry->d_name);
xsymlinkat(path, sbin, entry->d_name);
}
// Dump binaries
mkdir(MAGISKTMP, 0755);
fd = xopen(MAGISKTMP "/config", O_WRONLY | O_CREAT, 0000);
write(fd, config.buf, config.sz);
close(fd);
fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755);
write(fd, self.buf, self.sz);
close(fd);
if (access("/system/apex", F_OK) == 0) {
LOGD("APEX detected, use wrapper\n");
dump_magisk("/sbin/magisk.bin", 0755);
patch_socket_name("/sbin/magisk.bin");
fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755);
write(fd, wrapper, sizeof(wrapper) - 1);
close(fd);
} else {
dump_magisk("/sbin/magisk", 0755);
patch_socket_name("/sbin/magisk");
}
// Create applet symlinks
for (int i = 0; applet_names[i]; ++i) {
sprintf(path, "/sbin/%s", applet_names[i]);
xsymlink("/sbin/magisk", path);
}
for (int i = 0; init_applet[i]; ++i) {
sprintf(path, "/sbin/%s", init_applet[i]);
xsymlink("/sbin/magiskinit", path);
}
close(rootdir);
close(sbin);
}
bool MagiskInit::patch_sepolicy() {
@ -603,99 +675,8 @@ void MagiskInit::cleanup() {
umount_root(odm);
}
static inline void patch_socket_name(const char *path) {
uint8_t *buf;
char name[sizeof(MAIN_SOCKET)];
size_t size;
mmap_rw(path, buf, size);
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);
}
}
munmap(buf, size);
}
static const char wrapper[] =
"#!/system/bin/sh\n"
"export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH:/apex/com.android.runtime/" LIBNAME "\"\n"
"exec /sbin/magisk.bin \"$0\" \"$@\"\n";
void MagiskInit::setup_overlay() {
char path[128];
int fd;
// Wait for early-init start
while (access(EARLYINIT, F_OK) != 0)
usleep(10);
setcon("u:r:" SEPOL_PROC_DOMAIN ":s0");
unlink(EARLYINIT);
#ifdef MAGISK_DEBUG
kmsg = xfopen("/dev/kmsg", "ae");
setbuf(kmsg, nullptr);
#endif
LOGD("Setting up overlay\n");
// Mount the /sbin tmpfs overlay
xmount("tmpfs", "/sbin", "tmpfs", 0, nullptr);
chmod("/sbin", 0755);
setfilecon("/sbin", "u:object_r:rootfs:s0");
// Dump binaries
mkdir(MAGISKTMP, 0755);
fd = xopen(MAGISKTMP "/config", O_WRONLY | O_CREAT, 0000);
write(fd, config.buf, config.sz);
close(fd);
fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755);
write(fd, self.buf, self.sz);
close(fd);
if (access("/system/apex", F_OK) == 0) {
LOGD("APEX detected, use wrapper\n");
dump_magisk("/sbin/magisk.bin", 0755);
patch_socket_name("/sbin/magisk.bin");
setfilecon("/sbin/magisk.bin", "u:object_r:" SEPOL_FILE_DOMAIN ":s0");
fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755);
write(fd, wrapper, sizeof(wrapper) - 1);
close(fd);
} else {
dump_magisk("/sbin/magisk", 0755);
patch_socket_name("/sbin/magisk");
}
setfilecon("/sbin/magisk", "u:object_r:" SEPOL_FILE_DOMAIN ":s0");
setfilecon("/sbin/magiskinit", "u:object_r:" SEPOL_FILE_DOMAIN ":s0");
// Create applet symlinks
for (int i = 0; applet_names[i]; ++i) {
sprintf(path, "/sbin/%s", applet_names[i]);
xsymlink("/sbin/magisk", path);
}
for (int i = 0; init_applet[i]; ++i) {
sprintf(path, "/sbin/%s", init_applet[i]);
xsymlink("/sbin/magiskinit", path);
}
// Create symlinks pointing back to /root
DIR *dir = xopendir("/root");
struct dirent *entry;
fd = xopen("/sbin", O_RDONLY);
while((entry = xreaddir(dir))) {
if (entry->d_name == "."sv || entry->d_name == ".."sv)
continue;
sprintf(path, "/root/%s", entry->d_name);
xsymlinkat(path, fd, entry->d_name);
}
closedir(dir);
close(fd);
close(xopen(EARLYINITDONE, O_RDONLY | O_CREAT, 0));
exit(0);
}
void MagiskInit::re_exec_init() {
LOGD("Re-exec /init\n");
cleanup();
execv("/init", argv);
exit(1);
@ -722,6 +703,7 @@ void MagiskInit::start() {
preset();
early_mount();
setup_rootfs();
re_exec_init();
}
void MagiskInit::test() {
@ -767,14 +749,4 @@ int main(int argc, char *argv[]) {
// Run the main routine
init.start();
// Close all file descriptors
for (int i = 0; i < 30; ++i)
close(i);
// Launch daemon to setup overlay
if (fork_dont_care() == 0)
init.setup_overlay();
init.re_exec_init();
}

View File

@ -71,6 +71,7 @@ int magisk_main(int argc, char *argv[]) {
unlock_blocks();
return 0;
} else if (strcmp(argv[1], "--restorecon") == 0) {
restore_rootcon();
restorecon();
return 0;
} else if (strcmp(argv[1], "--clone-attr") == 0) {

View File

@ -1,15 +1,9 @@
#include <magisk.h>
#include <magiskpolicy.h>
static const char magiskrc[] =
constexpr const char magiskrc[] =
"\n\n"
"on early-init\n"
" write " EARLYINIT " 1\n"
" wait " EARLYINITDONE "\n"
" rm " EARLYINITDONE "\n"
"\n"
"on post-fs-data\n"
" start logd\n"
" load_persist_props\n"

View File

@ -6,8 +6,6 @@
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
#define LOGFILE "/cache/magisk.log"
#define UNBLOCKFILE "/dev/.magisk_unblock"
#define EARLYINIT "/dev/.magisk_early_init"
#define EARLYINITDONE "/dev/.magisk_early_init_done"
#define DISABLEFILE "/cache/.disable_magisk"
#define MAGISKTMP "/sbin/.magisk"
#define MIRRDIR MAGISKTMP "/mirror"

View File

@ -71,7 +71,7 @@ void crawl_procfs(DIR *dir, const function<bool (int)> &fn) {
}
}
bool proc_name_match(int pid, const char *name) {
static bool proc_name_match(int pid, const char *name) {
char buf[4019];
FILE *f;
#if 0

View File

@ -19,8 +19,6 @@
#define SAFETYNET_PKG "com.google.android.gms"
#define MICROG_SAFETYNET "org.microg.gms.droidguard"
#define WEVENT(s) (((s) & 0xffff0000) >> 16)
// CLI entries
void launch_magiskhide(int client);
int stop_magiskhide();
@ -29,15 +27,14 @@ int rm_list(int client);
void ls_list(int client);
// Process monitoring
void *update_uid_map(void * p = nullptr);
void proc_monitor();
void update_uid_map();
// Utility functions
void manage_selinux();
void clean_magisk_props();
void crawl_procfs(const std::function<bool (int)> &fn);
void crawl_procfs(DIR *dir, const std::function<bool (int)> &fn);
bool proc_name_match(int pid, const char *name);
extern bool hide_enabled;
extern pthread_mutex_t monitor_lock;

View File

@ -134,18 +134,21 @@ static bool parse_packages_xml(string_view s) {
return true;
}
void update_uid_map() {
MutexGuard lock(monitor_lock);
uid_proc_map.clear();
file_readline("/data/system/packages.xml", parse_packages_xml, true);
}
static void check_zygote() {
int min_zyg = 1;
if (access("/system/bin/app_process64", R_OK) == 0)
min_zyg = 2;
for (bool first = true; zygote_map.size() < min_zyg; first = false) {
if (!first)
usleep(10000);
for (;;) {
crawl_procfs([](int pid) -> bool {
char buf[512];
snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
FILE *f = fopen(buf, "re");
if (f) {
if (FILE *f = fopen(buf, "re"); f) {
fgets(buf, sizeof(buf), f);
if (strncmp(buf, "zygote", 6) == 0 && parse_ppid(pid) == 1)
new_zygote(pid);
@ -153,14 +156,41 @@ static void check_zygote() {
}
return true;
});
if (zygote_map.size() >= min_zyg)
break;
usleep(10000);
}
}
void *update_uid_map(void*) {
MutexGuard lock(monitor_lock);
uid_proc_map.clear();
file_readline("/data/system/packages.xml", parse_packages_xml, true);
return nullptr;
#define APP_PROC "/system/bin/app_process"
static void setup_inotify() {
inotify_fd = xinotify_init1(IN_CLOEXEC);
if (inotify_fd < 0)
term_thread();
// Setup inotify asynchronous I/O
fcntl(inotify_fd, F_SETFL, O_ASYNC);
struct f_owner_ex ex = {
.type = F_OWNER_TID,
.pid = gettid()
};
fcntl(inotify_fd, F_SETOWN_EX, &ex);
// Monitor packages.xml
inotify_add_watch(inotify_fd, "/data/system", IN_CLOSE_WRITE);
// Monitor app_process
if (access(APP_PROC "32", F_OK) == 0) {
inotify_add_watch(inotify_fd, APP_PROC "32", IN_ACCESS);
if (access(APP_PROC "64", F_OK) == 0)
inotify_add_watch(inotify_fd, APP_PROC "64", IN_ACCESS);
} else {
inotify_add_watch(inotify_fd, APP_PROC, IN_ACCESS);
}
// First find existing zygotes
check_zygote();
}
/*************************
@ -233,7 +263,10 @@ static void inotify_event(int) {
read(inotify_fd, buf, sizeof(buf));
if ((event->mask & IN_CLOSE_WRITE) && strcmp(event->name, "packages.xml") == 0) {
LOGD("proc_monitor: /data/system/packages.xml updated\n");
new_daemon_thread(update_uid_map);
uid_proc_map.clear();
file_readline("/data/system/packages.xml", parse_packages_xml, true);
} else if (event->mask & IN_ACCESS) {
check_zygote();
}
}
@ -362,12 +395,10 @@ static void new_zygote(int pid) {
xptrace(PTRACE_CONT, pid);
}
#define WEVENT(s) (((s) & 0xffff0000) >> 16)
#define DETACH_AND_CONT { detach = true; continue; }
void proc_monitor() {
inotify_fd = xinotify_init1(IN_CLOEXEC);
if (inotify_fd < 0)
term_thread();
void proc_monitor() {
// Unblock some signals
sigset_t block_set;
sigemptyset(&block_set);
@ -381,19 +412,7 @@ void proc_monitor() {
act.sa_handler = inotify_event;
sigaction(SIGIO, &act, nullptr);
// Setup inotify asynchronous I/O
fcntl(inotify_fd, F_SETFL, O_ASYNC);
struct f_owner_ex ex = {
.type = F_OWNER_TID,
.pid = gettid()
};
fcntl(inotify_fd, F_SETOWN_EX, &ex);
// Start monitoring packages.xml
inotify_add_watch(inotify_fd, "/data/system", IN_CLOSE_WRITE);
// First find existing zygotes
check_zygote();
setup_inotify();
int status;

View File

@ -54,6 +54,8 @@ void sepol_magisk_rules() {
// Let init run stuffs
sepol_allow("kernel", SEPOL_PROC_DOMAIN, "fd", "use");
sepol_allow("init", SEPOL_PROC_DOMAIN, "process", ALL);
sepol_allow("init", "tmpfs", "file", "getattr");
sepol_allow("init", "tmpfs", "file", "execute");
// Shell, properties, logs
if (sepol_exists("default_prop"))

View File

@ -36,6 +36,7 @@ void setfilecon_at(int dirfd, const char *name, const char *con);
void selinux_builtin_impl();
void dload_selinux();
void restorecon();
void restore_rootcon();
#ifdef __cplusplus
}

View File

@ -1,17 +1,21 @@
#include <sys/xattr.h>
#include <dlfcn.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <syscall.h>
#include <sys/xattr.h>
#include <string_view>
#include <magisk.h>
#include <utils.h>
#include <selinux.h>
using namespace std::literals;
#define UNLABEL_CON "u:object_r:unlabeled:s0"
#define SYSTEM_CON "u:object_r:system_file:s0"
#define ADB_CON "u:object_r:adb_data_file:s0"
#define ROOT_CON "u:object_r:rootfs:s0"
#define MAGISK_CON "u:object_r:" SEPOL_FILE_DOMAIN ":s0"
// Stub implementation
@ -164,7 +168,7 @@ static void restore_syscon(int dirfd) {
dir = xfdopendir(dirfd);
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
if (entry->d_name == "."sv || entry->d_name == ".."sv)
continue;
int fd = openat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
if (entry->d_type == DT_DIR) {
@ -193,7 +197,7 @@ static void restore_magiskcon(int dirfd) {
dir = xfdopendir(dirfd);
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
if (entry->d_name == "."sv || entry->d_name == ".."sv)
continue;
int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
if (entry->d_type == DT_DIR) {
@ -220,3 +224,22 @@ void restorecon() {
restore_magiskcon(fd);
close(fd);
}
void restore_rootcon() {
setfilecon("/sbin", ROOT_CON);
struct dirent *entry;
DIR *dir = xopendir("/sbin");
int dfd = dirfd(dir);
while ((entry = xreaddir(dir))) {
if (entry->d_name == "."sv || entry->d_name == ".."sv)
continue;
setfilecon_at(dfd, entry->d_name, ROOT_CON);
}
setfilecon("/sbin/magisk.bin", MAGISK_CON);
setfilecon("/sbin/magisk", MAGISK_CON);
setfilecon("/sbin/magiskinit", MAGISK_CON);
closedir(dir);
}