You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80b19c4412 | ||
|
|
a6f455218f | ||
|
|
87cf885070 | ||
|
|
b775d28c23 | ||
|
|
bf72296d33 | ||
|
|
9d648d9aa4 | ||
|
|
843086f6f3 | ||
|
|
49e3ac9d7a | ||
|
|
446ed92f26 | ||
|
|
2e9cbf79a7 | ||
|
|
cce8e6686f | ||
|
|
ff2658f2de | ||
|
|
f465cbf810 | ||
|
|
09b6673ab0 | ||
|
|
5f8eb4af09 | ||
|
|
8affc8f991 | ||
|
|
ec8475bca5 | ||
|
|
9ff1e27a7d | ||
|
|
6d9cc560cc | ||
|
|
f395cfb490 | ||
|
|
03575edd96 | ||
|
|
915749e59b | ||
|
|
d08b415577 | ||
|
|
f27aed5068 | ||
|
|
5365ab1f12 | ||
|
|
b99d042002 | ||
|
|
57d3d8a0ba | ||
|
|
e69aa5c527 | ||
|
|
9b5eb1bac7 |
88
.github/workflows/ci.yml
vendored
Normal file
88
.github/workflows/ci.yml
vendored
Normal 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/*"
|
||||||
9
.gitmodules
vendored
9
.gitmodules
vendored
@@ -1,9 +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
|
||||||
[submodule "zygiskd/src/external/binder_rs"]
|
|
||||||
path = zygiskd/src/external/binder_rs
|
|
||||||
url = https://github.com/Kernel-SU/binder_rs
|
|
||||||
|
|||||||
30
README.md
30
README.md
@@ -2,25 +2,25 @@
|
|||||||
|
|
||||||
Zygisk loader for KernelSU, allowing Zygisk modules to run without Magisk environment.
|
Zygisk loader for KernelSU, allowing Zygisk modules to run without Magisk environment.
|
||||||
|
|
||||||
Also works as standalone loader for Magisk on purpose of getting rid of LD_PRELOAD. (Coming soon)
|
Also works as standalone loader for Magisk on purpose of getting rid of LD_PRELOAD.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
+ Minimal KernelSU version: 10575
|
### General
|
||||||
+ Minimal ksud version: 10616
|
|
||||||
+ Full SELinux patch support (If non-gki kernel)
|
+ No multiple root implementation installed
|
||||||
|
|
||||||
|
### KernelSU
|
||||||
|
|
||||||
|
+ Minimal KernelSU version: 10654
|
||||||
|
+ Minimal ksud version: 10670
|
||||||
|
+ Kernel has full SELinux patch support
|
||||||
|
|
||||||
|
### Magisk
|
||||||
|
|
||||||
|
+ Minimal version: 25208
|
||||||
|
+ Original Zygisk turned off
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
Should work with everything except those rely on Magisk internal behaviors.
|
Should work with everything except those rely on Magisk internal behaviors.
|
||||||
|
|
||||||
## Development road map
|
|
||||||
|
|
||||||
- [x] [Inject] Basic Zygisk loader
|
|
||||||
- [x] [Inject] Stabilize injector
|
|
||||||
- [x] [Inject] Unload
|
|
||||||
- [x] [Daemon] Linker namespace
|
|
||||||
- [x] [Daemon] Separate zygiskd process
|
|
||||||
- [x] [Daemon] Handle 64 bit only devices
|
|
||||||
- [x] [Daemon] Handle zygote death
|
|
||||||
- [ ] [ Misc ] Support Magisk out of box
|
|
||||||
|
|||||||
@@ -31,8 +31,12 @@ 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.4.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 minKsudVersion by extra(10670)
|
||||||
|
val maxKsuVersion by extra(20000)
|
||||||
|
val minMagiskVersion by extra(25208)
|
||||||
|
|
||||||
val androidMinSdkVersion by extra(29)
|
val androidMinSdkVersion by extra(29)
|
||||||
val androidTargetSdkVersion by extra(33)
|
val androidTargetSdkVersion by extra(33)
|
||||||
|
|||||||
@@ -20,4 +20,4 @@ kotlin.code.style=official
|
|||||||
# Enables namespacing of each library's R class so that its R class includes only the
|
# Enables namespacing of each library's R class so that its R class includes only the
|
||||||
# resources declared in the library itself and none from the library's dependencies,
|
# resources declared in the library itself and none from the library's dependencies,
|
||||||
# thereby reducing the size of the R class for that library
|
# thereby reducing the size of the R class for that library
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ LOCAL_LDLIBS := -llog
|
|||||||
include $(BUILD_STATIC_LIBRARY)
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := zygiskloader
|
LOCAL_MODULE := zygisk_loader
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||||
FILE_LIST := $(filter %.cpp, $(call walk, $(LOCAL_PATH)/loader))
|
FILE_LIST := $(filter %.cpp, $(call walk, $(LOCAL_PATH)/loader))
|
||||||
LOCAL_SRC_FILES := $(FILE_LIST:COMMON_FILE_LIST:$(LOCAL_PATH)/%=%)
|
LOCAL_SRC_FILES := $(FILE_LIST:COMMON_FILE_LIST:$(LOCAL_PATH)/%=%)
|
||||||
@@ -22,7 +22,7 @@ LOCAL_LDLIBS := -llog
|
|||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := injector
|
LOCAL_MODULE := zygisk_injector
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||||
FILE_LIST := $(filter %.cpp, $(call walk, $(LOCAL_PATH)/injector))
|
FILE_LIST := $(filter %.cpp, $(call walk, $(LOCAL_PATH)/injector))
|
||||||
LOCAL_SRC_FILES := $(FILE_LIST:COMMON_FILE_LIST:$(LOCAL_PATH)/%=%)
|
LOCAL_SRC_FILES := $(FILE_LIST:COMMON_FILE_LIST:$(LOCAL_PATH)/%=%)
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +76,17 @@ namespace zygiskd {
|
|||||||
return socket_utils::read_string(fd);
|
return socket_utils::read_string(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t GetProcessFlags(uid_t uid) {
|
||||||
|
UniqueFd fd = Connect(1);
|
||||||
|
if (fd == -1) {
|
||||||
|
PLOGE("GetProcessFlags");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
socket_utils::write_u8(fd, (uint8_t) SocketAction::GetProcessFlags);
|
||||||
|
socket_utils::write_u32(fd, uid);
|
||||||
|
return socket_utils::read_u32(fd);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Module> ReadModules() {
|
std::vector<Module> ReadModules() {
|
||||||
std::vector<Module> modules;
|
std::vector<Module> modules;
|
||||||
UniqueFd fd = Connect(1);
|
UniqueFd fd = Connect(1);
|
||||||
|
|||||||
@@ -90,6 +90,10 @@ namespace socket_utils {
|
|||||||
return read_exact_or<uint8_t>(fd, 0);
|
return read_exact_or<uint8_t>(fd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t read_u32(int fd) {
|
||||||
|
return read_exact_or<uint32_t>(fd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
size_t read_usize(int fd) {
|
size_t read_usize(int fd) {
|
||||||
return read_exact_or<size_t>(fd, 0);
|
return read_exact_or<size_t>(fd, 0);
|
||||||
}
|
}
|
||||||
@@ -110,6 +114,10 @@ namespace socket_utils {
|
|||||||
return write_exact<uint8_t>(fd, val);
|
return write_exact<uint8_t>(fd, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool write_u32(int fd, uint32_t val) {
|
||||||
|
return write_exact<uint32_t>(fd, val);
|
||||||
|
}
|
||||||
|
|
||||||
bool write_string(int fd, std::string_view str) {
|
bool write_string(int fd, std::string_view str) {
|
||||||
return write_usize(fd, str.size()) && str.size() == xwrite(fd, str.data(), str.size());
|
return write_usize(fd, str.size()) && str.size() == xwrite(fd, str.data(), str.size());
|
||||||
}
|
}
|
||||||
|
|||||||
9
loader/src/external/Android.mk
vendored
9
loader/src/external/Android.mk
vendored
@@ -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)
|
||||||
|
|||||||
2
loader/src/external/parallel-hashmap
vendored
2
loader/src/external/parallel-hashmap
vendored
Submodule loader/src/external/parallel-hashmap updated: 87ece91c6e...55725dbe70
@@ -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;
|
||||||
@@ -54,6 +55,7 @@ namespace zygiskd {
|
|||||||
PingHeartBeat,
|
PingHeartBeat,
|
||||||
RequestLogcatFd,
|
RequestLogcatFd,
|
||||||
ReadNativeBridge,
|
ReadNativeBridge,
|
||||||
|
GetProcessFlags,
|
||||||
ReadModules,
|
ReadModules,
|
||||||
RequestCompanionSocket,
|
RequestCompanionSocket,
|
||||||
GetModuleDir,
|
GetModuleDir,
|
||||||
@@ -67,6 +69,8 @@ namespace zygiskd {
|
|||||||
|
|
||||||
std::vector<Module> ReadModules();
|
std::vector<Module> ReadModules();
|
||||||
|
|
||||||
|
uint32_t GetProcessFlags(uid_t uid);
|
||||||
|
|
||||||
int ConnectCompanion(size_t index);
|
int ConnectCompanion(size_t index);
|
||||||
|
|
||||||
int GetModuleDir(size_t index);
|
int GetModuleDir(size_t index);
|
||||||
|
|||||||
@@ -13,12 +13,16 @@ namespace socket_utils {
|
|||||||
|
|
||||||
uint8_t read_u8(int fd);
|
uint8_t read_u8(int fd);
|
||||||
|
|
||||||
|
uint32_t read_u32(int fd);
|
||||||
|
|
||||||
size_t read_usize(int fd);
|
size_t read_usize(int fd);
|
||||||
|
|
||||||
std::string read_string(int fd);
|
std::string read_string(int fd);
|
||||||
|
|
||||||
bool write_u8(int fd, uint8_t val);
|
bool write_u8(int fd, uint8_t val);
|
||||||
|
|
||||||
|
bool write_u32(int fd, uint32_t val);
|
||||||
|
|
||||||
int recv_fd(int fd);
|
int recv_fd(int fd);
|
||||||
|
|
||||||
bool write_usize(int fd, size_t val);
|
bool write_usize(int fd, size_t val);
|
||||||
|
|||||||
@@ -26,10 +26,3 @@ void entry(void *handle) {
|
|||||||
LOGD("Load injector successfully");
|
LOGD("Load injector successfully");
|
||||||
hook_functions();
|
hook_functions();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following code runs in zygote/app process
|
|
||||||
|
|
||||||
static inline bool should_load_modules(uint32_t flags) {
|
|
||||||
return (flags & UNMOUNT_MASK) != UNMOUNT_MASK &&
|
|
||||||
(flags & PROCESS_IS_MAGISK_APP) != PROCESS_IS_MAGISK_APP;
|
|
||||||
}
|
|
||||||
|
|||||||
122
loader/src/injector/files.cpp
Normal file
122
loader/src/injector/files.cpp
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
|
#include "files.hpp"
|
||||||
|
#include "misc.hpp"
|
||||||
|
|
||||||
|
using namespace std::string_view_literals;
|
||||||
|
|
||||||
|
void file_readline(bool trim, FILE *fp, const std::function<bool(std::string_view)> &fn) {
|
||||||
|
size_t len = 1024;
|
||||||
|
char *buf = (char *) malloc(len);
|
||||||
|
char *start;
|
||||||
|
ssize_t read;
|
||||||
|
while ((read = getline(&buf, &len, fp)) >= 0) {
|
||||||
|
start = buf;
|
||||||
|
if (trim) {
|
||||||
|
while (read && "\n\r "sv.find(buf[read - 1]) != std::string::npos)
|
||||||
|
--read;
|
||||||
|
buf[read] = '\0';
|
||||||
|
while (*start == ' ')
|
||||||
|
++start;
|
||||||
|
}
|
||||||
|
if (!fn(start))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_readline(bool trim, const char *file, const std::function<bool(std::string_view)> &fn) {
|
||||||
|
if (auto fp = open_file(file, "re"))
|
||||||
|
file_readline(trim, fp.get(), fn);
|
||||||
|
}
|
||||||
|
void file_readline(const char *file, const std::function<bool(std::string_view)> &fn) {
|
||||||
|
file_readline(false, file, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<mount_info> parse_mount_info(const char *pid) {
|
||||||
|
char buf[PATH_MAX] = {};
|
||||||
|
snprintf(buf, sizeof(buf), "/proc/%s/mountinfo", pid);
|
||||||
|
std::vector<mount_info> result;
|
||||||
|
|
||||||
|
file_readline(buf, [&result](std::string_view line) -> bool {
|
||||||
|
int root_start = 0, root_end = 0;
|
||||||
|
int target_start = 0, target_end = 0;
|
||||||
|
int vfs_option_start = 0, vfs_option_end = 0;
|
||||||
|
int type_start = 0, type_end = 0;
|
||||||
|
int source_start = 0, source_end = 0;
|
||||||
|
int fs_option_start = 0, fs_option_end = 0;
|
||||||
|
int optional_start = 0, optional_end = 0;
|
||||||
|
unsigned int id, parent, maj, min;
|
||||||
|
sscanf(line.data(),
|
||||||
|
"%u " // (1) id
|
||||||
|
"%u " // (2) parent
|
||||||
|
"%u:%u " // (3) maj:min
|
||||||
|
"%n%*s%n " // (4) mountroot
|
||||||
|
"%n%*s%n " // (5) target
|
||||||
|
"%n%*s%n" // (6) vfs options (fs-independent)
|
||||||
|
"%n%*[^-]%n - " // (7) optional fields
|
||||||
|
"%n%*s%n " // (8) FS type
|
||||||
|
"%n%*s%n " // (9) source
|
||||||
|
"%n%*s%n", // (10) fs options (fs specific)
|
||||||
|
&id, &parent, &maj, &min, &root_start, &root_end, &target_start,
|
||||||
|
&target_end, &vfs_option_start, &vfs_option_end,
|
||||||
|
&optional_start, &optional_end, &type_start, &type_end,
|
||||||
|
&source_start, &source_end, &fs_option_start, &fs_option_end);
|
||||||
|
|
||||||
|
auto root = line.substr(root_start, root_end - root_start);
|
||||||
|
auto target = line.substr(target_start, target_end - target_start);
|
||||||
|
auto vfs_option =
|
||||||
|
line.substr(vfs_option_start, vfs_option_end - vfs_option_start);
|
||||||
|
++optional_start;
|
||||||
|
--optional_end;
|
||||||
|
auto optional = line.substr(
|
||||||
|
optional_start,
|
||||||
|
optional_end - optional_start > 0 ? optional_end - optional_start : 0);
|
||||||
|
|
||||||
|
auto type = line.substr(type_start, type_end - type_start);
|
||||||
|
auto source = line.substr(source_start, source_end - source_start);
|
||||||
|
auto fs_option =
|
||||||
|
line.substr(fs_option_start, fs_option_end - fs_option_start);
|
||||||
|
|
||||||
|
unsigned int shared = 0;
|
||||||
|
unsigned int master = 0;
|
||||||
|
unsigned int propagate_from = 0;
|
||||||
|
if (auto pos = optional.find("shared:"); pos != std::string_view::npos) {
|
||||||
|
shared = parse_int(optional.substr(pos + 7));
|
||||||
|
}
|
||||||
|
if (auto pos = optional.find("master:"); pos != std::string_view::npos) {
|
||||||
|
master = parse_int(optional.substr(pos + 7));
|
||||||
|
}
|
||||||
|
if (auto pos = optional.find("propagate_from:");
|
||||||
|
pos != std::string_view::npos) {
|
||||||
|
propagate_from = parse_int(optional.substr(pos + 15));
|
||||||
|
}
|
||||||
|
|
||||||
|
result.emplace_back(mount_info {
|
||||||
|
.id = id,
|
||||||
|
.parent = parent,
|
||||||
|
.device = static_cast<dev_t>(makedev(maj, min)),
|
||||||
|
.root {root},
|
||||||
|
.target {target},
|
||||||
|
.vfs_option {vfs_option},
|
||||||
|
.optional {
|
||||||
|
.shared = shared,
|
||||||
|
.master = master,
|
||||||
|
.propagate_from = propagate_from,
|
||||||
|
},
|
||||||
|
.type {type},
|
||||||
|
.source {source},
|
||||||
|
.fs_option {fs_option},
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
sDIR make_dir(DIR *dp) {
|
||||||
|
return sDIR(dp, [](DIR *dp){ return dp ? closedir(dp) : 1; });
|
||||||
|
}
|
||||||
|
|
||||||
|
sFILE make_file(FILE *fp) {
|
||||||
|
return sFILE(fp, [](FILE *fp){ return fp ? fclose(fp) : 1; });
|
||||||
|
}
|
||||||
56
loader/src/injector/files.hpp
Normal file
56
loader/src/injector/files.hpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include <dirent.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct mount_info {
|
||||||
|
unsigned int id;
|
||||||
|
unsigned int parent;
|
||||||
|
dev_t device;
|
||||||
|
std::string root;
|
||||||
|
std::string target;
|
||||||
|
std::string vfs_option;
|
||||||
|
struct {
|
||||||
|
unsigned int shared;
|
||||||
|
unsigned int master;
|
||||||
|
unsigned int propagate_from;
|
||||||
|
} optional;
|
||||||
|
std::string type;
|
||||||
|
std::string source;
|
||||||
|
std::string fs_option;
|
||||||
|
};
|
||||||
|
|
||||||
|
void file_readline(bool trim, FILE *fp, const std::function<bool(std::string_view)> &fn);
|
||||||
|
void file_readline(bool trim, const char *file, const std::function<bool(std::string_view)> &fn);
|
||||||
|
void file_readline(const char *file, const std::function<bool(std::string_view)> &fn);
|
||||||
|
|
||||||
|
std::vector<mount_info> parse_mount_info(const char *pid);
|
||||||
|
|
||||||
|
using sFILE = std::unique_ptr<FILE, decltype(&fclose)>;
|
||||||
|
using sDIR = std::unique_ptr<DIR, decltype(&closedir)>;
|
||||||
|
sDIR make_dir(DIR *dp);
|
||||||
|
sFILE make_file(FILE *fp);
|
||||||
|
|
||||||
|
static inline sDIR open_dir(const char *path) {
|
||||||
|
return make_dir(opendir(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline sDIR xopen_dir(const char *path) {
|
||||||
|
return make_dir(opendir(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline sDIR xopen_dir(int dirfd) {
|
||||||
|
return make_dir(fdopendir(dirfd));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline sFILE open_file(const char *path, const char *mode) {
|
||||||
|
return make_file(fopen(path, mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline sFILE xopen_file(const char *path, const char *mode) {
|
||||||
|
return make_file(fopen(path, mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline sFILE xopen_file(int fd, const char *mode) {
|
||||||
|
return make_file(fdopen(fd, mode));
|
||||||
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#include <sys/mount.h>
|
|
||||||
|
|
||||||
#include "logging.h"
|
|
||||||
#include "misc.hpp"
|
|
||||||
#include "zygisk.hpp"
|
|
||||||
|
|
||||||
using namespace std::string_view_literals;
|
|
||||||
|
|
||||||
static void lazy_unmount(const char* mountpoint) {
|
|
||||||
if (umount2(mountpoint, MNT_DETACH) != -1)
|
|
||||||
LOGD("Unmounted (%s)", mountpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
void revert_unmount() {
|
|
||||||
parse_mnt("/proc/self/mounts", [](mntent* mentry) {
|
|
||||||
if (mentry->mnt_fsname == "/data/adb/ksu/modules"sv ||
|
|
||||||
std::string_view(mentry->mnt_opts).find("/data/adb/ksu/modules") != std::string_view::npos) {
|
|
||||||
lazy_unmount(mentry->mnt_fsname);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
#include "zygisk.hpp"
|
#include "zygisk.hpp"
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
#include "module.hpp"
|
#include "module.hpp"
|
||||||
#include "misc.hpp"
|
#include "files.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using jni_hook::hash_map;
|
using jni_hook::hash_map;
|
||||||
@@ -219,7 +219,11 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
|
|||||||
// Simply avoid doing any unmounts for SysUI to avoid potential issues.
|
// Simply avoid doing any unmounts for SysUI to avoid potential issues.
|
||||||
(g_ctx->info_flags & PROCESS_IS_SYS_UI) == 0) {
|
(g_ctx->info_flags & PROCESS_IS_SYS_UI) == 0) {
|
||||||
if (g_ctx->flags[DO_REVERT_UNMOUNT]) {
|
if (g_ctx->flags[DO_REVERT_UNMOUNT]) {
|
||||||
revert_unmount();
|
if (g_ctx->info_flags & PROCESS_ROOT_IS_KSU) {
|
||||||
|
revert_unmount_ksu();
|
||||||
|
} else if (g_ctx->info_flags & PROCESS_ROOT_IS_MAGISK) {
|
||||||
|
revert_unmount_magisk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zygisksu changed: No umount app_process */
|
/* Zygisksu changed: No umount app_process */
|
||||||
@@ -566,15 +570,13 @@ void HookContext::run_modules_post() {
|
|||||||
/* Zygisksu changed: Load module fds */
|
/* Zygisksu changed: Load module fds */
|
||||||
void HookContext::app_specialize_pre() {
|
void HookContext::app_specialize_pre() {
|
||||||
flags[APP_SPECIALIZE] = true;
|
flags[APP_SPECIALIZE] = true;
|
||||||
|
info_flags = zygiskd::GetProcessFlags(g_ctx->args.app->uid);
|
||||||
run_modules_pre();
|
run_modules_pre();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HookContext::app_specialize_post() {
|
void HookContext::app_specialize_post() {
|
||||||
run_modules_post();
|
run_modules_post();
|
||||||
if (info_flags & PROCESS_IS_MAGISK_APP) {
|
|
||||||
setenv("ZYGISK_ENABLED", "1", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanups
|
// Cleanups
|
||||||
env->ReleaseStringUTFChars(args.app->nice_name, process);
|
env->ReleaseStringUTFChars(args.app->nice_name, process);
|
||||||
|
|||||||
@@ -23,22 +23,27 @@ int parse_int(std::string_view s) {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_mnt(const char* file, const std::function<bool(mntent*)>& fn) {
|
std::list<std::string> split_str(std::string_view s, std::string_view delimiter) {
|
||||||
auto fp = sFILE(setmntent(file, "re"), endmntent);
|
std::list<std::string> ret;
|
||||||
if (fp) {
|
size_t pos = 0;
|
||||||
mntent mentry{};
|
while (pos < s.size()) {
|
||||||
char buf[PATH_MAX];
|
auto next = s.find(delimiter, pos);
|
||||||
while (getmntent_r(fp.get(), &mentry, buf, sizeof(buf))) {
|
if (next == std::string_view::npos) {
|
||||||
if (!fn(&mentry))
|
ret.emplace_back(s.substr(pos));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ret.emplace_back(s.substr(pos, next - pos));
|
||||||
|
pos = next + delimiter.size();
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sDIR make_dir(DIR *dp) {
|
std::string join_str(const std::list<std::string>& list, std::string_view delimiter) {
|
||||||
return sDIR(dp, [](DIR *dp){ return dp ? closedir(dp) : 1; });
|
std::string ret;
|
||||||
}
|
for (auto& s : list) {
|
||||||
|
if (!ret.empty())
|
||||||
sFILE make_file(FILE *fp) {
|
ret += delimiter;
|
||||||
return sFILE(fp, [](FILE *fp){ return fp ? fclose(fp) : 1; });
|
ret += s;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <list>
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mntent.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
@@ -34,6 +32,10 @@ private:
|
|||||||
using thread_entry = void *(*)(void *);
|
using thread_entry = void *(*)(void *);
|
||||||
int new_daemon_thread(thread_entry entry, void *arg);
|
int new_daemon_thread(thread_entry entry, void *arg);
|
||||||
|
|
||||||
|
static inline bool str_contains(std::string_view s, std::string_view ss) {
|
||||||
|
return s.find(ss) != std::string_view::npos;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, typename Impl>
|
template<typename T, typename Impl>
|
||||||
class stateless_allocator {
|
class stateless_allocator {
|
||||||
public:
|
public:
|
||||||
@@ -49,33 +51,23 @@ public:
|
|||||||
bool operator!=(const stateless_allocator&) { return false; }
|
bool operator!=(const stateless_allocator&) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
using sFILE = std::unique_ptr<FILE, decltype(&fclose)>;
|
template <typename T>
|
||||||
using sDIR = std::unique_ptr<DIR, decltype(&closedir)>;
|
class reversed_container {
|
||||||
sDIR make_dir(DIR *dp);
|
public:
|
||||||
sFILE make_file(FILE *fp);
|
reversed_container(T &base) : base(base) {}
|
||||||
|
decltype(std::declval<T>().rbegin()) begin() { return base.rbegin(); }
|
||||||
|
decltype(std::declval<T>().crbegin()) begin() const { return base.crbegin(); }
|
||||||
|
decltype(std::declval<T>().crbegin()) cbegin() const { return base.crbegin(); }
|
||||||
|
decltype(std::declval<T>().rend()) end() { return base.rend(); }
|
||||||
|
decltype(std::declval<T>().crend()) end() const { return base.crend(); }
|
||||||
|
decltype(std::declval<T>().crend()) cend() const { return base.crend(); }
|
||||||
|
private:
|
||||||
|
T &base;
|
||||||
|
};
|
||||||
|
|
||||||
static inline sDIR open_dir(const char *path) {
|
template <typename T>
|
||||||
return make_dir(opendir(path));
|
reversed_container<T> reversed(T &base) {
|
||||||
}
|
return reversed_container<T>(base);
|
||||||
|
|
||||||
static inline sDIR xopen_dir(const char *path) {
|
|
||||||
return make_dir(opendir(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline sDIR xopen_dir(int dirfd) {
|
|
||||||
return make_dir(fdopendir(dirfd));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline sFILE open_file(const char *path, const char *mode) {
|
|
||||||
return make_file(fopen(path, mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline sFILE xopen_file(const char *path, const char *mode) {
|
|
||||||
return make_file(fopen(path, mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline sFILE xopen_file(int fd, const char *mode) {
|
|
||||||
return make_file(fdopen(fd, mode));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@@ -95,7 +87,9 @@ struct StringCmp {
|
|||||||
*/
|
*/
|
||||||
int parse_int(std::string_view s);
|
int parse_int(std::string_view s);
|
||||||
|
|
||||||
void parse_mnt(const char* file, const std::function<bool(mntent*)>& fn);
|
std::list<std::string> split_str(std::string_view s, std::string_view delimiter);
|
||||||
|
|
||||||
|
std::string join_str(const std::list<std::string>& list, std::string_view delimiter);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline T align_to(T v, int a) {
|
static inline T align_to(T v, int a) {
|
||||||
|
|||||||
@@ -111,12 +111,11 @@ namespace {
|
|||||||
PROCESS_GRANTED_ROOT = zygisk::StateFlag::PROCESS_GRANTED_ROOT,
|
PROCESS_GRANTED_ROOT = zygisk::StateFlag::PROCESS_GRANTED_ROOT,
|
||||||
PROCESS_ON_DENYLIST = zygisk::StateFlag::PROCESS_ON_DENYLIST,
|
PROCESS_ON_DENYLIST = zygisk::StateFlag::PROCESS_ON_DENYLIST,
|
||||||
|
|
||||||
PROCESS_IS_SYS_UI = (1u << 29),
|
PROCESS_ROOT_IS_KSU = (1u << 29),
|
||||||
DENYLIST_ENFORCING = (1u << 30),
|
PROCESS_ROOT_IS_MAGISK = (1u << 30),
|
||||||
PROCESS_IS_MAGISK_APP = (1u << 31),
|
PROCESS_IS_SYS_UI = (1u << 31),
|
||||||
|
|
||||||
UNMOUNT_MASK = (PROCESS_ON_DENYLIST | DENYLIST_ENFORCING),
|
PRIVATE_MASK = PROCESS_IS_SYS_UI
|
||||||
PRIVATE_MASK = (PROCESS_IS_SYS_UI | DENYLIST_ENFORCING | PROCESS_IS_MAGISK_APP)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct api_abi_base {
|
struct api_abi_base {
|
||||||
|
|||||||
122
loader/src/injector/unmount.cpp
Normal file
122
loader/src/injector/unmount.cpp
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
#include <mntent.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
|
||||||
|
#include "files.hpp"
|
||||||
|
#include "logging.h"
|
||||||
|
#include "misc.hpp"
|
||||||
|
#include "zygisk.hpp"
|
||||||
|
|
||||||
|
using namespace std::string_view_literals;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr auto MODULE_DIR = "/data/adb/modules";
|
||||||
|
|
||||||
|
struct overlay_backup {
|
||||||
|
std::string target;
|
||||||
|
std::string vfs_option;
|
||||||
|
std::string fs_option;
|
||||||
|
};
|
||||||
|
|
||||||
|
void lazy_unmount(const char* mountpoint) {
|
||||||
|
if (umount2(mountpoint, MNT_DETACH) != -1) {
|
||||||
|
LOGD("Unmounted (%s)", mountpoint);
|
||||||
|
} else {
|
||||||
|
PLOGE("Unmount (%s)", mountpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PARSE_OPT(name, flag) \
|
||||||
|
if (opt == (name)) { \
|
||||||
|
flags |= (flag); \
|
||||||
|
return true; \
|
||||||
|
}
|
||||||
|
|
||||||
|
void revert_unmount_ksu() {
|
||||||
|
std::string ksu_loop;
|
||||||
|
std::vector<std::string> targets;
|
||||||
|
std::list<overlay_backup> backups;
|
||||||
|
|
||||||
|
// 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 on /data/adb except ksu module dir
|
||||||
|
if (info.target.starts_with("/data/adb")) {
|
||||||
|
targets.emplace_back(info.target);
|
||||||
|
}
|
||||||
|
// Unmount ksu overlays
|
||||||
|
if (info.type == "overlay") {
|
||||||
|
if (str_contains(info.fs_option, MODULE_DIR)) {
|
||||||
|
targets.emplace_back(info.target);
|
||||||
|
} else {
|
||||||
|
auto backup = overlay_backup{
|
||||||
|
.target = info.target,
|
||||||
|
.vfs_option = info.vfs_option,
|
||||||
|
.fs_option = info.fs_option,
|
||||||
|
};
|
||||||
|
backups.emplace_back(backup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affirm unmounted system overlays
|
||||||
|
for (auto& info: parse_mount_info("self")) {
|
||||||
|
if (info.type == "overlay") {
|
||||||
|
backups.remove_if([&](overlay_backup& mnt) {
|
||||||
|
return mnt.target == info.target && mnt.fs_option == info.fs_option;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore system overlays
|
||||||
|
for (auto& mnt: backups) {
|
||||||
|
auto opts = split_str(mnt.vfs_option, ",");
|
||||||
|
opts.splice(opts.end(), split_str(mnt.fs_option, ","));
|
||||||
|
unsigned long flags = 0;
|
||||||
|
opts.remove_if([&](auto& opt) {
|
||||||
|
PARSE_OPT(MNTOPT_RO, MS_RDONLY)
|
||||||
|
PARSE_OPT(MNTOPT_NOSUID, MS_NOSUID)
|
||||||
|
PARSE_OPT("relatime", MS_RELATIME)
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
auto mnt_data = join_str(opts, ",");
|
||||||
|
if (mount("overlay", mnt.target.data(), "overlay", flags, mnt_data.data()) != -1) {
|
||||||
|
LOGD("Remounted (%s)", mnt.target.data());
|
||||||
|
} else {
|
||||||
|
PLOGE("Remount (%s, %s)", mnt.target.data(), mnt.fs_option.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void revert_unmount_magisk() {
|
||||||
|
std::vector<std::string> targets;
|
||||||
|
|
||||||
|
// Unmount dummy skeletons and MAGISKTMP
|
||||||
|
// since mirror nodes are always mounted under skeleton, we don't have to specifically unmount
|
||||||
|
for (auto& info: parse_mount_info("self")) {
|
||||||
|
if (info.source == "magisk" || info.source == "worker" || // magisktmp tmpfs
|
||||||
|
info.root.starts_with("/adb/modules")) { // bind mount from data partition
|
||||||
|
targets.push_back(info.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& s: reversed(targets)) {
|
||||||
|
lazy_unmount(s.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,4 +8,7 @@ extern void *self_handle;
|
|||||||
|
|
||||||
void hook_functions();
|
void hook_functions();
|
||||||
|
|
||||||
void revert_unmount();
|
void revert_unmount_ksu();
|
||||||
|
|
||||||
|
void revert_unmount_magisk();
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ uint8_t NativeBridgeItf[sizeof(NativeBridgeCallbacks<__ANDROID_API_R__>) * 2]{0}
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr auto kZygoteProcesses = {"zygote", "zygote32", "zygote64", "usap32", "usap64"};
|
constexpr auto kZygoteProcesses = {"zygote", "zygote32", "zygote64", "usap32", "usap64"};
|
||||||
constexpr auto kInjector = "/system/" LP_SELECT("lib", "lib64") "/libinjector.so";
|
constexpr auto kInjector = "/system/" LP_SELECT("lib", "lib64") "/libzygisk_injector.so";
|
||||||
|
|
||||||
void* sOriginalBridge = nullptr;
|
void* sOriginalBridge = nullptr;
|
||||||
}
|
}
|
||||||
@@ -70,13 +70,13 @@ void Constructor() {
|
|||||||
LOGI("Load original native bridge: %s", native_bridge.data());
|
LOGI("Load original native bridge: %s", native_bridge.data());
|
||||||
sOriginalBridge = dlopen(native_bridge.data(), RTLD_NOW);
|
sOriginalBridge = dlopen(native_bridge.data(), RTLD_NOW);
|
||||||
if (sOriginalBridge == nullptr) {
|
if (sOriginalBridge == nullptr) {
|
||||||
LOGE("dlopen failed: %s", dlerror());
|
LOGE("%s", dlerror());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* original_native_bridge_itf = dlsym(sOriginalBridge, "NativeBridgeItf");
|
auto* original_native_bridge_itf = dlsym(sOriginalBridge, "NativeBridgeItf");
|
||||||
if (original_native_bridge_itf == nullptr) {
|
if (original_native_bridge_itf == nullptr) {
|
||||||
LOGE("dlsym failed: %s", dlerror());
|
LOGE("%s", dlerror());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ val moduleId: String by rootProject.extra
|
|||||||
val moduleName: String by rootProject.extra
|
val moduleName: String by rootProject.extra
|
||||||
val verCode: Int by rootProject.extra
|
val verCode: Int by rootProject.extra
|
||||||
val verName: String by rootProject.extra
|
val verName: String by rootProject.extra
|
||||||
|
val minKsuVersion: Int by rootProject.extra
|
||||||
|
val minKsudVersion: Int by rootProject.extra
|
||||||
|
val maxKsuVersion: Int by rootProject.extra
|
||||||
|
val minMagiskVersion: Int by rootProject.extra
|
||||||
|
|
||||||
android.buildFeatures {
|
android.buildFeatures {
|
||||||
androidResources = false
|
androidResources = false
|
||||||
@@ -34,7 +38,7 @@ androidComponents.onVariants { variant ->
|
|||||||
into(moduleDir)
|
into(moduleDir)
|
||||||
from("${rootProject.projectDir}/README.md")
|
from("${rootProject.projectDir}/README.md")
|
||||||
from("$projectDir/src") {
|
from("$projectDir/src") {
|
||||||
exclude("module.prop", "customize.sh", "daemon.sh")
|
exclude("module.prop", "customize.sh", "service.sh")
|
||||||
filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf"))
|
filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf"))
|
||||||
}
|
}
|
||||||
from("$projectDir/src") {
|
from("$projectDir/src") {
|
||||||
@@ -47,9 +51,13 @@ androidComponents.onVariants { variant ->
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
from("$projectDir/src") {
|
from("$projectDir/src") {
|
||||||
include("customize.sh", "daemon.sh")
|
include("customize.sh", "service.sh")
|
||||||
val tokens = mapOf(
|
val tokens = mapOf(
|
||||||
"DEBUG" to if (buildTypeLowered == "debug") "true" else "false"
|
"DEBUG" to if (buildTypeLowered == "debug") "true" else "false",
|
||||||
|
"MIN_KSU_VERSION" to "$minKsuVersion",
|
||||||
|
"MIN_KSUD_VERSION" to "$minKsudVersion",
|
||||||
|
"MAX_KSU_VERSION" to "$maxKsuVersion",
|
||||||
|
"MIN_MAGISK_VERSION" to "$minMagiskVersion",
|
||||||
)
|
)
|
||||||
filter<ReplaceTokens>("tokens" to tokens)
|
filter<ReplaceTokens>("tokens" to tokens)
|
||||||
filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf"))
|
filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf"))
|
||||||
@@ -106,7 +114,7 @@ androidComponents.onVariants { variant ->
|
|||||||
val installMagiskTask = task<Exec>("installMagisk$variantCapped") {
|
val installMagiskTask = task<Exec>("installMagisk$variantCapped") {
|
||||||
group = "module"
|
group = "module"
|
||||||
dependsOn(pushTask)
|
dependsOn(pushTask)
|
||||||
commandLine("adb", "shell", "su", "-c", "KSU=true magisk --install-module /data/local/tmp/$zipFileName")
|
commandLine("adb", "shell", "su", "-c", "magisk --install-module /data/local/tmp/$zipFileName")
|
||||||
}
|
}
|
||||||
|
|
||||||
task<Exec>("installKsuAndReboot$variantCapped") {
|
task<Exec>("installKsuAndReboot$variantCapped") {
|
||||||
|
|||||||
@@ -2,28 +2,56 @@
|
|||||||
SKIPUNZIP=1
|
SKIPUNZIP=1
|
||||||
|
|
||||||
DEBUG=@DEBUG@
|
DEBUG=@DEBUG@
|
||||||
|
MIN_KSU_VERSION=@MIN_KSU_VERSION@
|
||||||
|
MIN_KSUD_VERSION=@MIN_KSUD_VERSION@
|
||||||
|
MAX_KSU_VERSION=@MAX_KSU_VERSION@
|
||||||
|
MIN_MAGISK_VERSION=@MIN_MAGISK_VERSION@
|
||||||
|
|
||||||
if [ $BOOTMODE ] && [ "$KSU" == "true" ]; then
|
if [ "$BOOTMODE" ] && [ "$KSU" ]; then
|
||||||
ui_print "- Installing from KernelSU app"
|
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 "$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
|
||||||
|
if ! [ "$KSU_VER_CODE" ] || [ "$KSU_VER_CODE" -lt "$MIN_KSUD_VERSION" ]; then
|
||||||
|
ui_print "*********************************************************"
|
||||||
|
ui_print "! ksud version is too old!"
|
||||||
|
ui_print "! Please update KernelSU Manager to latest version"
|
||||||
|
abort "*********************************************************"
|
||||||
|
fi
|
||||||
|
if [ "$(which magisk)" ]; then
|
||||||
|
ui_print "*********************************************************"
|
||||||
|
ui_print "! Multiple root implementation is NOT supported!"
|
||||||
|
ui_print "! Please uninstall Magisk before installing Zygisksu"
|
||||||
|
abort "*********************************************************"
|
||||||
|
fi
|
||||||
|
elif [ "$BOOTMODE" ] && [ "$MAGISK_VER_CODE" ]; then
|
||||||
|
ui_print "- Installing from Magisk app"
|
||||||
|
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"
|
||||||
|
abort "*********************************************************"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
ui_print "*********************************************************"
|
ui_print "*********************************************************"
|
||||||
ui_print "! Install from recovery or Magisk is NOT supported"
|
ui_print "! Install from recovery is not supported"
|
||||||
ui_print "! Please install from KernelSU app"
|
ui_print "! Please install from KernelSU or Magisk app"
|
||||||
abort "*********************************************************"
|
abort "*********************************************************"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
VERSION=$(grep_prop version "${TMPDIR}/module.prop")
|
VERSION=$(grep_prop version "${TMPDIR}/module.prop")
|
||||||
ui_print "- Installing Zygisksu $VERSION"
|
ui_print "- Installing Zygisksu $VERSION"
|
||||||
|
|
||||||
# check KernelSU
|
|
||||||
ui_print "- KernelSU version: $KSU_KERNEL_VER_CODE (kernel) + $KSU_VER_CODE (ksud)"
|
|
||||||
if [ "$KSU_KERNEL_VER_CODE" -lt 10575 ]; then
|
|
||||||
ui_print "*********************************************************"
|
|
||||||
ui_print "! KernelSU version is too old!"
|
|
||||||
ui_print "! Please update KernelSU to latest version"
|
|
||||||
abort "*********************************************************"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# check android
|
# check android
|
||||||
if [ "$API" -lt 29 ]; then
|
if [ "$API" -lt 29 ]; then
|
||||||
ui_print "! Unsupported sdk: $API"
|
ui_print "! Unsupported sdk: $API"
|
||||||
@@ -52,19 +80,25 @@ extract "$ZIPFILE" 'customize.sh' "$TMPDIR/.vunzip"
|
|||||||
extract "$ZIPFILE" 'verify.sh' "$TMPDIR/.vunzip"
|
extract "$ZIPFILE" 'verify.sh' "$TMPDIR/.vunzip"
|
||||||
extract "$ZIPFILE" 'sepolicy.rule' "$TMPDIR"
|
extract "$ZIPFILE" 'sepolicy.rule' "$TMPDIR"
|
||||||
|
|
||||||
ui_print "- Checking SELinux patches"
|
if [ "$KSU" ]; then
|
||||||
if ! check_sepolicy "$TMPDIR/sepolicy.rule"; then
|
ui_print "- Checking SELinux patches"
|
||||||
ui_print "*********************************************************"
|
if [ "$(getprop ro.product.first_api_level)" -lt 31 ]; then
|
||||||
ui_print "! Unable to apply SELinux patches!"
|
echo "allow zygote appdomain_tmpfs file *" >> "$TMPDIR/sepolicy.rule"
|
||||||
ui_print "! Your kernel may not support SELinux patch fully"
|
echo "allow zygote appdomain_tmpfs dir *" >> "$TMPDIR/sepolicy.rule"
|
||||||
abort "*********************************************************"
|
fi
|
||||||
|
if ! check_sepolicy "$TMPDIR/sepolicy.rule"; then
|
||||||
|
ui_print "*********************************************************"
|
||||||
|
ui_print "! Unable to apply SELinux patches!"
|
||||||
|
ui_print "! Your kernel may not support SELinux patch fully"
|
||||||
|
abort "*********************************************************"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_print "- Extracting module files"
|
ui_print "- Extracting module files"
|
||||||
extract "$ZIPFILE" 'daemon.sh' "$MODPATH"
|
|
||||||
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"
|
||||||
|
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
|
||||||
@@ -79,8 +113,8 @@ if [ "$ARCH" = "x86" ] || [ "$ARCH" = "x64" ]; then
|
|||||||
ui_print "- Extracting x86 libraries"
|
ui_print "- Extracting x86 libraries"
|
||||||
extract "$ZIPFILE" 'bin/x86/zygiskd' "$MODPATH/bin" true
|
extract "$ZIPFILE" 'bin/x86/zygiskd' "$MODPATH/bin" true
|
||||||
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd32"
|
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd32"
|
||||||
extract "$ZIPFILE" 'lib/x86/libinjector.so' "$MODPATH/system/lib" true
|
extract "$ZIPFILE" 'lib/x86/libzygisk_injector.so' "$MODPATH/system/lib" true
|
||||||
extract "$ZIPFILE" 'lib/x86/libzygiskloader.so' "$MODPATH/system/lib" true
|
extract "$ZIPFILE" 'lib/x86/libzygisk_loader.so' "$MODPATH/system/lib" true
|
||||||
ln -sf "zygiskd32" "$MODPATH/bin/zygiskwd"
|
ln -sf "zygiskd32" "$MODPATH/bin/zygiskwd"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -88,8 +122,8 @@ if [ "$ARCH" = "x86" ] || [ "$ARCH" = "x64" ]; then
|
|||||||
ui_print "- Extracting x64 libraries"
|
ui_print "- Extracting x64 libraries"
|
||||||
extract "$ZIPFILE" 'bin/x86_64/zygiskd' "$MODPATH/bin" true
|
extract "$ZIPFILE" 'bin/x86_64/zygiskd' "$MODPATH/bin" true
|
||||||
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd64"
|
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd64"
|
||||||
extract "$ZIPFILE" 'lib/x86_64/libinjector.so' "$MODPATH/system/lib64" true
|
extract "$ZIPFILE" 'lib/x86_64/libzygisk_injector.so' "$MODPATH/system/lib64" true
|
||||||
extract "$ZIPFILE" 'lib/x86_64/libzygiskloader.so' "$MODPATH/system/lib64" true
|
extract "$ZIPFILE" 'lib/x86_64/libzygisk_loader.so' "$MODPATH/system/lib64" true
|
||||||
ln -sf "zygiskd64" "$MODPATH/bin/zygiskwd"
|
ln -sf "zygiskd64" "$MODPATH/bin/zygiskwd"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -97,8 +131,8 @@ else
|
|||||||
ui_print "- Extracting arm libraries"
|
ui_print "- Extracting arm libraries"
|
||||||
extract "$ZIPFILE" 'bin/armeabi-v7a/zygiskd' "$MODPATH/bin" true
|
extract "$ZIPFILE" 'bin/armeabi-v7a/zygiskd' "$MODPATH/bin" true
|
||||||
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd32"
|
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd32"
|
||||||
extract "$ZIPFILE" 'lib/armeabi-v7a/libinjector.so' "$MODPATH/system/lib" true
|
extract "$ZIPFILE" 'lib/armeabi-v7a/libzygisk_injector.so' "$MODPATH/system/lib" true
|
||||||
extract "$ZIPFILE" 'lib/armeabi-v7a/libzygiskloader.so' "$MODPATH/system/lib" true
|
extract "$ZIPFILE" 'lib/armeabi-v7a/libzygisk_loader.so' "$MODPATH/system/lib" true
|
||||||
ln -sf "zygiskd32" "$MODPATH/bin/zygiskwd"
|
ln -sf "zygiskd32" "$MODPATH/bin/zygiskwd"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -106,26 +140,15 @@ else
|
|||||||
ui_print "- Extracting arm64 libraries"
|
ui_print "- Extracting arm64 libraries"
|
||||||
extract "$ZIPFILE" 'bin/arm64-v8a/zygiskd' "$MODPATH/bin" true
|
extract "$ZIPFILE" 'bin/arm64-v8a/zygiskd' "$MODPATH/bin" true
|
||||||
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd64"
|
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd64"
|
||||||
extract "$ZIPFILE" 'lib/arm64-v8a/libinjector.so' "$MODPATH/system/lib64" true
|
extract "$ZIPFILE" 'lib/arm64-v8a/libzygisk_injector.so' "$MODPATH/system/lib64" true
|
||||||
extract "$ZIPFILE" 'lib/arm64-v8a/libzygiskloader.so' "$MODPATH/system/lib64" true
|
extract "$ZIPFILE" 'lib/arm64-v8a/libzygisk_loader.so' "$MODPATH/system/lib64" true
|
||||||
ln -sf "zygiskd64" "$MODPATH/bin/zygiskwd"
|
ln -sf "zygiskd64" "$MODPATH/bin/zygiskwd"
|
||||||
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/libinjector.so"
|
|
||||||
sed -i "s/socket_placeholder/$SOCKET_PATCH/g" "$MODPATH/system/lib/libzygiskloader.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/libinjector.so"
|
|
||||||
sed -i "s/socket_placeholder/$SOCKET_PATCH/g" "$MODPATH/system/lib64/libzygiskloader.so"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
ui_print "- Setting permissions"
|
ui_print "- Setting permissions"
|
||||||
chmod 0744 "$MODPATH/daemon.sh"
|
chmod 0744 "$MODPATH/daemon.sh"
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/system/bin/sh
|
|
||||||
|
|
||||||
DEBUG=@DEBUG@
|
|
||||||
|
|
||||||
# shellcheck disable=SC2155
|
|
||||||
export NATIVE_BRIDGE=$(getprop ro.dalvik.vm.native.bridge)
|
|
||||||
[ "$DEBUG" = true ] && export RUST_BACKTRACE=1
|
|
||||||
|
|
||||||
log -p i -t "zygisksu" "Start watchdog"
|
|
||||||
resetprop ro.dalvik.vm.native.bridge libzygiskloader.so
|
|
||||||
exec "bin/zygiskwd" "watchdog" >/dev/null 2>&1
|
|
||||||
@@ -1,8 +1,23 @@
|
|||||||
#!/system/bin/sh
|
#!/system/bin/sh
|
||||||
|
|
||||||
MODDIR=${0%/*}
|
MODDIR=${0%/*}
|
||||||
|
if [ "$ZYGISK_ENABLED" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
cd $MODDIR
|
cd "$MODDIR"
|
||||||
export NATIVE_BRIDGE=$(getprop ro.dalvik.vm.native.bridge)
|
getprop ro.dalvik.vm.native.bridge > /dev/.native_bridge
|
||||||
|
resetprop ro.dalvik.vm.native.bridge libzygisk_loader.so
|
||||||
|
|
||||||
unshare -m sh -c "./daemon.sh $@&"
|
if [ "$(which magisk)" ]; then
|
||||||
|
for file in ../*; do
|
||||||
|
if [ -d "$file" ] && [ -d "$file/zygisk" ] && ! [ -f "$file/disable" ]; then
|
||||||
|
if [ -f "$file/post-fs-data.sh" ]; then
|
||||||
|
cd "$file"
|
||||||
|
log -p i -t "zygisksu" "Manually trigger post-fs-data.sh for $file"
|
||||||
|
sh "$(realpath ./post-fs-data.sh)"
|
||||||
|
cd "$MODDIR"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|||||||
@@ -10,3 +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 system_file dir mounton
|
||||||
|
allow zygote labeledfs filesystem mount
|
||||||
|
allow zygote fs_type filesystem unmount
|
||||||
|
|||||||
29
module/src/service.sh
Normal file
29
module/src/service.sh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/system/bin/sh
|
||||||
|
|
||||||
|
DEBUG=@DEBUG@
|
||||||
|
|
||||||
|
MODDIR=${0%/*}
|
||||||
|
if [ "$ZYGISK_ENABLED" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$MODDIR"
|
||||||
|
export NATIVE_BRIDGE=$(cat /dev/.native_bridge)
|
||||||
|
rm /dev/.native_bridge
|
||||||
|
|
||||||
|
if [ "$(which magisk)" ]; then
|
||||||
|
for file in ../*; do
|
||||||
|
if [ -d "$file" ] && [ -d "$file/zygisk" ] && ! [ -f "$file/disable" ]; then
|
||||||
|
if [ -f "$file/service.sh" ]; then
|
||||||
|
cd "$file"
|
||||||
|
log -p i -t "zygisksu" "Manually trigger service.sh for $file"
|
||||||
|
sh "$(realpath ./service.sh)"
|
||||||
|
cd "$MODDIR"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
log -p i -t "zygisksu" "Start watchdog"
|
||||||
|
[ "$DEBUG" = true ] && export RUST_BACKTRACE=1
|
||||||
|
exec "bin/zygiskwd" "watchdog" >/dev/null 2>&1
|
||||||
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,19 +6,21 @@ edition = "2021"
|
|||||||
rust-version = "1.67"
|
rust-version = "1.67"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
android_logger = "0.12.0"
|
android_logger = "0.13.0"
|
||||||
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
||||||
clap = { version = "4.1.4", features = ["derive"] }
|
clap = { version = "4.1.4", features = ["derive"] }
|
||||||
const_format = "0.2.5"
|
const_format = "0.2.5"
|
||||||
|
konst = "0.3.4"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
memfd = "0.6.2"
|
memfd = "0.6.2"
|
||||||
nix = "0.26.2"
|
nix = "0.26.2"
|
||||||
num_enum = "0.5.9"
|
num_enum = "0.5.9"
|
||||||
|
once_cell = "1.17.1"
|
||||||
passfd = "0.1.5"
|
passfd = "0.1.5"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
|
||||||
binder = { path = "src/external/binder_rs/binder" }
|
binder = { git = "https://github.com/Kernel-SU/binder_rs" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true
|
strip = true
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ plugins {
|
|||||||
|
|
||||||
val verName: String by rootProject.extra
|
val verName: String by rootProject.extra
|
||||||
val verCode: Int 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 {
|
android.buildFeatures {
|
||||||
androidResources = false
|
androidResources = false
|
||||||
@@ -23,5 +26,8 @@ cargo {
|
|||||||
spec.environment("ANDROID_NDK_HOME", android.ndkDirectory.path)
|
spec.environment("ANDROID_NDK_HOME", android.ndkDirectory.path)
|
||||||
spec.environment("VERSION_CODE", verCode)
|
spec.environment("VERSION_CODE", verCode)
|
||||||
spec.environment("VERSION_NAME", verName)
|
spec.environment("VERSION_NAME", verName)
|
||||||
|
spec.environment("MIN_KSU_VERSION", minKsuVersion)
|
||||||
|
spec.environment("MAX_KSU_VERSION", maxKsuVersion)
|
||||||
|
spec.environment("MIN_MAGISK_VERSION", minMagiskVersion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,53 @@
|
|||||||
use const_format::concatcp;
|
use const_format::concatcp;
|
||||||
|
use konst::primitive::parse_i32;
|
||||||
|
use konst::unwrap_ctx;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
|
|
||||||
pub const VERSION_NAME: &str = env!("VERSION_NAME");
|
pub const VERSION_NAME: &str = env!("VERSION_NAME");
|
||||||
pub const VERSION_CODE: &str = env!("VERSION_CODE");
|
pub const VERSION_CODE: &str = env!("VERSION_CODE");
|
||||||
pub const VERSION_FULL: &str = concatcp!(VERSION_NAME, " (", 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)]
|
#[cfg(debug_assertions)]
|
||||||
pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Trace;
|
pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Trace;
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Info;
|
pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Info;
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! lp_select {
|
|
||||||
($lp32:expr, $lp64:expr) => { $lp64 };
|
|
||||||
}
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! lp_select {
|
|
||||||
($lp32:expr, $lp64:expr) => { $lp32 };
|
|
||||||
}
|
|
||||||
|
|
||||||
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_SVC_ZYGOTE: &str = "init.svc.zygote";
|
pub const PROP_CTL_RESTART: &str = "ctl.restart";
|
||||||
pub const ZYGISK_LOADER: &str = "libzygiskloader.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_MODULE_PROP: &str = "module.prop";
|
||||||
pub const PATH_MODULE_DIR: &str = "..";
|
|
||||||
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 STATUS_LOADED: &str = "😋 Zygisksu is loaded";
|
||||||
|
pub const STATUS_CRASHED: &str = "❌ Zygiskd has crashed";
|
||||||
|
pub const STATUS_ROOT_IMPL_NONE: &str = "❌ Unknown root implementation";
|
||||||
|
pub const STATUS_ROOT_IMPL_TOO_OLD: &str = "❌ Root implementation version too old";
|
||||||
|
pub const STATUS_ROOT_IMPL_ABNORMAL: &str = "❌ Abnormal root implementation version";
|
||||||
|
pub const STATUS_ROOT_IMPL_MULTIPLE: &str = "❌ Multiple root implementations installed";
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, TryFromPrimitive)]
|
#[derive(Debug, Eq, PartialEq, TryFromPrimitive)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum DaemonSocketAction {
|
pub enum DaemonSocketAction {
|
||||||
PingHeartbeat,
|
PingHeartbeat,
|
||||||
RequestLogcatFd,
|
RequestLogcatFd,
|
||||||
ReadNativeBridge,
|
ReadNativeBridge,
|
||||||
|
GetProcessFlags,
|
||||||
ReadModules,
|
ReadModules,
|
||||||
RequestCompanionSocket,
|
RequestCompanionSocket,
|
||||||
GetModuleDir,
|
GetModuleDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Zygisk process flags
|
||||||
|
pub const PROCESS_GRANTED_ROOT: u32 = 1 << 0;
|
||||||
|
pub const PROCESS_ON_DENYLIST: u32 = 1 << 1;
|
||||||
|
pub const PROCESS_ROOT_IS_KSU: u32 = 1 << 29;
|
||||||
|
pub const PROCESS_ROOT_IS_MAGISK: u32 = 1 << 30;
|
||||||
|
pub const PROCESS_IS_SYSUI: u32 = 1 << 31;
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ pub unsafe fn dlopen(path: &str, flags: i32) -> Result<*mut c_void> {
|
|||||||
let result = android_dlopen_ext(filename, flags, &info);
|
let result = android_dlopen_ext(filename, flags, &info);
|
||||||
if result.is_null() {
|
if result.is_null() {
|
||||||
let e = std::ffi::CStr::from_ptr(libc::dlerror()).to_string_lossy();
|
let e = std::ffi::CStr::from_ptr(libc::dlerror()).to_string_lossy();
|
||||||
bail!("dlopen failed: {}", e);
|
bail!(e);
|
||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|||||||
1
zygiskd/src/external/binder_rs
vendored
1
zygiskd/src/external/binder_rs
vendored
Submodule zygiskd/src/external/binder_rs deleted from 6d958bb94a
19
zygiskd/src/magic.rs
Normal file
19
zygiskd/src/magic.rs
Normal 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(())
|
||||||
|
}
|
||||||
@@ -3,10 +3,13 @@
|
|||||||
mod companion;
|
mod companion;
|
||||||
mod constants;
|
mod constants;
|
||||||
mod dl;
|
mod dl;
|
||||||
|
mod magic;
|
||||||
|
mod root_impl;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod watchdog;
|
mod watchdog;
|
||||||
mod zygiskd;
|
mod zygiskd;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
use clap::{Subcommand, Parser};
|
use clap::{Subcommand, Parser};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@@ -35,19 +38,24 @@ fn init_android_logger(tag: &str) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start() -> Result<()> {
|
||||||
|
root_impl::setup();
|
||||||
|
magic::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() {
|
fn main() {
|
||||||
let process = std::env::args().next().unwrap();
|
let process = std::env::args().next().unwrap();
|
||||||
let nice_name = process.split('/').last().unwrap();
|
let nice_name = process.split('/').last().unwrap();
|
||||||
init_android_logger(nice_name);
|
init_android_logger(nice_name);
|
||||||
|
|
||||||
let cli = Args::parse();
|
if let Err(e) = start() {
|
||||||
let result = match cli.command {
|
|
||||||
Commands::Watchdog => watchdog::entry(),
|
|
||||||
Commands::Daemon => zygiskd::entry(),
|
|
||||||
Commands::Companion { fd } => companion::entry(fd),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(e) = &result {
|
|
||||||
log::error!("Crashed: {}\n{}", e, e.backtrace());
|
log::error!("Crashed: {}\n{}", e, e.backtrace());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
43
zygiskd/src/root_impl/kernelsu.rs
Normal file
43
zygiskd/src/root_impl/kernelsu.rs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
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: usize = 2;
|
||||||
|
const CMD_GET_ALLOW_LIST: usize = 5;
|
||||||
|
const CMD_GET_DENY_LIST: usize = 6;
|
||||||
|
|
||||||
|
pub enum Version {
|
||||||
|
Supported,
|
||||||
|
TooOld,
|
||||||
|
Abnormal,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_kernel_su() -> Option<Version> {
|
||||||
|
let mut version = 0;
|
||||||
|
unsafe { prctl(KERNEL_SU_OPTION, CMD_GET_VERSION, &mut version as *mut i32) };
|
||||||
|
match version {
|
||||||
|
0 => None,
|
||||||
|
MIN_KSU_VERSION..=MAX_KSU_VERSION => Some(Version::Supported),
|
||||||
|
1..=MIN_KSU_VERSION => Some(Version::TooOld),
|
||||||
|
_ => Some(Version::Abnormal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn uid_on_allowlist(uid: i32) -> bool {
|
||||||
|
let mut size = 1024u32;
|
||||||
|
let mut uids = vec![0; size as usize];
|
||||||
|
unsafe { prctl(KERNEL_SU_OPTION, CMD_GET_ALLOW_LIST, uids.as_mut_ptr(), &mut size as *mut u32) };
|
||||||
|
uids.resize(size as usize, 0);
|
||||||
|
uids.contains(&uid)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn uid_on_denylist(uid: i32) -> bool {
|
||||||
|
let mut size = 1024u32;
|
||||||
|
let mut uids = vec![0; size as usize];
|
||||||
|
unsafe { prctl(KERNEL_SU_OPTION, CMD_GET_DENY_LIST, uids.as_mut_ptr(), &mut size as *mut u32) };
|
||||||
|
uids.resize(size as usize, 0);
|
||||||
|
uids.contains(&uid)
|
||||||
|
}
|
||||||
48
zygiskd/src/root_impl/magisk.rs
Normal file
48
zygiskd/src/root_impl/magisk.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
use std::process::{Command, Stdio};
|
||||||
|
use crate::constants::MIN_MAGISK_VERSION;
|
||||||
|
|
||||||
|
pub enum Version {
|
||||||
|
Supported,
|
||||||
|
TooOld,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_magisk() -> Option<Version> {
|
||||||
|
let version: Option<i32> = Command::new("magisk")
|
||||||
|
.arg("-V")
|
||||||
|
.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.trim().parse().ok());
|
||||||
|
version.map(|version| {
|
||||||
|
if version >= MIN_MAGISK_VERSION {
|
||||||
|
Version::Supported
|
||||||
|
} else {
|
||||||
|
Version::TooOld
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn uid_on_allowlist(uid: i32) -> bool {
|
||||||
|
let output: Option<String> = Command::new("magisk")
|
||||||
|
.arg("--sqlite")
|
||||||
|
.arg("select uid from policies where policy=2")
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.spawn().ok()
|
||||||
|
.and_then(|child| child.wait_with_output().ok())
|
||||||
|
.and_then(|output| String::from_utf8(output.stdout).ok());
|
||||||
|
let lines = match &output {
|
||||||
|
Some(output) => output.lines(),
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
lines.into_iter().any(|line| {
|
||||||
|
line.trim().strip_prefix("uid=").and_then(|uid| uid.parse().ok()) == Some(uid)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn uid_on_denylist(uid: i32) -> bool {
|
||||||
|
// TODO: uid_on_denylist
|
||||||
|
return false;
|
||||||
|
}
|
||||||
61
zygiskd/src/root_impl/mod.rs
Normal file
61
zygiskd/src/root_impl/mod.rs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
mod kernelsu;
|
||||||
|
mod magisk;
|
||||||
|
|
||||||
|
pub enum RootImpl {
|
||||||
|
None,
|
||||||
|
TooOld,
|
||||||
|
Abnormal,
|
||||||
|
Multiple,
|
||||||
|
KernelSU,
|
||||||
|
Magisk,
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: OnceCell bugs on 32 bit
|
||||||
|
static mut ROOT_IMPL: RootImpl = RootImpl::None;
|
||||||
|
|
||||||
|
pub fn setup() {
|
||||||
|
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 {
|
||||||
|
kernelsu::Version::Supported => RootImpl::KernelSU,
|
||||||
|
kernelsu::Version::TooOld => RootImpl::TooOld,
|
||||||
|
kernelsu::Version::Abnormal => RootImpl::Abnormal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(None, Some(magisk_version)) => {
|
||||||
|
match magisk_version {
|
||||||
|
magisk::Version::Supported => RootImpl::Magisk,
|
||||||
|
magisk::Version::TooOld => RootImpl::TooOld,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe { ROOT_IMPL = impl_; }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_impl() -> &'static RootImpl {
|
||||||
|
unsafe { &ROOT_IMPL }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Without #[inline(never)], this function will lag forever
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn uid_on_allowlist(uid: i32) -> bool {
|
||||||
|
match get_impl() {
|
||||||
|
RootImpl::KernelSU => kernelsu::uid_on_allowlist(uid),
|
||||||
|
RootImpl::Magisk => magisk::uid_on_allowlist(uid),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn uid_on_denylist(uid: i32) -> bool {
|
||||||
|
match get_impl() {
|
||||||
|
RootImpl::KernelSU => kernelsu::uid_on_denylist(uid),
|
||||||
|
RootImpl::Magisk => magisk::uid_on_denylist(uid),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,45 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use nix::unistd::gettid;
|
use nix::unistd::gettid;
|
||||||
use std::{fs, io::{Read, Write}, os::unix::net::UnixStream, process::Command};
|
use std::{fs, io::{Read, Write}, os::unix::net::UnixStream, process::Command};
|
||||||
|
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")]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! lp_select {
|
||||||
|
($lp32:expr, $lp64:expr) => { $lp64 };
|
||||||
|
}
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! lp_select {
|
||||||
|
($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)
|
||||||
}
|
}
|
||||||
@@ -26,6 +60,24 @@ pub fn get_native_bridge() -> String {
|
|||||||
std::env::var("NATIVE_BRIDGE").unwrap_or_default()
|
std::env::var("NATIVE_BRIDGE").unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn log_raw(level: i32, tag: &str, message: &str) -> Result<()> {
|
||||||
|
let tag = std::ffi::CString::new(tag)?;
|
||||||
|
let message = std::ffi::CString::new(message)?;
|
||||||
|
unsafe {
|
||||||
|
__android_log_print(level as i32, tag.as_ptr(), message.as_ptr());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_property(name: &str) -> Result<String> {
|
||||||
|
let name = std::ffi::CString::new(name)?;
|
||||||
|
let mut buf = vec![0u8; 92];
|
||||||
|
unsafe {
|
||||||
|
__system_property_get(name.as_ptr(), buf.as_mut_ptr() as *mut c_char);
|
||||||
|
}
|
||||||
|
Ok(String::from_utf8(buf)?)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_property(name: &str, value: &str) -> Result<()> {
|
pub fn set_property(name: &str, value: &str) -> Result<()> {
|
||||||
Command::new("resetprop")
|
Command::new("resetprop")
|
||||||
.arg(name)
|
.arg(name)
|
||||||
@@ -40,6 +92,7 @@ pub trait UnixStreamExt {
|
|||||||
fn read_usize(&mut self) -> Result<usize>;
|
fn read_usize(&mut self) -> Result<usize>;
|
||||||
fn read_string(&mut self) -> Result<String>;
|
fn read_string(&mut self) -> Result<String>;
|
||||||
fn write_u8(&mut self, value: u8) -> Result<()>;
|
fn write_u8(&mut self, value: u8) -> Result<()>;
|
||||||
|
fn write_u32(&mut self, value: u32) -> Result<()>;
|
||||||
fn write_usize(&mut self, value: usize) -> Result<()>;
|
fn write_usize(&mut self, value: usize) -> Result<()>;
|
||||||
fn write_string(&mut self, value: &str) -> Result<()>;
|
fn write_string(&mut self, value: &str) -> Result<()>;
|
||||||
}
|
}
|
||||||
@@ -75,6 +128,11 @@ impl UnixStreamExt for UnixStream {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_u32(&mut self, value: u32) -> Result<()> {
|
||||||
|
self.write_all(&value.to_ne_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn write_usize(&mut self, value: usize) -> Result<()> {
|
fn write_usize(&mut self, value: usize) -> Result<()> {
|
||||||
self.write_all(&value.to_ne_bytes())?;
|
self.write_all(&value.to_ne_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -96,3 +154,8 @@ pub fn abstract_namespace_socket(name: &str) -> Result<UnixListener> {
|
|||||||
let listener = unsafe { UnixListener::from_raw_fd(socket) };
|
let listener = unsafe { UnixListener::from_raw_fd(socket) };
|
||||||
Ok(listener)
|
Ok(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn __android_log_print(prio: i32, tag: *const c_char, fmt: *const c_char, ...) -> i32;
|
||||||
|
fn __system_property_get(name: *const c_char, value: *mut c_char) -> u32;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,21 +1,35 @@
|
|||||||
use crate::{constants, 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};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::{fs, thread};
|
use std::{fs, io, thread};
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::io::{BufRead, Write};
|
||||||
use std::os::unix::net::UnixListener;
|
use std::os::unix::net::UnixListener;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use binder::IBinder;
|
use binder::IBinder;
|
||||||
|
use nix::errno::Errno;
|
||||||
|
use nix::libc;
|
||||||
use nix::sys::signal::{kill, Signal};
|
use nix::sys::signal::{kill, Signal};
|
||||||
|
use crate::utils::LateInit;
|
||||||
|
|
||||||
static mut LOCK: Option<UnixListener> = None;
|
static LOCK: LateInit<UnixListener> = LateInit::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");
|
||||||
check_permission()?;
|
check_permission()?;
|
||||||
ensure_single_instance()?;
|
ensure_single_instance()?;
|
||||||
spawn_daemon()
|
mount_prop()?;
|
||||||
|
if check_and_set_hint()? == false {
|
||||||
|
log::warn!("Requirements not met, exiting");
|
||||||
|
utils::set_property(constants::PROP_NATIVE_BRIDGE, &utils::get_native_bridge())?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let end = spawn_daemon();
|
||||||
|
set_prop_hint(constants::STATUS_CRASHED)?;
|
||||||
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_permission() -> Result<()> {
|
fn check_permission() -> Result<()> {
|
||||||
@@ -41,14 +55,87 @@ 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) => unsafe { LOCK = Some(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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mount_prop() -> Result<()> {
|
||||||
|
let module_prop = if let root_impl::RootImpl::Magisk = root_impl::get_impl() {
|
||||||
|
let magisk_path = Command::new("magisk").arg("--path").output()?;
|
||||||
|
let mut magisk_path = String::from_utf8(magisk_path.stdout)?;
|
||||||
|
magisk_path.pop(); // Removing '\n'
|
||||||
|
let cwd = std::env::current_dir()?;
|
||||||
|
let dir = cwd.file_name().unwrap().to_string_lossy();
|
||||||
|
format!("{magisk_path}/.magisk/modules/{dir}/{}", constants::PATH_MODULE_PROP)
|
||||||
|
} else {
|
||||||
|
constants::PATH_MODULE_PROP.to_string()
|
||||||
|
};
|
||||||
|
log::info!("Mount {module_prop}");
|
||||||
|
let module_prop_file = fs::File::open(&module_prop)?;
|
||||||
|
let mut section = 0;
|
||||||
|
let mut sections: [String; 2] = [String::new(), String::new()];
|
||||||
|
let lines = io::BufReader::new(module_prop_file).lines();
|
||||||
|
for line in lines {
|
||||||
|
let line = line?;
|
||||||
|
if line.starts_with("description=") {
|
||||||
|
sections[0].push_str("description=");
|
||||||
|
sections[1].push_str(line.trim_start_matches("description="));
|
||||||
|
sections[1].push('\n');
|
||||||
|
section = 1;
|
||||||
|
} else {
|
||||||
|
sections[section].push_str(&line);
|
||||||
|
sections[section].push('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PROP_SECTIONS.init(sections);
|
||||||
|
|
||||||
|
fs::create_dir(magic::PATH_TMP_DIR.as_str())?;
|
||||||
|
fs::File::create(magic::PATH_TMP_PROP.as_str())?;
|
||||||
|
|
||||||
|
// FIXME: sys_mount cannot be compiled on 32 bit
|
||||||
|
unsafe {
|
||||||
|
let r = libc::mount(
|
||||||
|
CString::new(magic::PATH_TMP_PROP.as_str())?.as_ptr(),
|
||||||
|
CString::new(module_prop)?.as_ptr(),
|
||||||
|
std::ptr::null(),
|
||||||
|
libc::MS_BIND,
|
||||||
|
std::ptr::null(),
|
||||||
|
);
|
||||||
|
Errno::result(r)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_prop_hint(hint: &str) -> Result<()> {
|
||||||
|
let mut file = fs::File::create(magic::PATH_TMP_PROP.as_str())?;
|
||||||
|
file.write_all(PROP_SECTIONS[0].as_bytes())?;
|
||||||
|
file.write_all(b"[")?;
|
||||||
|
file.write_all(hint.as_bytes())?;
|
||||||
|
file.write_all(b"] ")?;
|
||||||
|
file.write_all(PROP_SECTIONS[1].as_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_and_set_hint() -> Result<bool> {
|
||||||
|
let root_impl = root_impl::get_impl();
|
||||||
|
match root_impl {
|
||||||
|
root_impl::RootImpl::None => set_prop_hint(constants::STATUS_ROOT_IMPL_NONE)?,
|
||||||
|
root_impl::RootImpl::TooOld => set_prop_hint(constants::STATUS_ROOT_IMPL_TOO_OLD)?,
|
||||||
|
root_impl::RootImpl::Abnormal => set_prop_hint(constants::STATUS_ROOT_IMPL_ABNORMAL)?,
|
||||||
|
root_impl::RootImpl::Multiple => set_prop_hint(constants::STATUS_ROOT_IMPL_MULTIPLE)?,
|
||||||
|
_ => {
|
||||||
|
set_prop_hint(constants::STATUS_LOADED)?;
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_daemon() -> Result<()> {
|
fn spawn_daemon() -> Result<()> {
|
||||||
let mut lives = 5;
|
let mut lives = 5;
|
||||||
loop {
|
loop {
|
||||||
@@ -99,7 +186,6 @@ fn spawn_daemon() -> Result<()> {
|
|||||||
|
|
||||||
log::error!("Restarting zygote...");
|
log::error!("Restarting zygote...");
|
||||||
utils::set_property(constants::PROP_NATIVE_BRIDGE, constants::ZYGISK_LOADER)?;
|
utils::set_property(constants::PROP_NATIVE_BRIDGE, constants::ZYGISK_LOADER)?;
|
||||||
utils::set_property(constants::PROP_SVC_ZYGOTE, "restart")?;
|
utils::set_property(constants::PROP_CTL_RESTART, "zygote")?;
|
||||||
thread::sleep(Duration::from_secs(2));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, 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::{
|
||||||
@@ -10,7 +10,6 @@ use nix::{
|
|||||||
use passfd::FdPassingExt;
|
use passfd::FdPassingExt;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::ffi::c_char;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::os::unix::{
|
use std::os::unix::{
|
||||||
net::{UnixListener, UnixStream},
|
net::{UnixListener, UnixStream},
|
||||||
@@ -64,20 +63,19 @@ pub fn entry() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_arch() -> Result<&'static str> {
|
fn get_arch() -> Result<&'static str> {
|
||||||
let output = Command::new("getprop").arg("ro.product.cpu.abi").output()?;
|
let system_arch = utils::get_property("ro.product.cpu.abi")?;
|
||||||
let system_arch = String::from_utf8(output.stdout)?;
|
|
||||||
if system_arch.contains("arm") {
|
if system_arch.contains("arm") {
|
||||||
return Ok(lp_select!("armeabi-v7a", "arm64-v8a"))
|
return Ok(lp_select!("armeabi-v7a", "arm64-v8a"));
|
||||||
}
|
}
|
||||||
if system_arch.contains("x86") {
|
if system_arch.contains("x86") {
|
||||||
return Ok(lp_select!("x86", "x86_64"))
|
return Ok(lp_select!("x86", "x86_64"));
|
||||||
}
|
}
|
||||||
bail!("Unsupported system architecture: {}", system_arch);
|
bail!("Unsupported system architecture: {}", system_arch);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_modules(arch: &str) -> Result<Vec<Module>> {
|
fn load_modules(arch: &str) -> Result<Vec<Module>> {
|
||||||
let mut modules = Vec::new();
|
let mut modules = Vec::new();
|
||||||
let dir = match fs::read_dir(constants::PATH_MODULE_DIR) {
|
let dir = match fs::read_dir(constants::PATH_MODULES_DIR) {
|
||||||
Ok(dir) => dir,
|
Ok(dir) => dir,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("Failed reading modules directory: {}", e);
|
log::warn!("Failed reading modules directory: {}", e);
|
||||||
@@ -93,7 +91,7 @@ fn load_modules(arch: &str) -> Result<Vec<Module>> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log::info!(" Loading module `{name}`...");
|
log::info!(" Loading module `{name}`...");
|
||||||
let memfd = match create_memfd(&name, &so_path) {
|
let memfd = match create_memfd(&so_path) {
|
||||||
Ok(memfd) => memfd,
|
Ok(memfd) => memfd,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!(" Failed to create memfd for `{name}`: {e}");
|
log::warn!(" Failed to create memfd for `{name}`: {e}");
|
||||||
@@ -116,10 +114,9 @@ fn load_modules(arch: &str) -> Result<Vec<Module>> {
|
|||||||
Ok(modules)
|
Ok(modules)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_memfd(name: &str, so_path: &PathBuf) -> Result<Memfd> {
|
fn create_memfd(so_path: &PathBuf) -> Result<Memfd> {
|
||||||
let opts = memfd::MemfdOptions::default().allow_sealing(true);
|
let opts = memfd::MemfdOptions::default().allow_sealing(true);
|
||||||
let memfd = opts.create(name)?;
|
let memfd = opts.create("jit-cache")?;
|
||||||
|
|
||||||
let file = fs::File::open(so_path)?;
|
let file = fs::File::open(so_path)?;
|
||||||
let mut reader = std::io::BufReader::new(file);
|
let mut reader = std::io::BufReader::new(file);
|
||||||
let mut writer = memfd.as_file();
|
let mut writer = memfd.as_file();
|
||||||
@@ -138,7 +135,7 @@ fn create_memfd(name: &str, 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)
|
||||||
@@ -182,17 +179,30 @@ fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()>
|
|||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
};
|
};
|
||||||
let tag = stream.read_string()?;
|
let tag = stream.read_string()?;
|
||||||
let tag = std::ffi::CString::new(tag)?;
|
|
||||||
let message = stream.read_string()?;
|
let message = stream.read_string()?;
|
||||||
let message = std::ffi::CString::new(message)?;
|
utils::log_raw(level as i32, &tag, &message)?;
|
||||||
unsafe {
|
|
||||||
__android_log_print(level as i32, tag.as_ptr(), message.as_ptr());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DaemonSocketAction::ReadNativeBridge => {
|
DaemonSocketAction::ReadNativeBridge => {
|
||||||
stream.write_string(&context.native_bridge)?;
|
stream.write_string(&context.native_bridge)?;
|
||||||
}
|
}
|
||||||
|
DaemonSocketAction::GetProcessFlags => {
|
||||||
|
let uid = stream.read_u32()? as i32;
|
||||||
|
let mut flags = 0u32;
|
||||||
|
if root_impl::uid_on_allowlist(uid) {
|
||||||
|
flags |= constants::PROCESS_GRANTED_ROOT;
|
||||||
|
}
|
||||||
|
if root_impl::uid_on_denylist(uid) {
|
||||||
|
flags |= constants::PROCESS_ON_DENYLIST;
|
||||||
|
}
|
||||||
|
match root_impl::get_impl() {
|
||||||
|
root_impl::RootImpl::KernelSU => flags |= constants::PROCESS_ROOT_IS_KSU,
|
||||||
|
root_impl::RootImpl::Magisk => flags |= constants::PROCESS_ROOT_IS_MAGISK,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
// TODO: PROCESS_IS_SYSUI?
|
||||||
|
stream.write_u32(flags)?;
|
||||||
|
}
|
||||||
DaemonSocketAction::ReadModules => {
|
DaemonSocketAction::ReadModules => {
|
||||||
stream.write_usize(context.modules.len())?;
|
stream.write_usize(context.modules.len())?;
|
||||||
for module in context.modules.iter() {
|
for module in context.modules.iter() {
|
||||||
@@ -221,14 +231,10 @@ fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()>
|
|||||||
DaemonSocketAction::GetModuleDir => {
|
DaemonSocketAction::GetModuleDir => {
|
||||||
let index = stream.read_usize()?;
|
let index = stream.read_usize()?;
|
||||||
let module = &context.modules[index];
|
let module = &context.modules[index];
|
||||||
let dir = format!("{}/{}", constants::PATH_MODULE_DIR, module.name);
|
let dir = format!("{}/{}", constants::PATH_MODULES_DIR, module.name);
|
||||||
let dir = fs::File::open(dir)?;
|
let dir = fs::File::open(dir)?;
|
||||||
stream.send_fd(dir.as_raw_fd())?;
|
stream.send_fd(dir.as_raw_fd())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn __android_log_print(prio: i32, tag: *const c_char, fmt: *const c_char, ...) -> i32;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user