diff --git a/native/jni/core/daemon.cpp b/native/jni/core/daemon.cpp index f284ccb56..719bec4a9 100644 --- a/native/jni/core/daemon.cpp +++ b/native/jni/core/daemon.cpp @@ -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); diff --git a/native/jni/core/init.cpp b/native/jni/core/init.cpp index 43da07002..7814ec1d3 100644 --- a/native/jni/core/init.cpp +++ b/native/jni/core/init.cpp @@ -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(); } diff --git a/native/jni/core/magisk.cpp b/native/jni/core/magisk.cpp index b2543f6f3..3468728cd 100644 --- a/native/jni/core/magisk.cpp +++ b/native/jni/core/magisk.cpp @@ -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) { diff --git a/native/jni/core/magiskrc.h b/native/jni/core/magiskrc.h index 40c0028c2..f0d7a7554 100644 --- a/native/jni/core/magiskrc.h +++ b/native/jni/core/magiskrc.h @@ -1,15 +1,9 @@ #include #include -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" diff --git a/native/jni/include/magisk.h b/native/jni/include/magisk.h index fc9bca31b..4ea5557ce 100644 --- a/native/jni/include/magisk.h +++ b/native/jni/include/magisk.h @@ -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" diff --git a/native/jni/magiskpolicy/rules.cpp b/native/jni/magiskpolicy/rules.cpp index e9907a104..ee9d96a46 100644 --- a/native/jni/magiskpolicy/rules.cpp +++ b/native/jni/magiskpolicy/rules.cpp @@ -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")) diff --git a/native/jni/utils/include/selinux.h b/native/jni/utils/include/selinux.h index 11801d813..21b0a4096 100644 --- a/native/jni/utils/include/selinux.h +++ b/native/jni/utils/include/selinux.h @@ -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 } diff --git a/native/jni/utils/selinux.cpp b/native/jni/utils/selinux.cpp index 3ac5484cc..f19600e62 100644 --- a/native/jni/utils/selinux.cpp +++ b/native/jni/utils/selinux.cpp @@ -1,17 +1,21 @@ +#include #include #include #include #include #include -#include +#include #include #include #include +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); +}