Skip to content

Commit

Permalink
add: APatch support (#4)
Browse files Browse the repository at this point in the history
This commit adds support for APatch.
  • Loading branch information
Flouzr authored Jun 23, 2024
1 parent 678d886 commit 2047bdb
Show file tree
Hide file tree
Showing 17 changed files with 218 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion loader/src/common/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions loader/src/include/daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class UniqueFd {

enum zygote_root_impl {
ZYGOTE_ROOT_IMPL_NONE,
ZYGOTE_ROOT_IMPL_APATCH,
ZYGOTE_ROOT_IMPL_KERNELSU,
ZYGOTE_ROOT_IMPL_MAGISK
};
Expand Down
2 changes: 2 additions & 0 deletions loader/src/injector/hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
1 change: 1 addition & 0 deletions loader/src/injector/module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
41 changes: 41 additions & 0 deletions loader/src/injector/unmount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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());
}
}
1 change: 1 addition & 0 deletions loader/src/injector/zygisk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ void revert_unmount_ksu();

void revert_unmount_magisk();

void revert_unmount_apatch();
5 changes: 5 additions & 0 deletions loader/src/ptracer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down
14 changes: 14 additions & 0 deletions module/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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)
Expand Down
9 changes: 9 additions & 0 deletions module/src/customize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions zygiskd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
3 changes: 3 additions & 0 deletions zygiskd/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -17,6 +18,7 @@ android.buildFeatures {

cargo {
module = "."
pythonCommand = "python3"
libname = "zygiskd"
targetIncludes = arrayOf("zygiskd")
targets = listOf("arm64", "arm", "x86", "x86_64")
Expand All @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions zygiskd/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")));
Expand Down Expand Up @@ -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;
Expand Down
113 changes: 113 additions & 0 deletions zygiskd/src/root_impl/apatch.rs
Original file line number Diff line number Diff line change
@@ -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
}
Loading

0 comments on commit 2047bdb

Please sign in to comment.