Add zygiskd

This commit is contained in:
Nullptr
2023-01-28 15:54:03 +08:00
parent 3d0efd6fc5
commit cd272c6370
17 changed files with 1358 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.gradle
.idea
.cxx
build
local.properties

50
build.gradle.kts Normal file
View File

@@ -0,0 +1,50 @@
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.gradle.BaseExtension
plugins {
id("com.android.application") apply false
id("com.android.library") apply false
}
val verCode by extra(25207)
val verName by extra("25.2-1")
val androidMinSdkVersion by extra(29)
val androidTargetSdkVersion by extra(33)
val androidCompileSdkVersion by extra(33)
val androidBuildToolsVersion by extra("33.0.1")
val androidCompileNdkVersion by extra("25.1.8937393")
val androidSourceCompatibility by extra(JavaVersion.VERSION_11)
val androidTargetCompatibility by extra(JavaVersion.VERSION_11)
tasks.register("Delete", Delete::class) {
delete(rootProject.buildDir)
}
fun Project.configureBaseExtension() {
extensions.findByType(BaseExtension::class)?.run {
compileSdkVersion(androidCompileSdkVersion)
ndkVersion = androidCompileNdkVersion
buildToolsVersion = androidBuildToolsVersion
defaultConfig {
minSdk = androidMinSdkVersion
targetSdk = androidTargetSdkVersion
versionCode = verCode
versionName = verName
}
}
extensions.findByType(ApplicationExtension::class)?.lint {
abortOnError = true
checkReleaseBuilds = false
}
}
subprojects {
plugins.withId("com.android.application") {
configureBaseExtension()
}
plugins.withId("com.android.library") {
configureBaseExtension()
}
}

23
gradle.properties Normal file
View File

@@ -0,0 +1,23 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# 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,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

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

185
gradlew vendored Executable file
View File

@@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

14
module/build.gradle.kts Normal file
View File

@@ -0,0 +1,14 @@
plugins {
id("com.android.application")
}
val moduleName = "Zygisk On KernelSU"
val moduleBaseId = "zygisksu"
val authors = "Nullptr"
val verCode: Int by rootProject.extra
val verName: String by rootProject.extra
android {
namespace = "icu.nullptr.zygisksu"
}

27
settings.gradle.kts Normal file
View File

