mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-05-08 05:26:53 +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
|
||||
if (access("/proc/cmdline", F_OK) != 0) {
|
||||
xmkdir("/proc", 0755);
|
||||
@ -86,7 +86,7 @@ static void recovery() {
|
||||
rm_rf("/.backup");
|
||||
}
|
||||
|
||||
void MagiskInit::legacy_system_as_root() {
|
||||
void MagiskInit::legacy_system_as_root() noexcept {
|
||||
LOGI("Legacy SAR Init\n");
|
||||
prepare_data();
|
||||
bool is_two_stage = mount_system_root();
|
||||
@ -96,7 +96,7 @@ void MagiskInit::legacy_system_as_root() {
|
||||
patch_ro_root();
|
||||
}
|
||||
|
||||
void MagiskInit::rootfs() {
|
||||
void MagiskInit::rootfs() noexcept {
|
||||
LOGI("RootFS Init\n");
|
||||
prepare_data();
|
||||
LOGD("Restoring /init\n");
|
||||
@ -104,7 +104,7 @@ void MagiskInit::rootfs() {
|
||||
patch_rw_root();
|
||||
}
|
||||
|
||||
void MagiskInit::start() {
|
||||
void MagiskInit::start() noexcept {
|
||||
if (argv[1] != nullptr && argv[1] == "selinux_setup"sv)
|
||||
second_stage();
|
||||
else if (config.skip_initramfs)
|
||||
@ -132,6 +132,5 @@ int main(int argc, char *argv[]) {
|
||||
if (getpid() != 1)
|
||||
return 1;
|
||||
|
||||
MagiskInit init(argv);
|
||||
init.start();
|
||||
rust::start_magisk_init(argv);
|
||||
}
|
||||
|
@ -12,40 +12,3 @@ bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes);
|
||||
bool check_two_stage();
|
||||
const char *backup_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};
|
||||
// Has to be pub so all symbols in that crate is included
|
||||
pub use magiskpolicy;
|
||||
use crate::ffi::{BootConfig, MagiskInit};
|
||||
|
||||
mod logging;
|
||||
mod mount;
|
||||
@ -31,6 +32,13 @@ pub mod ffi {
|
||||
partition_map: Vec<KeyValue>,
|
||||
}
|
||||
|
||||
struct MagiskInit {
|
||||
preinit_dev: String,
|
||||
mount_list: Vec<String>,
|
||||
argv: *mut *mut c_char,
|
||||
config: BootConfig,
|
||||
}
|
||||
|
||||
#[namespace = "rust"]
|
||||
extern "Rust" {
|
||||
fn setup_klog();
|
||||
@ -39,6 +47,7 @@ pub mod ffi {
|
||||
fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool;
|
||||
fn collect_overlay_contexts(src: Utf8CStrRef);
|
||||
fn reset_overlay_contexts();
|
||||
unsafe fn start_magisk_init(argv: *mut *mut c_char);
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
@ -51,5 +60,53 @@ pub mod ffi {
|
||||
fn print(self: &BootConfig);
|
||||
type 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];
|
||||
devinfo dev{};
|
||||
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())
|
||||
collect_devices();
|
||||
|
||||
@ -103,7 +103,7 @@ dev_t MagiskInit::find_block(const char *partname) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MagiskInit::mount_preinit_dir() {
|
||||
void MagiskInit::mount_preinit_dir() const noexcept {
|
||||
if (preinit_dev.empty()) return;
|
||||
auto dev = find_block(preinit_dev.data());
|
||||
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");
|
||||
|
||||
// there's no /dev in stub cpio
|
||||
@ -210,9 +210,10 @@ mount_root:
|
||||
return is_two_stage;
|
||||
}
|
||||
|
||||
void MagiskInit::exec_init() {
|
||||
void MagiskInit::exec_init() const noexcept {
|
||||
// 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)
|
||||
LOGD("Unmount [%s]\n", p.data());
|
||||
}
|
||||
@ -220,7 +221,7 @@ void MagiskInit::exec_init() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void MagiskInit::prepare_data() {
|
||||
void MagiskInit::prepare_data() const noexcept {
|
||||
LOGD("Setup data tmp\n");
|
||||
xmkdir("/data", 0755);
|
||||
xmount("magisk", "/data", "tmpfs", 0, "mode=755");
|
||||
@ -230,7 +231,7 @@ void MagiskInit::prepare_data() {
|
||||
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);
|
||||
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 {
|
||||
if (key == "PREINITDEVICE") {
|
||||
preinit_dev = value;
|
||||
preinit_dev = std::string(value);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void MagiskInit::patch_ro_root() {
|
||||
void MagiskInit::patch_ro_root() noexcept {
|
||||
mount_list.emplace_back("/data");
|
||||
parse_config_file();
|
||||
|
||||
@ -356,7 +356,7 @@ void MagiskInit::patch_ro_root() {
|
||||
#define PRE_TMPSRC "/magisk"
|
||||
#define PRE_TMPDIR PRE_TMPSRC "/tmp"
|
||||
|
||||
void MagiskInit::patch_rw_root() {
|
||||
void MagiskInit::patch_rw_root() noexcept {
|
||||
mount_list.emplace_back("/data");
|
||||
parse_config_file();
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
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");
|
||||
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_ENFORCE SELINUXMOCK "/enforce"
|
||||
|
||||
bool MagiskInit::hijack_sepolicy() {
|
||||
bool MagiskInit::hijack_sepolicy() noexcept {
|
||||
xmkdir(SELINUXMOCK, 0);
|
||||
|
||||
if (access("/system/bin/init", F_OK) == 0) {
|
||||
@ -76,10 +76,12 @@ bool MagiskInit::hijack_sepolicy() {
|
||||
|
||||
LOGD("Hijack [%s]\n", buf);
|
||||
|
||||
decltype(mount_list) new_mount_list;
|
||||
// Preserve sysfs and procfs for hijacking
|
||||
mount_list.erase(std::remove_if(
|
||||
mount_list.begin(), mount_list.end(),
|
||||
[](const string &s) { return s == "/proc" || s == "/sys"; }), mount_list.end());
|
||||
for (const auto &s: mount_list)
|
||||
if (s != "/proc" && s != "/sys")
|
||||
new_mount_list.emplace_back(s);
|
||||
new_mount_list.swap(mount_list);
|
||||
|
||||
mkfifo(MOCK_COMPAT, 0444);
|
||||
xmount(MOCK_COMPAT, buf, nullptr, MS_BIND, nullptr);
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
void MagiskInit::first_stage() {
|
||||
void MagiskInit::first_stage() const noexcept {
|
||||
LOGI("First Stage Init\n");
|
||||
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
|
||||
int src = xopen("/init", O_RDONLY);
|
||||
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);
|
||||
}
|
||||
|
||||
void MagiskInit::second_stage() {
|
||||
void MagiskInit::second_stage() noexcept {
|
||||
LOGI("Second Stage Init\n");
|
||||
umount2("/init", MNT_DETACH);
|
||||
umount2(INIT_PATH, MNT_DETACH); // just in case
|
||||
|
Loading…
x
Reference in New Issue
Block a user