mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-25 20:48:35 +00:00
Move MagiskInit to rust
This commit is contained in:
parent
6c612d66d7
commit
d203a6fff6
@ -60,7 +60,7 @@ void restore_ramdisk_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MagiskInit::MagiskInit(char **argv) : argv(argv), config{} {
|
void MagiskInit::init() noexcept {
|
||||||
// Get kernel data using procfs and sysfs
|
// Get kernel data using procfs and sysfs
|
||||||
if (access("/proc/cmdline", F_OK) != 0) {
|
if (access("/proc/cmdline", F_OK) != 0) {
|
||||||
xmkdir("/proc", 0755);
|
xmkdir("/proc", 0755);
|
||||||
@ -86,7 +86,7 @@ static void recovery() {
|
|||||||
rm_rf("/.backup");
|
rm_rf("/.backup");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::legacy_system_as_root() {
|
void MagiskInit::legacy_system_as_root() noexcept {
|
||||||
LOGI("Legacy SAR Init\n");
|
LOGI("Legacy SAR Init\n");
|
||||||
prepare_data();
|
prepare_data();
|
||||||
bool is_two_stage = mount_system_root();
|
bool is_two_stage = mount_system_root();
|
||||||
@ -96,7 +96,7 @@ void MagiskInit::legacy_system_as_root() {
|
|||||||
patch_ro_root();
|
patch_ro_root();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::rootfs() {
|
void MagiskInit::rootfs() noexcept {
|
||||||
LOGI("RootFS Init\n");
|
LOGI("RootFS Init\n");
|
||||||
prepare_data();
|
prepare_data();
|
||||||
LOGD("Restoring /init\n");
|
LOGD("Restoring /init\n");
|
||||||
@ -104,7 +104,7 @@ void MagiskInit::rootfs() {
|
|||||||
patch_rw_root();
|
patch_rw_root();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::start() {
|
void MagiskInit::start() noexcept {
|
||||||
if (argv[1] != nullptr && argv[1] == "selinux_setup"sv)
|
if (argv[1] != nullptr && argv[1] == "selinux_setup"sv)
|
||||||
second_stage();
|
second_stage();
|
||||||
else if (config.skip_initramfs)
|
else if (config.skip_initramfs)
|
||||||
@ -132,6 +132,5 @@ int main(int argc, char *argv[]) {
|
|||||||
if (getpid() != 1)
|
if (getpid() != 1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
MagiskInit init(argv);
|
rust::start_magisk_init(argv);
|
||||||
init.start();
|
|
||||||
}
|
}
|
||||||
|
@ -12,40 +12,3 @@ bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes);
|
|||||||
bool check_two_stage();
|
bool check_two_stage();
|
||||||
const char *backup_init();
|
const char *backup_init();
|
||||||
void restore_ramdisk_init();
|
void restore_ramdisk_init();
|
||||||
|
|
||||||
class MagiskInit {
|
|
||||||
private:
|
|
||||||
std::string preinit_dev;
|
|
||||||
std::vector<std::string> mount_list;
|
|
||||||
char **argv;
|
|
||||||
BootConfig config;
|
|
||||||
|
|
||||||
// Setup mounts and environment
|
|
||||||
void setup_tmp(const char *path);
|
|
||||||
void collect_devices();
|
|
||||||
void mount_preinit_dir();
|
|
||||||
void prepare_data();
|
|
||||||
dev_t find_block(const char *partname);
|
|
||||||
bool mount_system_root();
|
|
||||||
|
|
||||||
// Setup and patch root directory
|
|
||||||
void parse_config_file();
|
|
||||||
void patch_rw_root();
|
|
||||||
void patch_ro_root();
|
|
||||||
|
|
||||||
// Two stage init
|
|
||||||
void redirect_second_stage();
|
|
||||||
void first_stage();
|
|
||||||
void second_stage();
|
|
||||||
|
|
||||||
// SELinux
|
|
||||||
void patch_sepolicy(const char *in, const char *out);
|
|
||||||
bool hijack_sepolicy();
|
|
||||||
|
|
||||||
[[noreturn]] void exec_init();
|
|
||||||
void legacy_system_as_root();
|
|
||||||
void rootfs();
|
|
||||||
public:
|
|
||||||
explicit MagiskInit(char *argv[]);
|
|
||||||
void start();
|
|
||||||
};
|
|
||||||
|
@ -7,6 +7,7 @@ use mount::{is_device_mounted, switch_root};
|
|||||||
use rootdir::{collect_overlay_contexts, inject_magisk_rc, reset_overlay_contexts};
|
use rootdir::{collect_overlay_contexts, inject_magisk_rc, reset_overlay_contexts};
|
||||||
// Has to be pub so all symbols in that crate is included
|
// Has to be pub so all symbols in that crate is included
|
||||||
pub use magiskpolicy;
|
pub use magiskpolicy;
|
||||||
|
use crate::ffi::{BootConfig, MagiskInit};
|
||||||
|
|
||||||
mod logging;
|
mod logging;
|
||||||
mod mount;
|
mod mount;
|
||||||
@ -31,6 +32,13 @@ pub mod ffi {
|
|||||||
partition_map: Vec<KeyValue>,
|
partition_map: Vec<KeyValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MagiskInit {
|
||||||
|
preinit_dev: String,
|
||||||
|
mount_list: Vec<String>,
|
||||||
|
argv: *mut *mut c_char,
|
||||||
|
config: BootConfig,
|
||||||
|
}
|
||||||
|
|
||||||
#[namespace = "rust"]
|
#[namespace = "rust"]
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn setup_klog();
|
fn setup_klog();
|
||||||
@ -39,6 +47,7 @@ pub mod ffi {
|
|||||||
fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool;
|
fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool;
|
||||||
fn collect_overlay_contexts(src: Utf8CStrRef);
|
fn collect_overlay_contexts(src: Utf8CStrRef);
|
||||||
fn reset_overlay_contexts();
|
fn reset_overlay_contexts();
|
||||||
|
unsafe fn start_magisk_init(argv: *mut *mut c_char);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C++" {
|
unsafe extern "C++" {
|
||||||
@ -51,5 +60,53 @@ pub mod ffi {
|
|||||||
fn print(self: &BootConfig);
|
fn print(self: &BootConfig);
|
||||||
type kv_pairs;
|
type kv_pairs;
|
||||||
fn set(self: &mut BootConfig, config: &kv_pairs);
|
fn set(self: &mut BootConfig, config: &kv_pairs);
|
||||||
|
|
||||||
|
unsafe fn setup_tmp(self: &MagiskInit, path: *const c_char);
|
||||||
|
fn collect_devices(self: &MagiskInit);
|
||||||
|
fn mount_preinit_dir(self: &MagiskInit);
|
||||||
|
fn prepare_data(self: &MagiskInit);
|
||||||
|
unsafe fn find_block(self: &MagiskInit, partname: *const c_char) -> u64;
|
||||||
|
fn mount_system_root(self: &mut MagiskInit) -> bool;
|
||||||
|
|
||||||
|
// Setup and patch root directory
|
||||||
|
fn parse_config_file(self: &mut MagiskInit);
|
||||||
|
fn patch_rw_root(self: &mut MagiskInit);
|
||||||
|
fn patch_ro_root(self: &mut MagiskInit);
|
||||||
|
|
||||||
|
// Two stage init
|
||||||
|
fn redirect_second_stage(self: &MagiskInit);
|
||||||
|
fn first_stage(self: &MagiskInit);
|
||||||
|
fn second_stage(self: &mut MagiskInit);
|
||||||
|
|
||||||
|
// SELinux
|
||||||
|
unsafe fn patch_sepolicy(self: &MagiskInit, in_: *const c_char, out: *const c_char);
|
||||||
|
fn hijack_sepolicy(self: &mut MagiskInit) -> bool;
|
||||||
|
fn exec_init(self: &MagiskInit);
|
||||||
|
fn legacy_system_as_root(self: &mut MagiskInit);
|
||||||
|
fn rootfs(self: &mut MagiskInit);
|
||||||
|
fn start(self: &mut MagiskInit);
|
||||||
|
fn init(self: &mut MagiskInit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn start_magisk_init(argv: *mut *mut std::ffi::c_char) {
|
||||||
|
let mut init = MagiskInit {
|
||||||
|
preinit_dev: String::new(),
|
||||||
|
mount_list: Vec::new(),
|
||||||
|
argv,
|
||||||
|
config: BootConfig {
|
||||||
|
skip_initramfs: false,
|
||||||
|
force_normal_boot: false,
|
||||||
|
rootwait: false,
|
||||||
|
emulator: false,
|
||||||
|
slot: [0; 3],
|
||||||
|
dt_dir: [0; 64],
|
||||||
|
fstab_suffix: [0; 32],
|
||||||
|
hardware: [0; 32],
|
||||||
|
hardware_plat: [0; 32],
|
||||||
|
partition_map: Vec::new(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
init.init();
|
||||||
|
init.start();
|
||||||
|
}
|
||||||
|
@ -45,7 +45,7 @@ static void parse_device(devinfo *dev, const char *uevent) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::collect_devices() {
|
void MagiskInit::collect_devices() const noexcept {
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
devinfo dev{};
|
devinfo dev{};
|
||||||
if (auto dir = xopen_dir("/sys/dev/block"); dir) {
|
if (auto dir = xopen_dir("/sys/dev/block"); dir) {
|
||||||
@ -72,7 +72,7 @@ void MagiskInit::collect_devices() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_t MagiskInit::find_block(const char *partname) {
|
uint64_t MagiskInit::find_block(const char *partname) const noexcept {
|
||||||
if (dev_list.empty())
|
if (dev_list.empty())
|
||||||
collect_devices();
|
collect_devices();
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ dev_t MagiskInit::find_block(const char *partname) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::mount_preinit_dir() {
|
void MagiskInit::mount_preinit_dir() const noexcept {
|
||||||
if (preinit_dev.empty()) return;
|
if (preinit_dev.empty()) return;
|
||||||
auto dev = find_block(preinit_dev.data());
|
auto dev = find_block(preinit_dev.data());
|
||||||
if (dev == 0) {
|
if (dev == 0) {
|
||||||
@ -143,7 +143,7 @@ void MagiskInit::mount_preinit_dir() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MagiskInit::mount_system_root() {
|
bool MagiskInit::mount_system_root() noexcept {
|
||||||
LOGD("Mounting system_root\n");
|
LOGD("Mounting system_root\n");
|
||||||
|
|
||||||
// there's no /dev in stub cpio
|
// there's no /dev in stub cpio
|
||||||
@ -210,9 +210,10 @@ mount_root:
|
|||||||
return is_two_stage;
|
return is_two_stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::exec_init() {
|
void MagiskInit::exec_init() const noexcept {
|
||||||
// Unmount in reverse order
|
// Unmount in reverse order
|
||||||
for (auto &p : reversed(mount_list)) {
|
for (auto i = mount_list.size(); i > 0; --i) {
|
||||||
|
auto &p = mount_list[i - 1];
|
||||||
if (xumount2(p.data(), MNT_DETACH) == 0)
|
if (xumount2(p.data(), MNT_DETACH) == 0)
|
||||||
LOGD("Unmount [%s]\n", p.data());
|
LOGD("Unmount [%s]\n", p.data());
|
||||||
}
|
}
|
||||||
@ -220,7 +221,7 @@ void MagiskInit::exec_init() {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::prepare_data() {
|
void MagiskInit::prepare_data() const noexcept {
|
||||||
LOGD("Setup data tmp\n");
|
LOGD("Setup data tmp\n");
|
||||||
xmkdir("/data", 0755);
|
xmkdir("/data", 0755);
|
||||||
xmount("magisk", "/data", "tmpfs", 0, "mode=755");
|
xmount("magisk", "/data", "tmpfs", 0, "mode=755");
|
||||||
@ -230,7 +231,7 @@ void MagiskInit::prepare_data() {
|
|||||||
cp_afc("/overlay.d", "/data/overlay.d");
|
cp_afc("/overlay.d", "/data/overlay.d");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::setup_tmp(const char *path) {
|
void MagiskInit::setup_tmp(const char *path) const noexcept {
|
||||||
LOGD("Setup Magisk tmp at %s\n", path);
|
LOGD("Setup Magisk tmp at %s\n", path);
|
||||||
chdir("/data");
|
chdir("/data");
|
||||||
|
|
||||||
|
@ -257,17 +257,17 @@ static void extract_files(bool sbin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::parse_config_file() {
|
void MagiskInit::parse_config_file() noexcept {
|
||||||
parse_prop_file("/data/.backup/.magisk", [&](auto key, auto value) -> bool {
|
parse_prop_file("/data/.backup/.magisk", [&](auto key, auto value) -> bool {
|
||||||
if (key == "PREINITDEVICE") {
|
if (key == "PREINITDEVICE") {
|
||||||
preinit_dev = value;
|
preinit_dev = std::string(value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::patch_ro_root() {
|
void MagiskInit::patch_ro_root() noexcept {
|
||||||
mount_list.emplace_back("/data");
|
mount_list.emplace_back("/data");
|
||||||
parse_config_file();
|
parse_config_file();
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ void MagiskInit::patch_ro_root() {
|
|||||||
#define PRE_TMPSRC "/magisk"
|
#define PRE_TMPSRC "/magisk"
|
||||||
#define PRE_TMPDIR PRE_TMPSRC "/tmp"
|
#define PRE_TMPDIR PRE_TMPSRC "/tmp"
|
||||||
|
|
||||||
void MagiskInit::patch_rw_root() {
|
void MagiskInit::patch_rw_root() noexcept {
|
||||||
mount_list.emplace_back("/data");
|
mount_list.emplace_back("/data");
|
||||||
parse_config_file();
|
parse_config_file();
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void MagiskInit::patch_sepolicy(const char *in, const char *out) {
|
void MagiskInit::patch_sepolicy(const char *in, const char *out) const noexcept {
|
||||||
LOGD("Patching monolithic policy\n");
|
LOGD("Patching monolithic policy\n");
|
||||||
auto sepol = SePolicy::from_file(in);
|
auto sepol = SePolicy::from_file(in);
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ void MagiskInit::patch_sepolicy(const char *in, const char *out) {
|
|||||||
#define MOCK_LOAD SELINUXMOCK "/load"
|
#define MOCK_LOAD SELINUXMOCK "/load"
|
||||||
#define MOCK_ENFORCE SELINUXMOCK "/enforce"
|
#define MOCK_ENFORCE SELINUXMOCK "/enforce"
|
||||||
|
|
||||||
bool MagiskInit::hijack_sepolicy() {
|
bool MagiskInit::hijack_sepolicy() noexcept {
|
||||||
xmkdir(SELINUXMOCK, 0);
|
xmkdir(SELINUXMOCK, 0);
|
||||||
|
|
||||||
if (access("/system/bin/init", F_OK) == 0) {
|
if (access("/system/bin/init", F_OK) == 0) {
|
||||||
@ -76,10 +76,12 @@ bool MagiskInit::hijack_sepolicy() {
|
|||||||
|
|
||||||
LOGD("Hijack [%s]\n", buf);
|
LOGD("Hijack [%s]\n", buf);
|
||||||
|
|
||||||
|
decltype(mount_list) new_mount_list;
|
||||||
// Preserve sysfs and procfs for hijacking
|
// Preserve sysfs and procfs for hijacking
|
||||||
mount_list.erase(std::remove_if(
|
for (const auto &s: mount_list)
|
||||||
mount_list.begin(), mount_list.end(),
|
if (s != "/proc" && s != "/sys")
|
||||||
[](const string &s) { return s == "/proc" || s == "/sys"; }), mount_list.end());
|
new_mount_list.emplace_back(s);
|
||||||
|
new_mount_list.swap(mount_list);
|
||||||
|
|
||||||
mkfifo(MOCK_COMPAT, 0444);
|
mkfifo(MOCK_COMPAT, 0444);
|
||||||
xmount(MOCK_COMPAT, buf, nullptr, MS_BIND, nullptr);
|
xmount(MOCK_COMPAT, buf, nullptr, MS_BIND, nullptr);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void MagiskInit::first_stage() {
|
void MagiskInit::first_stage() const noexcept {
|
||||||
LOGI("First Stage Init\n");
|
LOGI("First Stage Init\n");
|
||||||
prepare_data();
|
prepare_data();
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ void MagiskInit::first_stage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::redirect_second_stage() {
|
void MagiskInit::redirect_second_stage() const noexcept {
|
||||||
// Patch init binary
|
// Patch init binary
|
||||||
int src = xopen("/init", O_RDONLY);
|
int src = xopen("/init", O_RDONLY);
|
||||||
int dest = xopen("/data/init", O_CREAT | O_WRONLY, 0);
|
int dest = xopen("/data/init", O_CREAT | O_WRONLY, 0);
|
||||||
@ -62,7 +62,7 @@ void MagiskInit::redirect_second_stage() {
|
|||||||
xmount("/data/init", "/init", nullptr, MS_BIND, nullptr);
|
xmount("/data/init", "/init", nullptr, MS_BIND, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::second_stage() {
|
void MagiskInit::second_stage() noexcept {
|
||||||
LOGI("Second Stage Init\n");
|
LOGI("Second Stage Init\n");
|
||||||
umount2("/init", MNT_DETACH);
|
umount2("/init", MNT_DETACH);
|
||||||
umount2(INIT_PATH, MNT_DETACH); // just in case
|
umount2(INIT_PATH, MNT_DETACH); // just in case
|
||||||
|
Loading…
x
Reference in New Issue
Block a user