From 6ef8e548a3610f331bdeba28e79afa41b6095834 Mon Sep 17 00:00:00 2001 From: Andrew Gunnerson Date: Sat, 3 Feb 2024 13:46:28 -0500 Subject: [PATCH] Add support for Magisk v27.0 Upstream Magisk now xz-compresses files in modifies in the ramdisk. This commit also implements the same in avbroot's MagiskRootPatcher. Signed-off-by: Andrew Gunnerson --- avbroot/src/patch/boot.rs | 92 ++++++++++++++++++++++++++++++--------- e2e/e2e.toml | 8 ++-- e2e/src/main.rs | 3 +- 3 files changed, 77 insertions(+), 26 deletions(-) diff --git a/avbroot/src/patch/boot.rs b/avbroot/src/patch/boot.rs index 95a343c..3b3024d 100644 --- a/avbroot/src/patch/boot.rs +++ b/avbroot/src/patch/boot.rs @@ -140,10 +140,13 @@ impl MagiskRootPatcher { // RULESDEVICE config option, which stored the writable block device as an // rdev major/minor pair, which was not consistent across reboots and was // replaced by PREINITDEVICE - const VERS_SUPPORTED: &'static [Range] = &[25102..25207, 25211..26500]; + const VERS_SUPPORTED: &'static [Range] = &[25102..25207, 25211..27100]; const VER_PREINIT_DEVICE: Range = 25211..Self::VERS_SUPPORTED[Self::VERS_SUPPORTED.len() - 1].end; const VER_RANDOM_SEED: Range = 25211..26103; + const VER_PATCH_VBMETA: Range = Self::VERS_SUPPORTED[0].start..26202; + const VER_XZ_BACKUP: Range = + 26403..Self::VERS_SUPPORTED[Self::VERS_SUPPORTED.len() - 1].end; pub fn new( path: &Path, @@ -216,6 +219,18 @@ impl MagiskRootPatcher { } } + fn xz_compress(reader: impl Read, cancel_signal: &AtomicBool) -> Result> { + let stream = Stream::new_easy_encoder(9, Check::Crc32)?; + let raw_writer = Cursor::new(Vec::new()); + let mut writer = XzEncoder::new_stream(raw_writer, stream); + + stream::copy(reader, &mut writer, cancel_signal)?; + + let raw_writer = writer.finish()?; + + Ok(raw_writer.into_inner()) + } + /// Compare old and new ramdisk entry lists, creating the Magisk `.backup/` /// directory structure. `.backup/.rmlist` will contain a sorted list of /// NULL-terminated strings, listing which files were newly added or @@ -223,7 +238,12 @@ impl MagiskRootPatcher { /// entries as `.backup/`. /// /// Both lists and entries within the lists may be mutated. - fn apply_magisk_backup(old_entries: &mut [CpioEntry], new_entries: &mut Vec) { + fn apply_magisk_backup( + old_entries: &mut [CpioEntry], + new_entries: &mut Vec, + xz_compress: bool, + cancel_signal: &AtomicBool, + ) -> Result<()> { cpio::sort(old_entries); cpio::sort(new_entries); @@ -269,10 +289,37 @@ impl MagiskRootPatcher { new_entries.push(CpioEntry::new_directory(b".backup", 0)); for old_entry in to_back_up { - let mut new_entry = old_entry.clone(); - new_entry.path = b".backup/".to_vec(); - new_entry.path.extend(&old_entry.path); - new_entries.push(new_entry); + let mut new_path = b".backup/".to_vec(); + new_path.extend(&old_entry.path); + + let mut new_data = None; + + if xz_compress { + if let CpioEntryData::Data(data) = &old_entry.data { + new_path.extend(b".xz"); + + let reader = Cursor::new(data); + let buf = Self::xz_compress(reader, cancel_signal)?; + new_data = Some(CpioEntryData::Data(buf)); + } + } + + new_entries.push(CpioEntry { + path: new_path, + data: new_data.unwrap_or_else(|| old_entry.data.clone()), + inode: old_entry.inode, + file_type: old_entry.file_type, + file_mode: old_entry.file_mode, + uid: old_entry.uid, + gid: old_entry.gid, + nlink: old_entry.nlink, + mtime: old_entry.mtime, + dev_maj: old_entry.dev_maj, + dev_min: old_entry.dev_min, + rdev_maj: old_entry.rdev_maj, + rdev_min: old_entry.rdev_min, + crc32: old_entry.crc32, + }); } new_entries.push(CpioEntry::new_file( @@ -280,6 +327,8 @@ impl MagiskRootPatcher { 0, CpioEntryData::Data(rm_list), )); + + Ok(()) } } @@ -347,7 +396,9 @@ impl BootImagePatch for MagiskRootPatcher { )); } - // Add xz-compressed magisk32 and magisk64. + // Add xz-compressed magisk32 and magisk64. We currently unconditionally + // include magisk32 because the boot image itself doesn't contain + // sufficient information to determine if a device is 64-bit only. let mut xz_files = HashMap::<&str, &[u8]>::new(); xz_files.insert( "lib/armeabi-v7a/libmagisk32.so", @@ -366,29 +417,28 @@ impl BootImagePatch for MagiskRootPatcher { for (source, target) in xz_files { let reader = zip.by_name(source)?; - let raw_writer = Cursor::new(vec![]); - let stream = Stream::new_easy_encoder(9, Check::Crc32)?; - let mut writer = XzEncoder::new_stream(raw_writer, stream); + let buf = Self::xz_compress(reader, cancel_signal)?; - stream::copy(reader, &mut writer, cancel_signal)?; - - let raw_writer = writer.finish()?; - - entries.push(CpioEntry::new_file( - target, - 0o644, - CpioEntryData::Data(raw_writer.into_inner()), - )); + entries.push(CpioEntry::new_file(target, 0o644, CpioEntryData::Data(buf))); } // Create Magisk .backup directory structure. - Self::apply_magisk_backup(&mut old_entries, &mut entries); + Self::apply_magisk_backup( + &mut old_entries, + &mut entries, + Self::VER_XZ_BACKUP.contains(&self.version), + cancel_signal, + )?; // Create Magisk config. let mut magisk_config = String::new(); magisk_config.push_str("KEEPVERITY=true\n"); magisk_config.push_str("KEEPFORCEENCRYPT=true\n"); - magisk_config.push_str("PATCHVBMETAFLAG=false\n"); + + if Self::VER_PATCH_VBMETA.contains(&self.version) { + magisk_config.push_str("PATCHVBMETAFLAG=false\n"); + } + magisk_config.push_str("RECOVERYMODE=false\n"); if Self::VER_PREINIT_DEVICE.contains(&self.version) { diff --git a/e2e/e2e.toml b/e2e/e2e.toml index a671be2..0026faf 100644 --- a/e2e/e2e.toml +++ b/e2e/e2e.toml @@ -47,7 +47,7 @@ data.ramdisks = ["otacerts"] [profile.pixel_v4_gki.hashes] original = "f9477a35e3b60a495e49431c61e3897f11775f453a6a9897ead568357c963618" -patched = "eb045799a514300727357a5ec471f9b04b276991daf4fd72f17f840b2a7dd1b8" +patched = "d3436650b4e0c60688dafb1472fa5fe95e67d19a8fad2da4850ffaa739d44574" # Google Pixel 6a # What's unique: boot (boot v4, no ramdisk) + vendor_boot (vendor v4, 2 ramdisks) @@ -81,7 +81,7 @@ data.ramdisks = ["init_and_otacerts", "dlkm"] [profile.pixel_v4_non_gki.hashes] original = "021b4510bc244f5f686fbff89eb2058ec9c96a2949c2fe8caa7750a78d593225" -patched = "5d1a36e2eb18d9d905ab397d4eaf2d7e7c94da6e7573afe3d4e4367841171fe3" +patched = "0f90ae4c26a54a735d48e13e98bea73b6d1c026b0e95fa5b4b26179a1d6bdc86" # Google Pixel 4a 5G # What's unique: boot (boot v3) + vendor_boot (vendor v3) @@ -116,7 +116,7 @@ data.ramdisks = ["otacerts"] [profile.pixel_v3.hashes] original = "12221a69ff32e137d5f19b61f576fc6b33f0973c4a81da7722c640554ff4bc4e" -patched = "e2049c6eba6990fc5ce30130af470c134a5ccc42947dcdd398f737fbca7ae44a" +patched = "0a92969bbd7cb30071a0799eb20028546d1cec3e6ec1ca4d7e1fe7776f1399fc" # Google Pixel 4a # What's unique: boot (boot v2) @@ -145,4 +145,4 @@ data.deps = ["system"] [profile.pixel_v2.hashes] original = "8b38d2d999b5b6e240e894f669e9e2643b3764c108d53bb7b02447da725e7c18" -patched = "16f56e3d02c08bb646d8d0694ce77a6edb02a613bbcff14b10ead4a448c3dc00" +patched = "85b411947145e89cdc7f71b7109a12586f4dbddce3021f0f96172fc465c189d6" diff --git a/e2e/src/main.rs b/e2e/src/main.rs index 6be863b..3d6c4dd 100644 --- a/e2e/src/main.rs +++ b/e2e/src/main.rs @@ -817,11 +817,12 @@ fn create_fake_magisk(output: &Path) -> Result<()> { "lib/x86_64/libmagiskinit.so", ] { zip_writer.start_file(path, FileOptions::default())?; + write!(zip_writer, "dummy contents for {path}")?; } // avbroot looks for the version number in this file. zip_writer.start_file("assets/util_functions.sh", FileOptions::default())?; - zip_writer.write_all(b"MAGISK_VER_CODE=26400\n")?; + zip_writer.write_all(b"MAGISK_VER_CODE=27000\n")?; Ok(()) }