From 134508193dc1c0416fbd7141fb66d4202658a33b Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sat, 16 Apr 2022 07:27:34 -0700 Subject: [PATCH] Mock selinuxfs load with regular file The hijacked load node does not need to be a FIFO. A FIFO is only required for blocking init's control flow, which is already achieved by hijacking the enforce node. --- native/jni/core/daemon.cpp | 8 -------- native/jni/init/selinux.cpp | 27 ++++++++++----------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/native/jni/core/daemon.cpp b/native/jni/core/daemon.cpp index 72831ef94..5318c43bc 100644 --- a/native/jni/core/daemon.cpp +++ b/native/jni/core/daemon.cpp @@ -362,14 +362,6 @@ static void daemon_entry() { } rm_rf((MAGISKTMP + "/" ROOTOVL).data()); - // SELinux mock cleanups - string selinux_mock = MAGISKTMP + "/" SELINUXMOCK; - string fs = selinux_mock + "/fs"; - if (access(fs.data(), F_OK) == 0) { - umount2(fs.data(), MNT_DETACH); - } - rm_rf(selinux_mock.data()); - // Load config status auto config = MAGISKTMP + "/" INTLROOT "/config"; parse_prop_file(config.data(), [](auto key, auto val) -> bool { diff --git a/native/jni/init/selinux.cpp b/native/jni/init/selinux.cpp index 4bce35b42..d006764ee 100644 --- a/native/jni/init/selinux.cpp +++ b/native/jni/init/selinux.cpp @@ -40,7 +40,6 @@ void MagiskInit::patch_sepolicy(const char *in, const char *out) { #define MOCK_COMPAT SELINUXMOCK "/compatible" #define MOCK_LOAD SELINUXMOCK "/load" #define MOCK_ENFORCE SELINUXMOCK "/enforce" -#define REAL_SELINUXFS SELINUXMOCK "/fs" bool MagiskInit::hijack_sepolicy() { xmkdir(SELINUXMOCK, 0); @@ -58,7 +57,7 @@ bool MagiskInit::hijack_sepolicy() { // the actual sepolicy being loaded into the kernel auto hijack = [&] { LOGD("Hijack [" SELINUX_LOAD "]\n"); - mkfifo(MOCK_LOAD, 0600); + close(xopen(MOCK_LOAD, O_CREAT | O_RDONLY, 0600)); xmount(MOCK_LOAD, SELINUX_LOAD, nullptr, MS_BIND, nullptr); LOGD("Hijack [" SELINUX_ENFORCE "]\n"); mkfifo(MOCK_ENFORCE, 0644); @@ -131,28 +130,21 @@ bool MagiskInit::hijack_sepolicy() { close(fd); } - // Read full sepolicy - int fd = xopen(MOCK_LOAD, O_RDONLY); - string policy = fd_full_read(fd); - close(fd); - auto sepol = unique_ptr(sepolicy::from_data(policy.data(), policy.length())); - - sepol->magisk_rules(); - sepol->load_rules(rules); - // This open will block until init calls security_getenforce - fd = xopen(MOCK_ENFORCE, O_WRONLY); + int fd = xopen(MOCK_ENFORCE, O_WRONLY); // Cleanup the hijacks umount2("/init", MNT_DETACH); xumount2(SELINUX_LOAD, MNT_DETACH); xumount2(SELINUX_ENFORCE, MNT_DETACH); - // Load patched policy - xmkdir(REAL_SELINUXFS, 0755); - xmount("selinuxfs", REAL_SELINUXFS, "selinuxfs", 0, nullptr); - sepol->to_file(REAL_SELINUXFS "/load"); - string enforce = full_read(SELINUX_ENFORCE); + // Load and patch policy + auto sepol = unique_ptr(sepolicy::from_file(MOCK_LOAD)); + sepol->magisk_rules(); + sepol->load_rules(rules); + + // Load patched policy into kernel + sepol->to_file(SELINUX_LOAD); // Write to the enforce node ONLY after sepolicy is loaded. We need to make sure // the actual init process is blocked until sepolicy is loaded, or else @@ -161,6 +153,7 @@ bool MagiskInit::hijack_sepolicy() { // it has been replaced with our FIFO file, init will block until we // write something into the pipe, effectively hijacking its control flow. + string enforce = full_read(SELINUX_ENFORCE); xwrite(fd, enforce.data(), enforce.length()); close(fd);