mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 23:17:33 +00:00
Compare commits
17 Commits
canary-280
...
canary-281
Author | SHA1 | Date | |
---|---|---|---|
![]() |
47cc532d96 | ||
![]() |
218327f92b | ||
![]() |
4eae66a1a7 | ||
![]() |
b09ceeb43c | ||
![]() |
4fb539c110 | ||
![]() |
849b284da5 | ||
![]() |
895b5f6cbf | ||
![]() |
cb3d4ea514 | ||
![]() |
0d89a2a97d | ||
![]() |
3ca5913055 | ||
![]() |
df6b808f49 | ||
![]() |
09c7ac754b | ||
![]() |
805da67c23 | ||
![]() |
3c6889505b | ||
![]() |
c8e9ce7627 | ||
![]() |
837c679a31 | ||
![]() |
06616659b8 |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -83,10 +83,10 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]
|
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
|
||||||
type: [""]
|
type: [""]
|
||||||
include:
|
include:
|
||||||
- version: 35
|
- version: "Baklava"
|
||||||
type: "google_apis"
|
type: "google_apis"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,6 +14,7 @@ native/out
|
|||||||
*.iml
|
*.iml
|
||||||
.gradle
|
.gradle
|
||||||
.idea
|
.idea
|
||||||
|
.kotlin
|
||||||
/local.properties
|
/local.properties
|
||||||
/build
|
/build
|
||||||
/captures
|
/captures
|
||||||
|
@@ -20,9 +20,9 @@ Some highlight features:
|
|||||||
|
|
||||||
Click the icon below to download Magisk apk.
|
Click the icon below to download Magisk apk.
|
||||||
|
|
||||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/v28.1)
|
||||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v28.0)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/v28.1)
|
||||||
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-28002)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-28101)
|
||||||
|
|
||||||
## Useful Links
|
## Useful Links
|
||||||
|
|
||||||
|
@@ -87,6 +87,9 @@
|
|||||||
<string name="logs_cleared">Логи успешно очищены</string>
|
<string name="logs_cleared">Логи успешно очищены</string>
|
||||||
<string name="pid">PID: %1$d</string>
|
<string name="pid">PID: %1$d</string>
|
||||||
<string name="target_uid">Целевой UID: %1$d</string>
|
<string name="target_uid">Целевой UID: %1$d</string>
|
||||||
|
<string name="target_pid">Целевой PID пространства имён: %s</string>
|
||||||
|
<string name="selinux_context">Контекст SELinux: %s</string>
|
||||||
|
<string name="supp_group">Дополнительная группа: %s</string>
|
||||||
|
|
||||||
<!--SafetyNet-->
|
<!--SafetyNet-->
|
||||||
|
|
||||||
@@ -164,11 +167,16 @@
|
|||||||
<string name="settings_su_reauth_title">Повторная аутентификация</string>
|
<string name="settings_su_reauth_title">Повторная аутентификация</string>
|
||||||
<string name="settings_su_reauth_summary">Повторный запрос прав суперпользователя после обновления приложений</string>
|
<string name="settings_su_reauth_summary">Повторный запрос прав суперпользователя после обновления приложений</string>
|
||||||
<string name="settings_su_tapjack_title">Защита от перехвата нажатий</string>
|
<string name="settings_su_tapjack_title">Защита от перехвата нажатий</string>
|
||||||
|
<string name="settings_su_auth_title">Аутентификация пользователя</string>
|
||||||
|
<string name="settings_su_auth_summary">Требовать аутентификацию пользователя при запросах Superuser</string>
|
||||||
|
<string name="settings_su_auth_insecure">На устройстве не настроен метод аутентификации</string>
|
||||||
<string name="settings_su_tapjack_summary">Окно запроса прав суперпользователя будет неактивно пока активированы наложения экрана</string>
|
<string name="settings_su_tapjack_summary">Окно запроса прав суперпользователя будет неактивно пока активированы наложения экрана</string>
|
||||||
<string name="settings_customization">Персонализация</string>
|
<string name="settings_customization">Персонализация</string>
|
||||||
<string name="setting_add_shortcut_summary">Добавить ярлык на рабочий стол для удобного восприятия приложения после его скрытия</string>
|
<string name="setting_add_shortcut_summary">Добавить ярлык на рабочий стол для удобного восприятия приложения после его скрытия</string>
|
||||||
<string name="settings_doh_title">DNS поверх HTTPS</string>
|
<string name="settings_doh_title">DNS поверх HTTPS</string>
|
||||||
<string name="settings_doh_description">Активировать DoH (используйте при проблемах с подключением к сети)</string>
|
<string name="settings_doh_description">Активировать DoH (используйте при проблемах с подключением к сети)</string>
|
||||||
|
<string name="settings_random_name_title">Случайное имя образа</string>
|
||||||
|
<string name="settings_random_name_description">Генерировать случайные имена для патченных образов и tar-файлов для предотвращения обнаружения</string>
|
||||||
|
|
||||||
<string name="multiuser_mode">Многопользовательский режим</string>
|
<string name="multiuser_mode">Многопользовательский режим</string>
|
||||||
<string name="settings_owner_only">Только администратор</string>
|
<string name="settings_owner_only">Только администратор</string>
|
||||||
|
@@ -130,8 +130,8 @@
|
|||||||
<string name="settings_update_custom">Власний</string>
|
<string name="settings_update_custom">Власний</string>
|
||||||
<string name="settings_update_custom_msg">Вставте власний URL</string>
|
<string name="settings_update_custom_msg">Вставте власний URL</string>
|
||||||
<string name="settings_zygisk_summary">Запускати частини Magisk в сервісі zygote</string>
|
<string name="settings_zygisk_summary">Запускати частини Magisk в сервісі zygote</string>
|
||||||
<string name="settings_denylist_title">Enforce DenyList</string>
|
<string name="settings_denylist_title">Увімкнути DenyList</string>
|
||||||
<string name="settings_denylist_summary">Processes on the denylist will have all Magisk modifications reverted</string>
|
<string name="settings_denylist_summary">Всі зміни, внесені Magisk, будуть приховані від процесів, позначених у DenyList</string>
|
||||||
<string name="settings_denylist_config_title">Налаштувати DenyList</string>
|
<string name="settings_denylist_config_title">Налаштувати DenyList</string>
|
||||||
<string name="settings_denylist_config_summary">Вибрати процеси, які будуть додані до denylist</string>
|
<string name="settings_denylist_config_summary">Вибрати процеси, які будуть додані до denylist</string>
|
||||||
<string name="settings_hosts_title">Позасистемні хости</string>
|
<string name="settings_hosts_title">Позасистемні хости</string>
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
<string name="superuser_notification">Сповіщення суперкористувача</string>
|
<string name="superuser_notification">Сповіщення суперкористувача</string>
|
||||||
<string name="settings_su_reauth_title">Повторна автентифікація</string>
|
<string name="settings_su_reauth_title">Повторна автентифікація</string>
|
||||||
<string name="settings_su_reauth_summary">Перевидача прав суперкористувача після оновлення застосунку</string>
|
<string name="settings_su_reauth_summary">Перевидача прав суперкористувача після оновлення застосунку</string>
|
||||||
<string name="settings_su_tapjack_title">Увімкнути захист від Tapjack</string>
|
<string name="settings_su_tapjack_title">Увімкнути захист від підміни натискань</string>
|
||||||
<string name="settings_su_tapjack_summary">Діалогове вікно суперкористувача не буде отримувати ввід від користувача, коли вікно перекрито іншим застосунком чи вікном</string>
|
<string name="settings_su_tapjack_summary">Діалогове вікно суперкористувача не буде отримувати ввід від користувача, коли вікно перекрито іншим застосунком чи вікном</string>
|
||||||
<string name="settings_customization">Оформлення</string>
|
<string name="settings_customization">Оформлення</string>
|
||||||
<string name="setting_add_shortcut_summary">Додати ярлик на домашній екран для зручного сприйняття застосунку після його приховування</string>
|
<string name="setting_add_shortcut_summary">Додати ярлик на домашній екран для зручного сприйняття застосунку після його приховування</string>
|
||||||
|
@@ -7,21 +7,26 @@ import org.objectweb.asm.MethodVisitor
|
|||||||
import org.objectweb.asm.Opcodes
|
import org.objectweb.asm.Opcodes
|
||||||
import org.objectweb.asm.Opcodes.ASM9
|
import org.objectweb.asm.Opcodes.ASM9
|
||||||
|
|
||||||
|
private const val ZIP_ENTRY_CLASS_NAME = "java.util.zip.ZipEntry"
|
||||||
private const val DESUGAR_CLASS_NAME = "com.topjohnwu.magisk.core.utils.Desugar"
|
private const val DESUGAR_CLASS_NAME = "com.topjohnwu.magisk.core.utils.Desugar"
|
||||||
private const val ZIP_ENTRY_GET_TIME_DESC = "()Ljava/nio/file/attribute/FileTime;"
|
private const val ZIP_ENTRY_GET_TIME_DESC = "()Ljava/nio/file/attribute/FileTime;"
|
||||||
private const val DESUGAR_GET_TIME_DESC = "(Ljava/util/zip/ZipEntry;)Ljava/nio/file/attribute/FileTime;"
|
private const val DESUGAR_GET_TIME_DESC =
|
||||||
|
"(Ljava/util/zip/ZipEntry;)Ljava/nio/file/attribute/FileTime;"
|
||||||
|
|
||||||
|
private fun ClassData.isTypeOf(name: String) = className == name || superClasses.contains(name)
|
||||||
|
|
||||||
abstract class DesugarClassVisitorFactory : AsmClassVisitorFactory<InstrumentationParameters.None> {
|
abstract class DesugarClassVisitorFactory : AsmClassVisitorFactory<InstrumentationParameters.None> {
|
||||||
override fun createClassVisitor(
|
override fun createClassVisitor(
|
||||||
classContext: ClassContext,
|
classContext: ClassContext,
|
||||||
nextClassVisitor: ClassVisitor
|
nextClassVisitor: ClassVisitor
|
||||||
): ClassVisitor {
|
): ClassVisitor {
|
||||||
return DesugarClassVisitor(nextClassVisitor)
|
return DesugarClassVisitor(classContext, nextClassVisitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isInstrumentable(classData: ClassData) = classData.className != DESUGAR_CLASS_NAME
|
override fun isInstrumentable(classData: ClassData) = classData.className != DESUGAR_CLASS_NAME
|
||||||
|
|
||||||
class DesugarClassVisitor(cv: ClassVisitor) : ClassVisitor(ASM9, cv) {
|
class DesugarClassVisitor(private val classContext: ClassContext, cv: ClassVisitor) :
|
||||||
|
ClassVisitor(ASM9, cv) {
|
||||||
override fun visitMethod(
|
override fun visitMethod(
|
||||||
access: Int,
|
access: Int,
|
||||||
name: String?,
|
name: String?,
|
||||||
@@ -29,39 +34,45 @@ abstract class DesugarClassVisitorFactory : AsmClassVisitorFactory<Instrumentati
|
|||||||
signature: String?,
|
signature: String?,
|
||||||
exceptions: Array<out String>?
|
exceptions: Array<out String>?
|
||||||
): MethodVisitor {
|
): MethodVisitor {
|
||||||
return DesugarMethodVisitor(super.visitMethod(access, name, descriptor, signature, exceptions))
|
return DesugarMethodVisitor(
|
||||||
}
|
super.visitMethod(access, name, descriptor, signature, exceptions)
|
||||||
}
|
)
|
||||||
|
|
||||||
class DesugarMethodVisitor(mv: MethodVisitor?) : MethodVisitor(ASM9, mv) {
|
|
||||||
override fun visitMethodInsn(
|
|
||||||
opcode: Int,
|
|
||||||
owner: String,
|
|
||||||
name: String,
|
|
||||||
descriptor: String,
|
|
||||||
isInterface: Boolean
|
|
||||||
) {
|
|
||||||
if (!process(name, descriptor)) {
|
|
||||||
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun process(name: String, descriptor: String): Boolean {
|
inner class DesugarMethodVisitor(mv: MethodVisitor?) :
|
||||||
if (descriptor != ZIP_ENTRY_GET_TIME_DESC)
|
MethodVisitor(ASM9, mv) {
|
||||||
return false
|
override fun visitMethodInsn(
|
||||||
when (name) {
|
opcode: Int,
|
||||||
"getLastModifiedTime", "getLastAccessTime", "getCreationTime" -> {
|
owner: String,
|
||||||
mv.visitMethodInsn(
|
name: String,
|
||||||
Opcodes.INVOKESTATIC,
|
descriptor: String,
|
||||||
DESUGAR_CLASS_NAME.replace('.', '/'),
|
isInterface: Boolean
|
||||||
name,
|
) {
|
||||||
DESUGAR_GET_TIME_DESC,
|
if (!process(owner, name, descriptor)) {
|
||||||
false
|
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
|
||||||
)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun process(owner: String, name: String, descriptor: String): Boolean {
|
||||||
|
val classData = classContext.loadClassData(owner.replace("/", ".")) ?: return false
|
||||||
|
if (!classData.isTypeOf(ZIP_ENTRY_CLASS_NAME))
|
||||||
|
return false
|
||||||
|
if (descriptor != ZIP_ENTRY_GET_TIME_DESC)
|
||||||
|
return false
|
||||||
|
return when (name) {
|
||||||
|
"getLastModifiedTime", "getLastAccessTime", "getCreationTime" -> {
|
||||||
|
mv.visitMethodInsn(
|
||||||
|
Opcodes.INVOKESTATIC,
|
||||||
|
DESUGAR_CLASS_NAME.replace('.', '/'),
|
||||||
|
name,
|
||||||
|
DESUGAR_GET_TIME_DESC,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
}
|
}
|
||||||
else -> return false
|
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,13 @@
|
|||||||
# Magisk Changelog
|
# Magisk Changelog
|
||||||
|
|
||||||
|
### v28.1
|
||||||
|
|
||||||
|
- [App] Fix stub APK download link
|
||||||
|
- [App] Fix support for Android lower than 8.0
|
||||||
|
- [General] Fix support for MTK Samsung devices
|
||||||
|
- [MagiskInit] Fix a regression for 2SI devices
|
||||||
|
- [MagiskPolicy] Fix a regression causing `overlay.d` replaced files to be not accessible
|
||||||
|
|
||||||
### v28.0
|
### v28.0
|
||||||
|
|
||||||
- [General] Support 16k page size
|
- [General] Support 16k page size
|
||||||
|
33
docs/releases/28100.md
Normal file
33
docs/releases/28100.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
## 2024.12.6 Magisk v28.1
|
||||||
|
|
||||||
|
- [App] Fix stub APK download link
|
||||||
|
- [App] Fix support for Android lower than 8.0
|
||||||
|
- [General] Fix support for MTK Samsung devices
|
||||||
|
- [MagiskInit] Fix a regression for 2SI devices
|
||||||
|
- [MagiskPolicy] Fix a regression causing `overlay.d` replaced files to be not accessible
|
||||||
|
|
||||||
|
## Magisk v28.0 Changes
|
||||||
|
|
||||||
|
- [General] Support 16k page size
|
||||||
|
- [General] Add basic support for RISC-V (not built in releases)
|
||||||
|
- [General] Use a minimal libc to build static executables (`magiskinit` and `magiskboot`) for smaller sizes
|
||||||
|
- [Core] Remove unnecessary mirror for magic mount
|
||||||
|
- [Core] Update boot image detection logic to support more devices
|
||||||
|
- [MagiskInit] Rewrite 2SI logic for injecting `magiskinit` as `init`
|
||||||
|
- [MagiskInit] Update preinit partition detection
|
||||||
|
- [Zygisk] Update internal JNI hooking implementation
|
||||||
|
- [MagiskPolicy] Preserve sepolicy config flag after patching
|
||||||
|
- [MagiskPolicy] Optimize patching rules to reduce the amount of new rules being injected
|
||||||
|
- [DenyList] Support enforcing denylist when Zygisk is disabled
|
||||||
|
- [Resetprop] Improve implementation to workaround several property modification detections
|
||||||
|
- [Resetprop] Update to properly work with property overlays
|
||||||
|
- [App] Major internal code refactoring
|
||||||
|
- [App] Support patching Samsung firmware with images larger than 8GiB
|
||||||
|
- [App] Use user-initiated job instead of foreground services on Android 14
|
||||||
|
- [App] Support Android 13+ built-in per-app language preferences
|
||||||
|
- [App] Add `action.sh` support to allow modules to define an action triggered from UI
|
||||||
|
- [MagiskBoot] Support spliting kernel images without decompression
|
||||||
|
- [MagiskBoot] Properly support vendor boot images
|
||||||
|
- [MagiskBoot] Disable Samsung PROCA from kernel image
|
||||||
|
|
||||||
|
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
@@ -1,5 +1,6 @@
|
|||||||
# Release Notes
|
# Release Notes
|
||||||
|
|
||||||
|
- [v28.1](28100.md)
|
||||||
- [v28.0](28000.md)
|
- [v28.0](28000.md)
|
||||||
- [v27.0](27000.md)
|
- [v27.0](27000.md)
|
||||||
- [v26.4](26400.md)
|
- [v26.4](26400.md)
|
||||||
|
@@ -30,5 +30,5 @@ android.nonFinalResIds=false
|
|||||||
|
|
||||||
# Magisk
|
# Magisk
|
||||||
magisk.stubVersion=40
|
magisk.stubVersion=40
|
||||||
magisk.versionCode=28002
|
magisk.versionCode=28101
|
||||||
magisk.ondkVersion=r27.4
|
magisk.ondkVersion=r27.4
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[versions]
|
[versions]
|
||||||
kotlin = "2.0.21"
|
kotlin = "2.0.21"
|
||||||
android = "8.7.2"
|
android = "8.7.3"
|
||||||
ksp = "2.0.21-1.0.28"
|
ksp = "2.0.21-1.0.28"
|
||||||
rikka = "1.3.0"
|
rikka = "1.3.0"
|
||||||
navigation = "2.8.4"
|
navigation = "2.8.4"
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
72
native/src/Cargo.lock
generated
72
native/src/Cargo.lock
generated
@@ -2,6 +2,12 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "argh"
|
name = "argh"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
@@ -111,6 +117,32 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codespan-reporting"
|
name = "codespan-reporting"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@@ -182,16 +214,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxx"
|
name = "cxx"
|
||||||
version = "1.0.124"
|
version = "1.0.133"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
|
"cxxbridge-cmd",
|
||||||
"cxxbridge-flags",
|
"cxxbridge-flags",
|
||||||
"cxxbridge-macro",
|
"cxxbridge-macro",
|
||||||
|
"foldhash",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxx-gen"
|
name = "cxx-gen"
|
||||||
version = "0.7.124"
|
version = "0.7.133"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -199,16 +233,28 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cxxbridge-cmd"
|
||||||
|
version = "1.0.133"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"codespan-reporting",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxxbridge-flags"
|
name = "cxxbridge-flags"
|
||||||
version = "1.0.124"
|
version = "1.0.133"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxxbridge-macro"
|
name = "cxxbridge-macro"
|
||||||
version = "1.0.124"
|
version = "1.0.133"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
"rustversion",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -305,6 +351,12 @@ version = "0.4.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec"
|
checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foldhash"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
@@ -709,6 +761,12 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sec1"
|
name = "sec1"
|
||||||
version = "0.8.0-rc.0"
|
version = "0.8.0-rc.0"
|
||||||
@@ -803,6 +861,12 @@ dependencies = [
|
|||||||
"der",
|
"der",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
|
@@ -49,6 +49,7 @@ pub mod ffi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[namespace = "rust"]
|
#[namespace = "rust"]
|
||||||
|
#[allow(unused_unsafe)]
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
unsafe fn extract_boot_from_payload(
|
unsafe fn extract_boot_from_payload(
|
||||||
partition: *const c_char,
|
partition: *const c_char,
|
||||||
|
@@ -148,8 +148,8 @@ static bool check_safe_mode() {
|
|||||||
* Boot Stage Handlers *
|
* Boot Stage Handlers *
|
||||||
***********************/
|
***********************/
|
||||||
|
|
||||||
bool MagiskD::post_fs_data() const {
|
bool MagiskD::post_fs_data() const noexcept {
|
||||||
as_rust().setup_logfile();
|
setup_logfile();
|
||||||
|
|
||||||
LOGI("** post-fs-data mode running\n");
|
LOGI("** post-fs-data mode running\n");
|
||||||
|
|
||||||
@@ -194,8 +194,8 @@ bool MagiskD::post_fs_data() const {
|
|||||||
return safe_mode;
|
return safe_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskD::late_start() const {
|
void MagiskD::late_start() const noexcept {
|
||||||
as_rust().setup_logfile();
|
setup_logfile();
|
||||||
|
|
||||||
LOGI("** late_start service mode running\n");
|
LOGI("** late_start service mode running\n");
|
||||||
|
|
||||||
@@ -203,8 +203,8 @@ void MagiskD::late_start() const {
|
|||||||
exec_module_scripts("service");
|
exec_module_scripts("service");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskD::boot_complete() const {
|
void MagiskD::boot_complete() const noexcept {
|
||||||
as_rust().setup_logfile();
|
setup_logfile();
|
||||||
|
|
||||||
LOGI("** boot-complete triggered\n");
|
LOGI("** boot-complete triggered\n");
|
||||||
|
|
||||||
|
@@ -128,20 +128,8 @@ static void poll_ctrl_handler(pollfd *pfd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MagiskD &MagiskD::get() {
|
void MagiskD::reboot() const noexcept {
|
||||||
return *reinterpret_cast<const MagiskD*>(&rust::get_magiskd());
|
if (is_recovery())
|
||||||
}
|
|
||||||
|
|
||||||
const rust::MagiskD *MagiskD::operator->() const {
|
|
||||||
return reinterpret_cast<const rust::MagiskD*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const rust::MagiskD &MagiskD::as_rust() const {
|
|
||||||
return *operator->();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MagiskD::reboot() const {
|
|
||||||
if (as_rust().is_recovery())
|
|
||||||
exec_command_sync("/system/bin/reboot", "recovery");
|
exec_command_sync("/system/bin/reboot", "recovery");
|
||||||
else
|
else
|
||||||
exec_command_sync("/system/bin/reboot");
|
exec_command_sync("/system/bin/reboot");
|
||||||
@@ -171,7 +159,7 @@ static void handle_request_async(int client, int code, const sock_cred &cred) {
|
|||||||
write_int(client, 0);
|
write_int(client, 0);
|
||||||
close(client);
|
close(client);
|
||||||
if (do_reboot) {
|
if (do_reboot) {
|
||||||
MagiskD::get().reboot();
|
MagiskD().reboot();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -196,7 +184,7 @@ static void handle_request_sync(int client, int code) {
|
|||||||
write_int(client, MAGISK_VER_CODE);
|
write_int(client, MAGISK_VER_CODE);
|
||||||
break;
|
break;
|
||||||
case +RequestCode::START_DAEMON:
|
case +RequestCode::START_DAEMON:
|
||||||
MagiskD::get()->setup_logfile();
|
MagiskD().setup_logfile();
|
||||||
break;
|
break;
|
||||||
case +RequestCode::STOP_DAEMON: {
|
case +RequestCode::STOP_DAEMON: {
|
||||||
// Unmount all overlays
|
// Unmount all overlays
|
||||||
@@ -298,7 +286,7 @@ static void handle_request(pollfd *pfd) {
|
|||||||
exec_task([=, fd = client.release()] { handle_request_async(fd, code, cred); });
|
exec_task([=, fd = client.release()] { handle_request_async(fd, code, cred); });
|
||||||
} else {
|
} else {
|
||||||
exec_task([=, fd = client.release()] {
|
exec_task([=, fd = client.release()] {
|
||||||
MagiskD::get()->boot_stage_handler(fd, code);
|
MagiskD().boot_stage_handler(fd, code);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::io;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::sync::{Mutex, OnceLock};
|
use std::sync::{Mutex, OnceLock};
|
||||||
use std::{io, mem};
|
|
||||||
|
|
||||||
use base::libc::{O_CLOEXEC, O_RDONLY};
|
use base::libc::{O_CLOEXEC, O_RDONLY};
|
||||||
use base::{
|
use base::{
|
||||||
@@ -10,7 +10,7 @@ use base::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::consts::MAIN_CONFIG;
|
use crate::consts::MAIN_CONFIG;
|
||||||
use crate::ffi::{get_magisk_tmp, CxxMagiskD, RequestCode};
|
use crate::ffi::{get_magisk_tmp, RequestCode};
|
||||||
use crate::get_prop;
|
use crate::get_prop;
|
||||||
use crate::logging::magisk_logging;
|
use crate::logging::magisk_logging;
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ impl MagiskD {
|
|||||||
match code {
|
match code {
|
||||||
RequestCode::POST_FS_DATA => {
|
RequestCode::POST_FS_DATA => {
|
||||||
if check_data() && !state.contains(BootState::PostFsDataDone) {
|
if check_data() && !state.contains(BootState::PostFsDataDone) {
|
||||||
if self.as_cxx().post_fs_data() {
|
if self.post_fs_data() {
|
||||||
state.set(BootState::SafeMode);
|
state.set(BootState::SafeMode);
|
||||||
}
|
}
|
||||||
state.set(BootState::PostFsDataDone);
|
state.set(BootState::PostFsDataDone);
|
||||||
@@ -75,7 +75,7 @@ impl MagiskD {
|
|||||||
unsafe { libc::close(client) };
|
unsafe { libc::close(client) };
|
||||||
if state.contains(BootState::PostFsDataDone) && !state.contains(BootState::SafeMode)
|
if state.contains(BootState::PostFsDataDone) && !state.contains(BootState::SafeMode)
|
||||||
{
|
{
|
||||||
self.as_cxx().late_start();
|
self.late_start();
|
||||||
state.set(BootState::LateStartDone);
|
state.set(BootState::LateStartDone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ impl MagiskD {
|
|||||||
unsafe { libc::close(client) };
|
unsafe { libc::close(client) };
|
||||||
if state.contains(BootState::PostFsDataDone) {
|
if state.contains(BootState::PostFsDataDone) {
|
||||||
state.set(BootState::BootComplete);
|
state.set(BootState::BootComplete);
|
||||||
self.as_cxx().boot_complete()
|
self.boot_complete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -91,11 +91,6 @@ impl MagiskD {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn as_cxx(&self) -> &CxxMagiskD {
|
|
||||||
unsafe { mem::transmute(self) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn daemon_entry() {
|
pub fn daemon_entry() {
|
||||||
|
@@ -108,7 +108,7 @@ db_settings::db_settings() {
|
|||||||
data[SU_MULTIUSER_MODE] = MULTIUSER_MODE_OWNER_ONLY;
|
data[SU_MULTIUSER_MODE] = MULTIUSER_MODE_OWNER_ONLY;
|
||||||
data[SU_MNT_NS] = NAMESPACE_MODE_REQUESTER;
|
data[SU_MNT_NS] = NAMESPACE_MODE_REQUESTER;
|
||||||
data[DENYLIST_CONFIG] = false;
|
data[DENYLIST_CONFIG] = false;
|
||||||
data[ZYGISK_CONFIG] = MagiskD::get()->is_emulator();
|
data[ZYGISK_CONFIG] = MagiskD().is_emulator();
|
||||||
data[BOOTLOOP_COUNT] = 0;
|
data[BOOTLOOP_COUNT] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,29 +2,6 @@
|
|||||||
|
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
|
|
||||||
namespace rust {
|
|
||||||
struct MagiskD;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MagiskD {
|
|
||||||
// Make sure only references can exist
|
|
||||||
~MagiskD() = delete;
|
|
||||||
|
|
||||||
// Binding to Rust
|
|
||||||
static const MagiskD &get();
|
|
||||||
|
|
||||||
// C++ implementation
|
|
||||||
void reboot() const;
|
|
||||||
bool post_fs_data() const;
|
|
||||||
void late_start() const;
|
|
||||||
void boot_complete() const;
|
|
||||||
|
|
||||||
const rust::MagiskD *operator->() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const rust::MagiskD &as_rust() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *get_magisk_tmp();
|
const char *get_magisk_tmp();
|
||||||
|
|
||||||
// Rust bindings
|
// Rust bindings
|
||||||
|
@@ -74,12 +74,6 @@ pub mod ffi {
|
|||||||
fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String;
|
fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String;
|
||||||
|
|
||||||
fn switch_mnt_ns(pid: i32) -> i32;
|
fn switch_mnt_ns(pid: i32) -> i32;
|
||||||
|
|
||||||
#[cxx_name = "MagiskD"]
|
|
||||||
type CxxMagiskD;
|
|
||||||
fn post_fs_data(self: &CxxMagiskD) -> bool;
|
|
||||||
fn late_start(self: &CxxMagiskD);
|
|
||||||
fn boot_complete(self: &CxxMagiskD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
@@ -99,18 +93,28 @@ pub mod ffi {
|
|||||||
unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>);
|
unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>);
|
||||||
unsafe fn persist_delete_prop(name: Utf8CStrRef) -> bool;
|
unsafe fn persist_delete_prop(name: Utf8CStrRef) -> bool;
|
||||||
unsafe fn persist_set_prop(name: Utf8CStrRef, value: Utf8CStrRef) -> bool;
|
unsafe fn persist_set_prop(name: Utf8CStrRef, value: Utf8CStrRef) -> bool;
|
||||||
|
|
||||||
|
#[namespace = "rust"]
|
||||||
|
fn daemon_entry();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[namespace = "rust"]
|
// FFI for MagiskD
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn daemon_entry();
|
|
||||||
|
|
||||||
type MagiskD;
|
type MagiskD;
|
||||||
fn get_magiskd() -> &'static MagiskD;
|
|
||||||
fn setup_logfile(self: &MagiskD);
|
fn setup_logfile(self: &MagiskD);
|
||||||
fn is_emulator(self: &MagiskD) -> bool;
|
fn is_emulator(self: &MagiskD) -> bool;
|
||||||
fn is_recovery(self: &MagiskD) -> bool;
|
fn is_recovery(self: &MagiskD) -> bool;
|
||||||
fn boot_stage_handler(self: &MagiskD, client: i32, code: i32);
|
fn boot_stage_handler(self: &MagiskD, client: i32, code: i32);
|
||||||
|
|
||||||
|
#[cxx_name = "MagiskD"]
|
||||||
|
fn get_magiskd() -> &'static MagiskD;
|
||||||
|
}
|
||||||
|
unsafe extern "C++" {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn reboot(self: &MagiskD);
|
||||||
|
fn post_fs_data(self: &MagiskD) -> bool;
|
||||||
|
fn late_start(self: &MagiskD);
|
||||||
|
fn boot_complete(self: &MagiskD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -177,26 +177,23 @@ void tmpfs_node::mount() {
|
|||||||
class magisk_node : public node_entry {
|
class magisk_node : public node_entry {
|
||||||
public:
|
public:
|
||||||
explicit magisk_node(const char *name) : node_entry(name, DT_REG, this) {}
|
explicit magisk_node(const char *name) : node_entry(name, DT_REG, this) {}
|
||||||
|
explicit magisk_node(const char *name, const char *target)
|
||||||
|
: node_entry(name, DT_LNK, this), target(target) {}
|
||||||
|
|
||||||
void mount() override {
|
void mount() override {
|
||||||
const string src = get_magisk_tmp() + "/"s + name();
|
if (target) {
|
||||||
if (access(src.data(), F_OK))
|
string dest = isa<tmpfs_node>(parent()) ? worker_path() : node_path();
|
||||||
return;
|
VLOGD("create", target, dest.data());
|
||||||
|
xsymlink(target, dest.data());
|
||||||
const string dir_name = isa<tmpfs_node>(parent()) ? parent()->worker_path() : parent()->node_path();
|
|
||||||
if (name() == "magisk") {
|
|
||||||
for (int i = 0; applet_names[i]; ++i) {
|
|
||||||
string dest = dir_name + "/" + applet_names[i];
|
|
||||||
VLOGD("create", "./magisk", dest.data());
|
|
||||||
xsymlink("./magisk", dest.data());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
string dest = dir_name + "/supolicy";
|
string src = get_magisk_tmp() + "/"s + name();
|
||||||
VLOGD("create", "./magiskpolicy", dest.data());
|
if (access(src.data(), F_OK) == 0)
|
||||||
xsymlink("./magiskpolicy", dest.data());
|
create_and_mount("magisk", src, true);
|
||||||
}
|
}
|
||||||
create_and_mount("magisk", src, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char *target = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class zygisk_node : public node_entry {
|
class zygisk_node : public node_entry {
|
||||||
@@ -231,10 +228,10 @@ static void inject_magisk_bins(root_node *system) {
|
|||||||
bin->insert(new magisk_node("magisk"));
|
bin->insert(new magisk_node("magisk"));
|
||||||
bin->insert(new magisk_node("magiskpolicy"));
|
bin->insert(new magisk_node("magiskpolicy"));
|
||||||
|
|
||||||
// Also delete all applets to make sure no modules can override it
|
// Also insert all applets to make sure no one can override it
|
||||||
for (int i = 0; applet_names[i]; ++i)
|
for (int i = 0; applet_names[i]; ++i)
|
||||||
delete bin->extract(applet_names[i]);
|
bin->insert(new magisk_node(applet_names[i], "./magisk"));
|
||||||
delete bin->extract("supolicy");
|
bin->insert(new magisk_node("supolicy", "./magiskpolicy"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inject_zygisk_libs(root_node *system) {
|
static void inject_zygisk_libs(root_node *system) {
|
||||||
|
2
native/src/external/cxx-rs
vendored
2
native/src/external/cxx-rs
vendored
Submodule native/src/external/cxx-rs updated: 7535230afb...08cb634704
@@ -11,8 +11,6 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
vector<string> mount_list;
|
|
||||||
|
|
||||||
template<char... cs> using chars = integer_sequence<char, cs...>;
|
template<char... cs> using chars = integer_sequence<char, cs...>;
|
||||||
|
|
||||||
// If quoted, parsing ends when we find char in [breaks]
|
// If quoted, parsing ends when we find char in [breaks]
|
||||||
@@ -148,6 +146,12 @@ void BootConfig::set(const kv_pairs &kv) {
|
|||||||
strscpy(fstab_suffix, value.data(), sizeof(fstab_suffix));
|
strscpy(fstab_suffix, value.data(), sizeof(fstab_suffix));
|
||||||
} else if (key == "qemu") {
|
} else if (key == "qemu") {
|
||||||
emulator = true;
|
emulator = true;
|
||||||
|
} else if (key == "androidboot.partition_map") {
|
||||||
|
// androidboot.partition_map allows mapping a partition name to a raw block device.
|
||||||
|
// For example, "androidboot.partition_map=vdb,metadata;vdc,userdata" maps
|
||||||
|
// "vdb" to "metadata", and "vdc" to "userdata".
|
||||||
|
// https://android.googlesource.com/platform/system/core/+/refs/heads/android13-release/init/devices.cpp#191
|
||||||
|
partition_map = parse_partition_map(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,41 +169,29 @@ void BootConfig::print() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define read_dt(name, key) \
|
#define read_dt(name, key) \
|
||||||
ssprintf(file_name, sizeof(file_name), "%s/" name, config->dt_dir); \
|
ssprintf(file_name, sizeof(file_name), "%s/" name, dt_dir); \
|
||||||
if (access(file_name, R_OK) == 0) { \
|
if (access(file_name, R_OK) == 0) { \
|
||||||
string data = full_read(file_name); \
|
string data = full_read(file_name); \
|
||||||
if (!data.empty()) { \
|
if (!data.empty()) { \
|
||||||
data.pop_back(); \
|
data.pop_back(); \
|
||||||
strscpy(config->key, data.data(), sizeof(config->key)); \
|
strscpy(key, data.data(), sizeof(key)); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_kernel_info(BootConfig *config) {
|
void BootConfig::init() {
|
||||||
// Get kernel data using procfs and sysfs
|
set(parse_cmdline(full_read("/proc/cmdline")));
|
||||||
xmkdir("/proc", 0755);
|
set(parse_bootconfig(full_read("/proc/bootconfig")));
|
||||||
xmount("proc", "/proc", "proc", 0, nullptr);
|
|
||||||
xmkdir("/sys", 0755);
|
|
||||||
xmount("sysfs", "/sys", "sysfs", 0, nullptr);
|
|
||||||
|
|
||||||
mount_list.emplace_back("/proc");
|
parse_prop_file("/.backup/.magisk", [&](auto key, auto value) -> bool {
|
||||||
mount_list.emplace_back("/sys");
|
|
||||||
|
|
||||||
// Log to kernel
|
|
||||||
rust::setup_klog();
|
|
||||||
|
|
||||||
config->set(parse_cmdline(full_read("/proc/cmdline")));
|
|
||||||
config->set(parse_bootconfig(full_read("/proc/bootconfig")));
|
|
||||||
|
|
||||||
parse_prop_file("/.backup/.magisk", [=](auto key, auto value) -> bool {
|
|
||||||
if (key == "RECOVERYMODE" && value == "true") {
|
if (key == "RECOVERYMODE" && value == "true") {
|
||||||
config->skip_initramfs = config->emulator || !check_key_combo();
|
skip_initramfs = emulator || !check_key_combo();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config->dt_dir[0] == '\0')
|
if (dt_dir[0] == '\0')
|
||||||
strscpy(config->dt_dir, DEFAULT_DT_DIR, sizeof(config->dt_dir));
|
strscpy(dt_dir, DEFAULT_DT_DIR, sizeof(dt_dir));
|
||||||
|
|
||||||
char file_name[128];
|
char file_name[128];
|
||||||
read_dt("fstab_suffix", fstab_suffix)
|
read_dt("fstab_suffix", fstab_suffix)
|
||||||
@@ -207,26 +199,7 @@ void load_kernel_info(BootConfig *config) {
|
|||||||
read_dt("hardware.platform", hardware_plat)
|
read_dt("hardware.platform", hardware_plat)
|
||||||
|
|
||||||
LOGD("Device config:\n");
|
LOGD("Device config:\n");
|
||||||
config->print();
|
print();
|
||||||
}
|
|
||||||
|
|
||||||
// `androidboot.partition_map` allows associating a partition name for a raw block device
|
|
||||||
// through a comma separated and semicolon deliminated list. For example,
|
|
||||||
// `androidboot.partition_map=vdb,metadata;vdc,userdata` maps `vdb` to `metadata` and `vdc` to
|
|
||||||
// `userdata`.
|
|
||||||
// https://android.googlesource.com/platform/system/core/+/refs/heads/android13-release/init/devices.cpp#191
|
|
||||||
|
|
||||||
kv_pairs load_partition_map() {
|
|
||||||
const string_view kPartitionMapKey = "androidboot.partition_map";
|
|
||||||
for (const auto &[key, value] : parse_cmdline(full_read("/proc/cmdline"))) {
|
|
||||||
if (key == kPartitionMapKey)
|
|
||||||
return parse_partition_map(value);
|
|
||||||
}
|
|
||||||
for (const auto &[key, value] : parse_bootconfig(full_read("/proc/bootconfig"))) {
|
|
||||||
if (key == kPartitionMapKey)
|
|
||||||
return parse_partition_map(value);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_two_stage() {
|
bool check_two_stage() {
|
||||||
@@ -244,7 +217,7 @@ bool check_two_stage() {
|
|||||||
return init.contains("selinux_setup");
|
return init.contains("selinux_setup");
|
||||||
}
|
}
|
||||||
|
|
||||||
void unxz_init(const char *init_xz, const char *init) {
|
static void unxz_init(const char *init_xz, const char *init) {
|
||||||
LOGD("unxz %s -> %s\n", init_xz, init);
|
LOGD("unxz %s -> %s\n", init_xz, init);
|
||||||
int fd = xopen(init, O_WRONLY | O_CREAT, 0777);
|
int fd = xopen(init, O_WRONLY | O_CREAT, 0777);
|
||||||
fd_stream ch(fd);
|
fd_stream ch(fd);
|
||||||
|
@@ -60,16 +60,67 @@ void restore_ramdisk_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RecoveryInit : public BaseInit {
|
MagiskInit::MagiskInit(char **argv) : argv(argv), config{} {
|
||||||
public:
|
// Get kernel data using procfs and sysfs
|
||||||
using BaseInit::BaseInit;
|
if (access("/proc/cmdline", F_OK) != 0) {
|
||||||
void start() override {
|
xmkdir("/proc", 0755);
|
||||||
LOGD("Ramdisk is recovery, abort\n");
|
xmount("proc", "/proc", "proc", 0, nullptr);
|
||||||
restore_ramdisk_init();
|
mount_list.emplace_back("/proc");
|
||||||
rm_rf("/.backup");
|
|
||||||
exec_init();
|
|
||||||
}
|
}
|
||||||
};
|
if (access("/sys/block", F_OK) != 0) {
|
||||||
|
xmkdir("/sys", 0755);
|
||||||
|
xmount("sysfs", "/sys", "sysfs", 0, nullptr);
|
||||||
|
mount_list.emplace_back("/sys");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log to kernel
|
||||||
|
rust::setup_klog();
|
||||||
|
|
||||||
|
// Load kernel configs
|
||||||
|
config.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recovery() {
|
||||||
|
LOGI("Ramdisk is recovery, abort\n");
|
||||||
|
restore_ramdisk_init();
|
||||||
|
rm_rf("/.backup");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MagiskInit::legacy_system_as_root() {
|
||||||
|
LOGI("Legacy SAR Init\n");
|
||||||
|
prepare_data();
|
||||||
|
bool is_two_stage = mount_system_root();
|
||||||
|
if (is_two_stage)
|
||||||
|
redirect_second_stage();
|
||||||
|
else
|
||||||
|
patch_ro_root();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MagiskInit::rootfs() {
|
||||||
|
LOGI("RootFS Init\n");
|
||||||
|
prepare_data();
|
||||||
|
LOGD("Restoring /init\n");
|
||||||
|
rename(backup_init(), "/init");
|
||||||
|
patch_rw_root();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MagiskInit::start() {
|
||||||
|
if (argv[1] != nullptr && argv[1] == "selinux_setup"sv)
|
||||||
|
second_stage();
|
||||||
|
else if (config.skip_initramfs)
|
||||||
|
legacy_system_as_root();
|
||||||
|
else if (config.force_normal_boot)
|
||||||
|
first_stage();
|
||||||
|
else if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0)
|
||||||
|
recovery();
|
||||||
|
else if (check_two_stage())
|
||||||
|
first_stage();
|
||||||
|
else
|
||||||
|
rootfs();
|
||||||
|
|
||||||
|
// Finally execute the original init
|
||||||
|
exec_init();
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
umask(0);
|
umask(0);
|
||||||
@@ -81,29 +132,6 @@ int main(int argc, char *argv[]) {
|
|||||||
if (getpid() != 1)
|
if (getpid() != 1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
BaseInit *init;
|
MagiskInit init(argv);
|
||||||
BootConfig config{};
|
init.start();
|
||||||
|
|
||||||
if (argc > 1 && argv[1] == "selinux_setup"sv) {
|
|
||||||
rust::setup_klog();
|
|
||||||
init = new SecondStageInit(argv);
|
|
||||||
} else {
|
|
||||||
// This will also mount /sys and /proc
|
|
||||||
load_kernel_info(&config);
|
|
||||||
|
|
||||||
if (config.skip_initramfs)
|
|
||||||
init = new LegacySARInit(argv, &config);
|
|
||||||
else if (config.force_normal_boot)
|
|
||||||
init = new FirstStageInit(argv, &config);
|
|
||||||
else if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0)
|
|
||||||
init = new RecoveryInit(argv, &config);
|
|
||||||
else if (check_two_stage())
|
|
||||||
init = new FirstStageInit(argv, &config);
|
|
||||||
else
|
|
||||||
init = new RootFSInit(argv, &config);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the main routine
|
|
||||||
init->start();
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,10 @@ struct BootConfig {
|
|||||||
char fstab_suffix[32];
|
char fstab_suffix[32];
|
||||||
char hardware[32];
|
char hardware[32];
|
||||||
char hardware_plat[32];
|
char hardware_plat[32];
|
||||||
|
kv_pairs partition_map;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
private:
|
||||||
void set(const kv_pairs &);
|
void set(const kv_pairs &);
|
||||||
void print();
|
void print();
|
||||||
};
|
};
|
||||||
@@ -24,120 +27,45 @@ struct BootConfig {
|
|||||||
#define INIT_PATH "/system/bin/init"
|
#define INIT_PATH "/system/bin/init"
|
||||||
#define REDIR_PATH "/data/magiskinit"
|
#define REDIR_PATH "/data/magiskinit"
|
||||||
|
|
||||||
extern std::vector<std::string> mount_list;
|
|
||||||
|
|
||||||
int magisk_proxy_main(int argc, char *argv[]);
|
int magisk_proxy_main(int argc, char *argv[]);
|
||||||
bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes);
|
bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes);
|
||||||
void load_kernel_info(BootConfig *config);
|
|
||||||
kv_pairs load_partition_map();
|
|
||||||
bool check_two_stage();
|
bool check_two_stage();
|
||||||
const char *backup_init();
|
const char *backup_init();
|
||||||
void restore_ramdisk_init();
|
void restore_ramdisk_init();
|
||||||
|
|
||||||
/***************
|
class MagiskInit {
|
||||||
* Base classes
|
|
||||||
***************/
|
|
||||||
|
|
||||||
class BaseInit {
|
|
||||||
protected:
|
|
||||||
BootConfig *config = nullptr;
|
|
||||||
char **argv = nullptr;
|
|
||||||
|
|
||||||
[[noreturn]] void exec_init();
|
|
||||||
void prepare_data();
|
|
||||||
public:
|
|
||||||
BaseInit(char *argv[], BootConfig *config = nullptr) : config(config), argv(argv) {}
|
|
||||||
virtual ~BaseInit() = default;
|
|
||||||
virtual void start() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MagiskInit : public BaseInit {
|
|
||||||
private:
|
private:
|
||||||
std::string preinit_dev;
|
std::string preinit_dev;
|
||||||
|
std::vector<std::string> mount_list;
|
||||||
|
char **argv;
|
||||||
|
BootConfig config;
|
||||||
|
|
||||||
void parse_config_file();
|
// Setup mounts and environment
|
||||||
void patch_sepolicy(const char *in, const char *out);
|
|
||||||
bool hijack_sepolicy();
|
|
||||||
void setup_tmp(const char *path);
|
void setup_tmp(const char *path);
|
||||||
protected:
|
void collect_devices();
|
||||||
|
void mount_preinit_dir();
|
||||||
|
void prepare_data();
|
||||||
|
dev_t find_block(const char *partname);
|
||||||
|
bool mount_system_root();
|
||||||
|
|
||||||
|
// Setup and patch root directory
|
||||||
|
void parse_config_file();
|
||||||
void patch_rw_root();
|
void patch_rw_root();
|
||||||
void patch_ro_root();
|
void patch_ro_root();
|
||||||
|
|
||||||
|
// Two stage init
|
||||||
|
void redirect_second_stage();
|
||||||
|
void first_stage();
|
||||||
|
void second_stage();
|
||||||
|
|
||||||
|
// SELinux
|
||||||
|
void patch_sepolicy(const char *in, const char *out);
|
||||||
|
bool hijack_sepolicy();
|
||||||
|
|
||||||
|
[[noreturn]] void exec_init();
|
||||||
|
void legacy_system_as_root();
|
||||||
|
void rootfs();
|
||||||
public:
|
public:
|
||||||
using BaseInit::BaseInit;
|
explicit MagiskInit(char *argv[]);
|
||||||
};
|
void start();
|
||||||
|
|
||||||
/***************
|
|
||||||
* 2 Stage Init
|
|
||||||
***************/
|
|
||||||
|
|
||||||
class FirstStageInit : public BaseInit {
|
|
||||||
private:
|
|
||||||
void prepare();
|
|
||||||
public:
|
|
||||||
FirstStageInit(char *argv[], BootConfig *config) : BaseInit(argv, config) {
|
|
||||||
LOGD("%s\n", __FUNCTION__);
|
|
||||||
};
|
|
||||||
void start() override {
|
|
||||||
prepare();
|
|
||||||
exec_init();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SecondStageInit : public MagiskInit {
|
|
||||||
private:
|
|
||||||
bool prepare();
|
|
||||||
public:
|
|
||||||
SecondStageInit(char *argv[]) : MagiskInit(argv) {
|
|
||||||
LOGD("%s\n", __FUNCTION__);
|
|
||||||
};
|
|
||||||
|
|
||||||
void start() override {
|
|
||||||
bool is_rootfs = prepare();
|
|
||||||
if (is_rootfs)
|
|
||||||
patch_rw_root();
|
|
||||||
else
|
|
||||||
patch_ro_root();
|
|
||||||
exec_init();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*************
|
|
||||||
* Legacy SAR
|
|
||||||
*************/
|
|
||||||
|
|
||||||
class LegacySARInit : public MagiskInit {
|
|
||||||
private:
|
|
||||||
bool mount_system_root();
|
|
||||||
void first_stage_prep();
|
|
||||||
public:
|
|
||||||
LegacySARInit(char *argv[], BootConfig *config) : MagiskInit(argv, config) {
|
|
||||||
LOGD("%s\n", __FUNCTION__);
|
|
||||||
};
|
|
||||||
void start() override {
|
|
||||||
prepare_data();
|
|
||||||
bool is_two_stage = mount_system_root();
|
|
||||||
if (is_two_stage)
|
|
||||||
first_stage_prep();
|
|
||||||
else
|
|
||||||
patch_ro_root();
|
|
||||||
exec_init();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/************
|
|
||||||
* Initramfs
|
|
||||||
************/
|
|
||||||
|
|
||||||
class RootFSInit : public MagiskInit {
|
|
||||||
private:
|
|
||||||
void prepare();
|
|
||||||
public:
|
|
||||||
RootFSInit(char *argv[], BootConfig *config) : MagiskInit(argv, config) {
|
|
||||||
LOGD("%s\n", __FUNCTION__);
|
|
||||||
}
|
|
||||||
void start() override {
|
|
||||||
prepare();
|
|
||||||
patch_rw_root();
|
|
||||||
exec_init();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
@@ -45,7 +45,7 @@ static void parse_device(devinfo *dev, const char *uevent) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void collect_devices(const auto &partition_map) {
|
void MagiskInit::collect_devices() {
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
devinfo dev{};
|
devinfo dev{};
|
||||||
if (auto dir = xopen_dir("/sys/dev/block"); dir) {
|
if (auto dir = xopen_dir("/sys/dev/block"); dir) {
|
||||||
@@ -59,9 +59,9 @@ static void collect_devices(const auto &partition_map) {
|
|||||||
auto name = rtrim(full_read(path));
|
auto name = rtrim(full_read(path));
|
||||||
strscpy(dev.dmname, name.data(), sizeof(dev.dmname));
|
strscpy(dev.dmname, name.data(), sizeof(dev.dmname));
|
||||||
}
|
}
|
||||||
if (auto it = std::ranges::find_if(partition_map, [&](const auto &i) {
|
if (auto it = std::ranges::find_if(config.partition_map, [&](const auto &i) {
|
||||||
return i.first == dev.devname;
|
return i.first == dev.devname;
|
||||||
}); dev.partname[0] == '\0' && it != partition_map.end()) {
|
}); dev.partname[0] == '\0' && it != config.partition_map.end()) {
|
||||||
// use androidboot.partition_map as partname fallback.
|
// use androidboot.partition_map as partname fallback.
|
||||||
strscpy(dev.partname, it->second.data(), sizeof(dev.partname));
|
strscpy(dev.partname, it->second.data(), sizeof(dev.partname));
|
||||||
}
|
}
|
||||||
@@ -72,52 +72,45 @@ static void collect_devices(const auto &partition_map) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct {
|
dev_t MagiskInit::find_block(const char *partname) {
|
||||||
char partname[32];
|
|
||||||
char block_dev[64];
|
|
||||||
} blk_info;
|
|
||||||
|
|
||||||
static dev_t setup_block() {
|
|
||||||
static const auto partition_map = load_partition_map();
|
|
||||||
if (dev_list.empty())
|
if (dev_list.empty())
|
||||||
collect_devices(partition_map);
|
collect_devices();
|
||||||
|
|
||||||
for (int tries = 0; tries < 3; ++tries) {
|
for (int tries = 0; tries < 3; ++tries) {
|
||||||
for (auto &dev : dev_list) {
|
for (auto &dev : dev_list) {
|
||||||
if (strcasecmp(dev.partname, blk_info.partname) == 0)
|
const char *name;
|
||||||
LOGD("Setup %s: [%s] (%d, %d)\n", dev.partname, dev.devname, dev.major, dev.minor);
|
if (strcasecmp(dev.partname, partname) == 0)
|
||||||
else if (strcasecmp(dev.dmname, blk_info.partname) == 0)
|
name = dev.partname;
|
||||||
LOGD("Setup %s: [%s] (%d, %d)\n", dev.dmname, dev.devname, dev.major, dev.minor);
|
else if (strcasecmp(dev.dmname, partname) == 0)
|
||||||
else if (strcasecmp(dev.devname, blk_info.partname) == 0)
|
name = dev.dmname;
|
||||||
LOGD("Setup %s: [%s] (%d, %d)\n", dev.devname, dev.devname, dev.major, dev.minor);
|
else if (strcasecmp(dev.devname, partname) == 0)
|
||||||
else if (std::string_view(dev.devpath).ends_with("/"s + blk_info.partname))
|
name = dev.devname;
|
||||||
LOGD("Setup %s: [%s] (%d, %d)\n", dev.devpath, dev.devname, dev.major, dev.minor);
|
else if (std::string_view(dev.devpath).ends_with("/"s + partname))
|
||||||
|
name = dev.devpath;
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dev_t rdev = makedev(dev.major, dev.minor);
|
LOGD("Found %s: [%s] (%d, %d)\n", name, dev.devname, dev.major, dev.minor);
|
||||||
xmknod(blk_info.block_dev, S_IFBLK | 0600, rdev);
|
return makedev(dev.major, dev.minor);
|
||||||
return rdev;
|
|
||||||
}
|
}
|
||||||
// Wait 10ms and try again
|
// Wait 10ms and try again
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
dev_list.clear();
|
dev_list.clear();
|
||||||
collect_devices(partition_map);
|
collect_devices();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The requested partname does not exist
|
// The requested partname does not exist
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mount_preinit_dir(string preinit_dev) {
|
void MagiskInit::mount_preinit_dir() {
|
||||||
if (preinit_dev.empty()) return;
|
if (preinit_dev.empty()) return;
|
||||||
strcpy(blk_info.partname, preinit_dev.data());
|
auto dev = find_block(preinit_dev.data());
|
||||||
strcpy(blk_info.block_dev, PREINITDEV);
|
|
||||||
auto dev = setup_block();
|
|
||||||
if (dev == 0) {
|
if (dev == 0) {
|
||||||
LOGE("Cannot find preinit %s, abort!\n", preinit_dev.data());
|
LOGE("Cannot find preinit %s, abort!\n", preinit_dev.data());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
xmknod(PREINITDEV, S_IFBLK | 0600, dev);
|
||||||
xmkdir(MIRRDIR, 0);
|
xmkdir(MIRRDIR, 0);
|
||||||
bool mounted = false;
|
bool mounted = false;
|
||||||
// First, find if it is already mounted
|
// First, find if it is already mounted
|
||||||
@@ -150,40 +143,40 @@ static void mount_preinit_dir(string preinit_dev) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LegacySARInit::mount_system_root() {
|
bool MagiskInit::mount_system_root() {
|
||||||
LOGD("Mounting system_root\n");
|
LOGD("Mounting system_root\n");
|
||||||
|
|
||||||
// there's no /dev in stub cpio
|
// there's no /dev in stub cpio
|
||||||
xmkdir("/dev", 0777);
|
xmkdir("/dev", 0777);
|
||||||
|
|
||||||
strcpy(blk_info.block_dev, "/dev/root");
|
dev_t dev;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Try legacy SAR dm-verity
|
// Try legacy SAR dm-verity
|
||||||
strcpy(blk_info.partname, "vroot");
|
dev = find_block("vroot");
|
||||||
auto dev = setup_block();
|
|
||||||
if (dev > 0)
|
if (dev > 0)
|
||||||
goto mount_root;
|
goto mount_root;
|
||||||
|
|
||||||
// Try NVIDIA naming scheme
|
// Try NVIDIA naming scheme
|
||||||
strcpy(blk_info.partname, "APP");
|
dev = find_block("APP");
|
||||||
dev = setup_block();
|
|
||||||
if (dev > 0)
|
if (dev > 0)
|
||||||
goto mount_root;
|
goto mount_root;
|
||||||
|
|
||||||
sprintf(blk_info.partname, "system%s", config->slot);
|
// Try normal partname
|
||||||
dev = setup_block();
|
char sys_part[32];
|
||||||
|
sprintf(sys_part, "system%s", config.slot);
|
||||||
|
dev = find_block(sys_part);
|
||||||
if (dev > 0)
|
if (dev > 0)
|
||||||
goto mount_root;
|
goto mount_root;
|
||||||
|
|
||||||
// Poll forever if rootwait was given in cmdline
|
// Poll forever if rootwait was given in cmdline
|
||||||
} while (config->rootwait);
|
} while (config.rootwait);
|
||||||
|
|
||||||
// We don't really know what to do at this point...
|
// We don't really know what to do at this point...
|
||||||
LOGE("Cannot find root partition, abort\n");
|
LOGE("Cannot find root partition, abort\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
mount_root:
|
mount_root:
|
||||||
|
xmknod("/dev/root", S_IFBLK | 0600, dev);
|
||||||
xmkdir("/system_root", 0755);
|
xmkdir("/system_root", 0755);
|
||||||
|
|
||||||
if (xmount("/dev/root", "/system_root", "ext4", MS_RDONLY, nullptr)) {
|
if (xmount("/dev/root", "/system_root", "ext4", MS_RDONLY, nullptr)) {
|
||||||
@@ -205,20 +198,19 @@ mount_root:
|
|||||||
|
|
||||||
// For API 28 AVD, it uses legacy SAR setup that requires
|
// For API 28 AVD, it uses legacy SAR setup that requires
|
||||||
// special hacks in magiskinit to work properly.
|
// special hacks in magiskinit to work properly.
|
||||||
if (!is_two_stage && config->emulator) {
|
if (!is_two_stage && config.emulator) {
|
||||||
avd_hack = true;
|
avd_hack = true;
|
||||||
// These values are hardcoded for API 28 AVD
|
// These values are hardcoded for API 28 AVD
|
||||||
|
auto vendor_dev = find_block("vendor");
|
||||||
xmkdir("/dev/block", 0755);
|
xmkdir("/dev/block", 0755);
|
||||||
strcpy(blk_info.block_dev, "/dev/block/vde1");
|
xmknod("/dev/block/vde1", S_IFBLK | 0600, vendor_dev);
|
||||||
strcpy(blk_info.partname, "vendor");
|
xmount("/dev/block/vde1", "/vendor", "ext4", MS_RDONLY, nullptr);
|
||||||
setup_block();
|
|
||||||
xmount(blk_info.block_dev, "/vendor", "ext4", MS_RDONLY, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_two_stage;
|
return is_two_stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInit::exec_init() {
|
void MagiskInit::exec_init() {
|
||||||
// Unmount in reverse order
|
// Unmount in reverse order
|
||||||
for (auto &p : reversed(mount_list)) {
|
for (auto &p : reversed(mount_list)) {
|
||||||
if (xumount2(p.data(), MNT_DETACH) == 0)
|
if (xumount2(p.data(), MNT_DETACH) == 0)
|
||||||
@@ -228,12 +220,12 @@ void BaseInit::exec_init() {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInit::prepare_data() {
|
void MagiskInit::prepare_data() {
|
||||||
LOGD("Setup data tmp\n");
|
LOGD("Setup data tmp\n");
|
||||||
xmkdir("/data", 0755);
|
xmkdir("/data", 0755);
|
||||||
xmount("magisk", "/data", "tmpfs", 0, "mode=755");
|
xmount("magisk", "/data", "tmpfs", 0, "mode=755");
|
||||||
|
|
||||||
cp_afc("/init", "/data/magiskinit");
|
cp_afc("/init", REDIR_PATH);
|
||||||
cp_afc("/.backup", "/data/.backup");
|
cp_afc("/.backup", "/data/.backup");
|
||||||
cp_afc("/overlay.d", "/data/overlay.d");
|
cp_afc("/overlay.d", "/data/overlay.d");
|
||||||
}
|
}
|
||||||
@@ -246,7 +238,7 @@ void MagiskInit::setup_tmp(const char *path) {
|
|||||||
xmkdir(DEVICEDIR, 0711);
|
xmkdir(DEVICEDIR, 0711);
|
||||||
xmkdir(WORKERDIR, 0);
|
xmkdir(WORKERDIR, 0);
|
||||||
|
|
||||||
mount_preinit_dir(preinit_dev);
|
mount_preinit_dir();
|
||||||
|
|
||||||
cp_afc(".backup/.magisk", MAIN_CONFIG);
|
cp_afc(".backup/.magisk", MAIN_CONFIG);
|
||||||
rm_rf(".backup");
|
rm_rf(".backup");
|
||||||
@@ -261,7 +253,7 @@ void MagiskInit::setup_tmp(const char *path) {
|
|||||||
chdir(path);
|
chdir(path);
|
||||||
|
|
||||||
// Prepare worker
|
// Prepare worker
|
||||||
xmount(WORKERDIR, WORKERDIR, nullptr, MS_BIND, nullptr);
|
xmount("magisk", WORKERDIR, "tmpfs", 0, "mode=755");
|
||||||
|
|
||||||
// Use isolated devpts if kernel support
|
// Use isolated devpts if kernel support
|
||||||
if (access("/dev/pts/ptmx", F_OK) == 0) {
|
if (access("/dev/pts/ptmx", F_OK) == 0) {
|
||||||
|
@@ -347,12 +347,6 @@ void MagiskInit::patch_ro_root() {
|
|||||||
chdir("/");
|
chdir("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootFSInit::prepare() {
|
|
||||||
prepare_data();
|
|
||||||
LOGD("Restoring /init\n");
|
|
||||||
rename(backup_init(), "/init");
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PRE_TMPSRC "/magisk"
|
#define PRE_TMPSRC "/magisk"
|
||||||
#define PRE_TMPDIR PRE_TMPSRC "/tmp"
|
#define PRE_TMPDIR PRE_TMPSRC "/tmp"
|
||||||
|
|
||||||
|
@@ -64,7 +64,7 @@ bool MagiskInit::hijack_sepolicy() {
|
|||||||
// This only happens on Android 8.0 - 9.0
|
// This only happens on Android 8.0 - 9.0
|
||||||
|
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
ssprintf(buf, sizeof(buf), "%s/fstab/compatible", config->dt_dir);
|
ssprintf(buf, sizeof(buf), "%s/fstab/compatible", config.dt_dir);
|
||||||
dt_compat = full_read(buf);
|
dt_compat = full_read(buf);
|
||||||
if (dt_compat.empty()) {
|
if (dt_compat.empty()) {
|
||||||
// Device does not do early mount and uses monolithic policy
|
// Device does not do early mount and uses monolithic policy
|
||||||
@@ -106,7 +106,7 @@ bool MagiskInit::hijack_sepolicy() {
|
|||||||
int fd = xopen(MOCK_COMPAT, O_WRONLY);
|
int fd = xopen(MOCK_COMPAT, O_WRONLY);
|
||||||
|
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
ssprintf(buf, sizeof(buf), "%s/fstab/compatible", config->dt_dir);
|
ssprintf(buf, sizeof(buf), "%s/fstab/compatible", config.dt_dir);
|
||||||
xumount2(buf, MNT_DETACH);
|
xumount2(buf, MNT_DETACH);
|
||||||
|
|
||||||
hijack();
|
hijack();
|
||||||
|
@@ -8,12 +8,13 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void FirstStageInit::prepare() {
|
void MagiskInit::first_stage() {
|
||||||
|
LOGI("First Stage Init\n");
|
||||||
prepare_data();
|
prepare_data();
|
||||||
|
|
||||||
if (struct stat st{}; fstatat(-1, "/sdcard", &st, AT_SYMLINK_NOFOLLOW) != 0 &&
|
if (struct stat st{}; fstatat(-1, "/sdcard", &st, AT_SYMLINK_NOFOLLOW) != 0 &&
|
||||||
fstatat(-1, "/first_stage_ramdisk/sdcard", &st, AT_SYMLINK_NOFOLLOW) != 0) {
|
fstatat(-1, "/first_stage_ramdisk/sdcard", &st, AT_SYMLINK_NOFOLLOW) != 0) {
|
||||||
if (config->force_normal_boot) {
|
if (config.force_normal_boot) {
|
||||||
xmkdirs("/first_stage_ramdisk/storage/self", 0755);
|
xmkdirs("/first_stage_ramdisk/storage/self", 0755);
|
||||||
xsymlink("/system/system/bin/init", "/first_stage_ramdisk/storage/self/primary");
|
xsymlink("/system/system/bin/init", "/first_stage_ramdisk/storage/self/primary");
|
||||||
LOGD("Symlink /first_stage_ramdisk/storage/self/primary -> /system/system/bin/init\n");
|
LOGD("Symlink /first_stage_ramdisk/storage/self/primary -> /system/system/bin/init\n");
|
||||||
@@ -29,8 +30,8 @@ void FirstStageInit::prepare() {
|
|||||||
LOGD("Bind mount /sdcard -> /sdcard\n");
|
LOGD("Bind mount /sdcard -> /sdcard\n");
|
||||||
} else {
|
} else {
|
||||||
// rootfs before 3.12
|
// rootfs before 3.12
|
||||||
xmount("/data/magiskinit", "/sdcard", nullptr, MS_BIND, nullptr);
|
xmount(REDIR_PATH, "/sdcard", nullptr, MS_BIND, nullptr);
|
||||||
LOGD("Bind mount /sdcard -> /data/magiskinit\n");
|
LOGD("Bind mount " REDIR_PATH " -> /sdcard\n");
|
||||||
}
|
}
|
||||||
restore_ramdisk_init();
|
restore_ramdisk_init();
|
||||||
} else {
|
} else {
|
||||||
@@ -44,7 +45,7 @@ void FirstStageInit::prepare() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LegacySARInit::first_stage_prep() {
|
void MagiskInit::redirect_second_stage() {
|
||||||
// Patch init binary
|
// Patch init binary
|
||||||
int src = xopen("/init", O_RDONLY);
|
int src = xopen("/init", O_RDONLY);
|
||||||
int dest = xopen("/data/init", O_CREAT | O_WRONLY, 0);
|
int dest = xopen("/data/init", O_CREAT | O_WRONLY, 0);
|
||||||
@@ -61,7 +62,8 @@ void LegacySARInit::first_stage_prep() {
|
|||||||
xmount("/data/init", "/init", nullptr, MS_BIND, nullptr);
|
xmount("/data/init", "/init", nullptr, MS_BIND, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SecondStageInit::prepare() {
|
void MagiskInit::second_stage() {
|
||||||
|
LOGI("Second Stage Init\n");
|
||||||
umount2("/init", MNT_DETACH);
|
umount2("/init", MNT_DETACH);
|
||||||
umount2(INIT_PATH, MNT_DETACH); // just in case
|
umount2(INIT_PATH, MNT_DETACH); // just in case
|
||||||
unlink("/data/init");
|
unlink("/data/init");
|
||||||
@@ -76,7 +78,8 @@ bool SecondStageInit::prepare() {
|
|||||||
// We are still on rootfs, so make sure we will execute the init of the 2nd stage
|
// We are still on rootfs, so make sure we will execute the init of the 2nd stage
|
||||||
unlink("/init");
|
unlink("/init");
|
||||||
xsymlink(INIT_PATH, "/init");
|
xsymlink(INIT_PATH, "/init");
|
||||||
return true;
|
patch_rw_root();
|
||||||
|
} else {
|
||||||
|
patch_ro_root();
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ if [ -z "$FIRST_STAGE" ]; then
|
|||||||
export ASH_STANDALONE=1
|
export ASH_STANDALONE=1
|
||||||
if [ $(./busybox id -u) -ne 0 ]; then
|
if [ $(./busybox id -u) -ne 0 ]; then
|
||||||
# Re-exec script with root
|
# Re-exec script with root
|
||||||
exec /system/xbin/su 0 ./busybox sh $0
|
exec /system/xbin/su 0 /data/local/tmp/busybox sh $0
|
||||||
else
|
else
|
||||||
# Re-exec script with busybox
|
# Re-exec script with busybox
|
||||||
exec ./busybox sh $0
|
exec ./busybox sh $0
|
||||||
@@ -66,7 +66,7 @@ fi
|
|||||||
|
|
||||||
# Stop zygote (and previous setup if exists)
|
# Stop zygote (and previous setup if exists)
|
||||||
magisk --stop 2>/dev/null
|
magisk --stop 2>/dev/null
|
||||||
stop
|
stop zygote
|
||||||
if [ -d /debug_ramdisk ]; then
|
if [ -d /debug_ramdisk ]; then
|
||||||
umount -l /debug_ramdisk 2>/dev/null
|
umount -l /debug_ramdisk 2>/dev/null
|
||||||
fi
|
fi
|
||||||
@@ -141,16 +141,17 @@ ln -s ./magisk $MAGISKTMP/resetprop
|
|||||||
ln -s ./magiskpolicy $MAGISKTMP/supolicy
|
ln -s ./magiskpolicy $MAGISKTMP/supolicy
|
||||||
|
|
||||||
mkdir -p $MAGISKTMP/.magisk/device
|
mkdir -p $MAGISKTMP/.magisk/device
|
||||||
|
mkdir -p $MAGISKTMP/.magisk/worker
|
||||||
|
mount -t tmpfs -o 'mode=0755' magisk $MAGISKTMP/.magisk/worker
|
||||||
|
mount --make-private $MAGISKTMP/.magisk/worker
|
||||||
touch $MAGISKTMP/.magisk/config
|
touch $MAGISKTMP/.magisk/config
|
||||||
|
|
||||||
export MAGISKTMP
|
export MAGISKTMP
|
||||||
MAKEDEV=1 $MAGISKTMP/magisk --preinit-device 2>&1
|
MAKEDEV=1 $MAGISKTMP/magisk --preinit-device 2>&1
|
||||||
|
|
||||||
RULESCMD=""
|
RULESCMD=""
|
||||||
for r in $MAGISKTMP/.magisk/preinit/*/sepolicy.rule; do
|
rule="$MAGISKTMP/.magisk/preinit/sepolicy.rule"
|
||||||
[ -f "$r" ] || continue
|
[ -f "$rule" ] && RULESCMD="--apply $rule"
|
||||||
RULESCMD="$RULESCMD --apply $r"
|
|
||||||
done
|
|
||||||
|
|
||||||
# SELinux stuffs
|
# SELinux stuffs
|
||||||
if [ -d /sys/fs/selinux ]; then
|
if [ -d /sys/fs/selinux ]; then
|
||||||
@@ -165,5 +166,8 @@ fi
|
|||||||
|
|
||||||
# Boot up
|
# Boot up
|
||||||
$MAGISKTMP/magisk --post-fs-data
|
$MAGISKTMP/magisk --post-fs-data
|
||||||
start
|
start zygote
|
||||||
$MAGISKTMP/magisk --service
|
$MAGISKTMP/magisk --service
|
||||||
|
# Make sure reset nb prop after zygote starts
|
||||||
|
sleep 2
|
||||||
|
$MAGISKTMP/magisk --boot-complete
|
||||||
|
@@ -8,7 +8,7 @@ lsposed_url='https://github.com/LSPosed/LSPosed/releases/download/v1.9.2/LSPosed
|
|||||||
emu_pid=
|
emu_pid=
|
||||||
|
|
||||||
atd_min_api=30
|
atd_min_api=30
|
||||||
atd_max_api=34
|
atd_max_api=35
|
||||||
lsposed_min_api=27
|
lsposed_min_api=27
|
||||||
lsposed_max_api=34
|
lsposed_max_api=34
|
||||||
huge_ram_min_api=26
|
huge_ram_min_api=26
|
||||||
@@ -25,6 +25,7 @@ cleanup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wait_for_bootanim() {
|
wait_for_bootanim() {
|
||||||
|
set -e
|
||||||
adb wait-for-device
|
adb wait-for-device
|
||||||
while true; do
|
while true; do
|
||||||
local result="$(adb exec-out getprop init.svc.bootanim)"
|
local result="$(adb exec-out getprop init.svc.bootanim)"
|
||||||
@@ -38,6 +39,7 @@ wait_for_bootanim() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wait_for_boot() {
|
wait_for_boot() {
|
||||||
|
set -e
|
||||||
adb wait-for-device
|
adb wait-for-device
|
||||||
while true; do
|
while true; do
|
||||||
local result="$(adb exec-out getprop sys.boot_completed)"
|
local result="$(adb exec-out getprop sys.boot_completed)"
|
||||||
@@ -79,8 +81,15 @@ test_emu() {
|
|||||||
|
|
||||||
test_setup $variant
|
test_setup $variant
|
||||||
|
|
||||||
# Install LSPosed
|
local lsposed
|
||||||
if [ $api -ge $lsposed_min_api -a $api -le $lsposed_max_api ]; then
|
if [ $api -ge $lsposed_min_api -a $api -le $lsposed_max_api ]; then
|
||||||
|
lsposed=true
|
||||||
|
else
|
||||||
|
lsposed=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install LSPosed
|
||||||
|
if $lsposed; then
|
||||||
adb push out/lsposed.zip /data/local/tmp/lsposed.zip
|
adb push out/lsposed.zip /data/local/tmp/lsposed.zip
|
||||||
echo 'PATH=$PATH:/debug_ramdisk magisk --install-module /data/local/tmp/lsposed.zip' | adb shell /system/xbin/su
|
echo 'PATH=$PATH:/debug_ramdisk magisk --install-module /data/local/tmp/lsposed.zip' | adb shell /system/xbin/su
|
||||||
fi
|
fi
|
||||||
@@ -91,7 +100,7 @@ test_emu() {
|
|||||||
test_app
|
test_app
|
||||||
|
|
||||||
# Try to launch LSPosed
|
# Try to launch LSPosed
|
||||||
if [ $api -ge $lsposed_min_api -a $api -le $atd_max_api ]; then
|
if $lsposed; then
|
||||||
adb shell rm -f /data/local/tmp/window_dump.xml
|
adb shell rm -f /data/local/tmp/window_dump.xml
|
||||||
adb shell am start -c org.lsposed.manager.LAUNCH_MANAGER com.android.shell/.BugreportWarningActivity
|
adb shell am start -c org.lsposed.manager.LAUNCH_MANAGER com.android.shell/.BugreportWarningActivity
|
||||||
while adb shell '[ ! -f /data/local/tmp/window_dump.xml ]'; do
|
while adb shell '[ ! -f /data/local/tmp/window_dump.xml ]'; do
|
||||||
@@ -113,6 +122,7 @@ run_test() {
|
|||||||
TiramisuPrivacySandbox) api=33 ;;
|
TiramisuPrivacySandbox) api=33 ;;
|
||||||
UpsideDownCakePrivacySandbox) api=34 ;;
|
UpsideDownCakePrivacySandbox) api=34 ;;
|
||||||
VanillaIceCream) api=35 ;;
|
VanillaIceCream) api=35 ;;
|
||||||
|
Baklava) api=36 ;;
|
||||||
*)
|
*)
|
||||||
print_error "! Unknown system image version '$ver'"
|
print_error "! Unknown system image version '$ver'"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -211,11 +221,11 @@ curl -L $lsposed_url -o out/lsposed.zip
|
|||||||
if [ -n "$1" ]; then
|
if [ -n "$1" ]; then
|
||||||
run_test $1 $2
|
run_test $1 $2
|
||||||
else
|
else
|
||||||
for api in $(seq 23 34); do
|
for api in $(seq 23 35); do
|
||||||
run_test $api
|
run_test $api
|
||||||
done
|
done
|
||||||
# Android 15 Beta
|
# Android 16 Beta
|
||||||
run_test 35 google_apis
|
run_test Baklava google_apis
|
||||||
# Run 16k page tests
|
# Run 16k page tests
|
||||||
run_test 35 google_apis_ps16k
|
run_test 35 google_apis_ps16k
|
||||||
fi
|
fi
|
||||||
|
Reference in New Issue
Block a user