diff --git a/build.gradle.kts b/build.gradle.kts index 91b01d6..8661ed5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,6 +33,9 @@ val moduleId by extra("zygisksu") val moduleName by extra("Zygisk on KernelSU") val verName by extra("v4-0.4.1") val verCode by extra(gitCommitCount) +val minKsuVersion by extra(10626) +val maxKsuVersion by extra(100000) +val minMagiskVersion by extra(25000) val androidMinSdkVersion by extra(29) val androidTargetSdkVersion by extra(33) diff --git a/module/build.gradle.kts b/module/build.gradle.kts index 7a39072..9ce479f 100644 --- a/module/build.gradle.kts +++ b/module/build.gradle.kts @@ -11,6 +11,9 @@ 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 minKsuVersion: Int by rootProject.extra +val maxKsuVersion: Int by rootProject.extra +val minMagiskVersion: Int by rootProject.extra android.buildFeatures { androidResources = false @@ -49,7 +52,10 @@ androidComponents.onVariants { variant -> from("$projectDir/src") { include("customize.sh", "daemon.sh") val tokens = mapOf( - "DEBUG" to if (buildTypeLowered == "debug") "true" else "false" + "DEBUG" to if (buildTypeLowered == "debug") "true" else "false", + "MIN_KSU_VERSION" to "$minKsuVersion", + "MAX_KSU_VERSION" to "$maxKsuVersion", + "MIN_MAGISK_VERSION" to "$minMagiskVersion", ) filter("tokens" to tokens) filter("eol" to FixCrLfFilter.CrLf.newInstance("lf")) diff --git a/module/src/customize.sh b/module/src/customize.sh index aa120b1..2e04098 100644 --- a/module/src/customize.sh +++ b/module/src/customize.sh @@ -2,19 +2,28 @@ SKIPUNZIP=1 DEBUG=@DEBUG@ +MIN_KSU_VERSION=@MIN_KSU_VERSION@ +MAX_KSU_VERSION=@MAX_KSU_VERSION@ +MIN_MAGISK_VERSION=@MIN_MAGISK_VERSION@ if [ "$BOOTMODE" ] && [ "$KSU" ]; then ui_print "- Installing from KernelSU app" ui_print "- KernelSU version: $KSU_KERNEL_VER_CODE (kernel) + $KSU_VER_CODE (ksud)" - if [ "$KSU_KERNEL_VER_CODE" ] && [ "$KSU_KERNEL_VER_CODE" -lt 10575 ]; then + if [ "$KSU_KERNEL_VER_CODE" ] && [ "$KSU_KERNEL_VER_CODE" -lt "$MIN_KSU_VERSION" ]; then ui_print "*********************************************************" ui_print "! KernelSU version is too old!" ui_print "! Please update KernelSU to latest version" abort "*********************************************************" + elif [ "$KSU_KERNEL_VER_CODE" -ge "$MAX_KSU_VERSION" ]; then + ui_print "*********************************************************" + ui_print "! KernelSU version abnormal!" + ui_print "! Please integrate KernelSU into your kernel" + ui_print " as submodule instead of copying the source code" + abort "*********************************************************" fi elif [ "$BOOTMODE" ] && [ "$MAGISK_VER_CODE" ]; then ui_print "- Installing from Magisk app" - if [ "$MAGISK_VER_CODE" -lt 25000 ]; then + if [ "$MAGISK_VER_CODE" -lt "$MIN_MAGISK_VERSION" ]; then ui_print "*********************************************************" ui_print "! Magisk version is too old!" ui_print "! Please update Magisk to latest version" diff --git a/zygiskd/Cargo.toml b/zygiskd/Cargo.toml index 60f2c57..49bb074 100644 --- a/zygiskd/Cargo.toml +++ b/zygiskd/Cargo.toml @@ -10,11 +10,13 @@ android_logger = "0.12.0" anyhow = { version = "1.0.68", features = ["backtrace"] } clap = { version = "4.1.4", features = ["derive"] } const_format = "0.2.5" +konst = "0.3.4" lazy_static = "1.4.0" log = "0.4.17" memfd = "0.6.2" nix = "0.26.2" num_enum = "0.5.9" +once_cell = "1.17.1" passfd = "0.1.5" rand = "0.8.5" diff --git a/zygiskd/build.gradle.kts b/zygiskd/build.gradle.kts index 1aa7c8d..7d07fdb 100644 --- a/zygiskd/build.gradle.kts +++ b/zygiskd/build.gradle.kts @@ -5,6 +5,9 @@ plugins { val verName: String by rootProject.extra val verCode: Int by rootProject.extra +val minKsuVersion: Int by rootProject.extra +val maxKsuVersion: Int by rootProject.extra +val minMagiskVersion: Int by rootProject.extra android.buildFeatures { androidResources = false @@ -23,5 +26,8 @@ cargo { spec.environment("ANDROID_NDK_HOME", android.ndkDirectory.path) spec.environment("VERSION_CODE", verCode) spec.environment("VERSION_NAME", verName) + spec.environment("MIN_KSU_VERSION", minKsuVersion) + spec.environment("MAX_KSU_VERSION", maxKsuVersion) + spec.environment("MIN_MAGISK_VERSION", minMagiskVersion) } } diff --git a/zygiskd/src/constants.rs b/zygiskd/src/constants.rs index 4fea015..d87ba9c 100644 --- a/zygiskd/src/constants.rs +++ b/zygiskd/src/constants.rs @@ -1,10 +1,15 @@ use const_format::concatcp; +use konst::primitive::parse_i32; +use konst::unwrap_ctx; use log::LevelFilter; use num_enum::TryFromPrimitive; pub const VERSION_NAME: &str = env!("VERSION_NAME"); pub const VERSION_CODE: &str = env!("VERSION_CODE"); pub const VERSION_FULL: &str = concatcp!(VERSION_NAME, " (", VERSION_CODE, ")"); +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"))); #[cfg(debug_assertions)] pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Trace; diff --git a/zygiskd/src/main.rs b/zygiskd/src/main.rs index 4c94d1b..4dd46db 100644 --- a/zygiskd/src/main.rs +++ b/zygiskd/src/main.rs @@ -8,6 +8,7 @@ mod utils; mod watchdog; mod zygiskd; +use anyhow::Result; use clap::{Subcommand, Parser}; #[derive(Parser, Debug)] @@ -36,19 +37,23 @@ fn init_android_logger(tag: &str) { ); } +fn start() -> Result<()> { + root_impl::setup()?; + let cli = Args::parse(); + match cli.command { + Commands::Watchdog => watchdog::entry()?, + Commands::Daemon => zygiskd::entry()?, + Commands::Companion { fd } => companion::entry(fd)?, + }; + Ok(()) +} + fn main() { let process = std::env::args().next().unwrap(); let nice_name = process.split('/').last().unwrap(); init_android_logger(nice_name); - let cli = Args::parse(); - let result = match cli.command { - Commands::Watchdog => watchdog::entry(), - Commands::Daemon => zygiskd::entry(), - Commands::Companion { fd } => companion::entry(fd), - }; - - if let Err(e) = &result { + if let Err(e) = start() { log::error!("Crashed: {}\n{}", e, e.backtrace()); } } diff --git a/zygiskd/src/root_impl/kernelsu.rs b/zygiskd/src/root_impl/kernelsu.rs index 3ba96a6..a34c148 100644 --- a/zygiskd/src/root_impl/kernelsu.rs +++ b/zygiskd/src/root_impl/kernelsu.rs @@ -1,15 +1,22 @@ +use anyhow::{bail, Result}; use nix::libc::prctl; +use crate::constants::{MIN_KSU_VERSION, MAX_KSU_VERSION}; const KERNEL_SU_OPTION: i32 = 0xdeadbeefu32 as i32; -const CMD_GET_VERSION: u64 = 2; -const CMD_GET_ALLOW_LIST: u64 = 5; -const CMD_GET_DENY_LIST: u64 = 6; +const CMD_GET_VERSION: usize = 2; +const CMD_GET_ALLOW_LIST: usize = 5; +const CMD_GET_DENY_LIST: usize = 6; -pub fn is_kernel_su() -> bool { +pub fn is_kernel_su() -> Result { let mut version = 0; unsafe { prctl(KERNEL_SU_OPTION, CMD_GET_VERSION, &mut version as *mut i32) }; - version > 0 + return match version { + 0 => Ok(false), + MIN_KSU_VERSION..=MAX_KSU_VERSION => Ok(true), + 1..=MIN_KSU_VERSION => bail!("KernelSU version too old: {}", version), + _ => bail!("KernelSU version abnormal: {}", version) + } } pub fn uid_on_allowlist(uid: i32) -> bool { diff --git a/zygiskd/src/root_impl/magisk.rs b/zygiskd/src/root_impl/magisk.rs index e2d487c..3dac272 100644 --- a/zygiskd/src/root_impl/magisk.rs +++ b/zygiskd/src/root_impl/magisk.rs @@ -1,13 +1,30 @@ +use anyhow::{bail, Result}; +use std::process::{Command, Stdio}; +use crate::constants::MIN_MAGISK_VERSION; - -pub fn is_magisk() -> bool { - todo!("is_magisk") +pub fn is_magisk() -> Result { + let version: Option = Command::new("magisk") + .arg("--version") + .stdout(Stdio::piped()) + .spawn().ok() + .and_then(|child| child.wait_with_output().ok()) + .and_then(|output| String::from_utf8(output.stdout).ok()) + .and_then(|output| output.parse().ok()); + if let Some(version) = version { + if version < MIN_MAGISK_VERSION { + bail!("Magisk version too old: {}", version); + } + return Ok(true); + } + Ok(false) } pub fn uid_on_allowlist(uid: i32) -> bool { - todo!("uid_on_allowlist") + // TODO: uid_on_allowlist + return false; } pub fn uid_on_denylist(uid: i32) -> bool { - todo!("uid_on_denylist") + // TODO: uid_on_denylist + return false; } diff --git a/zygiskd/src/root_impl/mod.rs b/zygiskd/src/root_impl/mod.rs index 870579c..67137cb 100644 --- a/zygiskd/src/root_impl/mod.rs +++ b/zygiskd/src/root_impl/mod.rs @@ -1,24 +1,37 @@ mod kernelsu; mod magisk; -pub fn uid_on_allowlist(uid: i32) -> bool { - if kernelsu::is_kernel_su() { - kernelsu::uid_on_allowlist(uid) - } else if magisk::is_magisk() { - magisk::uid_on_allowlist(uid) +use once_cell::sync::OnceCell; +use anyhow::{bail, Result}; + +enum RootImpl { + KernelSU, + Magisk, +} + +static ROOT_IMPL: OnceCell = OnceCell::new(); + +pub fn setup() -> Result<()> { + if kernelsu::is_kernel_su()? { + let _ = ROOT_IMPL.set(RootImpl::KernelSU); + } else if magisk::is_magisk()? { + let _ = ROOT_IMPL.set(RootImpl::Magisk); } else { - log::warn!("Unknown root implementation"); - false + bail!("Unknown root implementation"); + } + Ok(()) +} + +pub fn uid_on_allowlist(uid: i32) -> bool { + match ROOT_IMPL.get().unwrap() { + RootImpl::KernelSU => kernelsu::uid_on_allowlist(uid), + RootImpl::Magisk => magisk::uid_on_allowlist(uid), } } pub fn uid_on_denylist(uid: i32) -> bool { - if kernelsu::is_kernel_su() { - kernelsu::uid_on_denylist(uid) - } else if magisk::is_magisk() { - magisk::uid_on_denylist(uid) - } else { - log::warn!("Unknown root implementation"); - false + match ROOT_IMPL.get().unwrap() { + RootImpl::KernelSU => kernelsu::uid_on_denylist(uid), + RootImpl::Magisk => magisk::uid_on_denylist(uid), } }