add: APatch support (#4)

This commit adds support for APatch.
This commit is contained in:
Matt
2024-06-22 22:13:29 -04:00
committed by GitHub
parent 678d886343
commit 2047bdb1bf
17 changed files with 218 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
# ReZygisk
ReZygisk is a fork of Zygisk Next by Dr-TSNG, which is a standalone implementation of Zygisk, providing Zygisk API support for KernelSU, Magisk and futurely APatch.
ReZygisk is a fork of Zygisk Next by Dr-TSNG, which is a standalone implementation of Zygisk, providing Zygisk API support for KernelSU, Magisk and APatch.
It aims at the re-write of Zygisk Next to C, allowing also a more efficient and faster implementation of the Zygisk API with a more permissive license.

View File

@@ -23,6 +23,7 @@ val moduleName by extra("ReZygisk")
val verName by extra("v1.0.0")
val verCode by extra(gitCommitCount)
val commitHash by extra(gitCommitHash)
val minApatchVersion by extra(10655)
val minKsuVersion by extra(10940)
val minKsudVersion by extra(11425)
val maxKsuVersion by extra(20000)

View File

@@ -153,7 +153,9 @@ namespace zygiskd {
int flags = socket_utils::read_u32(fd);
if (flags & (1 << 29)) {
if (flags & (1 << 27)) {
info->root_impl = ZYGOTE_ROOT_IMPL_APATCH;
} else if (flags & (1 << 29)) {
info->root_impl = ZYGOTE_ROOT_IMPL_KERNELSU;
} else if (flags & (1 << 30)) {
info->root_impl = ZYGOTE_ROOT_IMPL_MAGISK;

View File

@@ -44,6 +44,7 @@ private:
enum zygote_root_impl {
ZYGOTE_ROOT_IMPL_NONE,
ZYGOTE_ROOT_IMPL_APATCH,
ZYGOTE_ROOT_IMPL_KERNELSU,
ZYGOTE_ROOT_IMPL_MAGISK
};

View File

@@ -145,6 +145,8 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
if (g_ctx->flags[DO_REVERT_UNMOUNT]) {
if (g_ctx->info_flags & PROCESS_ROOT_IS_KSU) {
revert_unmount_ksu();
} else if (g_ctx->info_flags & PROCESS_ROOT_IS_APATCH){
revert_unmount_apatch();
} else if (g_ctx->info_flags & PROCESS_ROOT_IS_MAGISK) {
revert_unmount_magisk();
}

View File

@@ -113,6 +113,7 @@ namespace {
PROCESS_ON_DENYLIST = zygisk::StateFlag::PROCESS_ON_DENYLIST,
PROCESS_IS_MANAGER = (1u << 28),
PROCESS_ROOT_IS_APATCH = (1u << 27),
PROCESS_ROOT_IS_KSU = (1u << 29),
PROCESS_ROOT_IS_MAGISK = (1u << 30),
PROCESS_IS_SYS_UI = (1u << 31),

View File

@@ -11,6 +11,7 @@ using namespace std::string_view_literals;
namespace {
constexpr auto MODULE_DIR = "/data/adb/modules";
constexpr auto KSU_OVERLAY_SOURCE = "KSU";
constexpr auto AP_OVERLAY_SOURCE = "APatch";
const std::vector<std::string> KSU_PARTITIONS{"/system", "/vendor", "/product", "/system_ext", "/odm", "/oem"};
void lazy_unmount(const char* mountpoint) {
@@ -84,3 +85,43 @@ void revert_unmount_magisk() {
lazy_unmount(s.data());
}
}
void revert_unmount_apatch() {
std::string ksu_loop;
std::vector<std::string> targets;
// Unmount ksu module dir last
targets.emplace_back(MODULE_DIR);
for (auto& info: parse_mount_info("self")) {
if (info.target == MODULE_DIR) {
ksu_loop = info.source;
continue;
}
// Unmount everything mounted to /data/adb
if (info.target.starts_with("/data/adb")) {
targets.emplace_back(info.target);
}
// Unmount ksu overlays
if (info.type == "overlay"
&& info.source == AP_OVERLAY_SOURCE
&& std::find(KSU_PARTITIONS.begin(), KSU_PARTITIONS.end(), info.target) != KSU_PARTITIONS.end()) {
targets.emplace_back(info.target);
}
// Unmount temp dir
if (info.type == "tmpfs" && info.source == AP_OVERLAY_SOURCE) {
targets.emplace_back(info.target);
}
}
for (auto& info: parse_mount_info("self")) {
// Unmount everything from ksu loop except ksu module dir
if (info.source == ksu_loop && info.target != MODULE_DIR) {
targets.emplace_back(info.target);
}
}
// Do unmount
for (auto& s: reversed(targets)) {
lazy_unmount(s.data());
}
}

View File

@@ -12,3 +12,4 @@ void revert_unmount_ksu();
void revert_unmount_magisk();
void revert_unmount_apatch();

View File

@@ -108,6 +108,11 @@ int main(int argc, char **argv) {
break;
}
case ZYGOTE_ROOT_IMPL_APATCH: {
printf("Root implementation: APatch\n");
break;
}
case ZYGOTE_ROOT_IMPL_KERNELSU: {
printf("Root implementation: KernelSU\n");

View File

@@ -24,6 +24,7 @@ val moduleId: String by rootProject.extra
val moduleName: String by rootProject.extra
val verCode: Int by rootProject.extra
val verName: String by rootProject.extra
val minApatchVersion: Int by rootProject.extra
val minKsuVersion: Int by rootProject.extra
val minKsudVersion: Int by rootProject.extra
val maxKsuVersion: Int by rootProject.extra
@@ -69,6 +70,7 @@ androidComponents.onVariants { variant ->
include("customize.sh", "post-fs-data.sh", "service.sh")
val tokens = mapOf(
"DEBUG" to if (buildTypeLowered == "debug") "true" else "false",
"MIN_APATCH_VERSION" to "$minApatchVersion",
"MIN_KSU_VERSION" to "$minKsuVersion",
"MIN_KSUD_VERSION" to "$minKsudVersion",
"MAX_KSU_VERSION" to "$maxKsuVersion",
@@ -214,12 +216,24 @@ androidComponents.onVariants { variant ->
}
}
val installApatchTask = task<Exec>("installApatch$variantCapped") {
group = "module"
dependsOn(pushTask)
commandLine("adb", "shell", "su", "-c", "/data/adb/apd module install /data/local/tmp/$zipFileName")
}
val installMagiskTask = task<Exec>("installMagisk$variantCapped") {
group = "module"
dependsOn(pushTask)
commandLine("adb", "shell", "su", "-M", "-c", "magisk --install-module /data/local/tmp/$zipFileName")
}
task<Exec>("installKpatchAndReboot$variantCapped") {
group = "module"
dependsOn(installApatchTask)
commandLine("adb", "reboot")
}
task<Exec>("installKsuAndReboot$variantCapped") {
group = "module"
dependsOn(installKsuTask)

View File

@@ -6,6 +6,7 @@ MIN_KSU_VERSION=@MIN_KSU_VERSION@
MIN_KSUD_VERSION=@MIN_KSUD_VERSION@
MAX_KSU_VERSION=@MAX_KSU_VERSION@
MIN_MAGISK_VERSION=@MIN_MAGISK_VERSION@
MIN_APATCH_VERSION=@MIN_APATCH_VERSION@
if [ "$BOOTMODE" ] && [ "$KSU" ]; then
ui_print "- Installing from KernelSU app"
@@ -34,6 +35,14 @@ if [ "$BOOTMODE" ] && [ "$KSU" ]; then
ui_print "! Please uninstall Magisk before installing ReZygisk"
abort "*********************************************************"
fi
elif [ "$BOOTMODE" ] && [ "$APATCH" ]; then
ui_print "- Installing from Apatch app"
if ! [ "$APATCH_VER_CODE" ] || [ "$APATCH_VER_CODE" -lt "$MIN_APATCH_VERSION" ]; then
ui_print "*********************************************************"
ui_print "! Apatch version is too old!"
ui_print "! Please update Apatch to latest version"
abort "*********************************************************"
fi
elif [ "$BOOTMODE" ] && [ "$MAGISK_VER_CODE" ]; then
ui_print "- Installing from Magisk app"
if [ "$MAGISK_VER_CODE" -lt "$MIN_MAGISK_VERSION" ]; then

View File

@@ -6,6 +6,8 @@ edition = "2021"
rust-version = "1.69"
[dependencies]
csv = "1.3.0"
serde = { version = "1.0.130", features = ["derive"] }
android_logger = "0.13"
anyhow = { version = "1.0", features = ["backtrace"] }
bitflags = { version = "2.3" }

View File

@@ -3,6 +3,7 @@ plugins {
alias(libs.plugins.rust.android)
}
val minApatchVersion: Int by rootProject.extra
val minKsuVersion: Int by rootProject.extra
val maxKsuVersion: Int by rootProject.extra
val minMagiskVersion: Int by rootProject.extra
@@ -17,6 +18,7 @@ android.buildFeatures {
cargo {
module = "."
pythonCommand = "python3"
libname = "zygiskd"
targetIncludes = arrayOf("zygiskd")
targets = listOf("arm64", "arm", "x86", "x86_64")
@@ -25,6 +27,7 @@ cargo {
profile = if (isDebug) "debug" else "release"
exec = { spec, _ ->
spec.environment("ANDROID_NDK_HOME", android.ndkDirectory.path)
spec.environment("MIN_APATCH_VERSION", minApatchVersion)
spec.environment("MIN_KSU_VERSION", minKsuVersion)
spec.environment("MAX_KSU_VERSION", maxKsuVersion)
spec.environment("MIN_MAGISK_VERSION", minMagiskVersion)

View File

@@ -5,6 +5,7 @@ use konst::unwrap_ctx;
use log::LevelFilter;
use num_enum::TryFromPrimitive;
pub const MIN_APATCH_VERSION: i32 = unwrap_ctx!(parse_i32(env!("MIN_APATCH_VERSION")));
pub const MIN_KSU_VERSION: i32 = unwrap_ctx!(parse_i32(env!("MIN_KSU_VERSION")));
pub const MAX_KSU_VERSION: i32 = unwrap_ctx!(parse_i32(env!("MAX_KSU_VERSION")));
pub const MIN_MAGISK_VERSION: i32 = unwrap_ctx!(parse_i32(env!("MIN_MAGISK_VERSION")));
@@ -42,6 +43,7 @@ bitflags! {
const PROCESS_GRANTED_ROOT = 1 << 0;
const PROCESS_ON_DENYLIST = 1 << 1;
const PROCESS_IS_MANAGER = 1 << 28;
const PROCESS_ROOT_IS_APATCH = 1 << 27;
const PROCESS_ROOT_IS_KSU = 1 << 29;
const PROCESS_ROOT_IS_MAGISK = 1 << 30;
const PROCESS_IS_SYSUI = 1 << 31;

View File

@@ -0,0 +1,113 @@
use std::process::{Command, Stdio};
use std::fs::File;
use serde::Deserialize;
use crate::constants::MIN_APATCH_VERSION;
pub enum Version {
Supported,
TooOld,
Abnormal,
}
fn parse_version(output: &str) -> i32 {
let mut version: Option<i32> = None;
for line in output.lines() {
if let Some(num) = line.trim().split_whitespace().last() {
if let Ok(v) = num.parse::<i32>() {
version = Some(v);
break;
}
}
}
version.unwrap_or_default()
}
pub fn get_apatch() -> Option<Version> {
let output1 = Command::new("/data/adb/apd")
.arg("-V")
.stdout(Stdio::piped())
.stderr(Stdio::null())
.output()
.ok()?;
let stdout1 = String::from_utf8(output1.stdout).ok()?;
let version = parse_version(&stdout1);
const MAX_OLD_VERSION: i32 = MIN_APATCH_VERSION - 1;
match version {
0 => Some(Version::Abnormal),
v if v >= MIN_APATCH_VERSION && v <= 999999 => Some(Version::Supported),
v if v >= 1 && v <= MAX_OLD_VERSION => Some(Version::TooOld),
_ => None,
}
}
#[derive(Deserialize)]
#[allow(dead_code)]
struct PackageConfig {
pkg: String,
exclude: i32,
allow: i32,
uid: i32,
to_uid: i32,
sctx: String,
}
fn read_package_config() -> Result<Vec<PackageConfig>, std::io::Error> {
let file = File::open("/data/adb/ap/package_config")?;
let mut reader = csv::Reader::from_reader(file);
let mut package_configs = Vec::new();
for record in reader.deserialize() {
match record {
Ok(config) => package_configs.push(config),
Err(error) => {
log::warn!("Error deserializing record: {}", error);
}
}
}
Ok(package_configs)
}
pub fn uid_granted_root(uid: i32) -> bool {
match read_package_config() {
Ok(package_configs) => {
package_configs
.iter()
.find(|config| config.uid == uid)
.map(|config| config.allow == 1)
.unwrap_or(false)
}
Err(err) => {
log::warn!("Error reading package config: {}", err);
return false;
}
}
}
pub fn uid_should_umount(uid: i32) -> bool {
match read_package_config() {
Ok(package_configs) => {
package_configs
.iter()
.find(|config| config.uid == uid)
.map(|config| {
match config.exclude {
1 => true,
_ => false,
}
})
.unwrap_or(false)
}
Err(err) => {
log::warn!("Error reading package configs: {}", err);
false
}
}
}
// TODO: signature
pub fn uid_is_manager(uid: i32) -> bool {
if let Ok(s) = rustix::fs::stat("/data/user_de/0/me.bmax.apatch") {
return s.st_uid == uid as u32;
}
false
}

View File

@@ -2,6 +2,7 @@ use std::ptr::addr_of;
mod kernelsu;
mod magisk;
mod apatch;
#[derive(Debug)]
pub enum RootImpl {
@@ -11,26 +12,34 @@ pub enum RootImpl {
Multiple,
KernelSU,
Magisk,
APatch,
}
static mut ROOT_IMPL: RootImpl = RootImpl::None;
pub fn setup() {
let apatch_version = apatch::get_apatch();
let ksu_version = kernelsu::get_kernel_su();
let magisk_version = magisk::get_magisk();
let impl_ = match (ksu_version, magisk_version) {
(None, None) => RootImpl::None,
(Some(_), Some(_)) => RootImpl::Multiple,
(Some(ksu_version), None) => match ksu_version {
let impl_ = match (apatch_version, ksu_version, magisk_version) {
(None, None, None) => RootImpl::None,
(Some(_), Some(_), Some(_)) => RootImpl::Multiple,
(Some(apatch_version),None, None) => match apatch_version {
apatch::Version::Supported => RootImpl::APatch,
apatch::Version::TooOld => RootImpl::TooOld,
apatch::Version::Abnormal => RootImpl::Abnormal,
},
(None,Some(ksu_version), None) => match ksu_version {
kernelsu::Version::Supported => RootImpl::KernelSU,
kernelsu::Version::TooOld => RootImpl::TooOld,
kernelsu::Version::Abnormal => RootImpl::Abnormal,
},
(None, Some(magisk_version)) => match magisk_version {
(None, None, Some(magisk_version)) => match magisk_version {
magisk::Version::Supported => RootImpl::Magisk,
magisk::Version::TooOld => RootImpl::TooOld,
},
_ => RootImpl::None,
};
unsafe {
ROOT_IMPL = impl_;
@@ -45,6 +54,7 @@ pub fn uid_granted_root(uid: i32) -> bool {
match get_impl() {
RootImpl::KernelSU => kernelsu::uid_granted_root(uid),
RootImpl::Magisk => magisk::uid_granted_root(uid),
RootImpl::APatch => apatch::uid_granted_root(uid),
_ => panic!("uid_granted_root: unknown root impl {:?}", get_impl()),
}
}
@@ -53,6 +63,7 @@ pub fn uid_should_umount(uid: i32) -> bool {
match get_impl() {
RootImpl::KernelSU => kernelsu::uid_should_umount(uid),
RootImpl::Magisk => magisk::uid_should_umount(uid),
RootImpl::APatch => apatch::uid_should_umount(uid),
_ => panic!("uid_should_umount: unknown root impl {:?}", get_impl()),
}
}
@@ -61,6 +72,7 @@ pub fn uid_is_manager(uid: i32) -> bool {
match get_impl() {
RootImpl::KernelSU => kernelsu::uid_is_manager(uid),
RootImpl::Magisk => magisk::uid_is_manager(uid),
RootImpl::APatch => apatch::uid_is_manager(uid),
_ => panic!("uid_is_manager: unknown root impl {:?}", get_impl()),
}
}

View File

@@ -51,7 +51,7 @@ pub fn main() -> Result<()> {
{
let mut msg = Vec::<u8>::new();
let info = match root_impl::get_impl() {
root_impl::RootImpl::KernelSU | root_impl::RootImpl::Magisk => {
root_impl::RootImpl::KernelSU | root_impl::RootImpl::Magisk | root_impl::RootImpl::APatch => {
msg.extend_from_slice(&constants::DAEMON_SET_INFO.to_le_bytes());
let module_names: Vec<_> = modules.iter().map(|m| m.name.as_str()).collect();
format!(
@@ -254,6 +254,7 @@ fn handle_daemon_action(
match root_impl::get_impl() {
root_impl::RootImpl::KernelSU => flags |= ProcessFlags::PROCESS_ROOT_IS_KSU,
root_impl::RootImpl::Magisk => flags |= ProcessFlags::PROCESS_ROOT_IS_MAGISK,
root_impl::RootImpl::APatch => flags |= ProcessFlags::PROCESS_ROOT_IS_APATCH,
_ => panic!("wrong root impl: {:?}", root_impl::get_impl()),
}
trace!(