Skip to content
Merged
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
Binary file modified manager/app/src/main/jniLibs/arm64-v8a/libmagiskboot.so
Binary file not shown.
107 changes: 68 additions & 39 deletions userspace/ksud/src/boot_patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,38 +153,40 @@ fn parse_kmi_from_boot(magiskboot: &Path, image: &PathBuf, workdir: &Path) -> Re
parse_kmi_from_kernel(&image_path, workdir)
}

fn do_cpio_cmd(magiskboot: &Path, workdir: &Path, cmd: &str) -> Result<()> {
fn do_cpio_cmd(magiskboot: &Path, workdir: &Path, cpio_path: &Path, cmd: &str) -> Result<()> {
let status = Command::new(magiskboot)
.current_dir(workdir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.arg("cpio")
.arg("ramdisk.cpio")
.arg(cpio_path)
.arg(cmd)
.status()?;

ensure!(status.success(), "magiskboot cpio {} failed", cmd);
Ok(())
}

fn is_magisk_patched(magiskboot: &Path, workdir: &Path) -> Result<bool> {
fn is_magisk_patched(magiskboot: &Path, workdir: &Path, cpio_path: &Path) -> Result<bool> {
let status = Command::new(magiskboot)
.current_dir(workdir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.args(["cpio", "ramdisk.cpio", "test"])
.arg("cpio")
.arg(cpio_path)
.arg("test")
.status()?;

// 0: stock, 1: magisk
Ok(status.code() == Some(1))
}

fn is_kernelsu_patched(magiskboot: &Path, workdir: &Path) -> Result<bool> {
fn is_kernelsu_patched(magiskboot: &Path, workdir: &Path, cpio_path: &Path) -> Result<bool> {
let status = Command::new(magiskboot)
.current_dir(workdir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.args(["cpio", "ramdisk.cpio", "exists kernelsu.ko"])
.arg("cpio")
.arg(cpio_path)
.arg("exists kernelsu.ko")
.status()?;

Ok(status.success())
Expand Down Expand Up @@ -234,17 +236,36 @@ pub fn restore(
.status()?;
ensure!(status.success(), "magiskboot unpack failed");

let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
let mut ramdisk = workdir.join("ramdisk.cpio");
if !ramdisk.exists() {
ramdisk = workdir.join("vendor_ramdisk").join("init_boot.cpio")
}
if !ramdisk.exists() {
ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
}
if !ramdisk.exists() {
bail!("No compatible ramdisk found.")
}
let ramdisk = ramdisk.as_path();
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir, ramdisk)?;
ensure!(is_kernelsu_patched, "boot image is not patched by KernelSU");

let mut new_boot = None;
let mut from_backup = false;

#[cfg(target_os = "android")]
if do_cpio_cmd(&magiskboot, workdir, &format!("exists {BACKUP_FILENAME}")).is_ok() {
if do_cpio_cmd(
&magiskboot,
workdir,
ramdisk,
&format!("exists {BACKUP_FILENAME}"),
)
.is_ok()
{
do_cpio_cmd(
&magiskboot,
workdir,
ramdisk,
&format!("extract {BACKUP_FILENAME} {BACKUP_FILENAME}"),
)?;
let sha = std::fs::read(workdir.join(BACKUP_FILENAME))?;
Expand All @@ -268,15 +289,12 @@ pub fn restore(

if new_boot.is_none() {
// remove kernelsu.ko
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
do_cpio_cmd(&magiskboot, workdir, ramdisk, "rm kernelsu.ko")?;

// if init.real exists, restore it
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
let status = do_cpio_cmd(&magiskboot, workdir, ramdisk, "exists init.real").is_ok();
if status {
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
} else {
let ramdisk = workdir.join("ramdisk.cpio");
std::fs::remove_file(ramdisk)?;
do_cpio_cmd(&magiskboot, workdir, ramdisk, "mv init.real init")?;
}

println!("- Repacking boot image");
Expand All @@ -285,7 +303,7 @@ pub fn restore(
.stdout(Stdio::null())
.stderr(Stdio::null())
.arg("repack")
.arg(bootimage.display().to_string())
.arg(&bootimage)
.status()?;
ensure!(status.success(), "magiskboot repack failed");
new_boot = Some(workdir.join("new-boot.img"));
Expand Down Expand Up @@ -409,7 +427,7 @@ fn do_patch(
let (bootimage, bootdevice) =
find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir)?;

let bootimage = bootimage.display().to_string();
let bootimage = bootimage.as_path();

// try extract magiskboot/bootctl
let _ = assets::ensure_binaries(false);
Expand Down Expand Up @@ -438,48 +456,54 @@ fn do_patch(
assets::copy_assets_to_file("ksuinit", init_file).context("copy ksuinit failed")?;
}

// magiskboot unpack boot.img
// magiskboot cpio ramdisk.cpio 'cp init init.real'
// magiskboot cpio ramdisk.cpio 'add 0755 ksuinit init'
// magiskboot cpio ramdisk.cpio 'add 0755 <kmod> kernelsu.ko'

println!("- Unpacking boot image");
let status = Command::new(&magiskboot)
.current_dir(workdir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.arg("unpack")
.arg(&bootimage)
.arg(bootimage)
.status()?;
ensure!(status.success(), "magiskboot unpack failed");

let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir)?;
ensure!(
no_ramdisk || !is_magisk_patched,
"Cannot work with Magisk patched image"
);
let mut ramdisk = workdir.join("ramdisk.cpio");
if !ramdisk.exists() {
ramdisk = workdir.join("vendor_ramdisk").join("init_boot.cpio")
}
if !ramdisk.exists() {
ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
}
if !ramdisk.exists() {
bail!("No compatible ramdisk found.");
}
let ramdisk = ramdisk.as_path();
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir, ramdisk)?;
ensure!(!is_magisk_patched, "Cannot work with Magisk patched image");

println!("- Adding KernelSU LKM");
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir, ramdisk)?;

let mut need_backup = false;
if !is_kernelsu_patched {
// kernelsu.ko is not exist, backup init if necessary
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
let status = do_cpio_cmd(&magiskboot, workdir, ramdisk, "exists init");
if status.is_ok() {
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
do_cpio_cmd(&magiskboot, workdir, ramdisk, "mv init init.real")?;
}

need_backup = flash;
}

do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
do_cpio_cmd(&magiskboot, workdir, ramdisk, "add 0755 init init")?;
do_cpio_cmd(
&magiskboot,
workdir,
ramdisk,
"add 0755 kernelsu.ko kernelsu.ko",
)?;

#[cfg(target_os = "android")]
if need_backup {
if let Err(e) = do_backup(&magiskboot, workdir, &bootimage) {
if let Err(e) = do_backup(&magiskboot, workdir, ramdisk, bootimage) {
println!("- Backup stock image failed: {e}");
}
}
Expand All @@ -491,7 +515,7 @@ fn do_patch(
.stdout(Stdio::null())
.stderr(Stdio::null())
.arg("repack")
.arg(&bootimage)
.arg(bootimage)
.status()?;
ensure!(status.success(), "magiskboot repack failed");
let new_boot = workdir.join("new-boot.img");
Expand Down Expand Up @@ -546,7 +570,7 @@ fn calculate_sha1(file_path: impl AsRef<Path>) -> Result<String> {
}

#[cfg(target_os = "android")]
fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
fn do_backup(magiskboot: &Path, workdir: &Path, cpio_path: &Path, image: &Path) -> Result<()> {
let sha1 = calculate_sha1(image)?;
let filename = format!("{KSU_BACKUP_FILE_PREFIX}{sha1}");

Expand All @@ -558,6 +582,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
do_cpio_cmd(
magiskboot,
workdir,
cpio_path,
&format!("add 0755 {BACKUP_FILENAME} {BACKUP_FILENAME}"),
)?;
println!("- Stock image has been backup to");
Expand Down Expand Up @@ -655,8 +680,12 @@ fn find_boot_image(

let init_boot_exist =
Path::new(&format!("/dev/block/by-name/init_boot{slot_suffix}")).exists();
let vendor_boot_exist =
Path::new(&format!("/dev/block/by-name/vendor_boot{slot_suffix}")).exists();
let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init {
format!("/dev/block/by-name/init_boot{slot_suffix}")
} else if !is_replace_kernel && vendor_boot_exist && !skip_init {
format!("/dev/block/by-name/vendor_boot{slot_suffix}")
} else {
format!("/dev/block/by-name/boot{slot_suffix}")
};
Expand Down
Loading