Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions native/src/init/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ impl MagiskInit {
Self {
preinit_dev: String::new(),
mount_list: Vec::new(),
rc_list: Vec::new(),
overlay_con: Vec::new(),
argv,
config: BootConfig {
Expand Down
7 changes: 6 additions & 1 deletion native/src/init/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use logging::setup_klog;
// Has to be pub so all symbols in that crate is included
pub use magiskpolicy;
use mount::{is_device_mounted, switch_root};
use rootdir::{OverlayAttr, inject_magisk_rc};
use rootdir::{OverlayAttr, inject_magisk_rc, inject_custom_rc};

#[path = "../include/consts.rs"]
mod consts;
Expand Down Expand Up @@ -41,6 +41,7 @@ pub mod ffi {
struct MagiskInit {
preinit_dev: String,
mount_list: Vec<String>,
rc_list: Vec<String>,
argv: *mut *mut c_char,
config: BootConfig,
overlay_con: Vec<OverlayAttr>,
Expand All @@ -66,6 +67,7 @@ pub mod ffi {
#[namespace = "rust"]
extern "Rust" {
fn setup_klog();
fn inject_custom_rc(mut rc_list: Vec<String>, fd: i32, tmp_dir: Utf8CStrRef);
fn inject_magisk_rc(fd: i32, tmp_dir: Utf8CStrRef);
fn switch_root(path: Utf8CStrRef);
fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool;
Expand All @@ -88,6 +90,8 @@ pub mod ffi {
fn mount_overlay(self: &mut MagiskInit, dest: Utf8CStrRef);
fn handle_sepolicy(self: &mut MagiskInit);
fn restore_overlay_contexts(self: &MagiskInit);
fn load_overlay_rc(self: &mut MagiskInit, overlay: &Utf8CStrRef, module_path: &Utf8CStrRef);
fn handle_modules_rc(self: &mut MagiskInit, root_dir: &Utf8CStrRef);
}
unsafe extern "C++" {
// Used in Rust
Expand All @@ -100,6 +104,7 @@ pub mod ffi {
fn collect_devices(self: &MagiskInit);
fn mount_preinit_dir(self: &mut MagiskInit);
unsafe fn find_block(self: &MagiskInit, partname: *const c_char) -> u64;
unsafe fn patch_rc_scripts(self: &MagiskInit, src_path: *const c_char, tmp_path: *const c_char, writable: bool) -> bool;
unsafe fn patch_fissiond(self: &mut MagiskInit, tmp_path: *const c_char);
}
}
47 changes: 8 additions & 39 deletions native/src/init/rootdir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@

using namespace std;

static vector<string> rc_list;

#define NEW_INITRC_DIR "/system/etc/init/hw"
#define INIT_RC "init.rc"

Expand Down Expand Up @@ -41,7 +39,7 @@ static bool unxz(int fd, rust::Slice<const uint8_t> bytes) {
}

// When return true, run patch_fissiond
static bool patch_rc_scripts(const char *src_path, const char *tmp_path, bool writable) {
bool MagiskInit::patch_rc_scripts(const char *src_path, const char *tmp_path, bool writable) const noexcept {
auto src_dir = xopen_dir(src_path);
if (!src_dir) return false;
int src_fd = dirfd(src_dir.get());
Expand Down Expand Up @@ -93,12 +91,7 @@ static bool patch_rc_scripts(const char *src_path, const char *tmp_path, bool wr
fprintf(dest.get(), "\n");

// Inject custom rc scripts
for (auto &script : rc_list) {
// Replace template arguments of rc scripts with dynamic paths
replace_all(script, "${MAGISKTMP}", tmp_path);
fprintf(dest.get(), "\n%s\n", script.data());
}
rc_list.clear();
rust::inject_custom_rc(rc_list, fileno(dest.get()), tmp_path);

// Inject Magisk rc scripts
rust::inject_magisk_rc(fileno(dest.get()), tmp_path);
Expand Down Expand Up @@ -173,34 +166,6 @@ void MagiskInit::patch_fissiond(const char *tmp_path) noexcept {
}
}

static void load_overlay_rc(const char *overlay) {
auto dir = open_dir(overlay);
if (!dir) return;

int dfd = dirfd(dir.get());
// Do not allow overwrite init.rc
unlinkat(dfd, INIT_RC, 0);

// '/' + name + '\0'
char buf[NAME_MAX + 2];
buf[0] = '/';
for (dirent *entry; (entry = xreaddir(dir.get()));) {
if (!str_ends(entry->d_name, ".rc")) {
continue;
}
strscpy(buf + 1, entry->d_name, sizeof(buf) - 1);
if (access(buf, F_OK) == 0) {
LOGD("Replace rc script [%s]\n", entry->d_name);
} else {
LOGD("Found rc script [%s]\n", entry->d_name);
int rc = xopenat(dfd, entry->d_name, O_RDONLY | O_CLOEXEC);
rc_list.push_back(full_read(rc));
close(rc);
unlinkat(dfd, entry->d_name, 0);
}
}
}

static void recreate_sbin(const char *mirror, bool use_bind_mount) {
auto dp = xopen_dir(mirror);
int src = dirfd(dp.get());
Expand Down Expand Up @@ -305,12 +270,14 @@ void MagiskInit::patch_ro_root() noexcept {
close(dest);
}

load_overlay_rc(ROOTOVL);
load_overlay_rc(ROOTOVL, "");
if (access(ROOTOVL "/sbin", F_OK) == 0) {
// Move files in overlay.d/sbin into tmp_dir
mv_path(ROOTOVL "/sbin", ".");
}

handle_modules_rc(ROOTOVL);

// Patch init.rc
bool p;
if (access(NEW_INITRC_DIR "/" INIT_RC, F_OK) == 0) {
Expand Down Expand Up @@ -346,11 +313,13 @@ void MagiskInit::patch_rw_root() noexcept {
link_path("/sbin", "/root");

// Handle overlays
load_overlay_rc("/overlay.d");
load_overlay_rc("/overlay.d", "");
mv_path("/overlay.d", "/");
rm_rf("/data/overlay.d");
rm_rf("/.backup");

handle_modules_rc("/");

// Patch init.rc
if (patch_rc_scripts("/", "/sbin", true))
patch_fissiond("/sbin");
Expand Down
99 changes: 89 additions & 10 deletions native/src/init/rootdir.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
use crate::consts::{ROOTMNT, ROOTOVL};
use crate::consts::{PREINITMIRR, ROOTMNT, ROOTOVL};
use crate::ffi::MagiskInit;
use base::libc::{O_CREAT, O_RDONLY, O_WRONLY};
use base::{
BufReadExt, Directory, FsPathBuilder, LoggedResult, ResultExt, Utf8CStr, Utf8CString,
clone_attr, cstr, debug,
};
use std::io::BufReader;
use std::{
fs::File,
io::Write,
mem,
os::fd::{FromRawFd, RawFd},
clone_attr,
const_format::concatcp,
cstr, debug,
libc::{O_CLOEXEC, O_CREAT, O_RDONLY, O_WRONLY},
};
use std::{fs::File, io::BufReader, io::Read, io::Write, mem, os::fd::FromRawFd, os::fd::RawFd};

pub fn inject_magisk_rc(fd: RawFd, tmp_dir: &Utf8CStr) {
debug!("Injecting magisk rc");
Expand Down Expand Up @@ -43,6 +39,17 @@ on property:init.svc.zygote=stopped
mem::forget(file)
}

pub fn inject_custom_rc(mut rc_list: Vec<String>, fd: RawFd, tmp_dir: &Utf8CStr) {
let mut file = unsafe { File::from_raw_fd(fd) };
rc_list.iter().for_each(|rc| {
// Replace template arguments of rc scripts with dynamic paths
let rc = rc.replace("${MAGISKTMP}", tmp_dir.as_str());
write!(file, "\n{}\n", rc).ok();
});
mem::forget(file);
rc_list.clear();
}

pub struct OverlayAttr(Utf8CString, Utf8CString);

impl MagiskInit {
Expand All @@ -59,6 +66,78 @@ impl MagiskInit {
}
}

pub(crate) fn load_overlay_rc(&mut self, overlay: &Utf8CStr, module_path: &Utf8CStr) {
if let Ok(mut dir) = Directory::open(overlay) {
let init_rc = cstr::buf::dynamic(256)
.join_path(overlay)
.join_path("init.rc");
if init_rc.exists() {
// Do not allow overwrite init.rc
init_rc.remove().log_ok();
}
loop {
match dir.read() {
Ok(None) => break,
Ok(Some(e)) => {
let recursive = cstr::buf::dynamic(256).join_path(module_path).exists();
if (recursive && e.is_dir()) || e.is_file() {
let buf = &mut cstr::buf::dynamic(256);
e.resolve_path(buf).log_ok();
if e.is_file() && buf.ends_with(".rc") {
let mut path;
if recursive {
path = cstr::buf::dynamic(256)
.join_path(buf.replace(module_path.as_str(), ""));
} else {
path =
cstr::buf::dynamic(256).join_path("/").join_path(e.name());
}
if path.exists() {
debug!("Replace rc script [{}] -> [{}]", path, buf);
} else {
path = cstr::buf::dynamic(256).join_path(buf);
debug!("Found rc script [{}]", path);
let mut rc_content = String::new();
if let Ok(mut file) = path.open(O_RDONLY | O_CLOEXEC) {
file.read_to_string(&mut rc_content).log_ok();
self.rc_list.push(rc_content);
drop(file);
path.remove().log_ok();
}
}
} else if e.is_dir() {
self.load_overlay_rc(buf, module_path);
}
} else {
continue;
}
}
Err(_) => break,
}
}
}
}

pub(crate) fn handle_modules_rc(&mut self, root_dir: &Utf8CStr) {
if let Ok(mut dir) = Directory::open(cstr!(concatcp!("/data/", PREINITMIRR))) {
loop {
match dir.read() {
Ok(None) => break,
Ok(Some(e)) if e.is_dir() => {
let buf = &mut cstr::buf::dynamic(256);
e.resolve_path(buf).log_ok();
let path = cstr::buf::dynamic(256).join_path(&mut *buf);
self.load_overlay_rc(&path, buf);
let desc_path = cstr::buf::dynamic(256).join_path(root_dir);
path.copy_to(&desc_path).log_ok();
}
Ok(_) => continue,
Err(_) => break,
}
}
}
}

fn mount_impl(
&mut self,
src_dir: &Utf8CStr,
Expand Down
29 changes: 26 additions & 3 deletions scripts/util_functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,21 @@ copy_preinit_files() {
cat $r
echo
done > $PREINITDIR/sepolicy.rule

# Copy all enabled rc
find "$PREINITDIR/" -mindepth 1 -maxdepth 1 -type d -exec rm -rf {} \;
find /data/adb/modules* -mindepth 1 -maxdepth 1 -type d 2>/dev/null | while read -r MODDIR; do
local MODID=$(basename "$MODDIR")
[ -f "$MODDIR"/disable ] && continue
[ -f "$MODDIR"/remove ] && continue
[ -f "$MODDIR"/update ] && continue
find "$MODDIR" -mindepth 1 -type f -name "*.rc" | while read -r file; do
local path="${file%/*}"
path="$PREINITDIR/$MODID${path/$MODDIR/}"
mkdir -p "$path"
cp "$file" "$path/"
done
done
}

#################
Expand Down Expand Up @@ -720,9 +735,17 @@ install_module() {
cp -af $MODPATH/module.prop /data/adb/modules/$MODID/module.prop
fi

# Copy over custom sepolicy rules
if [ -f $MODPATH/sepolicy.rule ]; then
ui_print "- Installing custom sepolicy rules"
find "$MODPATH" -mindepth 1 -type f -name "init.rc" -exec rm -f {} \;
find "$MODPATH" -mindepth 1 -type f -name "*.rc" | while read -r file; do
local path="${file/$MODPATH/}"
if [ ! -f "$path" ]; then
mv "$file" "$MODPATH"
fi
rc=true
done
# Copy over custom sepolicy rules and rc
if [ -f $MODPATH/sepolicy.rule ] || "$rc"; then
ui_print "- Installing custom sepolicy rules or rc script"
copy_preinit_files
fi

Expand Down
Loading