@@ -0,0 +1,27 @@
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
plugins {
id("com.android.library") version "7.4.0"
id("com.android.application") version "7.4.0"
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "ZygiskOnKernelSU"
include(
":module",
":zygiskd",
)

494
zygiskd/Cargo.lock generated Normal file
View File

@@ -0,0 +1,494 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
[[package]]
name = "android_log-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e"
[[package]]
name = "android_logger"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "037f3e1da32ddba7770530e69258b742c15ad67bdf90e5f6b35f4b6db9a60eb7"
dependencies = [
"android_log-sys",
"env_logger",
"log",
"once_cell",
]
[[package]]
name = "anyhow"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "const_format"
version = "0.2.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "env_logger"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"humantime",
"is-terminal",
"log",
"regex",
"termcolor",
]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "indexmap"
version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "io-lifetimes"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
dependencies = [
"hermit-abi",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memfd"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b20a59d985586e4a5aef64564ac77299f8586d8be6cf9106a5a40207e8908efb"
dependencies = [
"rustix",
]
[[package]]
name = "memoffset"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
name = "nix"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
dependencies = [
"bitflags",
"cfg-if",
"libc",
"memoffset",
"pin-utils",
"static_assertions",
]
[[package]]
name = "nom8"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"
dependencies = [
"memchr",
]
[[package]]
name = "num_enum"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b"
dependencies = [
"num_enum_derive",
]
[[package]]
name = "num_enum_derive"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "once_cell"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "passfd"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40937dff86b281e4025fe0614c744d961797552ccf8dc681a297e694db283ef3"
dependencies = [
"libc",
]
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro-crate"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34"
dependencies = [
"once_cell",
"toml_edit",
]
[[package]]
name = "proc-macro2"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rustix"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"winapi-util",
]
[[package]]
name = "toml_datetime"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5"
[[package]]
name = "toml_edit"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b"
dependencies = [
"indexmap",
"nom8",
"toml_datetime",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
[[package]]
name = "zygiskd"
version = "1.0.0"
dependencies = [
"android_logger",
"anyhow",
"const_format",
"env_logger",
"log",
"memfd",
"nix",
"num_enum",
"passfd",
]

21
zygiskd/Cargo.toml Normal file
View File

@@ -0,0 +1,21 @@
[package]
name = "zygiskd"
version = "1.0.0"
edition = "2021"
rust-version = "1.65"
[dependencies]
android_logger = "0.12.0"
anyhow = "1.0.68"
const_format = "0.2.5"
env_logger = "0.10.0"
log = "0.4.17"
memfd = "0.6.2"
nix = "0.26.2"
num_enum = "0.5.9"
passfd = "0.1.5"
[profile.release]
strip = true
opt-level = "z"
lto = true

10
zygiskd/build.gradle.kts Normal file
View File

@@ -0,0 +1,10 @@
plugins {
id("com.android.library")
}
val verCode: Int by rootProject.extra
val verName: String by rootProject.extra
android {
namespace = "icu.nullptr.zygisksu"
}

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

@@ -0,0 +1,19 @@
use const_format::concatcp;
use num_enum::TryFromPrimitive;
pub const PROP_NATIVE_BRIDGE: &str = "ro.dalvik.vm.native.bridge";
pub const KSU_MODULE_DIR: &str = "/data/adb/ksu/modules";
pub const ZYGISKSU_DIR: &str = concatcp!(KSU_MODULE_DIR, "/zygisksu");
pub const ZYGISKWD: &str = concatcp!(ZYGISKSU_DIR, "/zygiskwd");
pub const ZYGISKD32: &str = concatcp!(ZYGISKSU_DIR, "/zygiskd32");
pub const ZYGISKD64: &str = concatcp!(ZYGISKSU_DIR, "/zygiskd64");
pub const DAEMON_LOCK: &str = concatcp!(ZYGISKSU_DIR, "/zygiskd.lock");
#[derive(Debug, Eq, PartialEq, TryFromPrimitive)]
#[repr(u8)]
pub enum DaemonSocketAction {
ReadNativeBridge,
ReadModules,
RequestCompanionSocket,
}

48
zygiskd/src/main.rs Normal file
View File

@@ -0,0 +1,48 @@
#![allow(dead_code)]
mod watchdog;
mod constants;
mod zygisk;
mod utils;
use anyhow::{anyhow, Result};
use log::LevelFilter;
use nix::libc;
fn init_android_logger(tag: &str) {
android_logger::init_once(
android_logger::Config::default()
.with_max_level(LevelFilter::Trace)
.with_tag(tag),
);
}
fn main() -> Result<()> {
let process = std::env::args().next().unwrap();
let process = process.split('/').last().unwrap();
env_logger::init();
// init_android_logger(process);
match process {
"zygiskwd" => {
log::info!("Start zygisksu watchdog");
// watchdog::check_permission()?;
watchdog::ensure_single_instance()?;
watchdog::spawn_daemon()?;
}
"zygiskd32" => {
log::info!("Start zygiskd32");
unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL); }
zygisk::start(false)?;
loop {}
}
"zygiskd64" => {
log::info!("Start zygiskd64");
unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL); }
zygisk::start(true)?;
}
_ => return {
Err(anyhow!("Unexpected process name: {process}"))
},
}
Ok(())
}

58
zygiskd/src/utils.rs Normal file
View File

