mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 16:07:39 +00:00
Move pattern matching to Rust
This commit is contained in:
parent
399b9e5eba
commit
9c7cf340a1
@ -114,7 +114,6 @@ LOCAL_SRC_FILES := \
|
|||||||
boot/compress.cpp \
|
boot/compress.cpp \
|
||||||
boot/format.cpp \
|
boot/format.cpp \
|
||||||
boot/dtb.cpp \
|
boot/dtb.cpp \
|
||||||
boot/pattern.cpp \
|
|
||||||
boot/boot-rs.cpp
|
boot/boot-rs.cpp
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "magiskboot.hpp"
|
#include "magiskboot.hpp"
|
||||||
#include "dtb.hpp"
|
#include "dtb.hpp"
|
||||||
#include "format.hpp"
|
#include "format.hpp"
|
||||||
|
#include "boot-rs.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -151,7 +152,7 @@ static bool dtb_patch(const char *file) {
|
|||||||
int len;
|
int len;
|
||||||
char *value = (char *) fdt_getprop(fdt, node, "fsmgr_flags", &len);
|
char *value = (char *) fdt_getprop(fdt, node, "fsmgr_flags", &len);
|
||||||
byte_data data(value, len);
|
byte_data data(value, len);
|
||||||
patched |= (patch_verity(data) != len);
|
patched |= (rust::patch_verity(data) != len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,7 +225,7 @@ static bool fdt_patch(void *fdt) {
|
|||||||
int len;
|
int len;
|
||||||
const void *value = fdt_getprop(fdt, node, "fsmgr_flags", &len);
|
const void *value = fdt_getprop(fdt, node, "fsmgr_flags", &len);
|
||||||
heap_data copy = byte_view(value, len).clone();
|
heap_data copy = byte_view(value, len).clone();
|
||||||
auto patched_sz = patch_verity(copy);
|
auto patched_sz = rust::patch_verity(copy);
|
||||||
if (patched_sz != len) {
|
if (patched_sz != len) {
|
||||||
modified = true;
|
modified = true;
|
||||||
fdt_setprop(fdt, node, "fsmgr_flags", copy.buf(), patched_sz);
|
fdt_setprop(fdt, node, "fsmgr_flags", copy.buf(), patched_sz);
|
||||||
|
@ -18,10 +18,7 @@ mod ramdisk;
|
|||||||
pub mod ffi {
|
pub mod ffi {
|
||||||
unsafe extern "C++" {
|
unsafe extern "C++" {
|
||||||
include!("compress.hpp");
|
include!("compress.hpp");
|
||||||
include!("magiskboot.hpp");
|
|
||||||
fn decompress(buf: &[u8], fd: i32) -> bool;
|
fn decompress(buf: &[u8], fd: i32) -> bool;
|
||||||
fn patch_encryption(buf: &mut [u8]) -> usize;
|
|
||||||
fn patch_verity(buf: &mut [u8]) -> usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[namespace = "rust"]
|
#[namespace = "rust"]
|
||||||
@ -34,5 +31,7 @@ pub mod ffi {
|
|||||||
|
|
||||||
unsafe fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool;
|
unsafe fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool;
|
||||||
fn hexpatch(file: &[u8], from: &[u8], to: &[u8]) -> bool;
|
fn hexpatch(file: &[u8], from: &[u8], to: &[u8]) -> bool;
|
||||||
|
fn patch_encryption(buf: &mut [u8]) -> usize;
|
||||||
|
fn patch_verity(buf: &mut [u8]) -> usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,6 @@ void repack(const char *src_img, const char *out_img, bool skip_comp = false);
|
|||||||
int split_image_dtb(const char *filename);
|
int split_image_dtb(const char *filename);
|
||||||
int dtb_commands(int argc, char *argv[]);
|
int dtb_commands(int argc, char *argv[]);
|
||||||
|
|
||||||
size_t patch_verity(rust::Slice<uint8_t> data);
|
|
||||||
size_t patch_encryption(rust::Slice<uint8_t> data);
|
|
||||||
|
|
||||||
static inline bool check_env(const char *name) {
|
static inline bool check_env(const char *name) {
|
||||||
using namespace std::string_view_literals;
|
using namespace std::string_view_literals;
|
||||||
const char *val = getenv(name);
|
const char *val = getenv(name);
|
||||||
|
@ -1,5 +1,90 @@
|
|||||||
use base::{MappedFile, MutBytesExt, ResultExt, Utf8CStr};
|
use base::{MappedFile, MutBytesExt, ResultExt, Utf8CStr};
|
||||||
|
|
||||||
|
// SAFETY: assert(buf.len() >= 1) && assert(len <= buf.len())
|
||||||
|
macro_rules! match_patterns {
|
||||||
|
($buf:ident, $($str:literal), *) => {{
|
||||||
|
let mut len = if *$buf.get_unchecked(0) == b',' { 1 } else { 0 };
|
||||||
|
let b = $buf.get_unchecked(len..);
|
||||||
|
let found = if b.is_empty() {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
$(
|
||||||
|
else if b.starts_with($str) {
|
||||||
|
len += $str.len();
|
||||||
|
true
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if found {
|
||||||
|
let b = $buf.get_unchecked(len..);
|
||||||
|
if !b.is_empty() && b[0] == b'=' {
|
||||||
|
for c in b.iter() {
|
||||||
|
if b" \n\0".contains(c) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(len)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_pattern(buf: &mut [u8], pattern_matcher: unsafe fn(&[u8]) -> Option<usize>) -> usize {
|
||||||
|
let mut write = 0_usize;
|
||||||
|
let mut read = 0_usize;
|
||||||
|
let mut sz = buf.len();
|
||||||
|
// SAFETY: assert(write <= read) && assert(read <= buf.len())
|
||||||
|
unsafe {
|
||||||
|
while read < buf.len() {
|
||||||
|
if let Some(len) = pattern_matcher(buf.get_unchecked(read..)) {
|
||||||
|
let skipped = buf.get_unchecked(read..(read + len));
|
||||||
|
// SAFETY: all matching patterns are ASCII bytes
|
||||||
|
let skipped = std::str::from_utf8_unchecked(skipped);
|
||||||
|
eprintln!("Remove pattern [{}]", skipped);
|
||||||
|
sz -= len;
|
||||||
|
read += len;
|
||||||
|
} else {
|
||||||
|
*buf.get_unchecked_mut(write) = *buf.get_unchecked(read);
|
||||||
|
write += 1;
|
||||||
|
read += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(buf) = buf.get_mut(write..) {
|
||||||
|
buf.fill(0);
|
||||||
|
}
|
||||||
|
sz
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn patch_verity(buf: &mut [u8]) -> usize {
|
||||||
|
unsafe fn match_verity_pattern(buf: &[u8]) -> Option<usize> {
|
||||||
|
match_patterns!(
|
||||||
|
buf,
|
||||||
|
b"verifyatboot",
|
||||||
|
b"verify",
|
||||||
|
b"avb_keys",
|
||||||
|
b"avb",
|
||||||
|
b"support_scfs",
|
||||||
|
b"fsverity"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_pattern(buf, match_verity_pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn patch_encryption(buf: &mut [u8]) -> usize {
|
||||||
|
unsafe fn match_encryption_pattern(buf: &[u8]) -> Option<usize> {
|
||||||
|
match_patterns!(buf, b"forceencrypt", b"forcefdeorfbe", b"fileencryption")
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_pattern(buf, match_encryption_pattern)
|
||||||
|
}
|
||||||
|
|
||||||
fn hex2byte(hex: &[u8]) -> Vec<u8> {
|
fn hex2byte(hex: &[u8]) -> Vec<u8> {
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
v.reserve(hex.len() / 2);
|
v.reserve(hex.len() / 2);
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
#include <base.hpp>
|
|
||||||
|
|
||||||
#include "magiskboot.hpp"
|
|
||||||
|
|
||||||
#define MATCH(p) else if (strncmp(s + skip, p, sizeof(p) - 1) == 0) skip += (sizeof(p) - 1)
|
|
||||||
|
|
||||||
static int skip_verity_pattern(const char *s) {
|
|
||||||
int skip = s[0] == ',';
|
|
||||||
|
|
||||||
if (0) {}
|
|
||||||
MATCH("verifyatboot");
|
|
||||||
MATCH("verify");
|
|
||||||
MATCH("avb_keys");
|
|
||||||
MATCH("avb");
|
|
||||||
MATCH("support_scfs");
|
|
||||||
MATCH("fsverity");
|
|
||||||
else return -1;
|
|
||||||
|
|
||||||
if (s[skip] == '=') {
|
|
||||||
while (!strchr(" \n,", s[skip]))
|
|
||||||
++skip;
|
|
||||||
}
|
|
||||||
return skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int skip_encryption_pattern(const char *s) {
|
|
||||||
int skip = s[0] == ',';
|
|
||||||
|
|
||||||
if (0) {}
|
|
||||||
MATCH("forceencrypt");
|
|
||||||
MATCH("forcefdeorfbe");
|
|
||||||
MATCH("fileencryption");
|
|
||||||
else return -1;
|
|
||||||
|
|
||||||
if (s[skip] == '=') {
|
|
||||||
while (!strchr(" \n,", s[skip]))
|
|
||||||
++skip;
|
|
||||||
}
|
|
||||||
return skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t remove_pattern(byte_data data, int(*pattern_skip)(const char *)) {
|
|
||||||
char *src = reinterpret_cast<char *>(data.buf());
|
|
||||||
size_t sz = data.sz();
|
|
||||||
int write = 0;
|
|
||||||
int read = 0;
|
|
||||||
while (read < data.sz()) {
|
|
||||||
if (int skip = pattern_skip(src + read); skip > 0) {
|
|
||||||
fprintf(stderr, "Remove pattern [%.*s]\n", skip, src + read);
|
|
||||||
sz -= skip;
|
|
||||||
read += skip;
|
|
||||||
} else {
|
|
||||||
src[write++] = src[read++];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memset(src + write, 0, data.sz() - write);
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t patch_verity(rust::Slice<uint8_t> data) {
|
|
||||||
return remove_pattern(data, skip_verity_pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t patch_encryption(rust::Slice<uint8_t> data) {
|
|
||||||
return remove_pattern(data, skip_encryption_pattern);
|
|
||||||
}
|
|
@ -7,7 +7,7 @@ use base::libc::{S_IFDIR, S_IFMT, S_IFREG};
|
|||||||
use base::Utf8CStr;
|
use base::Utf8CStr;
|
||||||
|
|
||||||
use crate::cpio::{Cpio, CpioEntry};
|
use crate::cpio::{Cpio, CpioEntry};
|
||||||
use crate::ffi::{patch_encryption, patch_verity};
|
use crate::patch::{patch_encryption, patch_verity};
|
||||||
|
|
||||||
pub trait MagiskCpio {
|
pub trait MagiskCpio {
|
||||||
fn patch(&mut self);
|
fn patch(&mut self);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user