9 Commits

Author SHA1 Message Date
Nullptr
80b19c4412 Bump to 0.6.3 2023-03-21 23:08:11 +08:00
Nullptr
a6f455218f No inline for root_impl 2023-03-21 22:55:14 +08:00
Nullptr
87cf885070 No hex patch 2023-03-20 17:36:59 +08:00
5ec1cff
b775d28c23 Add CI (#14)
* CI

Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>

* Update gradle.properties

* add rustup targets (#1)

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Use ccache and rust-cache

Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>

---------

Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>
Co-authored-by: Mufanc <47652878+Mufanc@users.noreply.github.com>
2023-03-16 17:26:29 +08:00
5ec1cff
bf72296d33 Fix revert umount sepolicy (#12)
* Fix revert umount sepolicy

Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>

* Update sepolicy.rule

---------

Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>
2023-03-13 18:10:30 +08:00
Nullptr
9d648d9aa4 Bump to 0.6.2 2023-03-03 18:20:50 +08:00
Nullptr
843086f6f3 Add more sepolicy 2023-03-03 18:20:50 +08:00
Nullptr
49e3ac9d7a Fix dependency bug: OnceCell crashes on 32 bit 2023-03-03 18:20:36 +08:00
Nullptr
446ed92f26 Change module dir and bump to 0.6.1 2023-03-01 12:42:12 +08:00
27 changed files with 252 additions and 80 deletions

88
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,88 @@
name: CI
on:
workflow_dispatch:
push:
branches: [ master ]
tags: [ v* ]
pull_request:
merge_group:
jobs:
build:
runs-on: ubuntu-latest
env:
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
CCACHE_NOHASHDIR: "true"
CCACHE_HARDLINK: "true"
CCACHE_BASEDIR: "${{ github.workspace }}"
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: "recursive"
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: "temurin"
java-version: "17"
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
with:
gradle-home-cache-cleanup: true
- name: Setup rust-cache
uses: Swatinem/rust-cache@v2
with:
workspaces: zygiskd/src -> ../build/intermediates/rust
cache-targets: false
- name: Setup Rust
run: |
rustup target add armv7-linux-androideabi
rustup target add aarch64-linux-android
rustup target add x86_64-linux-android
rustup target add i686-linux-android
- name: Set up ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
max-size: 2G
key: ${{ runner.os }}
restore-keys: ${{ runner.os }}
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
- name: Build with Gradle
run: |
echo 'org.gradle.parallel=true' >> gradle.properties
echo 'org.gradle.vfs.watch=true' >> gradle.properties
echo 'org.gradle.jvmargs=-Xmx2048m' >> gradle.properties
echo 'android.native.buildOutput=verbose' >> gradle.properties
sed -i 's/org.gradle.unsafe.configuration-cache=true//g' gradle.properties
./gradlew zipRelease
./gradlew zipDebug
- name: Prepare artifact
if: success()
id: prepareArtifact
run: |
releaseName=`ls module/build/outputs/release/Zygisk-on-KernelSU-v*-release.zip | awk -F '(/|.zip)' '{print $5}'` && echo "releaseName=$releaseName" >> $GITHUB_OUTPUT
debugName=`ls module/build/outputs/release/Zygisk-on-KernelSU-v*-debug.zip | awk -F '(/|.zip)' '{print $5}'` && echo "debugName=$debugName" >> $GITHUB_OUTPUT
unzip module/build/outputs/release/Zygisk-on-KernelSU-v*-release.zip -d zksu-release
unzip module/build/outputs/release/Zygisk-on-KernelSU-v*-debug.zip -d zksu-debug
- name: Upload release
uses: actions/upload-artifact@v3
with:
name: ${{ steps.prepareArtifact.outputs.releaseName }}
path: "./zksu-release/*"
- name: Upload debug
uses: actions/upload-artifact@v3
with:
name: ${{ steps.prepareArtifact.outputs.debugName }}
path: "./zksu-debug/*"

6
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
[submodule "loader/src/external/liblsplt"] [submodule "loader/src/external/lsplt"]
path = loader/src/external/liblsplt path = loader/src/external/lsplt
url = https://github.com/LSPosed/LSPlt url = https://github.com/LSPosed/lsplt
[submodule "loader/src/external/parallel-hashmap"] [submodule "loader/src/external/parallel-hashmap"]
path = loader/src/external/parallel-hashmap path = loader/src/external/parallel-hashmap
url = https://github.com/greg7mdp/parallel-hashmap url = https://github.com/greg7mdp/parallel-hashmap

View File

@@ -13,11 +13,8 @@ Also works as standalone loader for Magisk on purpose of getting rid of LD_PRELO
### KernelSU ### KernelSU
+ Minimal KernelSU version: 10654 + Minimal KernelSU version: 10654
+ Minimal ksud version: 10647 + Minimal ksud version: 10670
+ Kernel has full SELinux patch support + Kernel has full SELinux patch support
+ For old kernels, you may need to manually add the following code to `sepolicy.rule`:
`allow zygote appdomain_tmpfs file *`
`allow zygote appdomain_tmpfs dir *`
### Magisk ### Magisk

View File

@@ -31,10 +31,10 @@ val gitCommitHash = "git rev-parse --verify --short HEAD".execute()
val moduleId by extra("zygisksu") val moduleId by extra("zygisksu")
val moduleName by extra("Zygisk on KernelSU") val moduleName by extra("Zygisk on KernelSU")
val verName by extra("v4-0.6.0") val verName by extra("v4-0.6.3")
val verCode by extra(gitCommitCount) val verCode by extra(gitCommitCount)
val minKsuVersion by extra(10654) val minKsuVersion by extra(10654)
val minKsudVersion by extra(10647) val minKsudVersion by extra(10670)
val maxKsuVersion by extra(20000) val maxKsuVersion by extra(20000)
val minMagiskVersion by extra(25208) val minMagiskVersion by extra(25208)

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,7 +1,26 @@
import java.nio.file.Paths
import org.gradle.internal.os.OperatingSystem
plugins { plugins {
id("com.android.library") id("com.android.library")
} }
fun Project.findInPath(executable: String, property: String): String? {
val pathEnv = System.getenv("PATH")
return pathEnv.split(File.pathSeparator).map { folder ->
Paths.get("${folder}${File.separator}${executable}${if (OperatingSystem.current().isWindows) ".exe" else ""}")
.toFile()
}.firstOrNull { path ->
path.exists()
}?.absolutePath ?: properties.getOrDefault(property, null) as? String?
}
val ccachePatch by lazy {
project.findInPath("ccache", "ccache.path")?.also {
println("loader: Use ccache: $it")
}
}
android { android {
buildFeatures { buildFeatures {
androidResources = false androidResources = false
@@ -12,6 +31,16 @@ android {
externalNativeBuild.ndkBuild { externalNativeBuild.ndkBuild {
path("src/Android.mk") path("src/Android.mk")
} }
defaultConfig {
externalNativeBuild {
ndkBuild {
ccachePatch?.let {
arguments += "NDK_CCACHE=$it"
}
}
}
}
} }
dependencies { dependencies {

View File

@@ -8,19 +8,37 @@
namespace zygiskd { namespace zygiskd {
bool sMagicRead = false;
static std::string sSocketName;
void ReadMagic() {
sMagicRead = true;
char magic[PATH_MAX]{0};
auto fp = fopen(kZygiskMagic, "r");
if (fp == nullptr) {
PLOGE("Open magic file");
return;
}
fgets(magic, PATH_MAX, fp);
fclose(fp);
sSocketName.append(LP_SELECT("zygiskd32", "zygiskd64")).append(magic);
LOGD("Socket name: %s", sSocketName.data());
}
int Connect(uint8_t retry) { int Connect(uint8_t retry) {
if (!sMagicRead) ReadMagic();
int fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); int fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
struct sockaddr_un addr{ struct sockaddr_un addr{
.sun_family = AF_UNIX, .sun_family = AF_UNIX,
.sun_path={0}, .sun_path={0},
}; };
strncpy(addr.sun_path + 1, kZygiskSocket.data(), kZygiskSocket.size()); strcpy(addr.sun_path + 1, sSocketName.data());
socklen_t socklen = sizeof(sa_family_t) + strlen(addr.sun_path + 1) + 1; socklen_t socklen = sizeof(sa_family_t) + strlen(addr.sun_path + 1) + 1;
while (retry--) { while (retry--) {
int r = connect(fd, reinterpret_cast<struct sockaddr*>(&addr), socklen); int r = connect(fd, reinterpret_cast<struct sockaddr*>(&addr), socklen);
if (r == 0) return fd; if (r == 0) return fd;
LOGW("retrying to connect to zygiskd, sleep 1s"); LOGW("Retrying to connect to zygiskd, sleep 1s");
sleep(1); sleep(1);
} }

View File

@@ -3,18 +3,19 @@ LOCAL_PATH := $(call my-dir)
# liblsplt.a # liblsplt.a
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE:= liblsplt LOCAL_MODULE:= liblsplt
LOCAL_C_INCLUDES := $(LOCAL_PATH)/liblsplt/lsplt/src/main/jni/include LOCAL_C_INCLUDES := $(LOCAL_PATH)/lsplt/lsplt/src/main/jni/include
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
LOCAL_CFLAGS := -Wall -Wextra -Werror -fvisibility=hidden LOCAL_CFLAGS := -Wall -Wextra -Werror -fvisibility=hidden -DLOG_DISABLED
LOCAL_CPPFLAGS := -std=c++20 LOCAL_CPPFLAGS := -std=c++20
LOCAL_STATIC_LIBRARIES := libcxx LOCAL_STATIC_LIBRARIES := libcxx
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
liblsplt/lsplt/src/main/jni/elf_util.cc \ lsplt/lsplt/src/main/jni/elf_util.cc \
liblsplt/lsplt/src/main/jni/lsplt.cc lsplt/lsplt/src/main/jni/lsplt.cc
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
# Header only library # Header only library
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE:= libphmap LOCAL_MODULE:= libphmap
LOCAL_CFLAGS := -Wno-unused-value
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/parallel-hashmap LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/parallel-hashmap
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)

View File

@@ -10,7 +10,8 @@
#else #else
# define LP_SELECT(lp32, lp64) lp32 # define LP_SELECT(lp32, lp64) lp32
#endif #endif
constexpr std::string_view kZygiskSocket = LP_SELECT("zygiskd32", "zygiskd64") "socket_placeholder";
constexpr auto kZygiskMagic = "/system/zygisk_magic";
class UniqueFd { class UniqueFd {
using Fd = int; using Fd = int;

View File

@@ -9,7 +9,7 @@
using namespace std::string_view_literals; using namespace std::string_view_literals;
namespace { namespace {
constexpr auto KSU_MODULE_DIR = "/data/adb/ksu/modules"; constexpr auto MODULE_DIR = "/data/adb/modules";
struct overlay_backup { struct overlay_backup {
std::string target; std::string target;
@@ -38,10 +38,10 @@ void revert_unmount_ksu() {
std::list<overlay_backup> backups; std::list<overlay_backup> backups;
// Unmount ksu module dir last // Unmount ksu module dir last
targets.emplace_back(KSU_MODULE_DIR); targets.emplace_back(MODULE_DIR);
for (auto& info: parse_mount_info("self")) { for (auto& info: parse_mount_info("self")) {
if (info.target == KSU_MODULE_DIR) { if (info.target == MODULE_DIR) {
ksu_loop = info.source; ksu_loop = info.source;
continue; continue;
} }
@@ -51,8 +51,7 @@ void revert_unmount_ksu() {
} }
// Unmount ksu overlays // Unmount ksu overlays
if (info.type == "overlay") { if (info.type == "overlay") {
LOGV("Overlay: %s (%s)", info.target.data(), info.fs_option.data()); if (str_contains(info.fs_option, MODULE_DIR)) {
if (str_contains(info.fs_option, KSU_MODULE_DIR)) {
targets.emplace_back(info.target); targets.emplace_back(info.target);
} else { } else {
auto backup = overlay_backup{ auto backup = overlay_backup{
@@ -66,7 +65,7 @@ void revert_unmount_ksu() {
} }
for (auto& info: parse_mount_info("self")) { for (auto& info: parse_mount_info("self")) {
// Unmount everything from ksu loop except ksu module dir // Unmount everything from ksu loop except ksu module dir
if (info.source == ksu_loop && info.target != KSU_MODULE_DIR) { if (info.source == ksu_loop && info.target != MODULE_DIR) {
targets.emplace_back(info.target); targets.emplace_back(info.target);
} }
} }

View File

@@ -82,6 +82,10 @@ extract "$ZIPFILE" 'sepolicy.rule' "$TMPDIR"
if [ "$KSU" ]; then if [ "$KSU" ]; then
ui_print "- Checking SELinux patches" ui_print "- Checking SELinux patches"
if [ "$(getprop ro.product.first_api_level)" -lt 31 ]; then
echo "allow zygote appdomain_tmpfs file *" >> "$TMPDIR/sepolicy.rule"
echo "allow zygote appdomain_tmpfs dir *" >> "$TMPDIR/sepolicy.rule"
fi
if ! check_sepolicy "$TMPDIR/sepolicy.rule"; then if ! check_sepolicy "$TMPDIR/sepolicy.rule"; then
ui_print "*********************************************************" ui_print "*********************************************************"
ui_print "! Unable to apply SELinux patches!" ui_print "! Unable to apply SELinux patches!"
@@ -93,8 +97,8 @@ fi
ui_print "- Extracting module files" ui_print "- Extracting module files"
extract "$ZIPFILE" 'module.prop' "$MODPATH" extract "$ZIPFILE" 'module.prop' "$MODPATH"
extract "$ZIPFILE" 'post-fs-data.sh' "$MODPATH" extract "$ZIPFILE" 'post-fs-data.sh' "$MODPATH"
extract "$ZIPFILE" 'sepolicy.rule' "$MODPATH"
extract "$ZIPFILE" 'service.sh' "$MODPATH" extract "$ZIPFILE" 'service.sh' "$MODPATH"
mv "$TMPDIR/sepolicy.rule" "$MODPATH"
HAS32BIT=false && [ -d "/system/lib" ] && HAS32BIT=true HAS32BIT=false && [ -d "/system/lib" ] && HAS32BIT=true
HAS64BIT=false && [ -d "/system/lib64" ] && HAS64BIT=true HAS64BIT=false && [ -d "/system/lib64" ] && HAS64BIT=true
@@ -142,20 +146,9 @@ else
fi fi
fi fi
if [ $DEBUG = false ]; then ui_print "- Generating magic"
ui_print "- Hex patching" MAGIC=$(tr -dc 'a-f0-9' </dev/urandom | head -c 18)
SOCKET_PATCH=$(tr -dc 'a-f0-9' </dev/urandom | head -c 18) echo -n "$MAGIC" > "$MODPATH/system/zygisk_magic"
if [ "$HAS32BIT" = true ]; then
sed -i "s/socket_placeholder/$SOCKET_PATCH/g" "$MODPATH/bin/zygiskd32"
sed -i "s/socket_placeholder/$SOCKET_PATCH/g" "$MODPATH/system/lib/libzygisk_injector.so"
sed -i "s/socket_placeholder/$SOCKET_PATCH/g" "$MODPATH/system/lib/libzygisk_loader.so"
fi
if [ "$HAS64BIT" = true ]; then
sed -i "s/socket_placeholder/$SOCKET_PATCH/g" "$MODPATH/bin/zygiskd64"
sed -i "s/socket_placeholder/$SOCKET_PATCH/g" "$MODPATH/system/lib64/libzygisk_injector.so"
sed -i "s/socket_placeholder/$SOCKET_PATCH/g" "$MODPATH/system/lib64/libzygisk_loader.so"
fi
fi
ui_print "- Setting permissions" ui_print "- Setting permissions"
chmod 0744 "$MODPATH/daemon.sh" chmod 0744 "$MODPATH/daemon.sh"

View File

@@ -9,7 +9,7 @@ cd "$MODDIR"
getprop ro.dalvik.vm.native.bridge > /dev/.native_bridge getprop ro.dalvik.vm.native.bridge > /dev/.native_bridge
resetprop ro.dalvik.vm.native.bridge libzygisk_loader.so resetprop ro.dalvik.vm.native.bridge libzygisk_loader.so
if [ "$(which magisk)" ] && [ ".." -ef "/data/adb/modules" ]; then if [ "$(which magisk)" ]; then
for file in ../*; do for file in ../*; do
if [ -d "$file" ] && [ -d "$file/zygisk" ] && ! [ -f "$file/disable" ]; then if [ -d "$file" ] && [ -d "$file/zygisk" ] && ! [ -f "$file/disable" ]; then
if [ -f "$file/post-fs-data.sh" ]; then if [ -f "$file/post-fs-data.sh" ]; then

View File

@@ -10,6 +10,8 @@ allow * magisk_file lnk_file *
allow * magisk_file sock_file * allow * magisk_file sock_file *
allow system_server system_server process execmem allow system_server system_server process execmem
allow zygote adb_data_file dir search
allow zygote mnt_vendor_file dir search allow zygote mnt_vendor_file dir search
allow zygote system_file dir mounton allow zygote system_file dir mounton
allow zygote labeledfs filesystem mount allow zygote labeledfs filesystem mount
allow zygote fs_type filesystem unmount

View File

@@ -11,7 +11,7 @@ cd "$MODDIR"
export NATIVE_BRIDGE=$(cat /dev/.native_bridge) export NATIVE_BRIDGE=$(cat /dev/.native_bridge)
rm /dev/.native_bridge rm /dev/.native_bridge
if [ "$(which magisk)" ] && [ ".." -ef "/data/adb/modules" ]; then if [ "$(which magisk)" ]; then
for file in ../*; do for file in ../*; do
if [ -d "$file" ] && [ -d "$file/zygisk" ] && ! [ -f "$file/disable" ]; then if [ -d "$file" ] && [ -d "$file/zygisk" ] && ! [ -f "$file/disable" ]; then
if [ -f "$file/service.sh" ]; then if [ -f "$file/service.sh" ]; then

View File

@@ -7,8 +7,8 @@ pluginManagement {
gradlePluginPortal() gradlePluginPortal()
} }
plugins { plugins {
id("com.android.library") version "7.4.1" id("com.android.library") version "7.4.2"
id("com.android.application") version "7.4.1" id("com.android.application") version "7.4.2"
} }
} }

View File

@@ -19,15 +19,12 @@ pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Info;
pub const PROP_NATIVE_BRIDGE: &str = "ro.dalvik.vm.native.bridge"; pub const PROP_NATIVE_BRIDGE: &str = "ro.dalvik.vm.native.bridge";
pub const PROP_CTL_RESTART: &str = "ctl.restart"; pub const PROP_CTL_RESTART: &str = "ctl.restart";
pub const ZYGISK_LOADER: &str = "libzygisk_loader.so"; pub const ZYGISK_LOADER: &str = "libzygisk_loader.so";
pub const ZYGISK_MAGIC: &str = "/system/zygisk_magic";
pub const SOCKET_PLACEHOLDER: &str = "socket_placeholder";
pub const PATH_MODULES_DIR: &str = ".."; pub const PATH_MODULES_DIR: &str = "..";
pub const PATH_MODULE_PROP: &str = "module.prop"; pub const PATH_MODULE_PROP: &str = "module.prop";
pub const PATH_ZYGISKD32: &str = "bin/zygiskd32"; pub const PATH_ZYGISKD32: &str = "bin/zygiskd32";
pub const PATH_ZYGISKD64: &str = "bin/zygiskd64"; pub const PATH_ZYGISKD64: &str = "bin/zygiskd64";
pub const PATH_TMP_DIR: &str = concatcp!("/dev/", SOCKET_PLACEHOLDER);
pub const PATH_TMP_PROP: &str = concatcp!("/dev/", SOCKET_PLACEHOLDER, "/module.prop");
pub const STATUS_LOADED: &str = "😋 Zygisksu is loaded"; pub const STATUS_LOADED: &str = "😋 Zygisksu is loaded";
pub const STATUS_CRASHED: &str = "❌ Zygiskd has crashed"; pub const STATUS_CRASHED: &str = "❌ Zygiskd has crashed";

19
zygiskd/src/magic.rs Normal file
View File

@@ -0,0 +1,19 @@
use std::fs;
use anyhow::Result;
use crate::constants;
use crate::utils::LateInit;
pub static MAGIC: LateInit<String> = LateInit::new();
pub static PATH_TMP_DIR: LateInit<String> = LateInit::new();
pub static PATH_TMP_PROP: LateInit<String> = LateInit::new();
pub fn setup() -> Result<()> {
let name = fs::read_to_string(constants::ZYGISK_MAGIC)?;
let path_tmp_dir = format!("/dev/{}", name);
let path_tmp_prop = format!("{}/module.prop", path_tmp_dir);
MAGIC.init(name);
PATH_TMP_DIR.init(path_tmp_dir);
PATH_TMP_PROP.init(path_tmp_prop);
Ok(())
}

View File

@@ -3,6 +3,7 @@
mod companion; mod companion;
mod constants; mod constants;
mod dl; mod dl;
mod magic;
mod root_impl; mod root_impl;
mod utils; mod utils;
mod watchdog; mod watchdog;
@@ -39,6 +40,7 @@ fn init_android_logger(tag: &str) {
fn start() -> Result<()> { fn start() -> Result<()> {
root_impl::setup(); root_impl::setup();
magic::setup()?;
let cli = Args::parse(); let cli = Args::parse();
match cli.command { match cli.command {
Commands::Watchdog => watchdog::entry()?, Commands::Watchdog => watchdog::entry()?,

View File

@@ -24,6 +24,7 @@ pub fn get_kernel_su() -> Option<Version> {
} }
} }
#[inline(never)]
pub fn uid_on_allowlist(uid: i32) -> bool { pub fn uid_on_allowlist(uid: i32) -> bool {
let mut size = 1024u32; let mut size = 1024u32;
let mut uids = vec![0; size as usize]; let mut uids = vec![0; size as usize];
@@ -32,6 +33,7 @@ pub fn uid_on_allowlist(uid: i32) -> bool {
uids.contains(&uid) uids.contains(&uid)
} }
#[inline(never)]
pub fn uid_on_denylist(uid: i32) -> bool { pub fn uid_on_denylist(uid: i32) -> bool {
let mut size = 1024u32; let mut size = 1024u32;
let mut uids = vec![0; size as usize]; let mut uids = vec![0; size as usize];

View File

@@ -23,6 +23,7 @@ pub fn get_magisk() -> Option<Version> {
}) })
} }
#[inline(never)]
pub fn uid_on_allowlist(uid: i32) -> bool { pub fn uid_on_allowlist(uid: i32) -> bool {
let output: Option<String> = Command::new("magisk") let output: Option<String> = Command::new("magisk")
.arg("--sqlite") .arg("--sqlite")
@@ -40,6 +41,7 @@ pub fn uid_on_allowlist(uid: i32) -> bool {
}) })
} }
#[inline(never)]
pub fn uid_on_denylist(uid: i32) -> bool { pub fn uid_on_denylist(uid: i32) -> bool {
// TODO: uid_on_denylist // TODO: uid_on_denylist
return false; return false;

View File

@@ -1,8 +1,6 @@
mod kernelsu; mod kernelsu;
mod magisk; mod magisk;
use once_cell::sync::OnceCell;
pub enum RootImpl { pub enum RootImpl {
None, None,
TooOld, TooOld,
@@ -12,47 +10,50 @@ pub enum RootImpl {
Magisk, Magisk,
} }
static ROOT_IMPL: OnceCell<RootImpl> = OnceCell::new(); // FIXME: OnceCell bugs on 32 bit
static mut ROOT_IMPL: RootImpl = RootImpl::None;
pub fn setup() { pub fn setup() {
let ksu_version = kernelsu::get_kernel_su(); let ksu_version = kernelsu::get_kernel_su();
let magisk_version = magisk::get_magisk(); let magisk_version = magisk::get_magisk();
let _ = match (ksu_version, magisk_version) { let impl_ = match (ksu_version, magisk_version) {
(None, None) => ROOT_IMPL.set(RootImpl::None), (None, None) => RootImpl::None,
(Some(_), Some(_)) => ROOT_IMPL.set(RootImpl::Multiple), (Some(_), Some(_)) => RootImpl::Multiple,
(Some(ksu_version), None) => { (Some(ksu_version), None) => {
let val = match ksu_version { match ksu_version {
kernelsu::Version::Supported => RootImpl::KernelSU, kernelsu::Version::Supported => RootImpl::KernelSU,
kernelsu::Version::TooOld => RootImpl::TooOld, kernelsu::Version::TooOld => RootImpl::TooOld,
kernelsu::Version::Abnormal => RootImpl::Abnormal, kernelsu::Version::Abnormal => RootImpl::Abnormal,
}; }
ROOT_IMPL.set(val)
} }
(None, Some(magisk_version)) => { (None, Some(magisk_version)) => {
let val = match magisk_version { match magisk_version {
magisk::Version::Supported => RootImpl::Magisk, magisk::Version::Supported => RootImpl::Magisk,
magisk::Version::TooOld => RootImpl::TooOld, magisk::Version::TooOld => RootImpl::TooOld,
}; }
ROOT_IMPL.set(val)
} }
}; };
unsafe { ROOT_IMPL = impl_; }
} }
pub fn get_impl() -> &'static RootImpl { pub fn get_impl() -> &'static RootImpl {
ROOT_IMPL.get().unwrap() unsafe { &ROOT_IMPL }
} }
// FIXME: Without #[inline(never)], this function will lag forever
#[inline(never)]
pub fn uid_on_allowlist(uid: i32) -> bool { pub fn uid_on_allowlist(uid: i32) -> bool {
match ROOT_IMPL.get().unwrap() { match get_impl() {
RootImpl::KernelSU => kernelsu::uid_on_allowlist(uid), RootImpl::KernelSU => kernelsu::uid_on_allowlist(uid),
RootImpl::Magisk => magisk::uid_on_allowlist(uid), RootImpl::Magisk => magisk::uid_on_allowlist(uid),
_ => unreachable!(), _ => unreachable!(),
} }
} }
#[inline(never)]
pub fn uid_on_denylist(uid: i32) -> bool { pub fn uid_on_denylist(uid: i32) -> bool {
match ROOT_IMPL.get().unwrap() { match get_impl() {
RootImpl::KernelSU => kernelsu::uid_on_denylist(uid), RootImpl::KernelSU => kernelsu::uid_on_denylist(uid),
RootImpl::Magisk => magisk::uid_on_denylist(uid), RootImpl::Magisk => magisk::uid_on_denylist(uid),
_ => unreachable!(), _ => unreachable!(),

View File

@@ -5,6 +5,7 @@ use std::ffi::c_char;
use std::os::fd::FromRawFd; use std::os::fd::FromRawFd;
use std::os::unix::net::UnixListener; use std::os::unix::net::UnixListener;
use nix::sys::socket::{AddressFamily, SockFlag, SockType, UnixAddr}; use nix::sys::socket::{AddressFamily, SockFlag, SockType, UnixAddr};
use once_cell::sync::OnceCell;
use rand::distributions::{Alphanumeric, DistString}; use rand::distributions::{Alphanumeric, DistString};
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
@@ -18,6 +19,27 @@ macro_rules! lp_select {
($lp32:expr, $lp64:expr) => { $lp32 }; ($lp32:expr, $lp64:expr) => { $lp32 };
} }
pub struct LateInit<T> {
cell: OnceCell<T>,
}
impl<T> LateInit<T> {
pub const fn new() -> Self {
LateInit { cell: OnceCell::new() }
}
pub fn init(&self, value: T) {
assert!(self.cell.set(value).is_ok())
}
}
impl<T> std::ops::Deref for LateInit<T> {
type Target = T;
fn deref(&self) -> &T {
self.cell.get().unwrap()
}
}
pub fn random_string() -> String { pub fn random_string() -> String {
Alphanumeric.sample_string(&mut rand::thread_rng(), 8) Alphanumeric.sample_string(&mut rand::thread_rng(), 8)
} }

View File

@@ -1,4 +1,4 @@
use crate::{constants, root_impl, utils}; use crate::{constants, magic, root_impl, utils};
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use nix::unistd::{getgid, getuid, Pid}; use nix::unistd::{getgid, getuid, Pid};
use std::process::{Child, Command}; use std::process::{Child, Command};
@@ -12,10 +12,10 @@ use binder::IBinder;
use nix::errno::Errno; use nix::errno::Errno;
use nix::libc; use nix::libc;
use nix::sys::signal::{kill, Signal}; use nix::sys::signal::{kill, Signal};
use once_cell::sync::OnceCell; use crate::utils::LateInit;
static LOCK: OnceCell<UnixListener> = OnceCell::new(); static LOCK: LateInit<UnixListener> = LateInit::new();
static PROP_SECTIONS: OnceCell<[String; 2]> = OnceCell::new(); static PROP_SECTIONS: LateInit<[String; 2]> = LateInit::new();
pub fn entry() -> Result<()> { pub fn entry() -> Result<()> {
log::info!("Start zygisksu watchdog"); log::info!("Start zygisksu watchdog");
@@ -55,9 +55,9 @@ fn check_permission() -> Result<()> {
fn ensure_single_instance() -> Result<()> { fn ensure_single_instance() -> Result<()> {
log::info!("Ensure single instance"); log::info!("Ensure single instance");
let name = String::from("zygiskwd") + constants::SOCKET_PLACEHOLDER; let name = format!("zygiskwd{}", magic::MAGIC.as_str());
match utils::abstract_namespace_socket(&name) { match utils::abstract_namespace_socket(&name) {
Ok(socket) => { let _ = LOCK.set(socket); } Ok(socket) => LOCK.init(socket),
Err(e) => bail!("Failed to acquire lock: {e}. Maybe another instance is running?") Err(e) => bail!("Failed to acquire lock: {e}. Maybe another instance is running?")
} }
Ok(()) Ok(())
@@ -91,15 +91,15 @@ fn mount_prop() -> Result<()> {
sections[section].push('\n'); sections[section].push('\n');
} }
} }
let _ = PROP_SECTIONS.set(sections); PROP_SECTIONS.init(sections);
fs::create_dir(constants::PATH_TMP_DIR)?; fs::create_dir(magic::PATH_TMP_DIR.as_str())?;
fs::File::create(constants::PATH_TMP_PROP)?; fs::File::create(magic::PATH_TMP_PROP.as_str())?;
// FIXME: sys_mount cannot be compiled on 32 bit // FIXME: sys_mount cannot be compiled on 32 bit
unsafe { unsafe {
let r = libc::mount( let r = libc::mount(
CString::new(constants::PATH_TMP_PROP)?.as_ptr(), CString::new(magic::PATH_TMP_PROP.as_str())?.as_ptr(),
CString::new(module_prop)?.as_ptr(), CString::new(module_prop)?.as_ptr(),
std::ptr::null(), std::ptr::null(),
libc::MS_BIND, libc::MS_BIND,
@@ -112,13 +112,12 @@ fn mount_prop() -> Result<()> {
} }
fn set_prop_hint(hint: &str) -> Result<()> { fn set_prop_hint(hint: &str) -> Result<()> {
let mut file = fs::File::create(constants::PATH_TMP_PROP)?; let mut file = fs::File::create(magic::PATH_TMP_PROP.as_str())?;
let sections = PROP_SECTIONS.get().unwrap(); file.write_all(PROP_SECTIONS[0].as_bytes())?;
file.write_all(sections[0].as_bytes())?;
file.write_all(b"[")?; file.write_all(b"[")?;
file.write_all(hint.as_bytes())?; file.write_all(hint.as_bytes())?;
file.write_all(b"] ")?; file.write_all(b"] ")?;
file.write_all(sections[1].as_bytes())?; file.write_all(PROP_SECTIONS[1].as_bytes())?;
Ok(()) Ok(())
} }

View File

@@ -1,6 +1,6 @@
use crate::constants::DaemonSocketAction; use crate::constants::DaemonSocketAction;
use crate::utils::UnixStreamExt; use crate::utils::UnixStreamExt;
use crate::{constants, lp_select, root_impl, utils}; use crate::{constants, lp_select, magic, root_impl, utils};
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use memfd::Memfd; use memfd::Memfd;
use nix::{ use nix::{
@@ -135,7 +135,7 @@ fn create_memfd(so_path: &PathBuf) -> Result<Memfd> {
fn create_daemon_socket() -> Result<UnixListener> { fn create_daemon_socket() -> Result<UnixListener> {
utils::set_socket_create_context("u:r:zygote:s0")?; utils::set_socket_create_context("u:r:zygote:s0")?;
let prefix = lp_select!("zygiskd32", "zygiskd64"); let prefix = lp_select!("zygiskd32", "zygiskd64");
let name = String::from(prefix) + constants::SOCKET_PLACEHOLDER; let name = format!("{}{}", prefix, magic::MAGIC.as_str());
let listener = utils::abstract_namespace_socket(&name)?; let listener = utils::abstract_namespace_socket(&name)?;
log::debug!("Daemon socket: {name}"); log::debug!("Daemon socket: {name}");
Ok(listener) Ok(listener)
@@ -198,7 +198,7 @@ fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()>
match root_impl::get_impl() { match root_impl::get_impl() {
root_impl::RootImpl::KernelSU => flags |= constants::PROCESS_ROOT_IS_KSU, root_impl::RootImpl::KernelSU => flags |= constants::PROCESS_ROOT_IS_KSU,
root_impl::RootImpl::Magisk => flags |= constants::PROCESS_ROOT_IS_MAGISK, root_impl::RootImpl::Magisk => flags |= constants::PROCESS_ROOT_IS_MAGISK,
_ => () _ => unreachable!(),
} }
// TODO: PROCESS_IS_SYSUI? // TODO: PROCESS_IS_SYSUI?
stream.write_u32(flags)?; stream.write_u32(flags)?;