@@ -0,0 +1,58 @@
use crate::constants;
use anyhow::Result;
use nix::unistd::gettid;
use std::{fs, io::{Read, Write}, os::unix::net::UnixStream, process::Command};
pub fn set_socket_create_context(context: &str) -> Result<()> {
let path = "/proc/thread-self/attr/sockcreate";
match fs::write(path, context) {
Ok(_) => Ok(()),
Err(_) => {
let path = format!("/proc/self/task/{}/attr/sockcreate", gettid().as_raw());
fs::write(path, context)?;
Ok(())
}
}
}
pub fn get_native_bridge() -> String {
std::env::var("NATIVE_BRIDGE").unwrap_or("0".to_string())
}
pub fn restore_native_bridge() -> Result<()> {
let exec = format!("resetprop {} {}", constants::PROP_NATIVE_BRIDGE, get_native_bridge());
Command::new(exec).spawn()?.wait()?;
Ok(())
}
pub trait UnixStreamExt {
fn read_u8(&mut self) -> Result<u8>;
fn read_u32(&mut self) -> Result<u32>;
fn read_usize(&mut self) -> Result<usize>;
fn write_usize(&mut self, value: usize) -> Result<()>;
}
impl UnixStreamExt for UnixStream {
fn read_u8(&mut self) -> Result<u8> {
let mut buf = [0u8; 1];
self.read_exact(&mut buf)?;
Ok(buf[0])
}
fn read_u32(&mut self) -> Result<u32> {
let mut buf = [0u8; 4];
self.read_exact(&mut buf)?;
Ok(u32::from_le_bytes(buf))
}
fn read_usize(&mut self) -> Result<usize> {
let mut buf = [0u8; 8];
self.read_exact(&mut buf)?;
Ok(usize::from_le_bytes(buf))
}
fn write_usize(&mut self, value: usize) -> Result<()> {
self.write_all(&value.to_ne_bytes())?;
Ok(())
}
}

70
zygiskd/src/watchdog.rs Normal file
View File

@@ -0,0 +1,70 @@
use crate::constants;
use anyhow::{anyhow, Result};
use nix::fcntl::{flock, FlockArg};
use nix::unistd::{getgid, getuid};
use std::os::unix::prelude::AsRawFd;
use std::process::{Child, Command};
use std::sync::mpsc;
use std::{fs, thread};
static mut LOCK_FILE: Option<fs::File> = None;
pub fn check_permission() -> Result<()> {
log::info!("Check permission");
let uid = getuid();
if uid.as_raw() != 0 {
return Err(anyhow!("UID is not 0"));
}
let gid = getgid();
if gid.as_raw() != 0 {
return Err(anyhow!("GID is not 0"));
}
let context = fs::read_to_string("/proc/self/attr/current")?;
if context != "u:r:su:s0" {
return Err(anyhow!("SELinux context is not u:r:su:s0"));
}
Ok(())
}
pub fn ensure_single_instance() -> Result<()> {
log::info!("Ensure single instance");
let metadata = fs::metadata(constants::ZYGISKSU_DIR);
if metadata.is_err() || !metadata.unwrap().is_dir() {
return Err(anyhow!("Zygisksu is not installed"));
}
unsafe {
match fs::File::create(constants::DAEMON_LOCK) {
Ok(file) => LOCK_FILE = Some(file),
Err(e) => return Err(anyhow!("Failed to open lock file: {e}")),
};
let fd = LOCK_FILE.as_ref().unwrap().as_raw_fd();
if let Err(e) = flock(fd, FlockArg::LockExclusiveNonblock) {
return Err(anyhow!(
"Failed to acquire lock: {e}. Maybe another instance is running?"
));
}
}
Ok(())
}
pub fn spawn_daemon() -> Result<()> {
let daemon32 = Command::new(constants::ZYGISKD32).spawn()?;
let daemon64 = Command::new(constants::ZYGISKD64).spawn()?;
let (sender, receiver) = mpsc::channel();
let spawn = |mut daemon: Child| {
let sender = sender.clone();
thread::spawn(move || {
let result = daemon.wait().unwrap();
log::error!("Daemon process {} died: {}", daemon.id(), result);
drop(daemon);
sender.send(()).unwrap();
});
};
spawn(daemon32);
spawn(daemon64);
let _ = receiver.recv();
Err(anyhow!("Daemon process died"))
}

