diff --git a/native/src/base/include/base.hpp b/native/src/base/include/base.hpp index 1518ed48c..2b57e5dcf 100644 --- a/native/src/base/include/base.hpp +++ b/native/src/base/include/base.hpp @@ -1,8 +1,8 @@ #pragma once -#include "../missing.hpp" #include "../xwrap.hpp" #include "../files.hpp" #include "../misc.hpp" #include "../logging.hpp" +#include "../missing.hpp" #include "../base-rs.hpp" diff --git a/native/src/base/misc.hpp b/native/src/base/misc.hpp index 125b3a116..70ec9ae33 100644 --- a/native/src/base/misc.hpp +++ b/native/src/base/misc.hpp @@ -179,10 +179,8 @@ struct byte_data : public byte_view { byte_data() = default; byte_data(void *buf, size_t sz) : byte_view(buf, sz) {} - // We don't want mutable references to be copied or moved around; pass bytes as byte_view - // Subclasses are free to implement their own constructors - byte_data(const byte_data &) = delete; - byte_data(byte_data &&) = delete; + // byte_data, or any of its subclass, can be copied as byte_data + byte_data(const byte_data &o) : byte_data(o._buf, o._sz) {} // Transparent conversion from common C++ types to mutable byte references byte_data(std::string &s, bool with_nul = true) @@ -194,9 +192,7 @@ struct byte_data : public byte_view { operator rust::Slice() { return rust::Slice(_buf, _sz); } using byte_view::buf; - using byte_view::sz; uint8_t *buf() { return _buf; } - size_t &sz() { return _sz; } void swap(byte_data &o); std::vector patch(byte_view from, byte_view to); diff --git a/native/src/base/missing.hpp b/native/src/base/missing.hpp index ff5e948b0..c33f3138c 100644 --- a/native/src/base/missing.hpp +++ b/native/src/base/missing.hpp @@ -10,7 +10,7 @@ static inline int fexecve(int fd, char* const* argv, char* const* envp) { syscall(__NR_execveat, fd, "", argv, envp, AT_EMPTY_PATH); if (errno == ENOSYS) { char buf[256]; - std::snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); + ssprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); execve(buf, argv, envp); } return -1; diff --git a/native/src/base/stream.cpp b/native/src/base/stream.cpp index 20edff22c..b7a775c73 100644 --- a/native/src/base/stream.cpp +++ b/native/src/base/stream.cpp @@ -132,7 +132,7 @@ void chunk_out_stream::finalize() { } ssize_t byte_channel::read(void *buf, size_t len) { - len = std::min((size_t) len, _data.sz() - _pos); + len = std::min((size_t) len, _data._sz- _pos); memcpy(buf, _data.buf() + _pos, len); _pos += len; return len; @@ -142,7 +142,7 @@ bool byte_channel::write(const void *buf, size_t len) { resize(_pos + len); memcpy(_data.buf() + _pos, buf, len); _pos += len; - _data.sz() = std::max(_data.sz(), _pos); + _data._sz= std::max(_data.sz(), _pos); return true; } @@ -153,7 +153,7 @@ off_t byte_channel::seek(off_t off, int whence) { np = _pos + off; break; case SEEK_END: - np = _data.sz() + off; + np = _data._sz+ off; break; case SEEK_SET: np = off; diff --git a/native/src/boot/cpio.rs b/native/src/boot/cpio.rs index 412781d35..1da77731b 100644 --- a/native/src/boot/cpio.rs +++ b/native/src/boot/cpio.rs @@ -1,13 +1,3 @@ -use crate::ramdisk::MagiskCpio; -use anyhow::{anyhow, Context}; -use base::libc::{ - c_char, dev_t, gid_t, major, makedev, minor, mknod, mmap, mode_t, munmap, uid_t, MAP_FAILED, - MAP_PRIVATE, PROT_READ, S_IFBLK, S_IFCHR, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, S_IRGRP, S_IROTH, - S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR, -}; -use base::{ptr_to_str_result, ResultExt, WriteExt}; -use clap::{Parser, Subcommand}; -use size::{Base, Size, Style}; use std::collections::BTreeMap; use std::ffi::CStr; use std::fmt::{Display, Formatter}; @@ -19,6 +9,19 @@ use std::os::unix::fs::{symlink, DirBuilderExt, FileTypeExt, MetadataExt}; use std::path::Path; use std::process::exit; +use anyhow::{anyhow, Context}; +use clap::{Parser, Subcommand}; +use size::{Base, Size, Style}; + +use base::libc::{ + c_char, dev_t, gid_t, major, makedev, minor, mknod, mmap, mode_t, munmap, uid_t, MAP_FAILED, + MAP_PRIVATE, PROT_READ, S_IFBLK, S_IFCHR, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, S_IRGRP, S_IROTH, + S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR, +}; +use base::{ptr_to_str_result, ResultExt, WriteExt}; + +use crate::ramdisk::MagiskCpio; + #[derive(Parser)] struct CpioCli { #[command(subcommand)] @@ -108,6 +111,7 @@ impl Cpio { entries: BTreeMap::new(), } } + fn load_from_data(data: &[u8]) -> anyhow::Result { let mut cpio = Cpio::new(); let mut pos = 0usize; @@ -147,6 +151,7 @@ impl Cpio { } Ok(cpio) } + pub(crate) fn load_from_file(path: &str) -> anyhow::Result { eprintln!("Loading cpio: [{}]", path); let file = File::open(path)?; @@ -173,6 +178,7 @@ impl Cpio { } Ok(cpio) } + fn dump(&self, path: &str) -> anyhow::Result<()> { eprintln!("Dumping cpio: [{}]", path); let mut file = File::create(path)?; @@ -215,6 +221,7 @@ impl Cpio { file.write_zeros(align_4(pos) - pos)?; Ok(()) } + pub(crate) fn rm(&mut self, path: &str, recursive: bool) -> anyhow::Result<()> { let path = norm_path(path); let entry = self @@ -242,6 +249,7 @@ impl Cpio { } Ok(()) } + fn extract_entry(&self, path: &str, out: &Path) -> anyhow::Result<()> { let entry = self.entries.get(path).ok_or(anyhow!("No such file"))?; eprintln!("Extracting entry [{}] to [{}]", path, out.to_string_lossy()); @@ -280,6 +288,7 @@ impl Cpio { } Ok(()) } + fn extract(&self, path: Option<&str>, out: Option<&str>) -> anyhow::Result<()> { let path = path.map(norm_path); let out = out.map(Path::new); @@ -295,9 +304,11 @@ impl Cpio { } Ok(()) } + pub(crate) fn exists(&self, path: &str) -> bool { self.entries.contains_key(&norm_path(path)) } + fn add(&mut self, mode: &mode_t, path: &str, file: &str) -> anyhow::Result<()> { if path.ends_with('/') { return Err(anyhow!("path cannot end with / for add")); @@ -334,6 +345,7 @@ impl Cpio { eprintln!("Add file [{}] ({:04o})", path, mode); Ok(()) } + fn mkdir(&mut self, mode: &mode_t, dir: &str) { self.entries.insert( norm_path(dir), @@ -348,6 +360,7 @@ impl Cpio { ); eprintln!("Create directory [{}] ({:04o})", dir, mode); } + fn ln(&mut self, src: &str, dst: &str) { self.entries.insert( norm_path(dst), @@ -362,6 +375,7 @@ impl Cpio { ); eprintln!("Create symlink [{}] -> [{}]", dst, src); } + fn mv(&mut self, from: &str, to: &str) -> anyhow::Result<()> { let entry = self .entries @@ -371,6 +385,7 @@ impl Cpio { eprintln!("Move [{}] -> [{}]", from, to); Ok(()) } + fn ls(&self, path: Option<&str>, recursive: bool) { let path = path .map(norm_path) @@ -489,10 +504,7 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool { .is_ok() } -fn x8u(x: &[u8; 8]) -> anyhow::Result -where - U: TryFrom, -{ +fn x8u>(x: &[u8; 8]) -> anyhow::Result { // parse hex let mut ret = 0u32; for i in x { diff --git a/native/src/boot/dtb.cpp b/native/src/boot/dtb.cpp index bb95f4aac..b030942c2 100644 --- a/native/src/boot/dtb.cpp +++ b/native/src/boot/dtb.cpp @@ -151,7 +151,7 @@ static bool dtb_patch(const char *file) { int len; char *value = (char *) fdt_getprop(fdt, node, "fsmgr_flags", &len); byte_data data(value, len); - patched |= patch_verity(data); + patched |= (patch_verity(data) != len); } } } @@ -224,9 +224,10 @@ static bool fdt_patch(void *fdt) { int len; const void *value = fdt_getprop(fdt, node, "fsmgr_flags", &len); heap_data copy = byte_view(value, len).clone(); - if (patch_verity(copy)) { + auto patched_sz = patch_verity(copy); + if (patched_sz != len) { modified = true; - fdt_setprop(fdt, node, "fsmgr_flags", copy.buf(), copy.sz()); + fdt_setprop(fdt, node, "fsmgr_flags", copy.buf(), patched_sz); } if (name == "system"sv) { fprintf(stderr, "Setting [mnt_point] to [/system_root]\n"); diff --git a/native/src/boot/lib.rs b/native/src/boot/lib.rs index e748590ea..d1bbf5acf 100644 --- a/native/src/boot/lib.rs +++ b/native/src/boot/lib.rs @@ -20,8 +20,8 @@ pub mod ffi { include!("compress.hpp"); include!("magiskboot.hpp"); fn decompress(buf: &[u8], fd: i32) -> bool; - fn patch_encryption(buf: &mut [u8]); - fn patch_verity(buf: &mut [u8]); + fn patch_encryption(buf: &mut [u8]) -> usize; + fn patch_verity(buf: &mut [u8]) -> usize; } #[namespace = "rust"] diff --git a/native/src/boot/magiskboot.hpp b/native/src/boot/magiskboot.hpp index abe20408b..699b4fdbf 100644 --- a/native/src/boot/magiskboot.hpp +++ b/native/src/boot/magiskboot.hpp @@ -18,15 +18,12 @@ int unpack(const char *image, bool skip_decomp = false, bool hdr = false); void repack(const char *src_img, const char *out_img, bool skip_comp = false); int split_image_dtb(const char *filename); int hexpatch(const char *file, std::string_view from, std::string_view to); -int cpio_commands(int argc, char *argv[]); int dtb_commands(int argc, char *argv[]); -bool patch_verity(byte_data data); -void patch_verity(rust::Slice data); -bool patch_encryption(byte_data data); -void patch_encryption(rust::Slice data); +size_t patch_verity(rust::Slice data); +size_t patch_encryption(rust::Slice data); -inline bool check_env(const char *name) { +static inline bool check_env(const char *name) { using namespace std::string_view_literals; const char *val = getenv(name); return val != nullptr && val == "true"sv; diff --git a/native/src/boot/pattern.cpp b/native/src/boot/pattern.cpp index 780fb1f09..8eca66aec 100644 --- a/native/src/boot/pattern.cpp +++ b/native/src/boot/pattern.cpp @@ -39,36 +39,28 @@ static int skip_encryption_pattern(const char *s) { return skip; } -static bool remove_pattern(byte_data &data, int(*pattern_skip)(const char *)) { +static size_t remove_pattern(byte_data data, int(*pattern_skip)(const char *)) { char *src = reinterpret_cast(data.buf()); - size_t orig_sz = data.sz(); + size_t sz = data.sz(); int write = 0; int read = 0; - while (read < orig_sz) { + while (read < data.sz()) { if (int skip = pattern_skip(src + read); skip > 0) { fprintf(stderr, "Remove pattern [%.*s]\n", skip, src + read); - data.sz() -= skip; + sz -= skip; read += skip; } else { src[write++] = src[read++]; } } - memset(src + write, 0, orig_sz - write); - return data.sz() != orig_sz; + memset(src + write, 0, data.sz() - write); + return sz; } -bool patch_verity(byte_data data) { +size_t patch_verity(rust::Slice data) { return remove_pattern(data, skip_verity_pattern); } -void patch_verity(rust::Slice data) { - patch_verity(byte_data{data.data(), data.size()}); -} - -bool patch_encryption(byte_data data) { +size_t patch_encryption(rust::Slice data) { return remove_pattern(data, skip_encryption_pattern); } - -void patch_encryption(rust::Slice data) { - patch_encryption(byte_data{data.data(), data.size()}); -} diff --git a/native/src/boot/ramdisk.rs b/native/src/boot/ramdisk.rs index 275ea22e7..7428c5edb 100644 --- a/native/src/boot/ramdisk.rs +++ b/native/src/boot/ramdisk.rs @@ -1,11 +1,13 @@ -use crate::cpio::{Cpio, CpioEntry}; -use crate::ffi::{patch_encryption, patch_verity}; -use base::libc::{S_IFDIR, S_IFMT, S_IFREG}; use std::cmp::Ordering; use std::collections::HashMap; use std::env; use std::str::from_utf8; +use base::libc::{S_IFDIR, S_IFMT, S_IFREG}; + +use crate::cpio::{Cpio, CpioEntry}; +use crate::ffi::{patch_encryption, patch_verity}; + pub trait MagiskCpio { fn patch(&mut self); fn test(&self) -> i32; @@ -40,17 +42,24 @@ impl MagiskCpio for Cpio { if !keep_verity { if fstab { eprintln!("Found fstab file [{}]", name); - patch_verity(entry.data.as_mut_slice()); + let len = patch_verity(entry.data.as_mut_slice()); + if len != entry.data.len() { + entry.data.resize(len, 0); + } } else if name == "verity_key" { return false; } } if !keep_force_encrypt && fstab { - patch_encryption(entry.data.as_mut_slice()); + let len = patch_encryption(entry.data.as_mut_slice()); + if len != entry.data.len() { + entry.data.resize(len, 0); + } } true }); } + fn test(&self) -> i32 { let mut ret = 0; for file in [ @@ -78,6 +87,7 @@ impl MagiskCpio for Cpio { } ret } + fn restore(&mut self) -> anyhow::Result<()> { let mut backups = HashMap::::new(); let mut rm_list = String::new(); @@ -106,6 +116,7 @@ impl MagiskCpio for Cpio { Ok(()) } + fn backup(&mut self, origin: &str) -> anyhow::Result<()> { let mut backups = HashMap::::new(); let mut rm_list = String::new();