240
zygiskd/src/zygisk.rs Normal file
View File

@@ -0,0 +1,240 @@
use crate::constants::DaemonSocketAction;
use crate::utils::{restore_native_bridge, UnixStreamExt};
use crate::{constants, utils};
use anyhow::{anyhow, Result};
use memfd::Memfd;
use nix::{
libc::{self, dlsym},
unistd::getppid,
};
use passfd::FdPassingExt;
use std::cell::Cell;
use std::io::Write;
use std::sync::Arc;
use std::thread;
use std::{
ffi::c_void,
fs,
os::unix::{
net::{UnixListener, UnixStream},
prelude::AsRawFd,
},
path::PathBuf,
};
type ZygiskCompanionEntryFn = unsafe extern "C" fn(i32);
struct Module {
name: String,
memfd: Memfd,
companion_entry: Option<ZygiskCompanionEntryFn>,
}
struct Context {
native_bridge: String,
modules: Arc<Vec<Module>>,
stream: Cell<UnixStream>,
}
pub fn start(is64: bool) -> Result<()> {
// check_parent()?;
let arch = get_arch(is64)?;
log::debug!("Daemon architecture: {arch}");
log::info!("Load modules");
let modules = load_modules(arch)?;
log::info!("Create socket");
let listener = create_daemon_socket(is64)?;
log::info!("Waiting for connection");
let (stream, _) = listener.accept()?;
drop(listener);
let context = Context {
native_bridge: utils::get_native_bridge(),
modules: Arc::new(modules),
stream: Cell::new(stream),
};
log::info!("Connection established");
restore_native_bridge()?;
handle_daemon_actions(context)?;
Ok(())
}
fn check_parent() -> Result<()> {
let parent = fs::read_link(format!("/proc/{}/exe", getppid().as_raw()))?;
let parent = parent.file_name().unwrap().to_str().unwrap();
if parent != constants::ZYGISKWD {
return Err(anyhow!("zygiskd is not started by watchdog"));
}
Ok(())
}
fn get_arch(is64: bool) -> Result<&'static str> {
// let output = Command::new("getprop ro.product.cpu.abi").output()?;
// let system_arch = String::from_utf8(output.stdout)?;
let system_arch = "x86_64"; // DEBUGGING
let is_arm = system_arch.contains("arm");
let is_x86 = system_arch.contains("x86");
if is64 {
match (is_arm, is_x86) {
(true, _) => Ok("arm64-v8a"),
(_, true) => Ok("x86_64"),
_ => Err(anyhow!("Unsupported system architecture: {}", system_arch)),
}
} else {
match (is_arm, is_x86) {
(true, _) => Ok("armeabi-v7a"),
(_, true) => Ok("x86"),
_ => Err(anyhow!("Unsupported system architecture: {}", system_arch)),
}
}
}
fn load_modules(arch: &str) -> Result<Vec<Module>> {
let mut modules = Vec::new();
let dir = match fs::read_dir(constants::KSU_MODULE_DIR) {
Ok(dir) => dir,
Err(e) => {
log::warn!("Failed reading modules directory: {}", e);
return Ok(modules);
}
};
for entry_result in dir.into_iter() {
let entry = entry_result?;
let name = entry.file_name().into_string().unwrap();
let so_path = entry.path().join(format!("zygisk/{arch}.so"));
if !so_path.exists() {
continue;
}
log::info!(" Loading module `{name}`...");
let memfd = match create_memfd(&name, &so_path) {
Ok(memfd) => memfd,
Err(e) => {
log::warn!(" Failed to create memfd for `{name}`: {e}");
continue;
}
};
let companion_entry = match preload_module(&memfd) {
Ok(companion_entry) => companion_entry,
Err(e) => {
log::warn!(" Failed to preload `{name}`: {e}");
continue;
}
};
let module = Module {
name,
memfd,
companion_entry,
};
modules.push(module);
}
Ok(modules)
}
fn create_memfd(name: &str, so_path: &PathBuf) -> Result<memfd::Memfd> {
let opts = memfd::MemfdOptions::default().allow_sealing(true);
let memfd = opts.create(name)?;
let file = fs::File::open(so_path)?;
let mut reader = std::io::BufReader::new(file);
let mut writer = memfd.as_file();
std::io::copy(&mut reader, &mut writer)?;
let mut seals = memfd::SealsHashSet::new();
seals.insert(memfd::FileSeal::SealShrink);
seals.insert(memfd::FileSeal::SealGrow);
seals.insert(memfd::FileSeal::SealWrite);
seals.insert(memfd::FileSeal::SealSeal);
memfd.add_seals(&seals)?;
Ok(memfd)
}
fn preload_module(memfd: &Memfd) -> Result<Option<ZygiskCompanionEntryFn>> {
unsafe {
let path = format!("/proc/self/fd/{}", memfd.as_raw_fd());
let filename = std::ffi::CString::new(path)?;
let handle = libc::dlopen(filename.as_ptr(), libc::RTLD_LAZY);
if handle.is_null() {
let e = std::ffi::CStr::from_ptr(libc::dlerror())
.to_string_lossy()
.into_owned();
return Err(anyhow!("dlopen failed: {}", e));
}
let symbol = std::ffi::CString::new("zygisk_companion_entry")?;
let entry = dlsym(handle, symbol.as_ptr());
if entry.is_null() {
return Ok(None);
}
let fnptr = std::mem::transmute::<*mut c_void, ZygiskCompanionEntryFn>(entry);
Ok(Some(fnptr))
}
}
fn create_daemon_socket(is64: bool) -> Result<UnixListener> {
utils::set_socket_create_context("u:r:zygote:s0")?;
let socket_name = if is64 { "zygiskd64" } else { "zygiskd32" };
let listener = UnixListener::bind(socket_name)?;
Ok(listener)
}
fn handle_daemon_actions(mut context: Context) -> Result<()> {
let stream = context.stream.get_mut();
loop {
let action = stream.read_u8()?;
match DaemonSocketAction::try_from(action) {
Ok(DaemonSocketAction::ReadNativeBridge) => {
stream.write_usize(context.native_bridge.len())?;
stream.write_all(context.native_bridge.as_bytes())?;
}
Ok(DaemonSocketAction::ReadModules) => {
stream.write_usize(context.modules.len())?;
for module in context.modules.iter() {
stream.write_usize(module.name.len())?;
stream.write_all(module.name.as_bytes())?;
stream.send_fd(module.memfd.as_raw_fd())?;
}
}
Ok(DaemonSocketAction::RequestCompanionSocket) => {
let (server, client) = UnixStream::pair()?;
stream.send_fd(client.as_raw_fd())?;
let modules_ref = Arc::clone(&context.modules);
thread::spawn(move || {
if let Err(e) = create_companion(server, modules_ref.as_ref()) {
log::warn!("Companion thread exited: {e}");
}
});
}
Err(_) => {
return Err(anyhow!("Invalid action code: {action}"));
}
}
}
}
fn create_companion(mut server: UnixStream, modules: &Vec<Module>) -> Result<()> {
loop {
let index = match server.read_usize() {
Ok(index) => index,
Err(_) => return Ok(()), // EOF
};
let module = &modules[index];
log::debug!("New companion request from module {}", module.name);
unsafe {
match module.companion_entry {
Some(entry) => {
let (sock_app, sock_companion) = UnixStream::pair()?;
server.send_fd(sock_app.as_raw_fd())?;
entry(sock_companion.as_raw_fd());
}
None => (),
}
}
}
}