mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-12-11 12:22:20 +00:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
975120d6a6 | ||
|
|
e489b3b6dd | ||
|
|
589a270b8d | ||
|
|
7961be5cfa | ||
|
|
959430e030 | ||
|
|
2923c8ccd1 | ||
|
|
7df4a9d74f | ||
|
|
bf4ed295da | ||
|
|
a5fca960dc | ||
|
|
f99912b9db | ||
|
|
a54bdb54e4 | ||
|
|
cd9851a1fe | ||
|
|
9ca469898c | ||
|
|
0665549473 | ||
|
|
9d7a14b335 | ||
|
|
62e29fee74 | ||
|
|
e472db552b | ||
|
|
466e4bd4e1 | ||
|
|
4cf525c588 | ||
|
|
c8aec2510d | ||
|
|
ccbfe0e66e | ||
|
|
23ea28de6f | ||
|
|
55c3ee3a6f | ||
|
|
2a42ca2b8f | ||
|
|
a897e82fa4 | ||
|
|
ffa15831d3 | ||
|
|
a344ebf28c | ||
|
|
78f7fa348e | ||
|
|
d8c448b99d | ||
|
|
d4b83b6a44 | ||
|
|
e5d36d1d24 | ||
|
|
ff18cb8e70 | ||
|
|
37a9724a54 | ||
|
|
d660401063 | ||
|
|
88541d6f49 | ||
|
|
ecd6129fe5 | ||
|
|
6dfe9df9e2 |
2
.github/actions/setup/action.yml
vendored
2
.github/actions/setup/action.yml
vendored
@@ -45,7 +45,7 @@ runs:
|
|||||||
env:
|
env:
|
||||||
SCCACHE_DIRECT: false
|
SCCACHE_DIRECT: false
|
||||||
SCCACHE_DIR: ${{ github.workspace }}/.sccache
|
SCCACHE_DIR: ${{ github.workspace }}/.sccache
|
||||||
SCCACHE_CACHE_SIZE: 2G
|
SCCACHE_CACHE_SIZE: ${{ inputs.is-asset-build == 'true' && '2G' || '300M' }}
|
||||||
SCCACHE_IDLE_TIMEOUT: 0
|
SCCACHE_IDLE_TIMEOUT: 0
|
||||||
run: |
|
run: |
|
||||||
bash $GITHUB_ACTION_PATH/sccache.sh
|
bash $GITHUB_ACTION_PATH/sccache.sh
|
||||||
|
|||||||
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -82,12 +82,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, 35]
|
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, "36.0-CANARY"]
|
||||||
type: [""]
|
type: [""]
|
||||||
include:
|
include:
|
||||||
- version: 36
|
- version: "36.0-CANARY"
|
||||||
type: "google_apis"
|
|
||||||
- version: 36
|
|
||||||
type: "google_apis_ps16k"
|
type: "google_apis_ps16k"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import androidx.core.widget.ImageViewCompat
|
|||||||
import androidx.databinding.BindingAdapter
|
import androidx.databinding.BindingAdapter
|
||||||
import androidx.databinding.InverseBindingAdapter
|
import androidx.databinding.InverseBindingAdapter
|
||||||
import androidx.databinding.InverseBindingListener
|
import androidx.databinding.InverseBindingListener
|
||||||
|
import androidx.databinding.InverseMethod
|
||||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
|
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
@@ -33,9 +34,11 @@ import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
|||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
|
import com.google.android.material.slider.Slider
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
import com.topjohnwu.magisk.core.di.ServiceLocator
|
||||||
|
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
||||||
import com.topjohnwu.magisk.utils.TextHolder
|
import com.topjohnwu.magisk.utils.TextHolder
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
import com.topjohnwu.widget.IndeterminateCheckBox
|
import com.topjohnwu.widget.IndeterminateCheckBox
|
||||||
@@ -306,3 +309,38 @@ fun TextView.setText(text: TextHolder) {
|
|||||||
fun Spinner.setAdapter(items: Array<Any>, layoutRes: Int) {
|
fun Spinner.setAdapter(items: Array<Any>, layoutRes: Int) {
|
||||||
adapter = ArrayAdapter(context, layoutRes, items)
|
adapter = ArrayAdapter(context, layoutRes, items)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BindingAdapter("labelFormatter")
|
||||||
|
fun Slider.setLabelFormatter(formatter: (Float) -> Int) {
|
||||||
|
setLabelFormatter { value -> resources.getString(formatter(value)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@InverseBindingAdapter(attribute = "android:value")
|
||||||
|
fun Slider.getValueBinding() = value
|
||||||
|
|
||||||
|
@BindingAdapter("android:valueAttrChanged")
|
||||||
|
fun Slider.setListener(attrChange: InverseBindingListener) {
|
||||||
|
addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
|
||||||
|
override fun onStartTrackingTouch(slider: Slider) = Unit
|
||||||
|
override fun onStopTrackingTouch(slider: Slider) = attrChange.onChange()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@InverseMethod("sliderValueToPolicy")
|
||||||
|
fun policyToSliderValue(policy: Int): Float {
|
||||||
|
return when (policy) {
|
||||||
|
SuPolicy.DENY -> 1f
|
||||||
|
SuPolicy.RESTRICT -> 2f
|
||||||
|
SuPolicy.ALLOW -> 3f
|
||||||
|
else -> 1f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sliderValueToPolicy(value: Float): Int {
|
||||||
|
return when (value) {
|
||||||
|
1f -> SuPolicy.DENY
|
||||||
|
2f -> SuPolicy.RESTRICT
|
||||||
|
3f -> SuPolicy.ALLOW
|
||||||
|
else -> SuPolicy.DENY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -322,6 +322,12 @@ object Reauthenticate : BaseSettingsItem.Toggle() {
|
|||||||
override var value by Config::suReAuth
|
override var value by Config::suReAuth
|
||||||
|
|
||||||
override fun refresh() {
|
override fun refresh() {
|
||||||
isEnabled = Build.VERSION.SDK_INT < Build.VERSION_CODES.O && Info.showSuperUser
|
isEnabled = Build.VERSION.SDK_INT < Build.VERSION_CODES.O
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Restrict : BaseSettingsItem.Toggle() {
|
||||||
|
override val title = CoreR.string.settings_su_restrict_title.asText()
|
||||||
|
override val description = CoreR.string.settings_su_restrict_summary.asText()
|
||||||
|
override var value by Config::suRestrict
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ import com.topjohnwu.magisk.core.ktx.activity
|
|||||||
import com.topjohnwu.magisk.core.ktx.toast
|
import com.topjohnwu.magisk.core.ktx.toast
|
||||||
import com.topjohnwu.magisk.core.tasks.AppMigration
|
import com.topjohnwu.magisk.core.tasks.AppMigration
|
||||||
import com.topjohnwu.magisk.core.utils.LocaleSetting
|
import com.topjohnwu.magisk.core.utils.LocaleSetting
|
||||||
|
import com.topjohnwu.magisk.core.utils.RootUtils
|
||||||
import com.topjohnwu.magisk.databinding.bindExtra
|
import com.topjohnwu.magisk.databinding.bindExtra
|
||||||
import com.topjohnwu.magisk.events.AddHomeIconEvent
|
import com.topjohnwu.magisk.events.AddHomeIconEvent
|
||||||
import com.topjohnwu.magisk.events.AuthEvent
|
import com.topjohnwu.magisk.events.AuthEvent
|
||||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||||
import com.topjohnwu.superuser.Shell
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
||||||
@@ -83,6 +83,9 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
|||||||
// Can hide overlay windows on 12.0+
|
// Can hide overlay windows on 12.0+
|
||||||
list.remove(Tapjack)
|
list.remove(Tapjack)
|
||||||
}
|
}
|
||||||
|
if (Const.Version.atLeast_30_1()) {
|
||||||
|
list.add(Restrict)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list
|
return list
|
||||||
@@ -127,7 +130,8 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createHosts() {
|
private fun createHosts() {
|
||||||
Shell.cmd("add_hosts_module").submit {
|
viewModelScope.launch {
|
||||||
|
RootUtils.addSystemlessHosts()
|
||||||
AppContext.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT)
|
AppContext.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ import android.graphics.drawable.Drawable
|
|||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
||||||
import com.topjohnwu.magisk.databinding.DiffItem
|
import com.topjohnwu.magisk.databinding.DiffItem
|
||||||
import com.topjohnwu.magisk.databinding.ItemWrapper
|
import com.topjohnwu.magisk.databinding.ItemWrapper
|
||||||
import com.topjohnwu.magisk.databinding.ObservableRvItem
|
import com.topjohnwu.magisk.databinding.ObservableRvItem
|
||||||
import com.topjohnwu.magisk.databinding.set
|
import com.topjohnwu.magisk.databinding.set
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class PolicyRvItem(
|
class PolicyRvItem(
|
||||||
private val viewModel: SuperuserViewModel,
|
private val viewModel: SuperuserViewModel,
|
||||||
@@ -33,14 +35,34 @@ class PolicyRvItem(
|
|||||||
var isExpanded = false
|
var isExpanded = false
|
||||||
set(value) = set(value, field, { field = it }, BR.expanded)
|
set(value) = set(value, field, { field = it }, BR.expanded)
|
||||||
|
|
||||||
|
val showSlider = Config.suRestrict || item.policy == SuPolicy.RESTRICT
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var isEnabled
|
var isEnabled
|
||||||
get() = item.policy == SuPolicy.ALLOW
|
get() = item.policy >= SuPolicy.ALLOW
|
||||||
set(value) = setImpl(value, isEnabled) {
|
set(value) = setImpl(value, isEnabled) {
|
||||||
notifyPropertyChanged(BR.enabled)
|
notifyPropertyChanged(BR.enabled)
|
||||||
viewModel.togglePolicy(this, value)
|
viewModel.updatePolicy(this, if (it) SuPolicy.ALLOW else SuPolicy.DENY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@get:Bindable
|
||||||
|
var sliderValue
|
||||||
|
get() = item.policy
|
||||||
|
set(value) = setImpl(value, sliderValue) {
|
||||||
|
notifyPropertyChanged(BR.sliderValue)
|
||||||
|
notifyPropertyChanged(BR.enabled)
|
||||||
|
viewModel.updatePolicy(this, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
val sliderValueToPolicyString: (Float) -> Int = { value ->
|
||||||
|
when (value.toInt()) {
|
||||||
|
1 -> CoreR.string.deny
|
||||||
|
2 -> CoreR.string.restrict
|
||||||
|
3 -> CoreR.string.grant
|
||||||
|
else -> CoreR.string.deny
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var shouldNotify
|
var shouldNotify
|
||||||
get() = item.notification
|
get() = item.notification
|
||||||
|
|||||||
@@ -156,15 +156,16 @@ class SuperuserViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun togglePolicy(item: PolicyRvItem, enable: Boolean) {
|
fun updatePolicy(item: PolicyRvItem, policy: Int) {
|
||||||
val items = itemsPolicies.filter { it.item.uid == item.item.uid }
|
val items = itemsPolicies.filter { it.item.uid == item.item.uid }
|
||||||
fun updateState() {
|
fun updateState() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val res = if (enable) R.string.su_snack_grant else R.string.su_snack_deny
|
val res = if (policy >= SuPolicy.ALLOW) R.string.su_snack_grant else R.string.su_snack_deny
|
||||||
item.item.policy = if (enable) SuPolicy.ALLOW else SuPolicy.DENY
|
item.item.policy = policy
|
||||||
db.update(item.item)
|
db.update(item.item)
|
||||||
items.forEach {
|
items.forEach {
|
||||||
it.notifyPropertyChanged(BR.enabled)
|
it.notifyPropertyChanged(BR.enabled)
|
||||||
|
it.notifyPropertyChanged(BR.sliderValue)
|
||||||
}
|
}
|
||||||
SnackbarEvent(res.asText(item.appName)).publish()
|
SnackbarEvent(res.asText(item.appName)).publish()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/log_track_container"
|
android:id="@+id/log_track_container"
|
||||||
bullet="@{item.log.action == 2 ? R.drawable.ic_check_md2 : R.drawable.ic_close_md2}"
|
bullet="@{item.log.action >= 2 ? R.drawable.ic_check_md2 : R.drawable.ic_close_md2}"
|
||||||
isBottom="@{item.isBottom}"
|
isBottom="@{item.isBottom}"
|
||||||
isSelected="@{item.log.action != 2}"
|
isSelected="@{item.log.action != 2}"
|
||||||
isTop="@{item.isTop}"
|
isTop="@{item.isTop}"
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
|
<import type="com.topjohnwu.magisk.databinding.DataBindingAdaptersKt" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="item"
|
name="item"
|
||||||
type="com.topjohnwu.magisk.ui.superuser.PolicyRvItem" />
|
type="com.topjohnwu.magisk.ui.superuser.PolicyRvItem" />
|
||||||
@@ -85,16 +87,32 @@
|
|||||||
app:layout_constraintVertical_bias="0"
|
app:layout_constraintVertical_bias="0"
|
||||||
tools:text="com.topjohnwu.magisk" />
|
tools:text="com.topjohnwu.magisk" />
|
||||||
|
|
||||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
<FrameLayout
|
||||||
android:id="@+id/policy_indicator"
|
android:id="@+id/policy_indicator"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="@dimen/l1"
|
android:layout_marginEnd="@dimen/l1"
|
||||||
android:checked="@={item.enabled}"
|
|
||||||
android:nextFocusLeft="@id/policy"
|
android:nextFocusLeft="@id/policy"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
gone="@{item.showSlider}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="@={item.enabled}" />
|
||||||
|
|
||||||
|
<com.google.android.material.slider.Slider
|
||||||
|
goneUnless="@{item.showSlider}"
|
||||||
|
labelFormatter="@{item.sliderValueToPolicyString}"
|
||||||
|
android:layout_width="96dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:stepSize="1"
|
||||||
|
android:value="@={DataBindingAdaptersKt.policyToSliderValue(item.sliderValue)}"
|
||||||
|
android:valueFrom="1"
|
||||||
|
android:valueTo="3" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,6 @@ gradlePlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
|
||||||
compilerOptions {
|
|
||||||
languageVersion = KotlinVersion.KOTLIN_2_0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("gradle-plugin", libs.versions.kotlin.get()))
|
implementation(kotlin("gradle-plugin", libs.versions.kotlin.get()))
|
||||||
implementation(libs.android.gradle.plugin)
|
implementation(libs.android.gradle.plugin)
|
||||||
|
|||||||
@@ -309,9 +309,9 @@ fun Project.setupStubApk() {
|
|||||||
outputs.dir(outResDir)
|
outputs.dir(outResDir)
|
||||||
doLast {
|
doLast {
|
||||||
val apkTmp = File("${apk}.tmp")
|
val apkTmp = File("${apk}.tmp")
|
||||||
exec {
|
providers.exec {
|
||||||
commandLine(aapt, "optimize", "-o", apkTmp, "--collapse-resource-names", apk)
|
commandLine(aapt, "optimize", "-o", apkTmp, "--collapse-resource-names", apk)
|
||||||
}
|
}.result.get()
|
||||||
|
|
||||||
val bos = ByteArrayOutputStream()
|
val bos = ByteArrayOutputStream()
|
||||||
ZipFile(apkTmp).use { src ->
|
ZipFile(apkTmp).use { src ->
|
||||||
|
|||||||
@@ -27,10 +27,15 @@ android {
|
|||||||
aidl = true
|
aidl = true
|
||||||
buildConfig = true
|
buildConfig = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
isCoreLibraryDesugaringEnabled = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":shared"))
|
api(project(":shared"))
|
||||||
|
coreLibraryDesugaring(libs.jdk.libs)
|
||||||
|
|
||||||
api(libs.timber)
|
api(libs.timber)
|
||||||
api(libs.markwon.core)
|
api(libs.markwon.core)
|
||||||
|
|||||||
1
app/core/proguard-rules.pro
vendored
1
app/core/proguard-rules.pro
vendored
@@ -38,3 +38,4 @@
|
|||||||
-allowaccessmodification
|
-allowaccessmodification
|
||||||
|
|
||||||
-dontwarn org.junit.**
|
-dontwarn org.junit.**
|
||||||
|
-dontwarn org.apache.**
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ package com.topjohnwu.magisk.core.utils;
|
|||||||
interface IRootUtils {
|
interface IRootUtils {
|
||||||
android.app.ActivityManager.RunningAppProcessInfo getAppProcess(int pid);
|
android.app.ActivityManager.RunningAppProcessInfo getAppProcess(int pid);
|
||||||
IBinder getFileSystem();
|
IBinder getFileSystem();
|
||||||
|
boolean addSystemlessHosts();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ object Config : PreferenceConfig, DBConfig {
|
|||||||
const val SU_NOTIFICATION = "su_notification"
|
const val SU_NOTIFICATION = "su_notification"
|
||||||
const val SU_REAUTH = "su_reauth"
|
const val SU_REAUTH = "su_reauth"
|
||||||
const val SU_TAPJACK = "su_tapjack"
|
const val SU_TAPJACK = "su_tapjack"
|
||||||
|
const val SU_RESTRICT = "su_restrict"
|
||||||
const val CHECK_UPDATES = "check_update"
|
const val CHECK_UPDATES = "check_update"
|
||||||
const val RELEASE_CHANNEL = "release_channel"
|
const val RELEASE_CHANNEL = "release_channel"
|
||||||
const val CUSTOM_CHANNEL = "custom_channel"
|
const val CUSTOM_CHANNEL = "custom_channel"
|
||||||
@@ -147,6 +148,7 @@ object Config : PreferenceConfig, DBConfig {
|
|||||||
}
|
}
|
||||||
var suReAuth by preference(Key.SU_REAUTH, false)
|
var suReAuth by preference(Key.SU_REAUTH, false)
|
||||||
var suTapjack by preference(Key.SU_TAPJACK, true)
|
var suTapjack by preference(Key.SU_TAPJACK, true)
|
||||||
|
var suRestrict by preference(Key.SU_RESTRICT, false)
|
||||||
|
|
||||||
private const val SU_FINGERPRINT = "su_fingerprint"
|
private const val SU_FINGERPRINT = "su_fingerprint"
|
||||||
private const val UPDATE_CHANNEL = "update_channel"
|
private const val UPDATE_CHANNEL = "update_channel"
|
||||||
|
|||||||
@@ -26,9 +26,11 @@ object Const {
|
|||||||
const val MIN_VERSION = "v22.0"
|
const val MIN_VERSION = "v22.0"
|
||||||
const val MIN_VERCODE = 22000
|
const val MIN_VERCODE = 22000
|
||||||
|
|
||||||
fun atLeast_24_0() = Info.env.versionCode >= 24000
|
private fun isCanary() = (Info.env.versionCode % 100) != 0
|
||||||
fun atLeast_25_0() = Info.env.versionCode >= 25000
|
fun atLeast_24_0() = Info.env.versionCode >= 24000 || isCanary()
|
||||||
fun atLeast_28_0() = Info.env.versionCode >= 28000
|
fun atLeast_25_0() = Info.env.versionCode >= 25000 || isCanary()
|
||||||
|
fun atLeast_28_0() = Info.env.versionCode >= 28000 || isCanary()
|
||||||
|
fun atLeast_30_1() = Info.env.versionCode >= 30100 || isCanary()
|
||||||
}
|
}
|
||||||
|
|
||||||
object ID {
|
object ID {
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ fun PackageManager.getPackageInfo(uid: Int, pid: Int): PackageInfo? {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
// Try to find package name from PID
|
// Try to find package name from PID
|
||||||
val proc = RootUtils.obj?.getAppProcess(pid)
|
val proc = RootUtils.getAppProcess(pid)
|
||||||
if (proc == null) {
|
if (proc == null) {
|
||||||
if (uid == Process.SHELL_UID) {
|
if (uid == Process.SHELL_UID) {
|
||||||
// It is possible that some apps installed are sharing UID with shell.
|
// It is possible that some apps installed are sharing UID with shell.
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ import java.io.IOException
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
import java.text.DateFormat
|
import java.time.Instant
|
||||||
import java.text.SimpleDateFormat
|
import java.time.ZoneId
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.format.FormatStyle
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
inline fun <In : Closeable, Out : Closeable> withInOut(
|
inline fun <In : Closeable, Out : Closeable> withInOut(
|
||||||
input: In,
|
input: In,
|
||||||
@@ -83,19 +84,15 @@ inline fun <T, R> Flow<T>.concurrentMap(crossinline transform: suspend (T) -> R)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Long.toTime(format: DateFormat) = format.format(this).orEmpty()
|
fun Long.toTime(format: DateTimeFormatter): String = format.format(Instant.ofEpochMilli(this))
|
||||||
|
|
||||||
// Some devices don't allow filenames containing ":"
|
// Some devices don't allow filenames containing ":"
|
||||||
val timeFormatStandard by lazy {
|
val timeFormatStandard: DateTimeFormatter by lazy {
|
||||||
SimpleDateFormat(
|
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH.mm.ss").withZone(ZoneId.systemDefault())
|
||||||
"yyyy-MM-dd'T'HH.mm.ss",
|
|
||||||
Locale.ROOT
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
val timeDateFormat: DateFormat by lazy {
|
val timeDateFormat: DateTimeFormatter by lazy {
|
||||||
DateFormat.getDateTimeInstance(
|
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withZone(ZoneId.systemDefault())
|
||||||
DateFormat.DEFAULT,
|
}
|
||||||
DateFormat.DEFAULT,
|
val dateFormat: DateTimeFormatter by lazy {
|
||||||
Locale.ROOT
|
DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withZone(ZoneId.systemDefault())
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import com.squareup.moshi.JsonClass
|
|||||||
import com.squareup.moshi.JsonQualifier
|
import com.squareup.moshi.JsonQualifier
|
||||||
import com.squareup.moshi.ToJson
|
import com.squareup.moshi.ToJson
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
import java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME
|
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
class UpdateJson(
|
class UpdateJson(
|
||||||
@@ -40,13 +39,13 @@ data class ReleaseAssets(
|
|||||||
|
|
||||||
class DateTimeAdapter {
|
class DateTimeAdapter {
|
||||||
@ToJson
|
@ToJson
|
||||||
fun toJson(date: LocalDateTime): String {
|
fun toJson(date: Instant): String {
|
||||||
return date.toString()
|
return date.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@FromJson
|
@FromJson
|
||||||
fun fromJson(date: String): LocalDateTime {
|
fun fromJson(date: String): Instant {
|
||||||
return LocalDateTime.parse(date, ISO_OFFSET_DATE_TIME)
|
return Instant.parse(date)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +56,7 @@ data class Release(
|
|||||||
val prerelease: Boolean,
|
val prerelease: Boolean,
|
||||||
val assets: List<ReleaseAssets>,
|
val assets: List<ReleaseAssets>,
|
||||||
val body: String,
|
val body: String,
|
||||||
@Json(name = "created_at") val createdTime: LocalDateTime,
|
@Json(name = "created_at") val createdTime: Instant,
|
||||||
) {
|
) {
|
||||||
val versionCode: Int get() {
|
val versionCode: Int get() {
|
||||||
return if (tag[0] == 'v') {
|
return if (tag[0] == 'v') {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import java.io.IOException
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
data class LocalModule(
|
data class LocalModule(
|
||||||
private val base: ExtendedFile,
|
val base: ExtendedFile,
|
||||||
) : Module() {
|
) : Module() {
|
||||||
private val svc get() = ServiceLocator.networkService
|
private val svc get() = ServiceLocator.networkService
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,16 @@ import com.topjohnwu.magisk.core.data.magiskdb.MagiskDB
|
|||||||
|
|
||||||
class SuPolicy(
|
class SuPolicy(
|
||||||
val uid: Int,
|
val uid: Int,
|
||||||
var policy: Int = INTERACTIVE,
|
var policy: Int = QUERY,
|
||||||
var remain: Long = -1L,
|
var remain: Long = -1L,
|
||||||
var logging: Boolean = true,
|
var logging: Boolean = true,
|
||||||
var notification: Boolean = true,
|
var notification: Boolean = true,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val INTERACTIVE = 0
|
const val QUERY = 0
|
||||||
const val DENY = 1
|
const val DENY = 1
|
||||||
const val ALLOW = 2
|
const val ALLOW = 2
|
||||||
|
const val RESTRICT = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toMap(): MutableMap<String, Any> {
|
fun toMap(): MutableMap<String, Any> {
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import com.topjohnwu.magisk.core.Config.Value.STABLE_CHANNEL
|
|||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.data.GithubApiServices
|
import com.topjohnwu.magisk.core.data.GithubApiServices
|
||||||
import com.topjohnwu.magisk.core.data.RawUrl
|
import com.topjohnwu.magisk.core.data.RawUrl
|
||||||
|
import com.topjohnwu.magisk.core.ktx.dateFormat
|
||||||
import com.topjohnwu.magisk.core.model.Release
|
import com.topjohnwu.magisk.core.model.Release
|
||||||
import com.topjohnwu.magisk.core.model.ReleaseAssets
|
import com.topjohnwu.magisk.core.model.ReleaseAssets
|
||||||
import com.topjohnwu.magisk.core.model.UpdateInfo
|
import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.time.format.DateTimeFormatter
|
|
||||||
|
|
||||||
class NetworkService(
|
class NetworkService(
|
||||||
private val raw: RawUrl,
|
private val raw: RawUrl,
|
||||||
@@ -74,7 +74,7 @@ class NetworkService(
|
|||||||
|
|
||||||
private inline fun Release.asPublicInfo(selector: (ReleaseAssets) -> Boolean): UpdateInfo {
|
private inline fun Release.asPublicInfo(selector: (ReleaseAssets) -> Boolean): UpdateInfo {
|
||||||
val version = tag.drop(1)
|
val version = tag.drop(1)
|
||||||
val date = createdTime.format(DateTimeFormatter.ofPattern("yyyy.M.d"))
|
val date = dateFormat.format(createdTime)
|
||||||
return UpdateInfo(
|
return UpdateInfo(
|
||||||
version = version,
|
version = version,
|
||||||
versionCode = versionCode,
|
versionCode = versionCode,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ object SuCallbackHandler {
|
|||||||
}.getOrNull() ?: createSuLog(fromUid, toUid, pid, command, policy, target, seContext, gids)
|
}.getOrNull() ?: createSuLog(fromUid, toUid, pid, command, policy, target, seContext, gids)
|
||||||
|
|
||||||
if (notify)
|
if (notify)
|
||||||
notify(context, log.action == SuPolicy.ALLOW, log.appName)
|
notify(context, log.action >= SuPolicy.ALLOW, log.appName)
|
||||||
|
|
||||||
runBlocking { ServiceLocator.logRepo.insert(log) }
|
runBlocking { ServiceLocator.logRepo.insert(log) }
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ object SuCallbackHandler {
|
|||||||
pm.getPackageInfo(uid, pid)?.applicationInfo?.getLabel(pm)
|
pm.getPackageInfo(uid, pid)?.applicationInfo?.getLabel(pm)
|
||||||
}.getOrNull() ?: "[UID] $uid"
|
}.getOrNull() ?: "[UID] $uid"
|
||||||
|
|
||||||
notify(context, policy == SuPolicy.ALLOW, appName)
|
notify(context, policy >= SuPolicy.ALLOW, appName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun notify(context: Context, granted: Boolean, appName: String) {
|
private fun notify(context: Context, granted: Boolean, appName: String) {
|
||||||
|
|||||||
@@ -82,7 +82,11 @@ class SuRequestHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun respond(action: Int, time: Long) {
|
suspend fun respond(action: Int, time: Long) {
|
||||||
policy.policy = action
|
if (action == SuPolicy.ALLOW && Config.suRestrict) {
|
||||||
|
policy.policy = SuPolicy.RESTRICT
|
||||||
|
} else {
|
||||||
|
policy.policy = action
|
||||||
|
}
|
||||||
if (time >= 0) {
|
if (time >= 0) {
|
||||||
policy.remain = TimeUnit.MINUTES.toSeconds(time)
|
policy.remain = TimeUnit.MINUTES.toSeconds(time)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -7,11 +7,14 @@ import android.content.ServiceConnection
|
|||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.system.Os
|
import android.system.Os
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
import com.topjohnwu.superuser.ipc.RootService
|
import com.topjohnwu.superuser.ipc.RootService
|
||||||
import com.topjohnwu.superuser.nio.FileSystemManager
|
import com.topjohnwu.superuser.nio.FileSystemManager
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.locks.AbstractQueuedSynchronizer
|
import java.util.concurrent.locks.AbstractQueuedSynchronizer
|
||||||
@@ -43,16 +46,7 @@ class RootUtils(stub: Any?) : RootService() {
|
|||||||
return object : IRootUtils.Stub() {
|
return object : IRootUtils.Stub() {
|
||||||
override fun getAppProcess(pid: Int) = safe(null) { getAppProcessImpl(pid) }
|
override fun getAppProcess(pid: Int) = safe(null) { getAppProcessImpl(pid) }
|
||||||
override fun getFileSystem(): IBinder = FileSystemManager.getService()
|
override fun getFileSystem(): IBinder = FileSystemManager.getService()
|
||||||
}
|
override fun addSystemlessHosts() = safe(false) { addSystemlessHostsImpl() }
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun <T> safe(default: T, block: () -> T): T {
|
|
||||||
return try {
|
|
||||||
block()
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
// The process died unexpectedly
|
|
||||||
Timber.e(e)
|
|
||||||
default
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +72,26 @@ class RootUtils(stub: Any?) : RootService() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addSystemlessHostsImpl(): Boolean {
|
||||||
|
val module = File(Const.MODULE_PATH, "hosts")
|
||||||
|
if (module.exists()) return true
|
||||||
|
val hosts = File(module, "system/etc/hosts")
|
||||||
|
if (!hosts.parentFile.mkdirs()) return false
|
||||||
|
File(module, "module.prop").outputStream().writer().use {
|
||||||
|
it.write("""
|
||||||
|
id=hosts
|
||||||
|
name=Systemless Hosts
|
||||||
|
version=1.0
|
||||||
|
versionCode=1
|
||||||
|
author=Magisk
|
||||||
|
description=Magisk app built-in systemless hosts module
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
|
File("/system/etc/hosts").copyTo(hosts)
|
||||||
|
File(module, "update").createNewFile()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
object Connection : AbstractQueuedSynchronizer(), ServiceConnection {
|
object Connection : AbstractQueuedSynchronizer(), ServiceConnection {
|
||||||
init {
|
init {
|
||||||
state = 1
|
state = 1
|
||||||
@@ -131,11 +145,25 @@ class RootUtils(stub: Any?) : RootService() {
|
|||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
private set
|
private set
|
||||||
var obj: IRootUtils? = null
|
private var obj: IRootUtils? = null
|
||||||
get() {
|
get() {
|
||||||
Connection.await()
|
Connection.await()
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
private set
|
|
||||||
|
fun getAppProcess(pid: Int) = safe(null) { obj?.getAppProcess(pid) }
|
||||||
|
|
||||||
|
suspend fun addSystemlessHosts() =
|
||||||
|
withContext(Dispatchers.IO) { safe(false) { obj?.addSystemlessHosts() ?: false } }
|
||||||
|
|
||||||
|
private inline fun <T> safe(default: T, block: () -> T): T {
|
||||||
|
return try {
|
||||||
|
block()
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
// The process died unexpectedly
|
||||||
|
Timber.e(e)
|
||||||
|
default
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ import com.topjohnwu.magisk.test.Environment.Companion.INVALID_ZYGISK
|
|||||||
import com.topjohnwu.magisk.test.Environment.Companion.MOUNT_TEST
|
import com.topjohnwu.magisk.test.Environment.Companion.MOUNT_TEST
|
||||||
import com.topjohnwu.magisk.test.Environment.Companion.REMOVE_TEST
|
import com.topjohnwu.magisk.test.Environment.Companion.REMOVE_TEST
|
||||||
import com.topjohnwu.magisk.test.Environment.Companion.SEPOLICY_RULE
|
import com.topjohnwu.magisk.test.Environment.Companion.SEPOLICY_RULE
|
||||||
|
import com.topjohnwu.magisk.test.Environment.Companion.UPGRADE_TEST
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
|
import org.junit.Assert.assertArrayEquals
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertFalse
|
import org.junit.Assert.assertFalse
|
||||||
import org.junit.Assert.assertNotNull
|
import org.junit.Assert.assertNotNull
|
||||||
@@ -55,7 +57,7 @@ class AdditionalTest : BaseTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testModuleCount() {
|
fun testModuleCount() {
|
||||||
var expected = 2
|
var expected = 4
|
||||||
if (Environment.mount()) expected++
|
if (Environment.mount()) expected++
|
||||||
if (Environment.preinit()) expected++
|
if (Environment.preinit()) expected++
|
||||||
if (Environment.lsposed()) expected++
|
if (Environment.lsposed()) expected++
|
||||||
@@ -90,17 +92,18 @@ class AdditionalTest : BaseTest {
|
|||||||
|
|
||||||
assertNotNull("$MOUNT_TEST is not installed", modules.find { it.id == MOUNT_TEST })
|
assertNotNull("$MOUNT_TEST is not installed", modules.find { it.id == MOUNT_TEST })
|
||||||
assertTrue(
|
assertTrue(
|
||||||
"/system/etc/newfile should exist",
|
"/system/fonts/newfile should exist",
|
||||||
RootUtils.fs.getFile("/system/etc/newfile").exists()
|
RootUtils.fs.getFile("/system/fonts/newfile").exists()
|
||||||
)
|
)
|
||||||
assertFalse(
|
assertFalse(
|
||||||
"/system/bin/screenrecord should not exist",
|
"/system/bin/screenrecord should not exist",
|
||||||
RootUtils.fs.getFile("/system/bin/screenrecord").exists()
|
RootUtils.fs.getFile("/system/bin/screenrecord").exists()
|
||||||
)
|
)
|
||||||
val egg = RootUtils.fs.getFile("/system/app/EasterEgg").list() ?: arrayOf()
|
val egg = RootUtils.fs.getFile("/system/app/EasterEgg").list() ?: arrayOf()
|
||||||
assertTrue(
|
assertArrayEquals(
|
||||||
"/system/app/EasterEgg should be empty",
|
"/system/app/EasterEgg should be replaced",
|
||||||
egg.isEmpty()
|
egg,
|
||||||
|
arrayOf("newfile")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,5 +137,25 @@ class AdditionalTest : BaseTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testRemoveModule() {
|
fun testRemoveModule() {
|
||||||
assertNull("$REMOVE_TEST should be removed", modules.find { it.id == REMOVE_TEST })
|
assertNull("$REMOVE_TEST should be removed", modules.find { it.id == REMOVE_TEST })
|
||||||
|
assertTrue(
|
||||||
|
"Uninstaller of $REMOVE_TEST should be run",
|
||||||
|
RootUtils.fs.getFile(Environment.REMOVE_TEST_MARKER).exists()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testModuleUpgrade() {
|
||||||
|
val module = modules.find { it.id == UPGRADE_TEST }
|
||||||
|
assertNotNull("$UPGRADE_TEST is not installed", module)
|
||||||
|
module!!
|
||||||
|
assertFalse("$UPGRADE_TEST should be disabled", module.enable)
|
||||||
|
assertTrue(
|
||||||
|
"$UPGRADE_TEST should be updated",
|
||||||
|
module.base.getChildFile("post-fs-data.sh").exists()
|
||||||
|
)
|
||||||
|
assertFalse(
|
||||||
|
"$UPGRADE_TEST should be updated",
|
||||||
|
module.base.getChildFile("service.sh").exists()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,12 +58,15 @@ class Environment : BaseTest {
|
|||||||
return Build.VERSION.SDK_INT >= 27
|
return Build.VERSION.SDK_INT >= 27
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const val MODULE_UPDATE_PATH = "/data/adb/modules_update"
|
||||||
private const val MODULE_ERROR = "Module zip processing incorrect"
|
private const val MODULE_ERROR = "Module zip processing incorrect"
|
||||||
const val MOUNT_TEST = "mount_test"
|
const val MOUNT_TEST = "mount_test"
|
||||||
const val SEPOLICY_RULE = "sepolicy_rule"
|
const val SEPOLICY_RULE = "sepolicy_rule"
|
||||||
const val INVALID_ZYGISK = "invalid_zygisk"
|
const val INVALID_ZYGISK = "invalid_zygisk"
|
||||||
const val REMOVE_TEST = "remove_test"
|
const val REMOVE_TEST = "remove_test"
|
||||||
|
const val REMOVE_TEST_MARKER = "/dev/.remove_test_removed"
|
||||||
const val EMPTY_ZYGISK = "empty_zygisk"
|
const val EMPTY_ZYGISK = "empty_zygisk"
|
||||||
|
const val UPGRADE_TEST = "upgrade_test"
|
||||||
}
|
}
|
||||||
|
|
||||||
object TimberLog : CallbackList<String>(Runnable::run) {
|
object TimberLog : CallbackList<String>(Runnable::run) {
|
||||||
@@ -98,8 +101,8 @@ class Environment : BaseTest {
|
|||||||
val error = "$MOUNT_TEST setup failed"
|
val error = "$MOUNT_TEST setup failed"
|
||||||
val path = root.getChildFile(MOUNT_TEST)
|
val path = root.getChildFile(MOUNT_TEST)
|
||||||
|
|
||||||
// Create /system/etc/newfile
|
// Create /system/fonts/newfile
|
||||||
val etc = path.getChildFile("system").getChildFile("etc")
|
val etc = path.getChildFile("system").getChildFile("fonts")
|
||||||
assertTrue(error, etc.mkdirs())
|
assertTrue(error, etc.mkdirs())
|
||||||
assertTrue(error, etc.getChildFile("newfile").createNewFile())
|
assertTrue(error, etc.getChildFile("newfile").createNewFile())
|
||||||
|
|
||||||
@@ -108,6 +111,9 @@ class Environment : BaseTest {
|
|||||||
assertTrue(error, egg.mkdirs())
|
assertTrue(error, egg.mkdirs())
|
||||||
assertTrue(error, egg.getChildFile(".replace").createNewFile())
|
assertTrue(error, egg.getChildFile(".replace").createNewFile())
|
||||||
|
|
||||||
|
// Create /system/app/EasterEgg/newfile
|
||||||
|
assertTrue(error, egg.getChildFile("newfile").createNewFile())
|
||||||
|
|
||||||
// Delete /system/bin/screenrecord
|
// Delete /system/bin/screenrecord
|
||||||
val bin = path.getChildFile("system").getChildFile("bin")
|
val bin = path.getChildFile("system").getChildFile("bin")
|
||||||
assertTrue(error, bin.mkdirs())
|
assertTrue(error, bin.mkdirs())
|
||||||
@@ -116,6 +122,12 @@ class Environment : BaseTest {
|
|||||||
assertTrue(error, Shell.cmd("set_default_perm $path").exec().isSuccess)
|
assertTrue(error, Shell.cmd("set_default_perm $path").exec().isSuccess)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupSystemlessHost() {
|
||||||
|
val error = "hosts setup failed"
|
||||||
|
assertTrue(error, runBlocking { RootUtils.addSystemlessHosts() })
|
||||||
|
assertTrue(error, RootUtils.fs.getFile(Const.MODULE_PATH).getChildFile("hosts").exists())
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupSepolicyRuleModule(root: ExtendedFile) {
|
private fun setupSepolicyRuleModule(root: ExtendedFile) {
|
||||||
val error = "$SEPOLICY_RULE setup failed"
|
val error = "$SEPOLICY_RULE setup failed"
|
||||||
val path = root.getChildFile(SEPOLICY_RULE)
|
val path = root.getChildFile(SEPOLICY_RULE)
|
||||||
@@ -163,12 +175,39 @@ class Environment : BaseTest {
|
|||||||
// Create a new module but mark is as "remove"
|
// Create a new module but mark is as "remove"
|
||||||
val module = LocalModule(path)
|
val module = LocalModule(path)
|
||||||
assertTrue(error, path.mkdirs())
|
assertTrue(error, path.mkdirs())
|
||||||
|
// Create uninstaller script
|
||||||
|
path.getChildFile("uninstall.sh").newOutputStream().writer().use {
|
||||||
|
it.write("touch $REMOVE_TEST_MARKER")
|
||||||
|
}
|
||||||
assertTrue(error, path.getChildFile("service.sh").createNewFile())
|
assertTrue(error, path.getChildFile("service.sh").createNewFile())
|
||||||
module.remove = true
|
module.remove = true
|
||||||
|
|
||||||
assertTrue(error, Shell.cmd("set_default_perm $path").exec().isSuccess)
|
assertTrue(error, Shell.cmd("set_default_perm $path").exec().isSuccess)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupUpgradeModule(root: ExtendedFile, update: ExtendedFile) {
|
||||||
|
val error = "$UPGRADE_TEST setup failed"
|
||||||
|
val oldPath = root.getChildFile(UPGRADE_TEST)
|
||||||
|
val newPath = update.getChildFile(UPGRADE_TEST)
|
||||||
|
|
||||||
|
// Create an existing module but mark as "disable
|
||||||
|
val module = LocalModule(oldPath)
|
||||||
|
assertTrue(error, oldPath.mkdirs())
|
||||||
|
module.enable = false
|
||||||
|
// Install service.sh into the old module
|
||||||
|
assertTrue(error, oldPath.getChildFile("service.sh").createNewFile())
|
||||||
|
|
||||||
|
// Create an upgrade module
|
||||||
|
assertTrue(error, newPath.mkdirs())
|
||||||
|
// Install post-fs-data.sh into the new module
|
||||||
|
assertTrue(error, newPath.getChildFile("post-fs-data.sh").createNewFile())
|
||||||
|
|
||||||
|
assertTrue(error, Shell.cmd(
|
||||||
|
"set_default_perm $oldPath",
|
||||||
|
"set_default_perm $newPath",
|
||||||
|
).exec().isSuccess)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun setupEnvironment() {
|
fun setupEnvironment() {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
@@ -213,11 +252,14 @@ class Environment : BaseTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val root = RootUtils.fs.getFile(Const.MODULE_PATH)
|
val root = RootUtils.fs.getFile(Const.MODULE_PATH)
|
||||||
if (mount()) { setupMountTest(root) }
|
val update = RootUtils.fs.getFile(MODULE_UPDATE_PATH)
|
||||||
if (preinit()) { setupSepolicyRuleModule(root) }
|
if (mount()) { setupMountTest(update) }
|
||||||
setupEmptyZygiskModule(root)
|
if (preinit()) { setupSepolicyRuleModule(update) }
|
||||||
setupInvalidZygiskModule(root)
|
setupSystemlessHost()
|
||||||
|
setupEmptyZygiskModule(update)
|
||||||
|
setupInvalidZygiskModule(update)
|
||||||
setupRemoveModule(root)
|
setupRemoveModule(root)
|
||||||
|
setupUpgradeModule(root, update)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
<string name="touch_filtered_warning">Como um app está ocultando uma solicitação de SuperUsuário, o Magisk não pode verificar sua resposta.</string>
|
<string name="touch_filtered_warning">Como um app está ocultando uma solicitação de SuperUsuário, o Magisk não pode verificar sua resposta.</string>
|
||||||
<string name="deny">Negar</string>
|
<string name="deny">Negar</string>
|
||||||
<string name="prompt">Perguntar</string>
|
<string name="prompt">Perguntar</string>
|
||||||
|
<string name="restrict">Restringir</string>
|
||||||
<string name="grant">Permitir</string>
|
<string name="grant">Permitir</string>
|
||||||
<string name="su_warning">Permite acesso total ao seu dispositivo.\nNão permita se você não tiver certeza do que está fazendo!</string>
|
<string name="su_warning">Permite acesso total ao seu dispositivo.\nNão permita se você não tiver certeza do que está fazendo!</string>
|
||||||
<string name="forever">Sempre</string>
|
<string name="forever">Sempre</string>
|
||||||
@@ -170,6 +171,8 @@
|
|||||||
<string name="settings_su_auth_title">Autenticação de usuário</string>
|
<string name="settings_su_auth_title">Autenticação de usuário</string>
|
||||||
<string name="settings_su_auth_summary">Solicite autenticação de usuário durante solicitações de SuperUsuário</string>
|
<string name="settings_su_auth_summary">Solicite autenticação de usuário durante solicitações de SuperUsuário</string>
|
||||||
<string name="settings_su_auth_insecure">Nenhum método de autenticação está configurado no dispositivo</string>
|
<string name="settings_su_auth_insecure">Nenhum método de autenticação está configurado no dispositivo</string>
|
||||||
|
<string name="settings_su_restrict_title">Restringir recursos root</string>
|
||||||
|
<string name="settings_su_restrict_summary">Restringirá novos apps de SuperUsuário por padrão. Aviso: isso quebrará a maioria dos apps. Não ative se você não souber o que está fazendo.</string>
|
||||||
<string name="settings_customization">Personalizações</string>
|
<string name="settings_customization">Personalizações</string>
|
||||||
<string name="setting_add_shortcut_summary">Adicione um atalho na tela inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o app.</string>
|
<string name="setting_add_shortcut_summary">Adicione um atalho na tela inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o app.</string>
|
||||||
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
<string name="touch_filtered_warning">Como um app está a ocultar um pedido de SuperUsuário, o Magisk não consegue verificar a sua resposta.</string>
|
<string name="touch_filtered_warning">Como um app está a ocultar um pedido de SuperUsuário, o Magisk não consegue verificar a sua resposta.</string>
|
||||||
<string name="deny">Negar</string>
|
<string name="deny">Negar</string>
|
||||||
<string name="prompt">Perguntar</string>
|
<string name="prompt">Perguntar</string>
|
||||||
|
<string name="restrict">Restringir</string>
|
||||||
<string name="grant">Permitir</string>
|
<string name="grant">Permitir</string>
|
||||||
<string name="su_warning">Permite o acesso total ao seu dispositivo.\nNão o permita se não tiver a certeza do que está a fazer!</string>
|
<string name="su_warning">Permite o acesso total ao seu dispositivo.\nNão o permita se não tiver a certeza do que está a fazer!</string>
|
||||||
<string name="forever">Sempre</string>
|
<string name="forever">Sempre</string>
|
||||||
@@ -129,7 +130,7 @@
|
|||||||
<string name="settings_restore_app_title">Restaurar app do Magisk</string>
|
<string name="settings_restore_app_title">Restaurar app do Magisk</string>
|
||||||
<string name="settings_restore_app_summary">Desoculta o app do Magisk e restaura o APK original</string>
|
<string name="settings_restore_app_summary">Desoculta o app do Magisk e restaura o APK original</string>
|
||||||
<string name="language">Idioma</string>
|
<string name="language">Idioma</string>
|
||||||
<string name="system_default">(Padrão do sistema)</string>
|
<string name="system_default">(Predefinição do sistema)</string>
|
||||||
<string name="settings_check_update_title">Verificar por atualizações</string>
|
<string name="settings_check_update_title">Verificar por atualizações</string>
|
||||||
<string name="settings_check_update_summary">Verifique automaticamente se há atualizações ao abrir o app</string>
|
<string name="settings_check_update_summary">Verifique automaticamente se há atualizações ao abrir o app</string>
|
||||||
<string name="settings_update_channel_title">Canal de atualização</string>
|
<string name="settings_update_channel_title">Canal de atualização</string>
|
||||||
@@ -170,6 +171,8 @@
|
|||||||
<string name="settings_su_auth_title">Autenticação de usuário</string>
|
<string name="settings_su_auth_title">Autenticação de usuário</string>
|
||||||
<string name="settings_su_auth_summary">Solicite autenticação de usuário durante pedidos de SuperUsuário</string>
|
<string name="settings_su_auth_summary">Solicite autenticação de usuário durante pedidos de SuperUsuário</string>
|
||||||
<string name="settings_su_auth_insecure">Nenhum método de autenticação está configurado no dispositivo</string>
|
<string name="settings_su_auth_insecure">Nenhum método de autenticação está configurado no dispositivo</string>
|
||||||
|
<string name="settings_su_restrict_title">Restringir recursos root</string>
|
||||||
|
<string name="settings_su_restrict_summary">Restringirá novos apps de SuperUsuário por predefinição. Aviso: isto quebrará a maioria dos apps. Não ative se você não souber o que está a fazer.</string>
|
||||||
<string name="settings_customization">Personalizações</string>
|
<string name="settings_customization">Personalizações</string>
|
||||||
<string name="setting_add_shortcut_summary">Adicione um atalho no ecrã inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o app.</string>
|
<string name="setting_add_shortcut_summary">Adicione um atalho no ecrã inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o app.</string>
|
||||||
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
||||||
|
|||||||
@@ -5,116 +5,114 @@
|
|||||||
<string name="superuser">Süper Kullanıcı</string>
|
<string name="superuser">Süper Kullanıcı</string>
|
||||||
<string name="logs">Günlükler</string>
|
<string name="logs">Günlükler</string>
|
||||||
<string name="settings">Ayarlar</string>
|
<string name="settings">Ayarlar</string>
|
||||||
<string name="install">Yükle</string>
|
<string name="install">Kur</string>
|
||||||
<string name="section_home">Ana Sayfa</string>
|
<string name="section_home">Ana Sayfa</string>
|
||||||
<string name="section_theme">Temalar</string>
|
<string name="section_theme">Temalar</string>
|
||||||
<string name="denylist">Reddetme Listesi</string>
|
<string name="denylist">Red Listesi</string>
|
||||||
|
|
||||||
<!--Home-->
|
<!--Home-->
|
||||||
<string name="no_connection">Bağlantı yok</string>
|
<string name="no_connection">Bağlantı Yok</string>
|
||||||
<string name="app_changelog">Değişiklik Günlüğü</string>
|
<string name="app_changelog">Değişiklik Günlüğü</string>
|
||||||
<string name="loading">Yükleniyor…</string>
|
<string name="loading">Yükleniyor…</string>
|
||||||
<string name="update">Güncelle</string>
|
<string name="update">Güncelle</string>
|
||||||
<string name="not_available">Yok</string>
|
<string name="not_available">Mevcut Değil</string>
|
||||||
<string name="hide">Gizle</string>
|
<string name="hide">Gizle</string>
|
||||||
<string name="home_package">Paket</string>
|
<string name="home_package">Paket</string>
|
||||||
<string name="home_app_title">Uygulama</string>
|
<string name="home_app_title">Uygulama</string>
|
||||||
|
<string name="home_notice_content">Magisk\'i YALNIZCA resmi GitHub sayfasından indirin. Bilinmeyen kaynaklardan gelen dosyalar kötü amaçlı olabilir!</string>
|
||||||
<string name="home_notice_content">Magisk\'i YALNIZCA resmi GitHub sayfasından indirin. Bilinmeyen kaynaklardan gelen dosyalar zararlı olabilir!</string>
|
<string name="home_support_title">Bize Destek Olun</string>
|
||||||
<string name="home_support_title">Bizi Destekleyin</string>
|
|
||||||
<string name="home_follow_title">Bizi Takip Edin</string>
|
<string name="home_follow_title">Bizi Takip Edin</string>
|
||||||
<string name="home_item_source">Kaynak</string>
|
<string name="home_item_source">Kaynak</string>
|
||||||
<string name="home_support_content">Magisk her zaman ücretsiz ve açık kaynak olacaktır. Ancak, bir bağış yaparak bize destek olabilirsiniz.</string>
|
<string name="home_support_content">Magisk ücretsizdir, açık kaynaklıdır ve her zaman öyle kalacaktır. Ancak, bağış yaparak bize değer verdiğinizi gösterebilirsiniz.</string>
|
||||||
<string name="home_installed_version">Yüklü Sürüm</string>
|
<string name="home_installed_version">Yüklü</string>
|
||||||
<string name="home_latest_version">En Son Sürüm</string>
|
<string name="home_latest_version">En Son</string>
|
||||||
<string name="invalid_update_channel">Geçersiz Güncelleme Kanalı</string>
|
<string name="invalid_update_channel">Geçersiz güncelleme kanalı</string>
|
||||||
<string name="uninstall_magisk_title">Magisk\'i Kaldır</string>
|
<string name="uninstall_magisk_title">Magisk\'i Kaldır</string>
|
||||||
<string name="uninstall_magisk_msg">Tüm modüller devre dışı bırakılacak/kaldırılacak!\nKök kaldırılacak!\nMagisk kullanılarak şifrelenmemiş herhangi bir dahili depolama yeniden şifrelenecek!</string>
|
<string name="uninstall_magisk_msg">Tüm modüller devre dışı bırakılacak/kaldırılacak!\nRoot kaldırılacak!\nMagisk kullanılarak şifresi çözülen dahili depolama birimleri yeniden şifrelenecek!</string>
|
||||||
|
|
||||||
<!--Install-->
|
<!--Install-->
|
||||||
<string name="keep_force_encryption">Zorla şifrelemeyi koru</string>
|
<string name="keep_force_encryption">Zorunlu Şifrelemeyi Koru</string>
|
||||||
<string name="keep_dm_verity">AVB 2.0/dm-verity\'yi koru</string>
|
<string name="keep_dm_verity">AVB 2.0/dm-verity Koru</string>
|
||||||
<string name="recovery_mode">Kurtarma Modu</string>
|
<string name="recovery_mode">Kurtarma Modu</string>
|
||||||
<string name="install_options_title">Seçenekler</string>
|
<string name="install_options_title">Seçenekler</string>
|
||||||
<string name="install_method_title">Yöntem</string>
|
<string name="install_method_title">Yöntem</string>
|
||||||
<string name="install_next">Sonraki</string>
|
<string name="install_next">Sonraki</string>
|
||||||
<string name="install_start">Hadi başlayalım</string>
|
<string name="install_start">Hadi Başlayalım</string>
|
||||||
<string name="manager_download_install">İndirmek ve yüklemek için basın</string>
|
<string name="manager_download_install">İndirmek ve kurmak için basın</string>
|
||||||
<string name="direct_install">Doğrudan Yükleme (Önerilir)</string>
|
<string name="direct_install">Doğrudan kurulum (Önerilen)</string>
|
||||||
<string name="install_inactive_slot">Etkin Olmayan Slot\'a Yükle (OTA Sonrası)</string>
|
<string name="install_inactive_slot">Etkin olmayan slota kur (OTA sonrası)</string>
|
||||||
<string name="install_inactive_slot_msg">Cihazınız yeniden başlatıldıktan sonra zorunlu olarak mevcut etkin olmayan slota önyükleme yapılacaktır!\nBu seçeneği yalnızca OTA tamamlandıktan sonra kullanın.\nDevam etmek istiyor musunuz?</string>
|
<string name="install_inactive_slot_msg">Cihazınız, yeniden başlattıktan sonra mevcut etkin olmayan slota önyükleme yapmaya ZORLANACAKTIR!\nBu seçeneği yalnızca OTA güncellemesi yapıldıktan sonra kullanın.\nDevam edilsin mi?</string>
|
||||||
<string name="setup_title">Ek Kurulum</string>
|
<string name="setup_title">Ek Kurulum</string>
|
||||||
<string name="select_patch_file">Bir Dosya Seç ve Yama Yap</string>
|
<string name="select_patch_file">Bir dosya seçin ve yamalayın</string>
|
||||||
<string name="patch_file_msg">Ham bir görüntü (*.img) veya bir ODIN tar dosyası (*.tar) veya bir payload.bin (*.bin) seçin</string>
|
<string name="patch_file_msg">Ham bir imaj (*.img), bir ODIN tar dosyası (*.tar) veya bir payload.bin (*.bin) seçin</string>
|
||||||
<string name="reboot_delay_toast">5 saniye içinde yeniden başlatılıyor…</string>
|
<string name="reboot_delay_toast">5 saniye içinde yeniden başlatılıyor…</string>
|
||||||
<string name="flash_screen_title">Yükleniyor</string>
|
<string name="flash_screen_title">Kuruluyor</string>
|
||||||
|
|
||||||
<!--Superuser-->
|
<!--Superuser-->
|
||||||
<string name="su_request_title">Süper Kullanıcı İsteği</string>
|
<string name="su_request_title">Süper Kullanıcı İsteği</string>
|
||||||
<string name="touch_filtered_warning">Bir uygulama bir Süper Kullanıcı isteğini engellediği için Magisk yanıtınızı doğrulayamıyor</string>
|
<string name="touch_filtered_warning">Bir uygulama Süper Kullanıcı isteğini engellediği için Magisk yanıtınızı doğrulayamıyor.</string>
|
||||||
<string name="deny">Reddet</string>
|
<string name="deny">Reddet</string>
|
||||||
<string name="prompt">İstem</string>
|
<string name="prompt">Sor</string>
|
||||||
|
<string name="restrict">Kısıtla</string>
|
||||||
<string name="grant">İzin Ver</string>
|
<string name="grant">İzin Ver</string>
|
||||||
<string name="su_warning">Cihazınıza tam erişim sağlar.\nEmin değilseniz reddedin!</string>
|
<string name="su_warning">Cihazınıza tam erişim sağlar.\nEmin değilseniz reddedin!</string>
|
||||||
<string name="forever">Daima</string>
|
<string name="forever">Her Zaman</string>
|
||||||
<string name="once">Bir kez</string>
|
<string name="once">Bir Kez</string>
|
||||||
<string name="tenmin">10 dakika</string>
|
<string name="tenmin">10 Dakika</string>
|
||||||
<string name="twentymin">20 dakika</string>
|
<string name="twentymin">20 Dakika</string>
|
||||||
<string name="thirtymin">30 dakika</string>
|
<string name="thirtymin">30 Dakika</string>
|
||||||
<string name="sixtymin">60 dakika</string>
|
<string name="sixtymin">60 Dakika</string>
|
||||||
<string name="su_allow_toast">%1$s uygulamasının süper kullanıcı hakları verildi</string>
|
<string name="su_allow_toast">%1$s uygulamasına Süper Kullanıcı hakları verildi</string>
|
||||||
<string name="su_deny_toast">%1$s uygulamasının süper kullanıcı hakları reddedildi</string>
|
<string name="su_deny_toast">%1$s uygulamasının Süper Kullanıcı hakları reddedildi</string>
|
||||||
<string name="su_snack_grant">%1$s uygulamasının süper kullanıcı hakları verildi</string>
|
<string name="su_snack_grant">%1$s uygulamasının Süper Kullanıcı hakları verildi</string>
|
||||||
<string name="su_snack_deny">%1$s uygulamasının süper kullanıcı hakları reddedildi</string>
|
<string name="su_snack_deny">%1$s uygulamasının Süper Kullanıcı hakları reddedildi</string>
|
||||||
<string name="su_snack_notif_on">%1$s uygulamasının bildirimleri etkinleştirildi</string>
|
<string name="su_snack_notif_on">%1$s bildirimleri etkinleştirildi</string>
|
||||||
<string name="su_snack_notif_off">%1$s uygulamasının bildirimleri devre dışı bırakıldı</string>
|
<string name="su_snack_notif_off">%1$s bildirimleri devre dışı bırakıldı</string>
|
||||||
<string name="su_snack_log_on">%1$s uygulamasının günlüğü etkinleştirildi</string>
|
<string name="su_snack_log_on">%1$s için günlük kaydı etkinleştirildi</string>
|
||||||
<string name="su_snack_log_off">%1$s uygulamasının günlüğü devre dışı bırakıldı</string>
|
<string name="su_snack_log_off">%1$s için günlük kaydı devre dışı bırakıldı</string>
|
||||||
<string name="su_revoke_title">İptal Et?</string>
|
<string name="su_revoke_title">İptal Edilsin mi?</string>
|
||||||
<string name="su_revoke_msg">%1$s uygulamasının süper kullanıcı haklarını iptal etmek istediğinize emin misiniz?</string>
|
<string name="su_revoke_msg">%1$s uygulamasının Süper Kullanıcı haklarını iptal etmeyi onaylayın</string>
|
||||||
<string name="toast">Bildirim</string>
|
<string name="toast">Bildirim Penceresi</string>
|
||||||
<string name="none">Yok</string>
|
<string name="none">Yok</string>
|
||||||
|
|
||||||
<string name="superuser_toggle_notification">Bildirimler</string>
|
<string name="superuser_toggle_notification">Bildirimler</string>
|
||||||
<string name="superuser_toggle_revoke">İptal Et</string>
|
<string name="superuser_toggle_revoke">İptal Et</string>
|
||||||
<string name="superuser_policy_none">Henüz hiçbir uygulama Süper Kullanıcı izni istemedi.</string>
|
<string name="superuser_policy_none">Henüz hiçbir uygulama Süper Kullanıcı izni istemedi.</string>
|
||||||
|
|
||||||
<!--Logs-->
|
<!--Logs-->
|
||||||
<string name="log_data_none">Günlük kullanmıyorsunuz, root (kök) uygulamalarınızı daha çok kullanmayı deneyin</string>
|
<string name="log_data_none">Günlüğünüz temiz. Root uygulamalarınızı daha fazla kullanmayı deneyin.</string>
|
||||||
<string name="log_data_magisk_none">Magisk günlükleri boş, bu tuhaf</string>
|
<string name="log_data_magisk_none">Magisk günlükleri boş, bu garip.</string>
|
||||||
<string name="menuSaveLog">Günlüğü kaydet</string>
|
<string name="menuSaveLog">Günlüğü Kaydet</string>
|
||||||
<string name="menuClearLog">Günlüğü şimdi temizle</string>
|
<string name="menuClearLog">Günlüğü Şimdi Temizle</string>
|
||||||
<string name="logs_cleared">Günlük kaydı başarıyla temizlendi</string>
|
<string name="logs_cleared">Günlük başarıyla temizlendi</string>
|
||||||
<string name="pid">PID: %1$d</string>
|
<string name="pid">PID: %1$d</string>
|
||||||
<string name="target_uid">Hedef UID: %1$d</string>
|
<string name="target_uid">Hedef UID: %1$d</string>
|
||||||
<string name="target_pid">Mount ns hedef PID: %s</string>
|
<string name="target_pid">Hedef PID: %s</string>
|
||||||
<string name="selinux_context">SELinux bağlamı: %s</string>
|
<string name="selinux_context">SELinux bağlamı: %s</string>
|
||||||
<string name="supp_group">Ek grup: %s</string>
|
<string name="supp_group">Ek grup: %s</string>
|
||||||
|
|
||||||
<!--SafetyNet-->
|
|
||||||
|
|
||||||
<!--MagiskHide-->
|
<!--MagiskHide-->
|
||||||
<string name="show_system_app">Sistem uygulamalarını göster</string>
|
<string name="show_system_app">Sistem Uygulamalarını Göster</string>
|
||||||
<string name="show_os_app">İşletim sistemi uygulamalarını göster</string>
|
<string name="show_os_app">İS Uygulamalarını Göster</string>
|
||||||
<string name="hide_filter_hint">İsme göre filtrele</string>
|
<string name="hide_filter_hint">Ada göre filtrele</string>
|
||||||
<string name="hide_search">Ara</string>
|
<string name="hide_search">Ara</string>
|
||||||
|
|
||||||
<!--Module-->
|
<!--Module-->
|
||||||
<string name="no_info_provided">(Bilgi verilmedi)</string>
|
<string name="no_info_provided">(Bilgi sağlanmadı)</string>
|
||||||
<string name="reboot_userspace">Hızlı yeniden başlat</string>
|
<string name="reboot_userspace">Hızlı Yeniden Başlat</string>
|
||||||
<string name="reboot_recovery">Kurtarma modunda yeniden başlat</string>
|
<string name="reboot_recovery">Kurtarma Modunda Yeniden Başlat</string>
|
||||||
<string name="reboot_bootloader">Önyükleyici modunda yeniden başlat</string>
|
<string name="reboot_bootloader">Önyükleyici Modunda Yeniden Başlat</string>
|
||||||
<string name="reboot_download">İndirme modunda yeniden başlat</string>
|
<string name="reboot_download">Download Modunda Yeniden Başlat</string>
|
||||||
<string name="reboot_edl">EDL modunda yeniden başlat</string>
|
<string name="reboot_edl">EDL Modunda Yeniden Başlat</string>
|
||||||
<string name="reboot_safe_mode">Güvenli mod</string>
|
<string name="reboot_safe_mode">Güvenli Mod</string>
|
||||||
<string name="module_version_author">%1$s / %2$s</string>
|
<string name="module_version_author">%1$s, Geliştirici: %2$s</string>
|
||||||
<string name="module_state_remove">Kaldır</string>
|
<string name="module_state_remove">Kaldır</string>
|
||||||
|
<string name="module_action">Eylem</string>
|
||||||
<string name="module_state_restore">Geri Yükle</string>
|
<string name="module_state_restore">Geri Yükle</string>
|
||||||
<string name="module_action_install_external">Depolamadan yükle</string>
|
<string name="module_action_install_external">Depolamadan yükle</string>
|
||||||
<string name="update_available">Güncelleme Mevcut</string>
|
<string name="update_available">Güncelleme mevcut</string>
|
||||||
<string name="suspend_text_riru">Modül, %1$s etkin olduğu için askıya alındı</string>
|
<string name="suspend_text_riru">Modül, %1$s etkin olduğu için askıya alındı</string>
|
||||||
<string name="suspend_text_zygisk">Modül, %1$s etkin olmadığı için askıya alındı</string>
|
<string name="suspend_text_zygisk">Modül, %1$s etkin olmadığı için askıya alındı</string>
|
||||||
<string name="zygisk_module_unloaded">Uyumsuzluk nedeniyle Zygisk modülü yüklenmedi</string>
|
<string name="zygisk_module_unloaded">Zygisk modülü uyumsuzluk nedeniyle yüklenmedi</string>
|
||||||
<string name="module_empty">Yüklü modül yok</string>
|
<string name="module_empty">Yüklü modül yok</string>
|
||||||
<string name="confirm_install">%1$s modülü yüklensin mi?</string>
|
<string name="confirm_install">%1$s modülü yüklensin mi?</string>
|
||||||
<string name="confirm_install_title">Yükleme Onayı</string>
|
<string name="confirm_install_title">Yükleme Onayı</string>
|
||||||
@@ -127,121 +125,125 @@
|
|||||||
<string name="settings_dark_mode_dark">Her Zaman Karanlık</string>
|
<string name="settings_dark_mode_dark">Her Zaman Karanlık</string>
|
||||||
<string name="settings_download_path_title">İndirme Yolu</string>
|
<string name="settings_download_path_title">İndirme Yolu</string>
|
||||||
<string name="settings_download_path_message">Dosyalar %1$s konumuna kaydedilecek</string>
|
<string name="settings_download_path_message">Dosyalar %1$s konumuna kaydedilecek</string>
|
||||||
<string name="settings_hide_app_title">Magisk uygulamasını gizle</string>
|
<string name="settings_hide_app_title">Magisk Uygulamasını Gizle</string>
|
||||||
<string name="settings_hide_app_summary">Rastgele bir paket kimliği ve özel uygulama etiketi olan bir vekil (proxy) uygulaması yükleyin</string>
|
<string name="settings_hide_app_summary">Rastgele bir paket kimliği ve özel uygulama etiketi ile bir proxy uygulaması yükleyin</string>
|
||||||
<string name="settings_restore_app_title">Magisk uygulamasını geri yükle</string>
|
<string name="settings_restore_app_title">Magisk Uygulamasını Geri Yükle</string>
|
||||||
<string name="settings_restore_app_summary">Uygulamayı göster ve orijinal APK\'yı geri yükle</string>
|
<string name="settings_restore_app_summary">Uygulamanın gizliliğini kaldırın ve orijinal APK\'yi geri yükleyin</string>
|
||||||
<string name="language">Dil</string>
|
<string name="language">Dil</string>
|
||||||
<string name="system_default">(Sistem Varsayılanı)</string>
|
<string name="system_default">(Sistem Varsayılanı)</string>
|
||||||
<string name="settings_check_update_title">Güncellemeleri Kontrol Et</string>
|
<string name="settings_check_update_title">Güncellemeleri Kontrol Et</string>
|
||||||
<string name="settings_check_update_summary">Arka planda düzenli olarak güncellemeleri kontrol et</string>
|
<string name="settings_check_update_summary">Arka planda periyodik olarak güncellemeleri kontrol et</string>
|
||||||
<string name="settings_update_channel_title">Güncelleme Kanalı</string>
|
<string name="settings_update_channel_title">Güncelleme Kanalı</string>
|
||||||
<string name="settings_update_stable">Kararlı</string>
|
<string name="settings_update_stable">Kararlı</string>
|
||||||
<string name="settings_update_beta">Beta</string>
|
<string name="settings_update_beta">Beta</string>
|
||||||
|
<string name="settings_update_debug">Hata Ayıklama</string>
|
||||||
<string name="settings_update_custom">Özel</string>
|
<string name="settings_update_custom">Özel</string>
|
||||||
<string name="settings_update_custom_msg">Özel kanal URL\'si girin</string>
|
<string name="settings_update_custom_msg">Özel bir kanal URL\'si girin</string>
|
||||||
<string name="settings_zygisk_summary">Magisk\'in bazı bölümlerini zygote daemon\'unda çalıştır</string>
|
<string name="settings_zygisk_summary">Magisk\'in bazı kısımlarını Zygote daemon içinde çalıştırın</string>
|
||||||
<string name="settings_denylist_title">Reddetme Listesini Zorla</string>
|
<string name="settings_denylist_title">Red Listesini Uygula</string>
|
||||||
<string name="settings_denylist_summary">Reddetme Listesindeki işlemler tüm Magisk değişikliklerini geri alacak</string>
|
<string name="settings_denylist_summary">Red listesindeki işlemlerin tüm Magisk değişiklikleri geri alınacak</string>
|
||||||
<string name="settings_denylist_config_title">Reddetme Listesini Yapılandır</string>
|
<string name="settings_denylist_config_title">Red Listesini Yapılandır</string>
|
||||||
<string name="settings_denylist_config_summary">Reddetme Listesine dahil edilecek işlemleri seçin</string>
|
<string name="settings_denylist_config_summary">Red listesine dahil edilecek işlemleri seçin</string>
|
||||||
<string name="settings_hosts_title">Sistemsiz ana makineler (systemless hosts)</string>
|
<string name="settings_hosts_title">Sistemsiz Hosts</string>
|
||||||
<string name="settings_hosts_summary">Reklam engelleme uygulamaları için sistemsiz ana makineler (systemless hosts) desteği</string>
|
<string name="settings_hosts_summary">Reklam engelleme uygulamaları için sistemsiz hosts desteği</string>
|
||||||
<string name="settings_hosts_toast">Sistemsiz ana makineler (systemless hosts) modülü eklendi</string>
|
<string name="settings_hosts_toast">Sistemsiz hosts modülü eklendi</string>
|
||||||
<string name="settings_app_name_hint">Yeni ad</string>
|
<string name="settings_app_name_hint">Yeni ad</string>
|
||||||
<string name="settings_app_name_helper">Uygulama bu isimle yeniden paketlenecek</string>
|
<string name="settings_app_name_helper">Uygulama bu adla yeniden paketlenecek</string>
|
||||||
<string name="settings_app_name_error">Geçersiz format</string>
|
<string name="settings_app_name_error">Geçersiz format</string>
|
||||||
<string name="settings_su_app_adb">Uygulamalar ve ADB</string>
|
<string name="settings_su_app_adb">Uygulamalar ve ADB</string>
|
||||||
<string name="settings_su_app">Sadece Uygulamalar</string>
|
<string name="settings_su_app">Sadece Uygulamalar</string>
|
||||||
<string name="settings_su_adb">Sadece ADB</string>
|
<string name="settings_su_adb">Sadece ADB</string>
|
||||||
<string name="settings_su_disable">Devre Dışı</string>
|
<string name="settings_su_disable">Devre Dışı</string>
|
||||||
<string name="settings_su_request_10">10 saniye</string>
|
<string name="settings_su_request_10">10 Saniye</string>
|
||||||
<string name="settings_su_request_15">15 saniye</string>
|
<string name="settings_su_request_15">15 Saniye</string>
|
||||||
<string name="settings_su_request_20">20 saniye</string>
|
<string name="settings_su_request_20">20 Saniye</string>
|
||||||
<string name="settings_su_request_30">30 saniye</string>
|
<string name="settings_su_request_30">30 Saniye</string>
|
||||||
<string name="settings_su_request_45">45 saniye</string>
|
<string name="settings_su_request_45">45 Saniye</string>
|
||||||
<string name="settings_su_request_60">60 saniye</string>
|
<string name="settings_su_request_60">60 Saniye</string>
|
||||||
<string name="superuser_access">Süper Kullanıcı Erişimi</string>
|
<string name="superuser_access">Süper Kullanıcı Erişimi</string>
|
||||||
<string name="auto_response">Otomatik Yanıt</string>
|
<string name="auto_response">Otomatik Yanıt</string>
|
||||||
<string name="request_timeout">İstek Zaman Aşımı</string>
|
<string name="request_timeout">İstek Zaman Aşımı</string>
|
||||||
<string name="superuser_notification">Süper Kullanıcı Bildirimi</string>
|
<string name="superuser_notification">Süper Kullanıcı Bildirimi</string>
|
||||||
<string name="settings_su_reauth_title">Yükseltme sonrası yeniden doğrulama yap</string>
|
<string name="settings_su_reauth_title">Yükseltmeden Sonra Yeniden Kimlik Doğrula</string>
|
||||||
<string name="settings_su_reauth_summary">Uygulama güncellemelerinden sonra Süper Kullanıcı izinlerini tekrar iste</string>
|
<string name="settings_su_reauth_summary">Uygulamaları yükselttikten sonra tekrar Süper Kullanıcı izinlerini iste</string>
|
||||||
<string name="settings_su_tapjack_title">Tapjacking Koruması</string>
|
<string name="settings_su_tapjack_title">Dokunma Saldırısı Koruması</string>
|
||||||
<string name="settings_su_tapjack_summary">Süper Kullanıcı istemi diyalogu, başka bir pencere veya katman tarafından gizlendiğinde girdilere yanıt vermeyecektir</string>
|
<string name="settings_su_tapjack_summary">Süper Kullanıcı istek penceresi, başka bir pencere veya katman tarafından engellendiğinde girdilere yanıt vermeyecektir</string>
|
||||||
<string name="settings_su_auth_title">Kullanıcı Kimlik Doğrulama</string>
|
<string name="settings_su_auth_title">Kullanıcı Kimlik Doğrulaması</string>
|
||||||
<string name="settings_su_auth_summary">Süper Kullanıcı isteklerinde kullanıcı kimlik doğrulaması iste</string>
|
<string name="settings_su_auth_summary">Süper Kullanıcı istekleri sırasında kullanıcı kimlik doğrulaması iste</string>
|
||||||
<string name="settings_su_auth_insecure">Cihazda yapılandırılmış bir kimlik doğrulama yöntemi yok</string>
|
<string name="settings_su_auth_insecure">Cihazda yapılandırılmış bir kimlik doğrulama yöntemi yok</string>
|
||||||
<string name="settings_customization">Özelleştir</string>
|
<string name="settings_su_restrict_title">Root Yeteneklerini Kısıtla</string>
|
||||||
<string name="setting_add_shortcut_summary">Uygulamayı gizledikten sonra adı ve simgeyi tanımakta zorlanıyorsanız ana ekrana güzel bir kısayol ekle</string>
|
<string name="settings_su_restrict_summary">Yeni Süper Kullanıcı uygulamalarını varsayılan olarak kısıtlayacaktır. Uyarı: Bu, çoğu uygulamayı bozacaktır. Ne yaptığınızı bilmiyorsanız etkinleştirmeyin.</string>
|
||||||
<string name="settings_doh_title">DNS üzerinden HTTPS</string>
|
<string name="settings_customization">Özelleştirme</string>
|
||||||
<string name="settings_doh_description">Bazı ülkelerde DNS zehirlemesine karşı geçici çözüm</string>
|
<string name="setting_add_shortcut_summary">Uygulamayı gizledikten sonra adı ve simgesi tanınması zor olursa ana ekrana güzel bir kısayol ekleyin</string>
|
||||||
<string name="settings_random_name_title">Çıkış adını rastgele seç</string>
|
<string name="settings_doh_title">HTTPS üzerinden DNS</string>
|
||||||
<string name="settings_random_name_description">Algılamayı önlemek için yamalı resimlerin ve tar dosyalarının çıkış dosya adını rastgele seç</string>
|
<string name="settings_doh_description">Bazı ülkelerdeki DNS zehirlenmesini aşmak için geçici çözüm</string>
|
||||||
|
<string name="settings_random_name_title">Çıktı Adını Rastgele Yap</string>
|
||||||
<string name="multiuser_mode">Çok Kullanıcılı Mod</string>
|
<string name="settings_random_name_description">Tespit edilmesini önlemek için yamalanmış imajların ve tar dosyalarının çıktı dosya adını rastgele yapın</string>
|
||||||
<string name="settings_owner_only">Yalnızca Cihaz Sahibi</string>
|
<string name="multiuser_mode">Çoklu Kullanıcı Modu</string>
|
||||||
<string name="settings_owner_manage">Cihaz Sahibi Yönetiminde</string>
|
<string name="settings_owner_only">Sadece Cihaz Sahibi</string>
|
||||||
|
<string name="settings_owner_manage">Cihaz Sahibi Tarafından Yönetilen</string>
|
||||||
<string name="settings_user_independent">Kullanıcıdan Bağımsız</string>
|
<string name="settings_user_independent">Kullanıcıdan Bağımsız</string>
|
||||||
<string name="owner_only_summary">Yalnızca sahip kök (root) erişimine sahiptir</string>
|
<string name="owner_only_summary">Sadece cihaz sahibi root erişimine sahiptir</string>
|
||||||
<string name="owner_manage_summary">Yalnızca sahip kök (root) erişimini yönetebilir ve istek uyarılarını alabilir</string>
|
<string name="owner_manage_summary">Sadece cihaz sahibi root erişimini yönetebilir ve istekleri alabilir</string>
|
||||||
<string name="user_independent_summary">Her kullanıcının kendi ayrı kök (root) kuralları vardır</string>
|
<string name="user_independent_summary">Her kullanıcının kendi ayrı root kuralları vardır</string>
|
||||||
|
|
||||||
<string name="mount_namespace_mode">Bağlama Ad Alanı Modu</string>
|
<string name="mount_namespace_mode">Bağlama Ad Alanı Modu</string>
|
||||||
<string name="settings_ns_global">Küresel Ad Alanı</string>
|
<string name="settings_ns_global">Genel Ad Alanı</string>
|
||||||
<string name="settings_ns_requester">Ad Alanını Devral</string>
|
<string name="settings_ns_requester">Ad Alanını Devral</string>
|
||||||
<string name="settings_ns_isolate">İzolasyon Ad Alanı</string>
|
<string name="settings_ns_isolate">Yalıtılmış Ad Alanı</string>
|
||||||
<string name="global_summary">Tüm kök (root) oturumları küresel bağlama ad alanını kullanır</string>
|
<string name="global_summary">Tüm root oturumları genel bağlama ad alanını kullanır</string>
|
||||||
<string name="requester_summary">Kök (root) oturumları isteyicisinin ad alanını devralacak</string>
|
<string name="requester_summary">Root oturumları, istekçilerinin ad alanını devralır</string>
|
||||||
<string name="isolate_summary">Her kök (root) oturumu kendi izole ad alanına sahip olacak</string>
|
<string name="isolate_summary">Her root oturumunun kendi yalıtılmış ad alanı olacaktır</string>
|
||||||
|
|
||||||
<!--Notifications-->
|
<!--Notifications-->
|
||||||
<string name="update_channel">Magisk Güncellemeleri</string>
|
<string name="update_channel">Magisk güncellemeleri</string>
|
||||||
<string name="progress_channel">İlerleme Bildirimleri</string>
|
<string name="progress_channel">İlerleme bildirimleri</string>
|
||||||
<string name="updated_channel">Güncelleme Tamamlandı</string>
|
<string name="updated_channel">Güncelleme tamamlandı</string>
|
||||||
<string name="download_complete">İndirme tamamlandı</string>
|
<string name="download_complete">İndirme tamamlandı</string>
|
||||||
<string name="download_file_error">Dosya indirilirken hata oluştu</string>
|
<string name="download_file_error">Dosya indirilirken hata oluştu</string>
|
||||||
<string name="magisk_update_title">Magisk Güncellemesi Mevcut!</string>
|
<string name="magisk_update_title">Magisk güncellemesi mevcut!</string>
|
||||||
<string name="updated_title">Magisk Güncellendi</string>
|
<string name="updated_title">Magisk güncellendi</string>
|
||||||
<string name="updated_text">Uygulamayı açmak için dokunun</string>
|
<string name="updated_text">Uygulamayı açmak için dokunun</string>
|
||||||
|
|
||||||
<!--Toasts, Dialogs-->
|
<!--Toasts, Dialogs-->
|
||||||
<string name="yes">Mevcut</string>
|
<string name="yes">Evet</string>
|
||||||
<string name="no">Mevcut Değil</string>
|
<string name="no">Hayır</string>
|
||||||
<string name="repo_install_title">%1$s %2$s(%3$d) Kur</string>
|
<string name="repo_install_title">%1$s %2$s(%3$d) Yüklensin mi?</string>
|
||||||
<string name="download">İndir</string>
|
<string name="download">İndir</string>
|
||||||
<string name="reboot">Yeniden Başlat</string>
|
<string name="reboot">Yeniden Başlat</string>
|
||||||
|
<string name="close">Kapat</string>
|
||||||
<string name="release_notes">Sürüm Notları</string>
|
<string name="release_notes">Sürüm Notları</string>
|
||||||
<string name="flashing">Yükleniyor...</string>
|
<string name="flashing">Flaşlanıyor…</string>
|
||||||
<string name="done">Tamamlandı!</string>
|
<string name="running">Çalışıyor…</string>
|
||||||
|
<string name="done">Bitti!</string>
|
||||||
|
<string name="done_action">%1$s eylemi tamamlandı</string>
|
||||||
<string name="failure">Başarısız!</string>
|
<string name="failure">Başarısız!</string>
|
||||||
<string name="hide_app_title">Magisk uygulaması gizleniyor…</string>
|
<string name="hide_app_title">Magisk uygulaması gizleniyor…</string>
|
||||||
<string name="open_link_failed_toast">Bağlantıyı açmak için uygulama bulunamadı</string>
|
<string name="open_link_failed_toast">Bağlantıyı açacak bir uygulama bulunamadı</string>
|
||||||
<string name="complete_uninstall">Tamamen Kaldır</string>
|
<string name="complete_uninstall">Tamamen Kaldır</string>
|
||||||
<string name="restore_img">Görüntüleri Geri Yükle</string>
|
<string name="restore_img">İmajları Geri Yükle</string>
|
||||||
<string name="restore_img_msg">Geri Yükleniyor...</string>
|
<string name="restore_img_msg">Geri yükleniyor…</string>
|
||||||
<string name="restore_done">Geri yükleme tamamlandı!</string>
|
<string name="restore_done">Geri yükleme tamamlandı!</string>
|
||||||
<string name="restore_fail">Stok yedeği mevcut değil!</string>
|
<string name="restore_fail">Stok yedeği mevcut değil!</string>
|
||||||
<string name="setup_fail">Kurulum başarısız oldu</string>
|
<string name="setup_fail">Kurulum başarısız oldu</string>
|
||||||
<string name="env_fix_title">Ek Ayar Gerekiyor</string>
|
<string name="env_fix_title">Ek Kurulum Gerektiriyor</string>
|
||||||
<string name="env_fix_msg">Magisk\'in düzgün çalışabilmesi için cihazınızın ek ayarlar yapması gerekiyor. Devam etmek ve yeniden başlatmak istiyor musunuz?</string>
|
<string name="env_fix_msg">Cihazınızın Magisk\'in düzgün çalışması için ek kuruluma ihtiyacı var. Devam edip yeniden başlatmak ister misiniz?</string>
|
||||||
<string name="env_full_fix_msg">Cihazınızın düzgün çalışabilmesi için Magisk\'in yeniden yüklenmesi gerekiyor. Lütfen Magisk\'i uygulama içinde yeniden yükleyin, kurtarma modu doğru cihaz bilgilerini alamaz.</string>
|
<string name="env_full_fix_msg">Cihazınızın düzgün çalışması için Magisk\'i yeniden flaşlamanız gerekiyor. Lütfen Magisk\'i uygulama içinden yeniden kurun, Kurtarma modu doğru cihaz bilgisini alamaz.</string>
|
||||||
<string name="setup_msg">Ortam kurulumu yapılıyor...</string>
|
<string name="setup_msg">Çalışma ortamı kuruluyor…</string>
|
||||||
<string name="unsupport_magisk_title">Desteklenmeyen Magisk Sürümü</string>
|
<string name="unsupport_magisk_title">Desteklenmeyen Magisk Sürümü</string>
|
||||||
<string name="unsupport_magisk_msg">Bu uygulama sürümü, %1$s altındaki Magisk sürümlerini desteklemiyor.\n\nUygulama, Magisk yüklü değilmiş gibi davranacaktır, lütfen en kısa sürede Magisk\'i güncelleyin.</string>
|
<string name="unsupport_magisk_msg">Uygulamanın bu sürümü, %1$s sürümünden daha düşük Magisk sürümlerini desteklemiyor.\n\nUygulama, Magisk yüklü değilmiş gibi davranacaktır. Lütfen Magisk\'i en kısa sürede güncelleyin.</string>
|
||||||
<string name="unsupport_general_title">Anormal Durum</string>
|
<string name="unsupport_general_title">Anormal Durum</string>
|
||||||
<string name="unsupport_system_app_msg">Bu uygulamanın sistem uygulaması olarak çalıştırılması desteklenmiyor. Lütfen uygulamayı kullanıcı uygulamasına geri döndürün.</string>
|
<string name="unsupport_system_app_msg">Bu uygulamanın bir sistem uygulaması olarak çalıştırılması desteklenmiyor. Lütfen uygulamayı bir kullanıcı uygulamasına geri döndürün.</string>
|
||||||
<string name="unsupport_other_su_msg">Magisk\'ten gelmeyen bir "su" ikili dosyası tespit edildi. Lütfen herhangi bir rakip kök (root) çözümünü kaldırın ve/veya Magisk\'i yeniden yükleyin.</string>
|
<string name="unsupport_other_su_msg">Magisk\'e ait olmayan bir "su" ikili dosyası tespit edildi. Lütfen rakip root çözümlerini kaldırın ve/veya Magisk\'i yeniden yükleyin.</string>
|
||||||
<string name="unsupport_external_storage_msg">Magisk harici depolamaya yüklendi. Lütfen uygulamayı dahili depolamaya taşıyın.</string>
|
<string name="unsupport_external_storage_msg">Magisk harici depolamaya kurulmuş. Lütfen uygulamayı dahili depolamaya taşıyın.</string>
|
||||||
<string name="unsupport_nonroot_stub_msg">Gizli Magisk uygulaması kök (root) erişimi kaybolduğu için çalışmaya devam edemez. Lütfen orijinal APK\'yı geri yükleyin.</string>
|
<string name="unsupport_nonroot_stub_msg">Gizlenmiş Magisk uygulaması, root kaybolduğu için çalışmaya devam edemiyor. Lütfen orijinal APK\'yi geri yükleyin.</string>
|
||||||
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
||||||
<string name="external_rw_permission_denied">Bu işlevselliği etkinleştirmek için depolama izni verin</string>
|
<string name="external_rw_permission_denied">Bu işlevi etkinleştirmek için depolama izni verin</string>
|
||||||
<string name="post_notifications_denied">Bu işlevselliği etkinleştirmek için bildirim izni verin</string>
|
<string name="post_notifications_denied">Bu işlevi etkinleştirmek için bildirim izni verin</string>
|
||||||
<string name="install_unknown_denied">Bu işlevselliği etkinleştirmek için "bilinmeyen uygulamaları yükle" iznini verin</string>
|
<string name="install_unknown_denied">Bu işlevi etkinleştirmek için "Bilinmeyen uygulamaları yükle" iznini verin</string>
|
||||||
<string name="add_shortcut_title">Ana ekrana kısayol ekle</string>
|
<string name="add_shortcut_title">Ana Ekrana Kısayol Ekle</string>
|
||||||
<string name="add_shortcut_msg">Bu uygulamayı gizledikten sonra adı ve simgesi tanınmayabilir. Ana ekrana güzel bir kısayol eklemek ister misiniz?</string>
|
<string name="add_shortcut_msg">Bu uygulamayı gizledikten sonra adı ve simgesi tanınması zor olabilir. Ana ekrana güzel bir kısayol eklemek ister misiniz?</string>
|
||||||
<string name="app_not_found">Bu işlemi gerçekleştirecek uygulama bulunamadı</string>
|
<string name="app_not_found">Bu eylemi gerçekleştirecek bir uygulama bulunamadı</string>
|
||||||
<string name="reboot_apply_change">Değişiklikleri uygulamak için yeniden başlatın</string>
|
<string name="reboot_apply_change">Değişiklikleri uygulamak için yeniden başlatın</string>
|
||||||
<string name="restore_app_confirmation">Bu, gizli uygulamayı orijinal uygulamaya geri yükleyecektir. Gerçekten bunu yapmak istiyor musunuz?</string>
|
<string name="restore_app_confirmation">Bu, gizlenmiş uygulamayı orijinal uygulamaya geri yükleyecektir. Bunu gerçekten yapmak istiyor musunuz?</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
<string name="touch_filtered_warning">由于某个应用遮挡了超级用户请求界面,因此 Magisk 无法验证您的回应</string>
|
<string name="touch_filtered_warning">由于某个应用遮挡了超级用户请求界面,因此 Magisk 无法验证您的回应</string>
|
||||||
<string name="deny">拒绝</string>
|
<string name="deny">拒绝</string>
|
||||||
<string name="prompt">提示</string>
|
<string name="prompt">提示</string>
|
||||||
|
<string name="restrict">受限</string>
|
||||||
<string name="grant">允许</string>
|
<string name="grant">允许</string>
|
||||||
<string name="su_warning">将授予对该设备的最高权限。\n如果不确定,请拒绝!</string>
|
<string name="su_warning">将授予对该设备的最高权限。\n如果不确定,请拒绝!</string>
|
||||||
<string name="forever">永久</string>
|
<string name="forever">永久</string>
|
||||||
@@ -173,6 +174,8 @@
|
|||||||
<string name="settings_su_auth_title">身份验证</string>
|
<string name="settings_su_auth_title">身份验证</string>
|
||||||
<string name="settings_su_auth_summary">对超级用户请求验证身份</string>
|
<string name="settings_su_auth_summary">对超级用户请求验证身份</string>
|
||||||
<string name="settings_su_auth_insecure">设备未配置验证方式</string>
|
<string name="settings_su_auth_insecure">设备未配置验证方式</string>
|
||||||
|
<string name="settings_su_restrict_title">限制超级用户权能</string>
|
||||||
|
<string name="settings_su_restrict_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(DoH)</string>
|
<string name="settings_doh_title">安全 DNS(DoH)</string>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
<string name="touch_filtered_warning">Because an app is obscuring a Superuser request, Magisk can\'t verify your response.</string>
|
<string name="touch_filtered_warning">Because an app is obscuring a Superuser request, Magisk can\'t verify your response.</string>
|
||||||
<string name="deny">Deny</string>
|
<string name="deny">Deny</string>
|
||||||
<string name="prompt">Prompt</string>
|
<string name="prompt">Prompt</string>
|
||||||
|
<string name="restrict">Restrict</string>
|
||||||
<string name="grant">Grant</string>
|
<string name="grant">Grant</string>
|
||||||
<string name="su_warning">Grants full access to your device.\nDeny if you\'re not sure!</string>
|
<string name="su_warning">Grants full access to your device.\nDeny if you\'re not sure!</string>
|
||||||
<string name="forever">Forever</string>
|
<string name="forever">Forever</string>
|
||||||
@@ -170,6 +171,8 @@
|
|||||||
<string name="settings_su_auth_title">User authentication</string>
|
<string name="settings_su_auth_title">User authentication</string>
|
||||||
<string name="settings_su_auth_summary">Ask for user authentication during Superuser requests</string>
|
<string name="settings_su_auth_summary">Ask for user authentication during Superuser requests</string>
|
||||||
<string name="settings_su_auth_insecure">No authentication method is configured on the device</string>
|
<string name="settings_su_auth_insecure">No authentication method is configured on the device</string>
|
||||||
|
<string name="settings_su_restrict_title">Restrict root capabilities</string>
|
||||||
|
<string name="settings_su_restrict_summary">Will restrict new Superuser apps by default. Warning: this will break most apps. Don\'t enable it unless you know what you\'re doing.</string>
|
||||||
<string name="settings_customization">Customization</string>
|
<string name="settings_customization">Customization</string>
|
||||||
<string name="setting_add_shortcut_summary">Add a pretty shortcut to the home screen in case the name and icon are difficult to recognize after hiding the app</string>
|
<string name="setting_add_shortcut_summary">Add a pretty shortcut to the home screen in case the name and icon are difficult to recognize after hiding the app</string>
|
||||||
<string name="settings_doh_title">DNS over HTTPS</string>
|
<string name="settings_doh_title">DNS over HTTPS</string>
|
||||||
|
|||||||
@@ -30,4 +30,4 @@ android.nonFinalResIds=false
|
|||||||
|
|
||||||
# Magisk
|
# Magisk
|
||||||
magisk.stubVersion=40
|
magisk.stubVersion=40
|
||||||
magisk.versionCode=30000
|
magisk.versionCode=30200
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
[versions]
|
[versions]
|
||||||
kotlin = "2.1.21"
|
kotlin = "2.2.0"
|
||||||
android = "8.11.0"
|
android = "8.12.0"
|
||||||
ksp = "2.1.21-2.0.1"
|
ksp = "2.2.0-2.0.2"
|
||||||
rikka = "1.3.0"
|
rikka = "1.3.0"
|
||||||
navigation = "2.9.0"
|
navigation = "2.9.3"
|
||||||
libsu = "6.0.0"
|
libsu = "6.0.0"
|
||||||
okhttp = "4.12.0"
|
okhttp = "5.1.0"
|
||||||
retrofit = "3.0.0"
|
retrofit = "3.0.0"
|
||||||
room = "2.7.2"
|
room = "2.7.2"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
bcpkix = { module = "org.bouncycastle:bcpkix-jdk18on", version = "1.81" }
|
bcpkix = { module = "org.bouncycastle:bcpkix-jdk18on", version = "1.81" }
|
||||||
commons-compress = { module = "org.apache.commons:commons-compress", version = "1.27.1" }
|
commons-compress = { module = "org.apache.commons:commons-compress", version = "1.28.0" }
|
||||||
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
||||||
retrofit-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "retrofit" }
|
retrofit-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "retrofit" }
|
||||||
retrofit-scalars = { module = "com.squareup.retrofit2:converter-scalars", version.ref = "retrofit" }
|
retrofit-scalars = { module = "com.squareup.retrofit2:converter-scalars", version.ref = "retrofit" }
|
||||||
@@ -41,9 +41,9 @@ transition = { module = "androidx.transition:transition", version = "1.6.0" }
|
|||||||
collection-ktx = { module = "androidx.collection:collection-ktx", version = "1.5.0" }
|
collection-ktx = { module = "androidx.collection:collection-ktx", version = "1.5.0" }
|
||||||
material = { module = "com.google.android.material:material", version = "1.12.0" }
|
material = { module = "com.google.android.material:material", version = "1.12.0" }
|
||||||
jdk-libs = { module = "com.android.tools:desugar_jdk_libs_nio", version = "2.1.5" }
|
jdk-libs = { module = "com.android.tools:desugar_jdk_libs_nio", version = "2.1.5" }
|
||||||
test-runner = { module = "androidx.test:runner", version = "1.6.2" }
|
test-runner = { module = "androidx.test:runner", version = "1.7.0" }
|
||||||
test-rules = { module = "androidx.test:rules", version = "1.6.1" }
|
test-rules = { module = "androidx.test:rules", version = "1.7.0" }
|
||||||
test-junit = { module = "androidx.test.ext:junit", version = "1.2.1" }
|
test-junit = { module = "androidx.test.ext:junit", version = "1.3.0" }
|
||||||
test-uiautomator = { module = "androidx.test.uiautomator:uiautomator", version = "2.3.0" }
|
test-uiautomator = { module = "androidx.test.uiautomator:uiautomator", version = "2.3.0" }
|
||||||
|
|
||||||
# topjohnwu
|
# topjohnwu
|
||||||
@@ -62,6 +62,6 @@ android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref
|
|||||||
ksp-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" }
|
ksp-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" }
|
||||||
navigation-safe-args-plugin = { module = "androidx.navigation:navigation-safe-args-gradle-plugin", version.ref = "navigation" }
|
navigation-safe-args-plugin = { module = "androidx.navigation:navigation-safe-args-gradle-plugin", version.ref = "navigation" }
|
||||||
lsparanoid-plugin = { module = "org.lsposed.lsparanoid:gradle-plugin", version = "0.6.0" }
|
lsparanoid-plugin = { module = "org.lsposed.lsparanoid:gradle-plugin", version = "0.6.0" }
|
||||||
moshi-plugin = { module = "dev.zacsweers.moshix:dev.zacsweers.moshix.gradle.plugin", version = "0.30.0" }
|
moshi-plugin = { module = "dev.zacsweers.moshix:dev.zacsweers.moshix.gradle.plugin", version = "0.31.0" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
|
|||||||
2
app/gradle/wrapper/gradle-wrapper.properties
vendored
2
app/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.14.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
- [Installation Instructions](install.md)
|
- [Installation Instructions](install.md)
|
||||||
- [Frequently Asked Questions](faq.md)
|
- [Frequently Asked Questions](faq.md)
|
||||||
- [Release Notes](releases/index.md)
|
|
||||||
- [Magisk Changelog](changes.md)
|
- [Magisk Changelog](changes.md)
|
||||||
|
|
||||||
The following sections are for developers
|
The following sections are for developers
|
||||||
|
|||||||
165
docs/changes.md
165
docs/changes.md
@@ -1,13 +1,24 @@
|
|||||||
# Magisk Changelog
|
# Magisk Changelog
|
||||||
|
|
||||||
### v30.0
|
### v30.2 (2025.8.6)
|
||||||
|
|
||||||
|
- [Core] Fix an edge case breaking modules when overlayfs is involved
|
||||||
|
- [Core] Fix module `.replace` functionality in certain situations
|
||||||
|
- [resetprop] Reduce property modification traces
|
||||||
|
|
||||||
|
### v30.1 (2025.7.3)
|
||||||
|
|
||||||
|
- [Core] Fix bug in module mounting implementation
|
||||||
|
- [MagiskSU] Add ability to restrict Linux capabilities even if running as root (uid=0)
|
||||||
|
|
||||||
|
### v30.0 (2025.7.1)
|
||||||
|
|
||||||
- [General] Various minor bug fixes
|
- [General] Various minor bug fixes
|
||||||
- [Core] Migrate module implementation to Rust
|
- [Core] Migrate module implementation to Rust
|
||||||
- [Core] Improve Magisk specific files injection logic
|
- [Core] Improve Magisk specific files injection logic
|
||||||
- [MagiskBoot] Migrate compression code to Rust
|
- [MagiskBoot] Migrate compression code to Rust
|
||||||
|
|
||||||
### v29.0
|
### v29.0 (2025.5.14)
|
||||||
|
|
||||||
- [General] Massive internal refactoring and code migration
|
- [General] Massive internal refactoring and code migration
|
||||||
- [App] Support downloading module zip files with XZ compression
|
- [App] Support downloading module zip files with XZ compression
|
||||||
@@ -16,7 +27,7 @@
|
|||||||
- [MagiskInit] Redesign sepolicy patching and injection logic
|
- [MagiskInit] Redesign sepolicy patching and injection logic
|
||||||
- [MagiskSU] Better TTY/PTY support
|
- [MagiskSU] Better TTY/PTY support
|
||||||
|
|
||||||
### v28.1
|
### v28.1 (2024.12.6)
|
||||||
|
|
||||||
- [App] Fix stub APK download link
|
- [App] Fix stub APK download link
|
||||||
- [App] Fix support for Android lower than 8.0
|
- [App] Fix support for Android lower than 8.0
|
||||||
@@ -24,7 +35,7 @@
|
|||||||
- [MagiskInit] Fix a regression for 2SI devices
|
- [MagiskInit] Fix a regression for 2SI devices
|
||||||
- [MagiskPolicy] Fix a regression causing `overlay.d` replaced files to be not accessible
|
- [MagiskPolicy] Fix a regression causing `overlay.d` replaced files to be not accessible
|
||||||
|
|
||||||
### v28.0
|
### v28.0 (2024.10.10)
|
||||||
|
|
||||||
- [General] Support 16k page size
|
- [General] Support 16k page size
|
||||||
- [General] Add basic support for RISC-V (not built in releases)
|
- [General] Add basic support for RISC-V (not built in releases)
|
||||||
@@ -48,7 +59,7 @@
|
|||||||
- [MagiskBoot] Properly support vendor boot images
|
- [MagiskBoot] Properly support vendor boot images
|
||||||
- [MagiskBoot] Disable Samsung PROCA from kernel image
|
- [MagiskBoot] Disable Samsung PROCA from kernel image
|
||||||
|
|
||||||
### v27.0
|
### v27.0 (2024.2.3)
|
||||||
|
|
||||||
- [Zygisk] Introduce new code injection mechanism
|
- [Zygisk] Introduce new code injection mechanism
|
||||||
- [Zygisk] Support new signature introduced in U QPR2
|
- [Zygisk] Support new signature introduced in U QPR2
|
||||||
@@ -56,7 +67,7 @@
|
|||||||
- [MagiskBoot] Support compressing `init` so Magisk is installable on devices with small boot partitions
|
- [MagiskBoot] Support compressing `init` so Magisk is installable on devices with small boot partitions
|
||||||
- [ResetProp] Add new wait for property feature `resetprop -w`
|
- [ResetProp] Add new wait for property feature `resetprop -w`
|
||||||
|
|
||||||
### v26.4
|
### v26.4 (2023.11.5)
|
||||||
|
|
||||||
- [MagiskBoot] Don't pad zeros if signed boot image is larger
|
- [MagiskBoot] Don't pad zeros if signed boot image is larger
|
||||||
- [MagiskPolicy] Fix `genfscon` and `filename_trans`
|
- [MagiskPolicy] Fix `genfscon` and `filename_trans`
|
||||||
@@ -67,14 +78,14 @@
|
|||||||
- [Daemon] Fix certificate parsing of APKs
|
- [Daemon] Fix certificate parsing of APKs
|
||||||
- [General] Fix logging errors from C++ code being ignored
|
- [General] Fix logging errors from C++ code being ignored
|
||||||
|
|
||||||
### v26.3
|
### v26.3 (2023.9.4)
|
||||||
|
|
||||||
- [General] Fix device information detection script
|
- [General] Fix device information detection script
|
||||||
- [General] Update BusyBox to 1.36.1
|
- [General] Update BusyBox to 1.36.1
|
||||||
- [General] Update toolchain that produces broken arm32 executables
|
- [General] Update toolchain that produces broken arm32 executables
|
||||||
- [App] Fix root service unable to bind on OnePlus devices
|
- [App] Fix root service unable to bind on OnePlus devices
|
||||||
|
|
||||||
### v26.2
|
### v26.2 (2023.8.27)
|
||||||
|
|
||||||
- [MagiskBoot] Support extracting boot image from `payload.bin`
|
- [MagiskBoot] Support extracting boot image from `payload.bin`
|
||||||
- [MagiskBoot] Support cpio files containing character files
|
- [MagiskBoot] Support cpio files containing character files
|
||||||
@@ -92,13 +103,13 @@
|
|||||||
- [App] Support patching boot image from ROM zips
|
- [App] Support patching boot image from ROM zips
|
||||||
- [App] Properly preserve `boot.img` when patching Samsung firmware with `init_boot.img`
|
- [App] Properly preserve `boot.img` when patching Samsung firmware with `init_boot.img`
|
||||||
|
|
||||||
### v26.1
|
### v26.1 (2023.4.11)
|
||||||
|
|
||||||
- [App] Fix crashing when revoking root permissions
|
- [App] Fix crashing when revoking root permissions
|
||||||
- [MagiskInit] Always prefer `ext4` partitions over `f2fs` when selecting the pre-init partition
|
- [MagiskInit] Always prefer `ext4` partitions over `f2fs` when selecting the pre-init partition
|
||||||
- [General] Restore module files' context/owner/group from mirror. This is a regression introduced in v26.0
|
- [General] Restore module files' context/owner/group from mirror. This is a regression introduced in v26.0
|
||||||
|
|
||||||
### v26.0
|
### v26.0 (2023.4.5)
|
||||||
|
|
||||||
- [General] Bump minimum supported Android version to Android 6.0
|
- [General] Bump minimum supported Android version to Android 6.0
|
||||||
- [General] New magic mount backend. It supports loading modules into system with `overlayfs` files injected
|
- [General] New magic mount backend. It supports loading modules into system with `overlayfs` files injected
|
||||||
@@ -115,7 +126,7 @@
|
|||||||
- [MagiskPolicy] Fix minor bug in command line argument parsing
|
- [MagiskPolicy] Fix minor bug in command line argument parsing
|
||||||
- [MagiskPolicy] Update rules to support Android U
|
- [MagiskPolicy] Update rules to support Android U
|
||||||
|
|
||||||
### v25.2
|
### v25.2 (2022.7.20)
|
||||||
|
|
||||||
- [MagiskInit] Fix a potential issue when stub cpio is used
|
- [MagiskInit] Fix a potential issue when stub cpio is used
|
||||||
- [MagiskInit] Fix reboot to recovery when stub cpio is used
|
- [MagiskInit] Fix reboot to recovery when stub cpio is used
|
||||||
@@ -123,7 +134,7 @@
|
|||||||
- [General] Better data encryption detection
|
- [General] Better data encryption detection
|
||||||
- [General] Move the whole logging infrastructure into Rust
|
- [General] Move the whole logging infrastructure into Rust
|
||||||
|
|
||||||
### v25.1
|
### v25.1 (2022.6.19)
|
||||||
|
|
||||||
- [MagiskBoot] Fix ramdisk backup being incorrectly skipped
|
- [MagiskBoot] Fix ramdisk backup being incorrectly skipped
|
||||||
- [MagiskBoot] Add new feature to detect unsupported dtb and abort during installation
|
- [MagiskBoot] Add new feature to detect unsupported dtb and abort during installation
|
||||||
@@ -132,7 +143,7 @@
|
|||||||
- [MagiskInit] Fix config not properly exported in legacy SAR devices
|
- [MagiskInit] Fix config not properly exported in legacy SAR devices
|
||||||
- [General] Enforce the Magisk app to always match or be newer than `magiskd`
|
- [General] Enforce the Magisk app to always match or be newer than `magiskd`
|
||||||
|
|
||||||
### v25.0
|
### v25.0 (2022.6.7)
|
||||||
|
|
||||||
- [MagiskInit] Update 2SI implementation, significantly increase device compatibility (e.g. Sony Xperia devices)
|
- [MagiskInit] Update 2SI implementation, significantly increase device compatibility (e.g. Sony Xperia devices)
|
||||||
- [MagiskInit] Introduce new `sepolicy` injection mechanism
|
- [MagiskInit] Introduce new `sepolicy` injection mechanism
|
||||||
@@ -150,13 +161,13 @@
|
|||||||
- [DenyList] Fix DenyList on shared UID apps
|
- [DenyList] Fix DenyList on shared UID apps
|
||||||
- [BusyBox] Add workaround for devices running old kernels
|
- [BusyBox] Add workaround for devices running old kernels
|
||||||
|
|
||||||
### v24.3
|
### v24.3 (2022.3.10)
|
||||||
|
|
||||||
- [General] Stop using `getrandom` syscall
|
- [General] Stop using `getrandom` syscall
|
||||||
- [Zygisk] Update API to v3, adding new fields to `AppSpecializeArgs`
|
- [Zygisk] Update API to v3, adding new fields to `AppSpecializeArgs`
|
||||||
- [App] Improve app repackaging installation workflow
|
- [App] Improve app repackaging installation workflow
|
||||||
|
|
||||||
### v24.2
|
### v24.2 (2022.3.1)
|
||||||
|
|
||||||
- [MagiskSU] Fix buffer overflow
|
- [MagiskSU] Fix buffer overflow
|
||||||
- [MagiskSU] Fix owner managed multiuser superuser settings
|
- [MagiskSU] Fix owner managed multiuser superuser settings
|
||||||
@@ -174,11 +185,11 @@
|
|||||||
- [App] Major app upgrade flow improvements
|
- [App] Major app upgrade flow improvements
|
||||||
- [General] Improve commandline error handling and messaging
|
- [General] Improve commandline error handling and messaging
|
||||||
|
|
||||||
### v24.1
|
### v24.1 (2022.1.28)
|
||||||
|
|
||||||
- [App] Stability improvements
|
- [App] Stability improvements
|
||||||
|
|
||||||
### v24.0
|
### v24.0 (2022.1.26)
|
||||||
|
|
||||||
- [General] MagiskHide is removed from Magisk
|
- [General] MagiskHide is removed from Magisk
|
||||||
- [General] Support Android 12
|
- [General] Support Android 12
|
||||||
@@ -207,7 +218,7 @@
|
|||||||
- [App] Restore the ability to install Magisk on the other slot on some A/B devices
|
- [App] Restore the ability to install Magisk on the other slot on some A/B devices
|
||||||
- [App] Allow modules to specify an update URL for in-app update + install
|
- [App] Allow modules to specify an update URL for in-app update + install
|
||||||
|
|
||||||
### v23.0
|
### v23.0 (2021.5.12)
|
||||||
|
|
||||||
- [App] Update snet extension. This fixes SafetyNet API errors.
|
- [App] Update snet extension. This fixes SafetyNet API errors.
|
||||||
- [App] Fix a bug in the stub app that causes APK installation to fail
|
- [App] Fix a bug in the stub app that causes APK installation to fail
|
||||||
@@ -221,7 +232,7 @@
|
|||||||
- [MagiskHide] Update package and process name validation logic
|
- [MagiskHide] Update package and process name validation logic
|
||||||
- [MagiskHide] Some changes that prevents zygote deadlock
|
- [MagiskHide] Some changes that prevents zygote deadlock
|
||||||
|
|
||||||
### v22.1
|
### v22.1 (2021.4.9)
|
||||||
|
|
||||||
- [App] Prevent multiple installation sessions running in parallel
|
- [App] Prevent multiple installation sessions running in parallel
|
||||||
- [App] Prevent OutOfMemory crashes when checking boot signature on PXA boot images
|
- [App] Prevent OutOfMemory crashes when checking boot signature on PXA boot images
|
||||||
@@ -236,7 +247,7 @@
|
|||||||
- [MagiskInit] Fix `sepolicy.rule` mounting strategy
|
- [MagiskInit] Fix `sepolicy.rule` mounting strategy
|
||||||
- [resetprop] Always delete existing `ro.` props before updating. This will fix bootloops that could be caused by modifying device fingerprint properties.
|
- [resetprop] Always delete existing `ro.` props before updating. This will fix bootloops that could be caused by modifying device fingerprint properties.
|
||||||
|
|
||||||
### v22.0
|
### v22.0 (2021.2.23)
|
||||||
|
|
||||||
- [General] Magisk and Magisk Manager is now merged into the same package!
|
- [General] Magisk and Magisk Manager is now merged into the same package!
|
||||||
- [App] The term "Magisk Manager" is no longer used elsewhere. We refer it as the Magisk app.
|
- [App] The term "Magisk Manager" is no longer used elsewhere. We refer it as the Magisk app.
|
||||||
@@ -248,18 +259,18 @@
|
|||||||
- [MagiskInit] Support Galaxy S21 series
|
- [MagiskInit] Support Galaxy S21 series
|
||||||
- [MagiskSU] Fix incorrect APEX paths that caused `libsqlite.so` fail to load
|
- [MagiskSU] Fix incorrect APEX paths that caused `libsqlite.so` fail to load
|
||||||
|
|
||||||
### v21.4
|
### v21.4 (2021.1.17)
|
||||||
|
|
||||||
- [MagiskSU] Fix `su -c` behavior that broke many root apps
|
- [MagiskSU] Fix `su -c` behavior that broke many root apps
|
||||||
- [General] Properly handle read/write over sockets (the `broken pipe` issue)
|
- [General] Properly handle read/write over sockets (the `broken pipe` issue)
|
||||||
|
|
||||||
### v21.3
|
### v21.3 (2021.1.16)
|
||||||
|
|
||||||
- [MagiskInit] Avoid mounting `f2fs` userdata as it may result in kernel crashes. This shall fix a lot of bootloops
|
- [MagiskInit] Avoid mounting `f2fs` userdata as it may result in kernel crashes. This shall fix a lot of bootloops
|
||||||
- [MagiskBoot] Fix a minor header checksum bug for `DHTB` header and ASUS `blob` image formats
|
- [MagiskBoot] Fix a minor header checksum bug for `DHTB` header and ASUS `blob` image formats
|
||||||
- [MagiskHide] Allowing hiding isolated processes if the mount namespace is separated
|
- [MagiskHide] Allowing hiding isolated processes if the mount namespace is separated
|
||||||
|
|
||||||
### v21.2
|
### v21.2 (2020.12.28)
|
||||||
|
|
||||||
- [MagiskInit] Detect 2SI after mounting `system_root` on legacy SAR devices
|
- [MagiskInit] Detect 2SI after mounting `system_root` on legacy SAR devices
|
||||||
- [General] Make sure `post-fs-data` scripts cannot block more than 35 seconds
|
- [General] Make sure `post-fs-data` scripts cannot block more than 35 seconds
|
||||||
@@ -268,7 +279,7 @@
|
|||||||
- [General] Directly log to file to prevent `logcat` weirdness
|
- [General] Directly log to file to prevent `logcat` weirdness
|
||||||
- [MagiskBoot] Fix header dump/load for header v3 images
|
- [MagiskBoot] Fix header dump/load for header v3 images
|
||||||
|
|
||||||
### v21.1
|
### v21.1 (2020.11.13)
|
||||||
|
|
||||||
- [MagiskBoot] Support boot header v3 (Pixel 5 and 4a 5G)
|
- [MagiskBoot] Support boot header v3 (Pixel 5 and 4a 5G)
|
||||||
- [MagiskBoot] Distinguish `lz4_lg` and `lz4_legacy` (Pixel 5 and 4a 5G)
|
- [MagiskBoot] Distinguish `lz4_lg` and `lz4_legacy` (Pixel 5 and 4a 5G)
|
||||||
@@ -283,7 +294,7 @@
|
|||||||
- [MagiskHide] Support hiding apps installed in secondary users (e.g. work profile)
|
- [MagiskHide] Support hiding apps installed in secondary users (e.g. work profile)
|
||||||
- [MagiskHide] Make zygote detection more robust
|
- [MagiskHide] Make zygote detection more robust
|
||||||
|
|
||||||
### v21.0
|
### v21.0 (2020.10.3)
|
||||||
|
|
||||||
- [General] Support Android 11 🎉
|
- [General] Support Android 11 🎉
|
||||||
- [General] Add Safe Mode detection. Disable all modules when the device is booting into Safe Mode.
|
- [General] Add Safe Mode detection. Disable all modules when the device is booting into Safe Mode.
|
||||||
@@ -303,7 +314,7 @@
|
|||||||
- [MagiskBoot] Pad boot images to original size with zeros
|
- [MagiskBoot] Pad boot images to original size with zeros
|
||||||
- [MagiskHide] Manipulate additional vendor properties
|
- [MagiskHide] Manipulate additional vendor properties
|
||||||
|
|
||||||
### v20.4
|
### v20.4 (2020.3.23)
|
||||||
|
|
||||||
- [MagiskInit] Fix potential bootloop in A-only 2SI devices
|
- [MagiskInit] Fix potential bootloop in A-only 2SI devices
|
||||||
- [MagiskInit] Properly support Tegra partition naming
|
- [MagiskInit] Properly support Tegra partition naming
|
||||||
@@ -321,11 +332,11 @@
|
|||||||
- [Scripts] Better addon.d (both v1 and v2) support
|
- [Scripts] Better addon.d (both v1 and v2) support
|
||||||
- [Scripts] Support Lineage Recovery for Android 10+
|
- [Scripts] Support Lineage Recovery for Android 10+
|
||||||
|
|
||||||
### v20.3
|
### v20.3 (2020.1.10)
|
||||||
|
|
||||||
- [MagiskBoot] Fix `lz4_legacy` decompression
|
- [MagiskBoot] Fix `lz4_legacy` decompression
|
||||||
|
|
||||||
### v20.2
|
### v20.2 (2020.1.2)
|
||||||
|
|
||||||
- [MagiskSU] Properly handle communication between daemon and application (root request prompt)
|
- [MagiskSU] Properly handle communication between daemon and application (root request prompt)
|
||||||
- [MagiskInit] Fix logging in kmsg
|
- [MagiskInit] Fix logging in kmsg
|
||||||
@@ -333,7 +344,7 @@
|
|||||||
- [General] Support pre-init sepolicy patch in modules
|
- [General] Support pre-init sepolicy patch in modules
|
||||||
- [Scripts] Update magisk stock image backup format
|
- [Scripts] Update magisk stock image backup format
|
||||||
|
|
||||||
### v20.1
|
### v20.1 (2019.11.2)
|
||||||
|
|
||||||
- [MagiskSU] Support component name agnostic communication (for stub APK)
|
- [MagiskSU] Support component name agnostic communication (for stub APK)
|
||||||
- [MagiskBoot] Set proper `header_size` in boot image headers (fix vbmeta error on Samsung devices)
|
- [MagiskBoot] Set proper `header_size` in boot image headers (fix vbmeta error on Samsung devices)
|
||||||
@@ -342,7 +353,7 @@
|
|||||||
- [General] Move acct to prevent daemon being killed
|
- [General] Move acct to prevent daemon being killed
|
||||||
- [General] Make sure "--remove-modules" will execute uninstall.sh after removal
|
- [General] Make sure "--remove-modules" will execute uninstall.sh after removal
|
||||||
|
|
||||||
### v20.0
|
### v20.0 (2019.10.11)
|
||||||
|
|
||||||
- [MagiskBoot] Support inject/modify `mnt_point` value in DTB fstab
|
- [MagiskBoot] Support inject/modify `mnt_point` value in DTB fstab
|
||||||
- [MagiskBoot] Support patching QCDT
|
- [MagiskBoot] Support patching QCDT
|
||||||
@@ -352,7 +363,7 @@
|
|||||||
- [MagiskHide] Fix bug that reject process names with ":"
|
- [MagiskHide] Fix bug that reject process names with ":"
|
||||||
- [MagicMount] Fix a bug that cause /product mirror not created
|
- [MagicMount] Fix a bug that cause /product mirror not created
|
||||||
|
|
||||||
### v19.4
|
### v19.4 (2019.9.19)
|
||||||
|
|
||||||
- [MagiskInit] [SAR] Boot system-as-root devices with system mounted as /
|
- [MagiskInit] [SAR] Boot system-as-root devices with system mounted as /
|
||||||
- [MagiskInit] [2SI] Support 2-stage-init for A/B devices (Pixel 3 Android 10)
|
- [MagiskInit] [2SI] Support 2-stage-init for A/B devices (Pixel 3 Android 10)
|
||||||
@@ -368,7 +379,7 @@
|
|||||||
- [General] Add new `--remove-modules` command to remove modules without root in ADB shell
|
- [General] Add new `--remove-modules` command to remove modules without root in ADB shell
|
||||||
- [General] Support Android 10 new APEX libraries (Project Mainline)
|
- [General] Support Android 10 new APEX libraries (Project Mainline)
|
||||||
|
|
||||||
### v19.3
|
### v19.3 (2019.6.5)
|
||||||
|
|
||||||
- [MagiskHide] Hugely improve process monitor implementation, hopefully should no longer cause 100% CPU and daemon crashes
|
- [MagiskHide] Hugely improve process monitor implementation, hopefully should no longer cause 100% CPU and daemon crashes
|
||||||
- [MagiskInit] Wait for partitions to be ready for early mount, should fix bootloops on a handful of devices
|
- [MagiskInit] Wait for partitions to be ready for early mount, should fix bootloops on a handful of devices
|
||||||
@@ -376,7 +387,7 @@
|
|||||||
- [MagiskSU] Properly implement mount namespace isolation
|
- [MagiskSU] Properly implement mount namespace isolation
|
||||||
- [MagiskBoot] Proper checksum calculation for header v2
|
- [MagiskBoot] Proper checksum calculation for header v2
|
||||||
|
|
||||||
### v19.2
|
### v19.2 (2019.5.20)
|
||||||
|
|
||||||
- [General] Fix uninstaller
|
- [General] Fix uninstaller
|
||||||
- [General] Fix bootloops on some devices with tmpfs mounting to /data
|
- [General] Fix bootloops on some devices with tmpfs mounting to /data
|
||||||
@@ -385,7 +396,7 @@
|
|||||||
This fix issues with users locking Magisk Manager with app lock, and prevent
|
This fix issues with users locking Magisk Manager with app lock, and prevent
|
||||||
video apps get messed up when an app is requesting root in the background.
|
video apps get messed up when an app is requesting root in the background.
|
||||||
|
|
||||||
### v19.1
|
### v19.1 (2019.5.1)
|
||||||
|
|
||||||
- [General] Support recovery based Magisk
|
- [General] Support recovery based Magisk
|
||||||
- [General] Support Android Q Beta 2
|
- [General] Support Android Q Beta 2
|
||||||
@@ -395,7 +406,7 @@
|
|||||||
- [MagicMount] Use self created device nodes for mirrors
|
- [MagicMount] Use self created device nodes for mirrors
|
||||||
- [MagicMount] Do not allow adding new files/folders in partition root folder (e.g. /system or /vendor)
|
- [MagicMount] Do not allow adding new files/folders in partition root folder (e.g. /system or /vendor)
|
||||||
|
|
||||||
### v19.0
|
### v19.0 (2019.3.28)
|
||||||
|
|
||||||
- [General] Remove usage of magisk.img
|
- [General] Remove usage of magisk.img
|
||||||
- [General] Add 64 bit magisk binary for native 64 bit support
|
- [General] Add 64 bit magisk binary for native 64 bit support
|
||||||
@@ -413,14 +424,14 @@
|
|||||||
- [MagiskSU] Use `ACTION_REBOOT` intent to workaround some OEM broadcast restrictions
|
- [MagiskSU] Use `ACTION_REBOOT` intent to workaround some OEM broadcast restrictions
|
||||||
- [General] Use `skip_mount` instead of `auto_mount`: from opt-in to opt-out
|
- [General] Use `skip_mount` instead of `auto_mount`: from opt-in to opt-out
|
||||||
|
|
||||||
### v18.1
|
### v18.1 (2019.2.4)
|
||||||
|
|
||||||
- [General] Support EMUI 9.0
|
- [General] Support EMUI 9.0
|
||||||
- [General] Support Kirin 960 devices
|
- [General] Support Kirin 960 devices
|
||||||
- [General] Support down to Android 4.2
|
- [General] Support down to Android 4.2
|
||||||
- [General] Major code base modernization under-the-hood
|
- [General] Major code base modernization under-the-hood
|
||||||
|
|
||||||
### v18.0
|
### v18.0 (2018.12.8)
|
||||||
|
|
||||||
- [General] Migrate all code base to C++
|
- [General] Migrate all code base to C++
|
||||||
- [General] Modify database natively instead of going through Magisk Manager
|
- [General] Modify database natively instead of going through Magisk Manager
|
||||||
@@ -442,7 +453,7 @@
|
|||||||
- [MagiskBoot] Try to repair broken v1 boot image headers
|
- [MagiskBoot] Try to repair broken v1 boot image headers
|
||||||
- [MagiskBoot] Add new CPIO command: "exists"
|
- [MagiskBoot] Add new CPIO command: "exists"
|
||||||
|
|
||||||
### v17.3
|
### v17.3 (2018.10.20)
|
||||||
|
|
||||||
- [MagiskBoot] Support boot image header v1 (Pixel 3)
|
- [MagiskBoot] Support boot image header v1 (Pixel 3)
|
||||||
- [MagiskSU] No more linked lists for caching `su_info`
|
- [MagiskSU] No more linked lists for caching `su_info`
|
||||||
@@ -453,13 +464,13 @@
|
|||||||
- [Scripts] Switch hexpatch to remove Samsung Defex to a more general pattern
|
- [Scripts] Switch hexpatch to remove Samsung Defex to a more general pattern
|
||||||
- [Scripts] Update data encryption detection for better custom recovery support
|
- [Scripts] Update data encryption detection for better custom recovery support
|
||||||
|
|
||||||
### v17.2
|
### v17.2 (2018.9.21)
|
||||||
|
|
||||||
- [ResetProp] Update to AOSP upstream to support serialized system properties
|
- [ResetProp] Update to AOSP upstream to support serialized system properties
|
||||||
- [MagiskInit] Randomize Magisk service names to prevent detection (e.g. FGO)
|
- [MagiskInit] Randomize Magisk service names to prevent detection (e.g. FGO)
|
||||||
- [MagiskSU] New communication scheme to communicate with Magisk Manager
|
- [MagiskSU] New communication scheme to communicate with Magisk Manager
|
||||||
|
|
||||||
### v17.0/17.1
|
### v17.0/17.1 (2018.9.1)
|
||||||
|
|
||||||
- [General] Bring back install to inactive slot for OTAs on A/B devices
|
- [General] Bring back install to inactive slot for OTAs on A/B devices
|
||||||
- [Script] Remove system based root in addon.d
|
- [Script] Remove system based root in addon.d
|
||||||
@@ -471,7 +482,7 @@
|
|||||||
- [MagiskHide] Kill all processes with same UID of the target to workaround OOS embryo optimization
|
- [MagiskHide] Kill all processes with same UID of the target to workaround OOS embryo optimization
|
||||||
- [MagiskInit] Move all sepolicy patches pre-init to prevent Pixel 2 (XL) boot service breakdown
|
- [MagiskInit] Move all sepolicy patches pre-init to prevent Pixel 2 (XL) boot service breakdown
|
||||||
|
|
||||||
### v16.7
|
### v16.7 (2018.7.19)
|
||||||
|
|
||||||
- [Scripts] Fix boot image patching errors on Android P (workaround the strengthened seccomp)
|
- [Scripts] Fix boot image patching errors on Android P (workaround the strengthened seccomp)
|
||||||
- [MagiskHide] Support hardlink based ns proc mnt (old kernel support)
|
- [MagiskHide] Support hardlink based ns proc mnt (old kernel support)
|
||||||
@@ -479,7 +490,7 @@
|
|||||||
- [Daemon] Log fatal errors only on debug builds
|
- [Daemon] Log fatal errors only on debug builds
|
||||||
- [MagiskInit] Detect early mount partname from fstab in device tree
|
- [MagiskInit] Detect early mount partname from fstab in device tree
|
||||||
|
|
||||||
### v16.6
|
### v16.6 (2018.7.8)
|
||||||
|
|
||||||
- [General] Add wrapper script to overcome weird `LD_XXX` flags set in apps
|
- [General] Add wrapper script to overcome weird `LD_XXX` flags set in apps
|
||||||
- [General] Prevent bootloop when flashing Magisk after full wipe on FBE devices
|
- [General] Prevent bootloop when flashing Magisk after full wipe on FBE devices
|
||||||
@@ -501,7 +512,7 @@
|
|||||||
- [ImgTool] Use precise free space calculation methods
|
- [ImgTool] Use precise free space calculation methods
|
||||||
- [ImgTool] Use our own set of loop devices hidden along side with sbin tmpfs overlay. This not only eliminates another possible detection method, but also fixes apps that mount OBB files as loop devices (huge thanks to dev of Pzizz for reporting this issue)
|
- [ImgTool] Use our own set of loop devices hidden along side with sbin tmpfs overlay. This not only eliminates another possible detection method, but also fixes apps that mount OBB files as loop devices (huge thanks to dev of Pzizz for reporting this issue)
|
||||||
|
|
||||||
### v16.4
|
### v16.4 (2018.4.29)
|
||||||
|
|
||||||
- [Daemon] Directly check logcat command instead of detecting logd, should fix logging and MagiskHide on several Samsung devices
|
- [Daemon] Directly check logcat command instead of detecting logd, should fix logging and MagiskHide on several Samsung devices
|
||||||
- [Daemon] Fix startup Magisk Manager APK installation on Android P
|
- [Daemon] Fix startup Magisk Manager APK installation on Android P
|
||||||
@@ -515,17 +526,17 @@
|
|||||||
- [resetprop] Add Protobuf encode/decode to support manipulating persist properties on Android P
|
- [resetprop] Add Protobuf encode/decode to support manipulating persist properties on Android P
|
||||||
- [MagiskHide] Include app sub-services as hiding targets. This might significantly increase the amount of apps that could be properly hidden
|
- [MagiskHide] Include app sub-services as hiding targets. This might significantly increase the amount of apps that could be properly hidden
|
||||||
|
|
||||||
### v16.3
|
### v16.3 (2018.3.28)
|
||||||
|
|
||||||
- [General] Remove symlinks used for backwards compatibility
|
- [General] Remove symlinks used for backwards compatibility
|
||||||
- [MagiskBoot] Fix a small size calculation bug
|
- [MagiskBoot] Fix a small size calculation bug
|
||||||
|
|
||||||
### v16.2
|
### v16.2 (2018.3.18)
|
||||||
|
|
||||||
- [General] Force use system binaries in handling ext4 images (fix module installation on Android P)
|
- [General] Force use system binaries in handling ext4 images (fix module installation on Android P)
|
||||||
- [MagiskHide] Change property state to disable if logd is disabled
|
- [MagiskHide] Change property state to disable if logd is disabled
|
||||||
|
|
||||||
### v16.1
|
### v16.1 (2018.3.11)
|
||||||
|
|
||||||
- [MagiskBoot] Fix MTK boot image packaging
|
- [MagiskBoot] Fix MTK boot image packaging
|
||||||
- [MagiskBoot] Add more Nook/Acclaim headers support
|
- [MagiskBoot] Add more Nook/Acclaim headers support
|
||||||
@@ -535,13 +546,13 @@
|
|||||||
- [resetprop] Support Android P new property context files
|
- [resetprop] Support Android P new property context files
|
||||||
- [MagiskPolicy] Add new rules for Android P
|
- [MagiskPolicy] Add new rules for Android P
|
||||||
|
|
||||||
### v16.0
|
### v16.0 (2018.2.22)
|
||||||
|
|
||||||
- [MagiskInit] Support non `skip_initramfs` devices with slot suffix (Huawei Treble)
|
- [MagiskInit] Support non `skip_initramfs` devices with slot suffix (Huawei Treble)
|
||||||
- [MagiskPolicy] Add rules for Magisk Manager
|
- [MagiskPolicy] Add rules for Magisk Manager
|
||||||
- [Compiler] Workaround an NDK compiler bug that causes bootloops
|
- [Compiler] Workaround an NDK compiler bug that causes bootloops
|
||||||
|
|
||||||
### v15.4
|
### v15.4 (2018.2.13)
|
||||||
|
|
||||||
- [MagiskBoot] Support Samsung PXA, DHTB header images
|
- [MagiskBoot] Support Samsung PXA, DHTB header images
|
||||||
- [MagiskBoot] Support ASUS blob images
|
- [MagiskBoot] Support ASUS blob images
|
||||||
@@ -553,13 +564,13 @@
|
|||||||
- [Daemon] Obfuscate binary names to prevent naive detections
|
- [Daemon] Obfuscate binary names to prevent naive detections
|
||||||
- [Daemon] Check logd before force trying to start logcat in a loop
|
- [Daemon] Check logd before force trying to start logcat in a loop
|
||||||
|
|
||||||
### v15.3
|
### v15.3 (2018.1.12)
|
||||||
|
|
||||||
- [Daemon] Fix the bug that only one script would be executed in post-fs-data.d/service.d
|
- [Daemon] Fix the bug that only one script would be executed in post-fs-data.d/service.d
|
||||||
- [Daemon] Add `MS_SILENT` flag when mounting, should fix some devices that cannot mount magisk.img
|
- [Daemon] Add `MS_SILENT` flag when mounting, should fix some devices that cannot mount magisk.img
|
||||||
- [MagiskBoot] Fix potential segmentation fault when patching ramdisk, should fix some installation failures
|
- [MagiskBoot] Fix potential segmentation fault when patching ramdisk, should fix some installation failures
|
||||||
|
|
||||||
### v15.2
|
### v15.2 (2018.1.1)
|
||||||
|
|
||||||
- [MagiskBoot] Fix dtb verity patches, should fix dm-verity bootloops on newer devices placing fstabs in dtb
|
- [MagiskBoot] Fix dtb verity patches, should fix dm-verity bootloops on newer devices placing fstabs in dtb
|
||||||
- [MagiskPolicy] Add new rules for proper Samsung support, should fix MagiskHide
|
- [MagiskPolicy] Add new rules for proper Samsung support, should fix MagiskHide
|
||||||
@@ -567,17 +578,17 @@
|
|||||||
- [Daemon] Use specific logcat buffers, some devices does not support all log buffers
|
- [Daemon] Use specific logcat buffers, some devices does not support all log buffers
|
||||||
- [scripts] Update scripts to double check whether boot slot is available, some devices set a boot slot without A/B partitions
|
- [scripts] Update scripts to double check whether boot slot is available, some devices set a boot slot without A/B partitions
|
||||||
|
|
||||||
### v15.1
|
### v15.1 (2017.12.29)
|
||||||
|
|
||||||
- [MagiskBoot] Fix faulty code in ramdisk patches which causes bootloops in some config and fstab format combos
|
- [MagiskBoot] Fix faulty code in ramdisk patches which causes bootloops in some config and fstab format combos
|
||||||
|
|
||||||
### v15.0
|
### v15.0 (2017.12.26)
|
||||||
|
|
||||||
- [Daemon] Fix the bug that Magisk cannot properly detect /data encryption state
|
- [Daemon] Fix the bug that Magisk cannot properly detect /data encryption state
|
||||||
- [Daemon] Add merging `/cache/magisk.img` and `/data/adb/magisk_merge.img` support
|
- [Daemon] Add merging `/cache/magisk.img` and `/data/adb/magisk_merge.img` support
|
||||||
- [Daemon] Update to upstream libsepol to support cutting edge split policy custom ROM cil compilations
|
- [Daemon] Update to upstream libsepol to support cutting edge split policy custom ROM cil compilations
|
||||||
|
|
||||||
### v14.6 (1468)
|
### v14.6 (2017.12.22)
|
||||||
|
|
||||||
- [General] Move all files into a safe location: /data/adb
|
- [General] Move all files into a safe location: /data/adb
|
||||||
- [Daemon] New invincible implementation: use `magiskinit_daemon` to monitor sockets
|
- [Daemon] New invincible implementation: use `magiskinit_daemon` to monitor sockets
|
||||||
@@ -590,12 +601,12 @@
|
|||||||
- [MagiskBoot] Massive refactor, rewrite all cpio operations and CLI
|
- [MagiskBoot] Massive refactor, rewrite all cpio operations and CLI
|
||||||
- [MagiskInit][magiskboot] Support ramdisk high compression mode
|
- [MagiskInit][magiskboot] Support ramdisk high compression mode
|
||||||
|
|
||||||
### v14.5 (1456)
|
### v14.5 (1456) (2017.11.23)
|
||||||
|
|
||||||
- [Magiskinit] Fix bootloop issues on several devices
|
- [Magiskinit] Fix bootloop issues on several devices
|
||||||
- [misc] Build binaries with NDK r10e, should get rid of the nasty linker warning when executing magisk
|
- [misc] Build binaries with NDK r10e, should get rid of the nasty linker warning when executing magisk
|
||||||
|
|
||||||
### v14.5 (1455)
|
### v14.5 (1455) (2017.11.23)
|
||||||
|
|
||||||
- [Daemon] Moved internal path to /sbin/.core, new image mountpoint is /sbin/.core/img
|
- [Daemon] Moved internal path to /sbin/.core, new image mountpoint is /sbin/.core/img
|
||||||
- [MagiskSU] Support switching package name, used when Magisk Manager is hidden
|
- [MagiskSU] Support switching package name, used when Magisk Manager is hidden
|
||||||
@@ -610,7 +621,7 @@
|
|||||||
- [script] Add dtbo.img backup and restore support
|
- [script] Add dtbo.img backup and restore support
|
||||||
- [misc] Many small adjustments to properly support old platforms like Android 5.0
|
- [misc] Many small adjustments to properly support old platforms like Android 5.0
|
||||||
|
|
||||||
### v14.3 (1437)
|
### v14.3 (2017.10.15)
|
||||||
|
|
||||||
- [MagiskBoot] Fix Pixel C installation
|
- [MagiskBoot] Fix Pixel C installation
|
||||||
- [MagiskBoot] Handle special `lz4_legacy` format properly, should fix all LG devices
|
- [MagiskBoot] Handle special `lz4_legacy` format properly, should fix all LG devices
|
||||||
@@ -620,11 +631,11 @@
|
|||||||
- [Daemon] Add brute-force image resizing mode, should prevent the notorious Samsung crappy resize2fs from affecting the result
|
- [Daemon] Add brute-force image resizing mode, should prevent the notorious Samsung crappy resize2fs from affecting the result
|
||||||
- [resetprop] Add new "-p" flag, used to toggle whether alter/access the actual persist storage for persist props
|
- [resetprop] Add new "-p" flag, used to toggle whether alter/access the actual persist storage for persist props
|
||||||
|
|
||||||
### v14.2
|
### v14.2 (2017.9.28)
|
||||||
|
|
||||||
- [MagicMount] Clone attributes to tmpfs mountpoint, should fix massive module breakage
|
- [MagicMount] Clone attributes to tmpfs mountpoint, should fix massive module breakage
|
||||||
|
|
||||||
### v14.1
|
### v14.1 (2017.9.28)
|
||||||
|
|
||||||
- [MagiskInit] Introduce a new init binary to support `skip_initramfs` devices (Pixel family)
|
- [MagiskInit] Introduce a new init binary to support `skip_initramfs` devices (Pixel family)
|
||||||
- [script] Fix typo in update-binary for x86 devices
|
- [script] Fix typo in update-binary for x86 devices
|
||||||
@@ -639,7 +650,7 @@
|
|||||||
- [resetprop] Fix a bug which delete props won't remove persist props not in memory
|
- [resetprop] Fix a bug which delete props won't remove persist props not in memory
|
||||||
- [MagicMount] Remove usage of dummy folder, directly mount tmpfs and construct file structure skeleton in place
|
- [MagicMount] Remove usage of dummy folder, directly mount tmpfs and construct file structure skeleton in place
|
||||||
|
|
||||||
### v14.0
|
### v14.0 (2017.9.6)
|
||||||
|
|
||||||
- [script] Simplify installation scripts
|
- [script] Simplify installation scripts
|
||||||
- [script] Fix a bug causing backing up and restoring stock boot images failure
|
- [script] Fix a bug causing backing up and restoring stock boot images failure
|
||||||
@@ -658,20 +669,20 @@
|
|||||||
- [Daemon] Adjustments to prevent stock Samsung kernel restrictions on exec system calls for binaries started from /data
|
- [Daemon] Adjustments to prevent stock Samsung kernel restrictions on exec system calls for binaries started from /data
|
||||||
- [Daemon] Workaround on Samsung device with weird fork behaviors
|
- [Daemon] Workaround on Samsung device with weird fork behaviors
|
||||||
|
|
||||||
### v13.3
|
### v13.3 (2017.7.18)
|
||||||
|
|
||||||
- [MagiskHide] Update to bypass Google CTS (2017.7.17)
|
- [MagiskHide] Update to bypass Google CTS (2017.7.17)
|
||||||
- [resetprop] Properly support removing persist props
|
- [resetprop] Properly support removing persist props
|
||||||
- [uninstaller] Remove Magisk Manager and persist props
|
- [uninstaller] Remove Magisk Manager and persist props
|
||||||
|
|
||||||
### v13.2
|
### v13.2 (2017.7.14)
|
||||||
|
|
||||||
- [magiskpolicy] Fix magiskpolicy segfault on old Android versions, should fix tons of older devices that couldn't use v13.1
|
- [magiskpolicy] Fix magiskpolicy segfault on old Android versions, should fix tons of older devices that couldn't use v13.1
|
||||||
- [MagiskHide] Set proper selinux context while re-linking /sbin to hide Magisk, should potentially fix many issues
|
- [MagiskHide] Set proper selinux context while re-linking /sbin to hide Magisk, should potentially fix many issues
|
||||||
- [MagiskBoot] Change lzma compression encoder flag from `LZMA_CHECK_CRC64` to `LZMA_CHECK_CRC32`, kernel only supports latter
|
- [MagiskBoot] Change lzma compression encoder flag from `LZMA_CHECK_CRC64` to `LZMA_CHECK_CRC32`, kernel only supports latter
|
||||||
- [General] Core-only mode now properly mounts systemless hosts and magiskhide
|
- [General] Core-only mode now properly mounts systemless hosts and magiskhide
|
||||||
|
|
||||||
### v13.1
|
### v13.1 (2017.7.11)
|
||||||
|
|
||||||
- [General] Merge MagiskSU, magiskhide, resetprop, magiskpolicy into one binary
|
- [General] Merge MagiskSU, magiskhide, resetprop, magiskpolicy into one binary
|
||||||
- [General] Add Android O support (tested on DP3)
|
- [General] Add Android O support (tested on DP3)
|
||||||
@@ -702,7 +713,7 @@
|
|||||||
- [MagiskHide] Remove background magiskhide daemon, spawn short life process for unmounting purpose
|
- [MagiskHide] Remove background magiskhide daemon, spawn short life process for unmounting purpose
|
||||||
- [Magic Mount] Ditched shell script based mounting, use proper C program to parse and mount files. Speed is SIGNIFICANTLY improved
|
- [Magic Mount] Ditched shell script based mounting, use proper C program to parse and mount files. Speed is SIGNIFICANTLY improved
|
||||||
|
|
||||||
### v12.0
|
### v12.0 (2017.3.31)
|
||||||
|
|
||||||
- [General] Move most binaries into magisk.img (Samsung cannot run su daemon in /data)
|
- [General] Move most binaries into magisk.img (Samsung cannot run su daemon in /data)
|
||||||
- [General] Move sepolicy live patch to `late_start` service
|
- [General] Move sepolicy live patch to `late_start` service
|
||||||
@@ -719,7 +730,7 @@
|
|||||||
- [MagiskBoot] Add lz4 legacy format support (most linux kernel using lz4 for compression is using this)
|
- [MagiskBoot] Add lz4 legacy format support (most linux kernel using lz4 for compression is using this)
|
||||||
- [MagiskBoot] Fix MTK kernels with MTK headers
|
- [MagiskBoot] Fix MTK kernels with MTK headers
|
||||||
|
|
||||||
### v11.5/11.6
|
### v11.5/11.6 (2017.3.21)
|
||||||
|
|
||||||
- [Magic Mount] Fix mounting issues with devices that have separate /vendor partitions
|
- [Magic Mount] Fix mounting issues with devices that have separate /vendor partitions
|
||||||
- [MagiskBoot] Whole new boot image patching tool, please check release note for more info
|
- [MagiskBoot] Whole new boot image patching tool, please check release note for more info
|
||||||
@@ -731,12 +742,12 @@
|
|||||||
- [MagiskSU] Fix read-only partition mounting issues
|
- [MagiskSU] Fix read-only partition mounting issues
|
||||||
- [MagiskSU] Disable -cn option, the option will do nothing, preserved for compatibility
|
- [MagiskSU] Disable -cn option, the option will do nothing, preserved for compatibility
|
||||||
|
|
||||||
### v11.1
|
### v11.1 (2017.2.6)
|
||||||
|
|
||||||
- [sepolicy-inject] Add missing messages
|
- [sepolicy-inject] Add missing messages
|
||||||
- [magiskhide] Start MagiskHide with scripts
|
- [magiskhide] Start MagiskHide with scripts
|
||||||
|
|
||||||
### v11.0
|
### v11.0 (2017.2.6)
|
||||||
|
|
||||||
- [Magic Mount] Support replacing symlinks.
|
- [Magic Mount] Support replacing symlinks.
|
||||||
Symlinks cannot be a target of a bind mounted, so they are treated the same as new files
|
Symlinks cannot be a target of a bind mounted, so they are treated the same as new files
|
||||||
@@ -764,13 +775,13 @@
|
|||||||
- [Addition] Add post-fs-data.d and service.d
|
- [Addition] Add post-fs-data.d and service.d
|
||||||
- [Addition] Add option to disable Magisk (MagiskSU will still be started)
|
- [Addition] Add option to disable Magisk (MagiskSU will still be started)
|
||||||
|
|
||||||
### v10.2
|
### v10.2 (2017.1.2)
|
||||||
|
|
||||||
- [Magic Mount] Remove apps/priv-app from whitelist, should fix all crashes
|
- [Magic Mount] Remove apps/priv-app from whitelist, should fix all crashes
|
||||||
- [phh] Fix binary out-of-date issue
|
- [phh] Fix binary out-of-date issue
|
||||||
- [scripts] Fix root disappear issue when upgrading within Magisk Manager
|
- [scripts] Fix root disappear issue when upgrading within Magisk Manager
|
||||||
|
|
||||||
### v10
|
### v10 (2017.1.2)
|
||||||
|
|
||||||
- [Magic Mount] Use a new way to mount system (vendor) mirrors
|
- [Magic Mount] Use a new way to mount system (vendor) mirrors
|
||||||
- [Magic Mount] Use universal way to deal with /vendor, handle both separate partition or not
|
- [Magic Mount] Use universal way to deal with /vendor, handle both separate partition or not
|
||||||
@@ -784,7 +795,7 @@
|
|||||||
- [scripts] Improve SuperSU integration, now uses sukernel to patch ramdisk, support SuperSU built in ramdisk restore
|
- [scripts] Improve SuperSU integration, now uses sukernel to patch ramdisk, support SuperSU built in ramdisk restore
|
||||||
- [template] Add PROPFILE option to load system.prop
|
- [template] Add PROPFILE option to load system.prop
|
||||||
|
|
||||||
### v9
|
### v9 (2016.11.14)
|
||||||
|
|
||||||
- **[API Change] Remove the interface for post-fs modules**
|
- **[API Change] Remove the interface for post-fs modules**
|
||||||
- [resetprop] New tool "resetprop" is added to Magisk to replace most post-fs modules' functionality
|
- [resetprop] New tool "resetprop" is added to Magisk to replace most post-fs modules' functionality
|
||||||
@@ -796,13 +807,13 @@
|
|||||||
- [Boot Image] Add support for Motorola boot image dtb, it shall now unpack correctly
|
- [Boot Image] Add support for Motorola boot image dtb, it shall now unpack correctly
|
||||||
- [Uninstaller] Add removal of SuperSU custom patch script
|
- [Uninstaller] Add removal of SuperSU custom patch script
|
||||||
|
|
||||||
### v8
|
### v8 (2016.10.19)
|
||||||
|
|
||||||
- Add Magisk Hide to bypass SafetyNet
|
- Add Magisk Hide to bypass SafetyNet
|
||||||
- Improve SuperSU integration: no longer changes the SuperSU PATH
|
- Improve SuperSU integration: no longer changes the SuperSU PATH
|
||||||
- Support rc script entry points not located in init.rc
|
- Support rc script entry points not located in init.rc
|
||||||
|
|
||||||
### v7
|
### v7 (2016.10.04)
|
||||||
|
|
||||||
- Fully open source
|
- Fully open source
|
||||||
- Remove supolicy dependency, use my own sepolicy-injection
|
- Remove supolicy dependency, use my own sepolicy-injection
|
||||||
@@ -814,17 +825,17 @@
|
|||||||
- New paths to toggle busybox, and support all root solutions
|
- New paths to toggle busybox, and support all root solutions
|
||||||
- Remove root management API; both SuperSU and phh has their own superior solutions
|
- Remove root management API; both SuperSU and phh has their own superior solutions
|
||||||
|
|
||||||
### v6
|
### [v6 (2016.8.21)](https://xdaforums.com/t/magisk-general-support-discussion.3432382/post-68298121)
|
||||||
|
|
||||||
- Fixed the algorithm for adding new files and dummy system
|
- Fixed the algorithm for adding new files and dummy system
|
||||||
- Updated the module template with a default permission, since people tend to forget them :)
|
- Updated the module template with a default permission, since people tend to forget them :)
|
||||||
|
|
||||||
### v5
|
### [v5 (2016.8.20)](https://xdaforums.com/t/magisk-general-support-discussion.3432382/post-68274534)
|
||||||
|
|
||||||
- Hotfix for older Android versions (detect policy before patching)
|
- Hotfix for older Android versions (detect policy before patching)
|
||||||
- Update uninstaller to NOT uninstall Magisk Manager, since it cause problems
|
- Update uninstaller to NOT uninstall Magisk Manager, since it cause problems
|
||||||
|
|
||||||
### v4
|
### [v4 (2016.8.19)](https://xdaforums.com/t/magisk-general-support-discussion.3432382/post-68269300)
|
||||||
|
|
||||||
- Important: Uninstall v1 - v3 Magisk before upgrading with the uninstaller in the OP!!
|
- Important: Uninstall v1 - v3 Magisk before upgrading with the uninstaller in the OP!!
|
||||||
- Massive Rewrite Magisk Interface API! All previous mods are NOT compatible! Please download the latest version of the mods you use (root/xposed)
|
- Massive Rewrite Magisk Interface API! All previous mods are NOT compatible! Please download the latest version of the mods you use (root/xposed)
|
||||||
@@ -833,7 +844,7 @@
|
|||||||
- Use minimal sepolicy patch in boot image for smaller ramdisk size. Live patch policies after bootup
|
- Use minimal sepolicy patch in boot image for smaller ramdisk size. Live patch policies after bootup
|
||||||
- Include updated open source sepolicy injection tool (source code available), support nearly all SuperSU supolicy tool's functionality
|
- Include updated open source sepolicy injection tool (source code available), support nearly all SuperSU supolicy tool's functionality
|
||||||
|
|
||||||
### v3
|
### [v3 (2016.8.11)](https://xdaforums.com/t/magisk-general-support-discussion.3432382/post-68146978)
|
||||||
|
|
||||||
- Fix bootimg-extract for Exynos Samsung devices (thanks to @phhusson), should fix all Samsung device issues
|
- Fix bootimg-extract for Exynos Samsung devices (thanks to @phhusson), should fix all Samsung device issues
|
||||||
- Add supolicy back to patch sepolicy (stock Samsung do not accept permissive domain)
|
- Add supolicy back to patch sepolicy (stock Samsung do not accept permissive domain)
|
||||||
@@ -843,7 +854,7 @@
|
|||||||
- Use the highest possible compression rate for ramdisk, hope to fix some devices with no boot partition space
|
- Use the highest possible compression rate for ramdisk, hope to fix some devices with no boot partition space
|
||||||
- Detect boot partition space insufficient, will abort installer instead of breaking your device
|
- Detect boot partition space insufficient, will abort installer instead of breaking your device
|
||||||
|
|
||||||
### v2
|
### [v2 (2016.8.9)](https://xdaforums.com/t/magisk-general-support-discussion.3432382/post-68108058)
|
||||||
|
|
||||||
- Fix verity patch. It should now work on all devices (might fix some of the unable-to-boot issues)
|
- Fix verity patch. It should now work on all devices (might fix some of the unable-to-boot issues)
|
||||||
- All scripts will now run in selinux permissive mode for maximum compatibility (this will **NOT** turn your device to permissive)
|
- All scripts will now run in selinux permissive mode for maximum compatibility (this will **NOT** turn your device to permissive)
|
||||||
@@ -853,6 +864,6 @@
|
|||||||
- Remove sepolicy patches that uses SuperSU's supolicy tool; it is now using a minimal set of modifications
|
- Remove sepolicy patches that uses SuperSU's supolicy tool; it is now using a minimal set of modifications
|
||||||
- Removed Magisk Manager in Magisk patch, it is now included in Magisk phh's superuser only
|
- Removed Magisk Manager in Magisk patch, it is now included in Magisk phh's superuser only
|
||||||
|
|
||||||
### v1
|
### [v1 (2016.8.3)](https://xdaforums.com/t/magisk-general-support-discussion.3432382/post-68034103)
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|||||||
12
docs/faq.md
12
docs/faq.md
@@ -16,9 +16,17 @@ The following details should ensure that modules are properly disabled:
|
|||||||
|
|
||||||
Magisk no longer handles root hiding. There are plenty of Magisk/Zygisk modules available that specifically provide these functionalities, please search around 😉
|
Magisk no longer handles root hiding. There are plenty of Magisk/Zygisk modules available that specifically provide these functionalities, please search around 😉
|
||||||
|
|
||||||
### Q: After I hidden the Magisk app, the app icon is broken.
|
### Q: Magisk App shows Magisk Installed = N/A after an update but magisk su is still working.
|
||||||
|
|
||||||
When hiding the Magisk app, it will install a "stub" APK that has nothing in it. The only functionality this stub app has is downloading the full Magisk app APK into its internal storage and dynamically loading it. Due to the fact that the APK is literally _empty_, it does not contain the image resource for the app icon.
|
If upgrading with App hidden (ie. you took the 'Hide the Magisk app' option), the stub app (for hiding Magisk) may remain while a full Magisk app is also installed. This creates a conflict and the full app fails to see or access root... Uninstalling and reinstalling the full app can fix this, but not if a hidden app (stub) still exists.
|
||||||
|
|
||||||
|
The solution is to check for a hidden stub app and remove it. It may not show up normally in your launcher homescreen any longer, but should be visible from general settings, Apps. The hidden app will be named 'Settings' (default) or whatever you named it during the hiding process. Note that it is possible to have multiple obfuscated apps present. Uninstall any iterations of the hidden app you find and try opening the full app again. If necessary, uninstall it and reinstall the full app matching the binaries installed. Typing magisk -c in a terminal emulator app will show the version and version code for Magisk binaries installed (despite Installed = N/A showing).
|
||||||
|
|
||||||
|
Additionally, if a 'second space', eg. Workspace, Parallel Space etc, or another sandboxed environment, eg. a Multiple User additional profile, Island app or similar, is set up, check that no iterations of Magisk (either hidden or full apps) are running within these environments.
|
||||||
|
|
||||||
|
### Q: After I take the 'Hide the Magisk app' option the app icon is broken.
|
||||||
|
|
||||||
|
When hiding the Magisk app, it will install a "stub" APK that has nothing in it. The only functionality this stub app has is to download the full Magisk app APK data into its internal storage and dynamically load it. Due to the fact that the stub APK is literally empty, it does not contain the image resource for the app icon.
|
||||||
|
|
||||||
When you open the hidden Magisk app, it will offer you the option to create a shortcut in the homescreen (which has both the correct app name and icon) for your convenience. You can also manually ask the app to create the icon in app settings.
|
When you open the hidden Magisk app, it will offer you the option to create a shortcut in the homescreen (which has both the correct app name and icon) for your convenience. You can also manually ask the app to create the icon in app settings.
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
## 2018.12.7 Magisk v18.0
|
|
||||||
|
|
||||||
Here comes a stable release, this time with quite a few major updates!
|
|
||||||
|
|
||||||
### MagiskHide Improvements
|
|
||||||
Starting from v18, the process monitor matches component names instead of process names. Android allow app services to name their process arbitrarily, and many apps starting to use dedicated services to detect root; it used to require adding all of these service process names to the list to hide Magisk effectively. Component names have the format: `<package name>/<java class name>`, which means we can always know which application spawned a given process.
|
|
||||||
|
|
||||||
**TL;DR, ALL processes spawned from the applications on the hide list will be targeted.**
|
|
||||||
|
|
||||||
Recently I discovered a *very widespread Linux kernel bug* affecting tons of Android devices (full write-up: [Medium Article](https://medium.com/@topjohnwu/from-anime-game-to-android-system-security-vulnerability-9b955a182f20)). This bug exposes the supposedly protected `procfs`, which is abused in some apps to detect Magisk with information leaked from other processes. Magisk will patch this bug on all Android 7.0+ devices. Yes, a fully effective MagiskHide requires the enhanced Android Sandbox in modern Android versions.
|
|
||||||
|
|
||||||
### Path Changes
|
|
||||||
The name of the folder `/sbin/.core` is confusing and will no longer be used; it is replaced with `/sbin/.magisk`. Another major change is the location to store general boot scripts. As these boot scripts should still run even if `magisk.img` is not mounted, they are moved out of `magisk.img`, from `<img>/.core/<stage>.d` to `/data/adb/<stage>.d` (stage is either `post-fs-data` or `service`). Say goodbye to stupid paths like `/sbin/.core/img/.core/post-fs-data.d`!
|
|
||||||
|
|
||||||
Quick recap:
|
|
||||||
|
|
||||||
- New `magisk.img` mountpoint: `/sbin/.magisk/img`
|
|
||||||
- New internal busybox PATH: `/sbin/.magisk/busybox`
|
|
||||||
- The folder `<img>/.core` is no longer used in any places. `magisk.img` is solely used for storing modules, no other functionality depends on it.
|
|
||||||
- **Symlinks are created so all old paths will still work. None of the existing apps/scripts depending on these internal paths should break, but please migrate to the new paths ASAP.**
|
|
||||||
|
|
||||||
### Dropping Legacy Support
|
|
||||||
**The NEXT Magisk Manager upgrade (not this one) will only support v18+, please upgrade ASAP.** Magisk Manager is always designed to be fully functional across a wide range of Magisk versions. However, to enforce full obfuscation, I will have to drop legacy support eventually.
|
|
||||||
|
|
||||||
This is also a good opportunity to push the whole community forward, all module developers should forget about backward compatibility (e.g. stop supporting the old Magisk paths, please don't torture yourself...). I expect very few structural changes in the near future, so again, please upgrade ASAP :)
|
|
||||||
|
|
||||||
### Modern C++ Code Base
|
|
||||||
Although this has nothing to do with the end user, tons of effort was done to migrate Magisk to a more modern C++ code base instead of the previous good plain old C. This makes the code easier to maintain and allows me to utilized many C++ language features.
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# 2019.2.4 Magisk v18.1
|
|
||||||
|
|
||||||
What is a better way to celebrate Chinese New Year than a new Magisk update!
|
|
||||||
|
|
||||||
### EMUI 9 Support
|
|
||||||
Welcome on board "again", Huawei! Even though Huawei had officially blocked bootloader unlocks, people still love to buy them (duh), and there are paid services that unlock Huawei bootloaders. So hey, get Magisk installed on that bad boy! One caveat is that since Huawei have changed the partitions, special workarounds has to be done. Details and instructions are in the newly created [instruction page](https://topjohnwu.github.io/Magisk/install.html)
|
|
||||||
|
|
||||||
### Support Down to Android 4.2
|
|
||||||
Because why not, it was quite a lot of fun LOL. All devices running KitKat and higher will have all features enabled. MagiskHide and resetprop aren't possible on Jellybean, and Magic Mount (modules) is temporarily disabled; basically it only works as a root solution for now. Android 4.1 isn't 100% usable yet, so installation is also temporarily blocked. Eventually, all Jellybean devices will have full Magic Mount and MagiskSU support.
|
|
||||||
|
|
||||||
### Major Magisk Manager Update
|
|
||||||
Aside from the obvious major UI overhaul, tons of little user experience and performance improvements are also added. The app is finally less crappy now :)
|
|
||||||
|
|
||||||
### Final Words
|
|
||||||
I'm aware that there are apps updated to detect Magisk, however no MagiskHide improvements efforts are done in this release; v18.1 is aimed to be as stable as possible. Stay tuned for future public betas, or if you are more adventurous, jump on the Canary Channel bandwagon for more aggressive hiding techniques :)
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# 2019.3.28 Magisk v19.0
|
|
||||||
|
|
||||||
I would say this is one of my most ambitious release of all time! Due to the extremely massive changes, this release will be a public beta. Calling it v18.2 doesn't do it justice, so v19.0 we go.
|
|
||||||
|
|
||||||
## Magisk Module installer
|
|
||||||
**Magisk module developers: pay extra attention!** A completely new [Magisk Module Installer](https://github.com/topjohnwu/magisk-module-installer) replaces the old Magisk module template. This new format decouples **ALL** installation logic from modules, and encourages developers to use the provided API for installation. This new format is **ENFORCED**, meaning all existing modules should upgrade ASAP, and new modules are **REQUIRED** to follow the rules.
|
|
||||||
|
|
||||||
Carefully read through the [updated docs](https://topjohnwu.github.io/Magisk/guides.html)!
|
|
||||||
|
|
||||||
**Warning: All existing modules that does not use the new module format will be automatically removed on May 1st, 2019. Module devs: upgrade your existing modules ASAP!**
|
|
||||||
|
|
||||||
## Imageless Magisk
|
|
||||||
Since the existence of Magisk, all modules are stored within an EXT4 image which will be loop mounted at boot. This approach has a few problems: resizing the image is a huge headache (no live resizing, `resize2fs` on some devices refuse to work properly), and also MANY devices using F2FS ships a broken driver with the kernel, causing EXT4 loop devices unable to be mounted at all. All these problems come to an end now: modules are now directly stored in `/data`! Backwards compatibility is provided, for modules that uses the official module template, installation should work just fine.
|
|
||||||
|
|
||||||
**Warning: Although module migration was tested, there are still chances that your modules will get lost in the process. Be prepared to reinstall your existing modules in that case.**
|
|
||||||
|
|
||||||
## Native 64 Bit is Back
|
|
||||||
At one point in history, Magisk uses native 64 binaries. However due to binary size considerations, all binaries was switched to 32 bit. Starting from v19, all static binaries are still 32 bit only, but the most important part: the main `magisk` binary now runs in native 64 bit on supported devices.
|
|
||||||
|
|
||||||
## Zygote Ptrace Based MagiskHide
|
|
||||||
MagiskHide used to use `logcat` to monitor activity manager events for new process creation. That method is extremely unreliable: even with constant improvements since introduction, it is still not working 100% of the time. Here comes a fundamentally new approach: ptrace the zygote process and step through all fork events. In layman's term, this new method is able to target a process before it even starts to run! The code for it is extremely tricky, but it was tested for quite a while in the canary channel, so I'm confident enough to release this to the public :)
|
|
||||||
|
|
||||||
## Android Q
|
|
||||||
Full support for Android Q Beta 1 is also introduced in this release. However, you cannot use it on the Pixel 3 (XL) due to the fact that Google decided to use logical partitions on the 3rd gen Pixels starting with Q. A solution is still WIP, please stay tuned!
|
|
||||||
|
|
||||||
## Final Words
|
|
||||||
What you can expect in upcoming releases: Samsung S10 support, and full logical partition support. Also, I *AM* aware of Google Pay issues, but these are not my main focus now since there are still tons of other issues for me to focus on. Several discussion threads on XDA provide seemingly working solutions, please do some research on your own.
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# 2019.5.1 Magisk v19.1
|
|
||||||
Finally, a lovely stable release!
|
|
||||||
|
|
||||||
For those that were using v18.1, here are some quick highlights of v19.0
|
|
||||||
|
|
||||||
- Imageless Magisk: Although module migration was tested, there are still chances that your modules will get lost in the process. Be prepared to reinstall your existing modules in that case.
|
|
||||||
- Native 64-bit support
|
|
||||||
- Zygote Ptrace Based MagiskHide
|
|
||||||
|
|
||||||
Other than adding support for Samsung system-as-root devices, this release is mostly bug fixes from v19.0. Enjoy :)
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# TODO
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# TODO
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# 2019.9.19 Magisk v19.4
|
|
||||||
This version is heavily tested and tons of bugs were squashed before release. However due to the massive changes, it is decided to release a public beta for people/root app developers to adjust/update before things hit public stable.
|
|
||||||
|
|
||||||
### New System-as-root Implementation
|
|
||||||
Magisk has supported system-as-root devices for a long time since the first Pixel came out. The goal is always to revert things back to the good old initramfs based root dir. However, this not only creates tons of issues on many devices, not easily hide-able with MagiskHide, but most importantly not even possible on Android 10. Starting with v19.4, Magisk will follow how Google has designed system-as-root: mounting system actually to `/` (root).
|
|
||||||
|
|
||||||
This implies several **MASSIVE** consequences for system-as-root devices:
|
|
||||||
- `/system` is no longer a valid mount point. For existing root apps that remounts `/system` to `rw`, you will have to remount `/` instead of `/system`
|
|
||||||
- The root directory (`/`) is no longer `rootfs`, but actually system. Remounting `/` to `rw` and modify files means you are writing to the actual system partition, NOT volatile storage as it used to be in `rootfs`. This is not recommended as user is not necessary aware that you are tampering an actual partition, sometimes dangerous if dm-verity/AVB-verity is enforced, or sometimes outright impossible since many devices now ship with read-only system partitions (e.g. EROFS, EXT4 dedup)
|
|
||||||
- Several custom kernel rely on Magisk's root directory overlay system (`overlay`) for modifying `/`. This is no longer compatible with the new implementation. A new overlay system (`overlay.d`) will replace the existing one as an alternative (details in [documentations](https://topjohnwu.github.io/Magisk/guides.html#root-directory-overlay-system)). To provide backwards compatibility, Magisk will switch to "Compat Mode" when `/overlay` is detected, which simply reverts to the old system-as-root setup. **Compat Mode will not work on Android 10 and will cause bootloop**. Although things will still work as it used to, **please upgrade to `overlay.d` ASAP**.
|
|
||||||
|
|
||||||
### Android 10 Support
|
|
||||||
Other than A-only devices running Android 10, Android 10 is fully supported with MagiskHide fully functioning. Android 10's biggest challenge is the new "2-Stage-Init" system-as-root implementation, which is the sole reason why A-only is not support yet. Stay tuned for further updates as that is the next thing on the list.
|
|
||||||
|
|
||||||
(For those interested in "2-Stage-Init" and other details of system-as-root, check [this Twitter thread I tweeted](https://twitter.com/topjohnwu/status/1174392824625676288))
|
|
||||||
|
|
||||||
### Product Partition Support
|
|
||||||
Magisk Module developers can now finally properly modify files in `/product`! This partition is now an essential part in Android 10, and many files are moved from system to product. Please check [documentations](https://topjohnwu.github.io/Magisk/details.html#magic-mount) for more details.
|
|
||||||
|
|
||||||
### A-Only System-as-root
|
|
||||||
A huge number of new devices have A-only system-as-root setups (Android 9.0). These unfortunate devices will have to install Magisk into the recovery partition. Please check the fully updated [Installation Guide](https://topjohnwu.github.io/Magisk/install.html) for more details.
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# 2019.10.11 Magisk v20.0
|
|
||||||
The following release notes are mostly the same as v19.4. Compared to v19.4 beta, the most notable change is adding tons of support for more devices on Android 10, along with several bug fixes.
|
|
||||||
|
|
||||||
### New System-as-root Implementation
|
|
||||||
Magisk has supported system-as-root devices for a long time since the first Pixel came out. The goal is always to revert things back to the good old initramfs based root dir. However, this not only creates tons of issues on many devices, not easily hide-able with MagiskHide, but most importantly not even possible on Android 10. Magisk will now start to follow how Google has designed system-as-root: mounting system actually to `/` (root).
|
|
||||||
|
|
||||||
This implies several **MASSIVE** consequences for system-as-root devices:
|
|
||||||
- `/system` is no longer a valid mount point. For existing root apps that remounts `/system` to `rw`, you will have to remount `/` instead of `/system`
|
|
||||||
- The root directory (`/`) is no longer `rootfs`, but actually system. Remounting `/` to `rw` and modify files means you are writing to the actual system partition, NOT volatile storage as it used to be in `rootfs`. This is not recommended as user is not necessary aware that you are tampering an actual partition, sometimes dangerous if dm-verity/AVB-verity is enforced, or sometimes outright impossible since many devices now ship with read-only system partitions (e.g. EROFS, EXT4 dedup)
|
|
||||||
- Several custom kernel rely on Magisk's root directory overlay system (`overlay`) for modifying `/`. This is no longer compatible with the new implementation. A new overlay system (`overlay.d`) will replace the existing one as an alternative (details in [documentations](https://topjohnwu.github.io/Magisk/guides.html#root-directory-overlay-system)). To provide backwards compatibility, Magisk will switch to "Compat Mode" when `/overlay` is detected, which simply reverts to the old system-as-root setup. **Compat Mode will not work on Android 10 and will cause bootloop**. Although things will still work as it used to, **please upgrade to `overlay.d` ASAP**.
|
|
||||||
|
|
||||||
### Android 10 Support
|
|
||||||
Android 10 is now fully supported with MagiskHide working as expected. Android 10's biggest challenge is the new "2-Stage-Init" system-as-root implementation, which requires modding early mount fstab in a specific way, and in many devices' cases involves patching DTBs in the boot image.
|
|
||||||
|
|
||||||
(For those interested in "2-Stage-Init" and other details of system-as-root, check [this Twitter thread I tweeted](https://twitter.com/topjohnwu/status/1174392824625676288))
|
|
||||||
|
|
||||||
### Product Partition Support
|
|
||||||
Magisk Module developers can now finally properly modify files in `/product`! This partition is now an essential part in Android 10, and many files are moved from system to product. Please check [documentations](https://topjohnwu.github.io/Magisk/details.html#magic-mount) for more details.
|
|
||||||
|
|
||||||
### A-Only System-as-root
|
|
||||||
A huge number of new devices have A-only system-as-root setups (Android 9.0). These unfortunate devices will have to install Magisk into the recovery partition. Please check the fully updated [Installation Guide](https://topjohnwu.github.io/Magisk/install.html) for more details.
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# 2019.11.2 Magisk v20.1
|
|
||||||
Lots of bug fixes from v20.0, and some cool new features!
|
|
||||||
|
|
||||||
### Updated Magisk Manager Hiding
|
|
||||||
Starting with Magisk v20.1 paired with Magisk Manager v7.4.0, a new hiding mode is introduced for Android 9.0+. On supported devices, Magisk Manager will download and customize a heavily obfuscated stub APK and use it as a replacement. The stub app will then download the full app into its private internal data, then dynamically load and run the actual full Magisk Manager.
|
|
||||||
|
|
||||||
Note, not all Android 9.0+ devices will be able to use this feature. To use an obfuscated stub as Magisk Manager, the Magisk daemon will have to rely on a special way to communicate with the app, and some OEMs (most likely Chinese manufacturers) block certain broadcasts, breaking the communication channel.
|
|
||||||
|
|
||||||
Magisk Manager will verify compatibility before it uses stubs to hide itself on Android 9.0+. **The verification relies on Magisk v20.1+, which means you have to fully upgrade and reboot in order to opt in this feature.** If you are already running a hidden Magisk Manager, **restore and upgrade Magisk Manager, upgrade Magisk and reboot, then re-hide the app**.
|
|
||||||
|
|
||||||
For those incompatible with the hiding-with-stub feature, there are also a few updates that everyone, regardless whether using stubs or not, can enjoy:
|
|
||||||
|
|
||||||
- You can now customize the app name of the repackaged Magisk Manager
|
|
||||||
- Magisk Manager will generate new keys to sign the repackaged APK to prevent signature detection
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# 2020.1.2 Magisk v20.2
|
|
||||||
|
|
||||||
Happy New Year! Let's start 2020 with a new Magisk release :)
|
|
||||||
|
|
||||||
### Pre-Init sepolicy Patches for Modules
|
|
||||||
Magisk v20.2 add support for modules to include its own custom sepolicy patches. Developers used to use boot scripts along with the `magiskpolicy` tool to do live sepolicy patches; however, this method leads to numerous issues as Android is no longer designed to allow live sepolicy patches, and on some devices (e.g. Huawei) this method is outright inapplicable.
|
|
||||||
|
|
||||||
To address this issue, Magisk allow module devs to create a new file called `sepolicy.rule` in their modules. The module installer script and Magisk daemon will make sure this file is stored in somewhere accessible pre-init to allow `magiskinit` to do its job every time your device boots up.
|
|
||||||
|
|
||||||
### New Module Installer Format
|
|
||||||
The old template is actually pretty convoluted: developers are expected to implement specific callback functions in their `install.sh`, and the zip file structure does not directly represent how modules are actually stored on your device. The new module installer format makes creating new modules very easy, but still give experienced developers tons of freedom to do anything they want in the installation process.
|
|
||||||
|
|
||||||
For details regarding `sepolicy.rule` and the new module installer format, please read the updated [Developer Guides](https://topjohnwu.github.io/Magisk/guides.html). Note that the old "Module Installer Template" is obsolete; creating a Magisk module no longer requires a "template" as it is now a straightforward process.
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# 2020.1.10 Magisk v20.3
|
|
||||||
|
|
||||||
### Magisk
|
|
||||||
- Fix `magiskboot` crashing when dealing with `lz4_legacy` format
|
|
||||||
|
|
||||||
### Magisk Manager
|
|
||||||
- Fix MagiskHide app component toggles
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
## 2020.3.23 Magisk v20.4
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
This release is mainly focused on stability and bug squashing. Please be aware that MagiskHide is no longer enabled by default. Since Google has enabled [hardware-based key attestation](https://twitter.com/topjohnwu/status/1237656703929180160?s=20) in SafetyNet ([FAQ](https://twitter.com/topjohnwu/status/1237830555523149824?s=20)), there is no effective way to pass full CTS SafetyNet anymore (although Google seems to have temporarily [reverted the change](https://twitter.com/topjohnwu/status/1238514375150850048?s=20)).
|
|
||||||
|
|
||||||
I decided that the fully redesigned Magisk Manager isn't fully ready for prime time yet, so this time around no Magisk Manager update is released. The WIP manager will continue to be improved and is available for testing on the canary channel.
|
|
||||||
|
|
||||||
### BusyBox Standalone Mode
|
|
||||||
Starting with Magisk v20.4, all Magisk related scripts, including boot scripts and module installation scripts, will run on BusyBox's shell (ash) in **standalone mode**. In BusyBox ash standalone mode, **every single command** will be **forced** to use the one that is in Magisk's BusyBox (if available). For instance, no matter how you change the environment variable `PATH`, the `rm` command will always use the one in BusyBox, not the one in system, external BusyBox, vendor, or included in custom recovery.
|
|
||||||
|
|
||||||
The reason behind this change is that all scripts will be guaranteed to have 100% consistent results no matter how the environment is setup. The internal BusyBox is significantly beefed up with patches from @osm0sis, and also with SELinux features enabled. It shall offer a very complete, reliable, and consistent scripting environment. If in any case you **require** to use a command outside of BusyBox, please call it with the full path (e.g. `/system/bin/nslookup`)
|
|
||||||
|
|
||||||
### Magisk Changelog
|
|
||||||
- [MagiskInit] Fix potential bootloop in A-only 2SI devices
|
|
||||||
- [MagiskInit] Properly support Tegra partition naming
|
|
||||||
- [General] Load libsqlite.so dynamically, which removes the need to use wrapper scripts on Android 10+
|
|
||||||
- [General] Detect API level with a fallback method on some devices
|
|
||||||
- [General] Workaround possible bug in x86 kernel readlinkat system call
|
|
||||||
- [BusyBox] Enable SELinux features. Add chcon/runcon etc., and '-Z' option to many applets
|
|
||||||
- [BusyBox] Introduce standalone mode. More details in release notes
|
|
||||||
- [MagiskHide] Disable MagiskHide by default
|
|
||||||
- [MagiskHide] Add more potential detectable system properties
|
|
||||||
- [MagiskHide] Add workaround for Xiaomi devices bootloop when MagiskHide is enabled on cross region ROMs
|
|
||||||
- [MagiskBoot] Support patching special Motorolla DTB format
|
|
||||||
- [MagiskPolicy] Support 'genfscon' sepolicy rules
|
|
||||||
- [Scripts] Support NAND based boot images (character nodes in /dev/block)
|
|
||||||
- [Scripts] Better addon.d (both v1 and v2) support
|
|
||||||
- [Scripts] Support Lineage Recovery for Android 10+
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
## 2020.10.3 Magisk v21.0
|
|
||||||
|
|
||||||
Long time no see! v21.0 is the largest release in Magisk's history. It comes with full Android 11 support (tons of stuff had to be rewritten from scratch!), and a completely redesigned Magisk Manager. These are the reasons why this particular public release took me over half a year to wrap up.
|
|
||||||
|
|
||||||
To the end user, not much has changed other than the fact that Magisk Manager has completely changed its appearance. However developers should pay attention to some changes due to adjustments for Android 11. Full changelogs are too massive to fit, so here I'll point out the main changes and links to updated documentations.
|
|
||||||
|
|
||||||
### Highlights
|
|
||||||
|
|
||||||
- Android 11 support 🎉
|
|
||||||
- Completely redesigned Magisk Manager
|
|
||||||
- Safe Mode detection: if you installed a module that bootloops your device, reboot into Safe Mode and all modules will be disabled. More instructions on how to deal with broken modules is linked [here](https://topjohnwu.github.io/Magisk/faq.html).
|
|
||||||
|
|
||||||
The following are for advanced users/developer:
|
|
||||||
|
|
||||||
- On Android 8.0+, Magisk now uses a new SELinux setup that keeps Android sandbox less compromised. This provides better security to rooted users, and also separates Magisk rules from original rules. Details [here](https://topjohnwu.github.io/Magisk/details.html#selinux-policies).
|
|
||||||
- On Android 11, `/sbin` may no longer exist. For developers, this means the Magisk's internal `tmpfs` directory is no longer always `/sbin`, and instead randomly created every boot. To get the `tmpfs` path, use the command `magisk --path` (more details [here](https://topjohnwu.github.io/Magisk/details.html)). For custom kernel developers that uses `overlay.d`, updated docs are [here](https://topjohnwu.github.io/Magisk/guides.html#root-directory-overlay-system).
|
|
||||||
- `magiskpolicy` gained more features and some minor syntax changes, details [here](https://topjohnwu.github.io/Magisk/tools.html#magiskpolicy).
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
## 2020.11.13 Magisk v21.1
|
|
||||||
|
|
||||||
v21.1 is a maintenance update from v21.0, mostly addressing bugs, refining some details, and adding new boot image format support (for Pixel 5 and 4a 5G). Checkout the full [v21.0 release notes](https://topjohnwu.github.io/Magisk/releases/21000.html) if coming from older releases.
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
## 2020.12.28 Magisk v21.2
|
|
||||||
|
|
||||||
v21.2 is a maintenance update, mostly addressing bugs, and expanding device compatibility. Checkout the full [v21.0 release notes](https://topjohnwu.github.io/Magisk/releases/21000.html) if coming from older releases.
|
|
||||||
|
|
||||||
### v21.2
|
|
||||||
|
|
||||||
- [MagiskInit] Detect 2SI after mounting `system_root` on legacy SAR devices
|
|
||||||
- [General] Make sure `post-fs-data` scripts cannot block more than 35 seconds
|
|
||||||
- [General] Fix the `magisk --install-module` command
|
|
||||||
- [General] Trim Windows newline when reading files
|
|
||||||
- [General] Directly log to file to prevent `logcat` weirdness
|
|
||||||
- [MagiskBoot] Fix header dump/load for header v3 images
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
## 2021.1.17 Magisk v21.4
|
|
||||||
|
|
||||||
**Update**: v21.4 adds more regression hot fixes.
|
|
||||||
|
|
||||||
Happy 2021! v21.3 adds a workaround for devices with buggy F2FS Linux kernel drivers. This F2FS bug may cause bootloops on many devices. Checkout the full [v21.0 release notes](https://topjohnwu.github.io/Magisk/releases/21000.html) if coming from older releases.
|
|
||||||
|
|
||||||
### v21.4
|
|
||||||
|
|
||||||
- [MagiskSU] Fix `su -c` behavior that broke many root apps
|
|
||||||
- [General] Properly handle read/write over sockets (the `broken pipe` issue)
|
|
||||||
|
|
||||||
### v21.3
|
|
||||||
|
|
||||||
- [MagiskInit] Avoid mounting `f2fs` userdata as it may result in kernel crashes. This shall fix a lot of bootloops
|
|
||||||
- [MagiskBoot] Fix a minor header checksum bug for `DHTB` header and ASUS `blob` image formats
|
|
||||||
- [MagiskHide] Allowing hiding isolated processes if the mount namespace is separated
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
## 2021.2.23 Magisk v22.0
|
|
||||||
|
|
||||||
### RESTORE THE EXISTING MAGISK MANAGER BACK TO NORMAL BEFORE UPGRADING IF HIDDEN!
|
|
||||||
|
|
||||||
Another major Magisk release! This time our focus is not the core Magisk implementation, but rather on improving the whole Magisk user experience.
|
|
||||||
|
|
||||||
### Magisk Manager is dead.<br>Long live the Magisk app!
|
|
||||||
|
|
||||||
Ever since the first Magisk release, Magisk (the core components) and Magisk Manager (the companion app) are released separately and isn't necessarily always in sync. This leads to some confusion and a lot of complexity when downloading/installing Magisk through the app. Starting from v22.0, the Magisk app (renamed from Magisk Manager) includes everything it needs within the APK itself, making installation a 100% offline process.
|
|
||||||
|
|
||||||
Custom recovery lovers, no worries! The Magisk app APK *itself* is a custom recovery flashable zip, just like MAGIC™🌈. Check out the updated [installation guide](https://topjohnwu.github.io/Magisk/install.html) for more info.
|
|
||||||
|
|
||||||
### App Hiding
|
|
||||||
|
|
||||||
Another major breakthrough in this release is that devices lower than Android 9.0 can now also use the advanced app hiding technique to hide the Magisk app. Due to this incompatible change, **RESTORE THE EXISTING MAGISK MANAGER BACK TO NORMAL BEFORE UPGRADING IF HIDDEN!**
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
- [MagiskHide] Fix a bug when stopping MagiskHide does not take effect
|
|
||||||
- [MagiskBoot] Fix bug when unpacking `lz4_lg` compressed boot images
|
|
||||||
- [MagiskInit] Support Galaxy S21 series
|
|
||||||
- [MagiskSU] Fix incorrect APEX paths that caused `libsqlite.so` fail to load
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
## 2021.4.9 Magisk v22.1
|
|
||||||
|
|
||||||
This release is focused on fixing regressions and bugs. Check the [v22.0 release notes](https://topjohnwu.github.io/Magisk/releases/22000.html) if coming from older releases.
|
|
||||||
|
|
||||||
Note: Magisk v22 is the last major version to support Jellybean and Kitkat. Magisk v23 will only support Android 5.0 and higher.
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
- [App] Prevent multiple installation sessions running in parallel
|
|
||||||
- [App] Prevent OutOfMemory crashes when checking boot signature on PXA boot images
|
|
||||||
- [General] Proper cgroup migration implementation
|
|
||||||
- [General] Rewrite log writer from scratch, should resolve any crashes and deadlocks
|
|
||||||
- [General] Many scripts updates fixing regressions
|
|
||||||
- [MagiskHide] Prevent possible deadlock when signal arrives
|
|
||||||
- [MagiskHide] Partial match process names if necessary
|
|
||||||
- [MagiskBoot] Preserve and patch AVB 2.0 structures/headers in boot images
|
|
||||||
- [MagiskBoot] Properly strip out data encryption flags
|
|
||||||
- [MagiskBoot] Prevent possible integer overflow
|
|
||||||
- [MagiskInit] Fix `sepolicy.rule` mounting strategy
|
|
||||||
- [resetprop] Always delete existing `ro.` props before updating. This will fix bootloops that could be caused by modifying device fingerprint properties.
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
## 2021.5.12 Magisk v23.0
|
|
||||||
|
|
||||||
This release is focused on fixing regressions and bugs.
|
|
||||||
|
|
||||||
Note: Magisk v22 is the last major version to support Jellybean and Kitkat. Magisk v23 only supports Android 5.0 and higher.
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
- [App] Update snet extension. This fixes SafetyNet API errors.
|
|
||||||
- [App] Fix a bug in the stub app that causes APK installation to fail
|
|
||||||
- [App] Hide annoying errors in logs when hidden as stub
|
|
||||||
- [App] Fix issues when patching ODIN tar files when the app is hidden
|
|
||||||
- [General] Remove all pre Android 5.0 support
|
|
||||||
- [General] Update BusyBox to use proper libc
|
|
||||||
- [General] Fix C++ undefined behaviors
|
|
||||||
- [General] Several `sepolicy.rule` copy/installation fixes
|
|
||||||
- [MagiskPolicy] Remove unnecessary sepolicy rules
|
|
||||||
- [MagiskHide] Update package and process name validation logic
|
|
||||||
- [MagiskHide] Some changes that prevents zygote deadlock
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
## 2022.1.26 Magisk v24.0
|
|
||||||
|
|
||||||
It has been a while since the last public release, long time no see! A personal update for those unaware: I am now working at Google on the Android Platform Security team. Without further ado, let's jump right into it!
|
|
||||||
|
|
||||||
### MagiskHide Removal
|
|
||||||
|
|
||||||
I have lost interest in fighting this battle for quite a while; plus, the existing MagiskHide implementation is flawed in so many ways. Decoupling Magisk from root hiding is, in my opinion, beneficial to the community. Ever since my announcement on Twitter months ago, highly effective "root hiding" modules (much **MUCH** better than MagiskHide) has been flourishing, which again shows that people are way more capable than I am on this subject. So why not give those determined their time to shine, and let me focus on improving Magisk instead of drowning in the everlasting cat-and-mouse game 😉.
|
|
||||||
|
|
||||||
### Sunsetting Magisk-Modules-Repo
|
|
||||||
|
|
||||||
Due to lack of time and maintenance, the centralized Magisk-Modules-Repo was frozen, and the functionality to download modules from the repo is removed in v24.0. As a supplement, module developers can now specify an `updateJson` URL in their modules. The Magisk app will use that to check, download, and install module updates.
|
|
||||||
|
|
||||||
### Introducing Zygisk
|
|
||||||
|
|
||||||
Zygisk is **Magisk in Zygote**, the next big thing for Magisk! When this feature is enabled, a part of Magisk will run in the `Zygote` daemon process, allowing module developers to run code directly in every Android apps' processes. If you've heard of [Riru](https://github.com/RikkaApps/Riru), then Zygisk is inspired by that project and is functionally similar, though the implementation is quite different internally. I cannot wait to see what module developers can achieve using Zygisk!
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
|
|
||||||
For developers, details about `updateJson` and building Zygisk modules can all be found in the updated [documentation](https://topjohnwu.github.io/Magisk/guides.html#magisk-modules).
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
## 2022.1.28 Magisk v24.1
|
|
||||||
|
|
||||||
> For those coming from v24.0, v24.1 only has some minor app improvements. The following are copied from v24.0 release notes.
|
|
||||||
|
|
||||||
It has been a while since the last public release, long time no see! A personal update for those unaware: I am now working at Google on the Android Platform Security team. Without further ado, let's jump right into it!
|
|
||||||
|
|
||||||
### MagiskHide Removal
|
|
||||||
|
|
||||||
I have lost interest in fighting this battle for quite a while; plus, the existing MagiskHide implementation is flawed in so many ways. Decoupling Magisk from root hiding is, in my opinion, beneficial to the community. Ever since my announcement on Twitter months ago, highly effective "root hiding" modules (much **MUCH** better than MagiskHide) has been flourishing, which again shows that people are way more capable than I am on this subject. So why not give those determined their time to shine, and let me focus on improving Magisk instead of drowning in the everlasting cat-and-mouse game 😉.
|
|
||||||
|
|
||||||
### Sunsetting Magisk-Modules-Repo
|
|
||||||
|
|
||||||
Due to lack of time and maintenance, the centralized Magisk-Modules-Repo was frozen, and the functionality to download modules from the repo is removed in v24.0. As a supplement, module developers can now specify an `updateJson` URL in their modules. The Magisk app will use that to check, download, and install module updates.
|
|
||||||
|
|
||||||
### Introducing Zygisk
|
|
||||||
|
|
||||||
Zygisk is **Magisk in Zygote**, the next big thing for Magisk! When this feature is enabled, a part of Magisk will run in the `Zygote` daemon process, allowing module developers to run code directly in every Android apps' processes. If you've heard of [Riru](https://github.com/RikkaApps/Riru), then Zygisk is inspired by that project and is functionally similar, though the implementation is quite different internally. I cannot wait to see what module developers can achieve using Zygisk!
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
|
|
||||||
For developers, details about `updateJson` and building Zygisk modules can all be found in the updated [documentation](https://topjohnwu.github.io/Magisk/guides.html#magisk-modules).
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
## 2022.3.1 Magisk v24.2
|
|
||||||
|
|
||||||
Maintenance release fixing various issues.
|
|
||||||
|
|
||||||
- [MagiskSU] Fix buffer overflow
|
|
||||||
- [MagiskSU] Fix owner managed multiuser superuser settings
|
|
||||||
- [MagiskSU] Fix command logging when using `su -c <cmd>`
|
|
||||||
- [MagiskSU] Prevent su request indefinite blocking
|
|
||||||
- [MagiskBoot] Support `lz4_legacy` archive with multiple magic
|
|
||||||
- [MagiskBoot] Fix `lz4_lg` compression
|
|
||||||
- [DenyList] Allow targeting processes running as system UID
|
|
||||||
- [Zygisk] Workaround Samsung's "early zygote"
|
|
||||||
- [Zygisk] Improved Zygisk loading mechanism
|
|
||||||
- [Zygisk] Fix application UID tracking
|
|
||||||
- [Zygisk] Fix improper `umask` being set in zygote
|
|
||||||
- [App] Fix BusyBox execution test
|
|
||||||
- [App] Improve stub loading mechanism
|
|
||||||
- [App] Major app upgrade flow improvements
|
|
||||||
- [General] Improve commandline error handling and messaging
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
## 2022.3.10 Magisk v24.3
|
|
||||||
|
|
||||||
For those coming from v24.1, check the full changelog for changes introduced in v24.2.
|
|
||||||
|
|
||||||
- [General] Stop using `getrandom` syscall
|
|
||||||
- [Zygisk] Update API to v3, adding new fields to `AppSpecializeArgs`
|
|
||||||
- [App] Improve app repackaging installation workflow
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
## 2022.6.7 Magisk v25.0
|
|
||||||
|
|
||||||
Another major release! A lot of the changes aren't visible at the surface, but v25 is actually a really substantial upgrade!
|
|
||||||
|
|
||||||
### MagiskInit Rewrite
|
|
||||||
|
|
||||||
A significant portion of `magiskinit` (the critical software that runs before your device boots up) is completely rewritten from scratch. Ever since Android introduced [Project Treble](https://android-developers.googleblog.com/2017/05/here-comes-treble-modular-base-for.html) in Android 8.0, Magisk has been constantly fighting against the increasingly complex partitioning and early mount setups of all kinds of devices, sometimes with weird OEM specific implementations. It got to a point that `magiskinit` had become so complicated that few people (including myself!) were aware of every detail, and maintaining this piece of software like this was clearly not sustainable. After many months of planning (yes, this whole re-architecture has been in my head for a long time) and some help from external contributors, a whole new `sepolicy` injection mechanism is introduced into Magisk, solving the "SELinux Problem" once and for all.
|
|
||||||
|
|
||||||
Since this is a full paradigm shift on how Magisk hot-patch the device at boot, several behaviors that many developers implicitly relied on might not exist. For example, Magisk no longer patches fstabs in most scenarios, which means AVB will remain intact; some custom kernels rely on AVB being stripped out for them by Magisk.
|
|
||||||
|
|
||||||
### MagiskSU Security Enhancements
|
|
||||||
|
|
||||||
The superuser functionality of Magisk has not seen much changes ever since its introduction. v25 focuses on making root permission management more accurate and secure:
|
|
||||||
|
|
||||||
- Add a whole new package tracking system to ensure malicious UID reuse attack cannot be performed
|
|
||||||
- Properly support and implement the UX in the Magisk app for packages using `sharedUserId`
|
|
||||||
- Enforce root manager APK signature verification to combat the rampant unofficial Magisk app "mods"
|
|
||||||
|
|
||||||
Many might not realize, but using a trusted, unmodified Magisk app is really important. Magisk's root daemon treats the Magisk app differently and gives it blanket root access without any restrictions. A modded Magisk app can potentially backdoor your device.
|
|
||||||
|
|
||||||
And in case some of you are about to put on your tin foil hats, this is not designed to "vendor lock-in"; the goal is to make sure your root management app comes from the same developer of the underlying root implementation. Magisk's build system allows custom distributors to use its own signing keys, and in addition, I am also providing official debug builds which skips any signature verification for development.
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
## 2022.6.19 Magisk v25.1
|
|
||||||
|
|
||||||
> v25.1 fixes some minor bugs over v25.0. The following are the same as v25.0 release notes.
|
|
||||||
|
|
||||||
Another major release! A lot of the changes aren't visible at the surface, but v25 is actually a really substantial upgrade!
|
|
||||||
|
|
||||||
### MagiskInit Rewrite
|
|
||||||
|
|
||||||
A significant portion of `magiskinit` (the critical software that runs before your device boots up) is completely rewritten from scratch. Ever since Android introduced [Project Treble](https://android-developers.googleblog.com/2017/05/here-comes-treble-modular-base-for.html) in Android 8.0, Magisk has been constantly fighting against the increasingly complex partitioning and early mount setups of all kinds of devices, sometimes with weird OEM specific implementations. It got to a point that `magiskinit` had become so complicated that few people (including myself!) were aware of every detail, and maintaining this piece of software like this was clearly not sustainable. After many months of planning (yes, this whole re-architecture has been in my head for a long time) and some help from external contributors, a whole new `sepolicy` injection mechanism is introduced into Magisk, solving the "SELinux Problem" once and for all.
|
|
||||||
|
|
||||||
Since this is a full paradigm shift on how Magisk hot-patch the device at boot, several behaviors that many developers implicitly relied on might not exist. For example, Magisk no longer patches fstabs in most scenarios, which means AVB will remain intact; some custom kernels rely on AVB being stripped out for them by Magisk.
|
|
||||||
|
|
||||||
### MagiskSU Security Enhancements
|
|
||||||
|
|
||||||
The superuser functionality of Magisk has not seen much changes ever since its introduction. v25 focuses on making root permission management more accurate and secure:
|
|
||||||
|
|
||||||
- Add a whole new package tracking system to ensure malicious UID reuse attack cannot be performed
|
|
||||||
- Properly support and implement the UX in the Magisk app for packages using `sharedUserId`
|
|
||||||
- Enforce root manager APK signature verification to combat the rampant unofficial Magisk app "mods"
|
|
||||||
|
|
||||||
Many might not realize, but using a trusted, unmodified Magisk app is really important. Magisk's root daemon treats the Magisk app differently and gives it blanket root access without any restrictions. A modded Magisk app can potentially backdoor your device.
|
|
||||||
|
|
||||||
And in case some of you are about to put on your tin foil hats, this is not designed to "vendor lock-in"; the goal is to make sure your root management app comes from the same developer of the underlying root implementation. Magisk's build system allows custom distributors to use its own signing keys, and in addition, I am also providing official debug builds which skips any signature verification for development.
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
## 2022.7.20 Magisk v25.2
|
|
||||||
|
|
||||||
Maintenance release fixing various issues.
|
|
||||||
|
|
||||||
- [MagiskInit] Fix a potential issue when stub cpio is used
|
|
||||||
- [MagiskInit] Fix reboot to recovery when stub cpio is used
|
|
||||||
- [MagiskInit] Fix sepolicy.rules symlink for rootfs devices
|
|
||||||
- [General] Better data encryption detection
|
|
||||||
- [General] Move the whole logging infrastructure into Rust
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
## 2023.4.5 Magisk v26.0
|
|
||||||
|
|
||||||
Hey! Long time no see!
|
|
||||||
|
|
||||||
### Bumping Minimum Android Version to 6.0
|
|
||||||
|
|
||||||
Magisk's support for Android Lollipop has been pretty broken for a while without it being noticed. Also, none of the active developers of Magisk have actual hardware to run Android Lollipop. We rely on using the official Android emulator for regression testing on older platforms, however Google never shipped a Lollipop emulator image with SELinux support, leaving us with no option but to drop Lollipop support since we don't feel comfortable supporting Android Lollipop without adequate testing.
|
|
||||||
|
|
||||||
### New Magic Mount Implementation
|
|
||||||
|
|
||||||
Magic Mount, the feature that make modules modify partitions, has gone through a major rewrite. The existing implementation doesn't work well with OEMs injecting overlays into their system using `overlayfs`. The new implementation fundamentally changes how filesystem mirrors are created, giving us a more accurate clone of the unmodified filesystem.
|
|
||||||
|
|
||||||
### New `sepolicy.rule` Implementation
|
|
||||||
|
|
||||||
Magisk allows modules to provide custom SELinux patches by including the file `sepolicy.rule`. Due to the complicated nature of SELinux patching, the compatibility of this functionality has been pretty spotty; many devices are not supported. In this release, a brand new pre-init partition detection mechanism has been designed to support even more devices. Due to complicated reasons, this detection mechanism cannot be performed in a custom recovery environment.
|
|
||||||
|
|
||||||
**This means that any installation of Magisk v26+ using custom recovery will be incomplete; a subsequent re-installation through the Magisk app after booting up is required.**
|
|
||||||
|
|
||||||
### Zygisk Updates
|
|
||||||
|
|
||||||
**The new Zygisk API v4 is now live!** It comes with new features and a refined PLT function hook API. The implementaton of Zygisk has also gone through some major refactoring, including new code loading/unloading mechanisms and a new PLT function hook implementation.
|
|
||||||
|
|
||||||
Head over to the [Zygisk Module Sample](https://github.com/topjohnwu/zygisk-module-sample) repository to check out the new API and documentation!
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
## 2023.4.11 Magisk v26.1
|
|
||||||
|
|
||||||
### Changes from v26.0
|
|
||||||
|
|
||||||
- [App] Fix crashing when revoking root permissions
|
|
||||||
- [MagiskInit] Always prefer `ext4` partitions over `f2fs` when selecting the pre-init partition
|
|
||||||
- [General] Restore module files' context/owner/group from mirror. This is a regression introduced in v26.0
|
|
||||||
|
|
||||||
(The following is the same as v26.0 release notes)
|
|
||||||
|
|
||||||
Hey! Long time no see!
|
|
||||||
|
|
||||||
### Bumping Minimum Android Version to 6.0
|
|
||||||
|
|
||||||
Magisk's support for Android Lollipop has been pretty broken for a while without it being noticed. Also, none of the active developers of Magisk have actual hardware to run Android Lollipop. We rely on using the official Android emulator for regression testing on older platforms, however Google never shipped a Lollipop emulator image with SELinux support, leaving us with no option but to drop Lollipop support since we don't feel comfortable supporting Android Lollipop without adequate testing.
|
|
||||||
|
|
||||||
### New Magic Mount Implementation
|
|
||||||
|
|
||||||
Magic Mount, the feature that make modules modify partitions, has gone through a major rewrite. The existing implementation doesn't work well with OEMs injecting overlays into their system using `overlayfs`. The new implementation fundamentally changes how filesystem mirrors are created, giving us a more accurate clone of the unmodified filesystem.
|
|
||||||
|
|
||||||
### New `sepolicy.rule` Implementation
|
|
||||||
|
|
||||||
Magisk allows modules to provide custom SELinux patches by including the file `sepolicy.rule`. Due to the complicated nature of SELinux patching, the compatibility of this functionality has been pretty spotty; many devices are not supported. In this release, a brand new pre-init partition detection mechanism has been designed to support even more devices. Due to complicated reasons, this detection mechanism cannot be performed in a custom recovery environment.
|
|
||||||
|
|
||||||
**This means that any installation of Magisk v26+ using custom recovery will be incomplete; a subsequent re-installation through the Magisk app after booting up is required.**
|
|
||||||
|
|
||||||
### Zygisk Updates
|
|
||||||
|
|
||||||
**The new Zygisk API v4 is now live!** It comes with new features and a refined PLT function hook API. The implementaton of Zygisk has also gone through some major refactoring, including new code loading/unloading mechanisms and a new PLT function hook implementation.
|
|
||||||
|
|
||||||
Head over to the [Zygisk Module Sample](https://github.com/topjohnwu/zygisk-module-sample) repository to check out the new API and documentation!
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
## 2023.8.27 Magisk v26.2
|
|
||||||
|
|
||||||
- [MagiskBoot] Support extracting boot image from `payload.bin`
|
|
||||||
- [MagiskBoot] Support cpio files containing character files
|
|
||||||
- [MagiskBoot] Support listing cpio content
|
|
||||||
- [MagiskBoot] Directly handle AVB 1.0 signing and verification without going through Java implementation
|
|
||||||
- [Daemon] Make daemon socket a fixed path in MAGISKTMP
|
|
||||||
- [resetprop] Support printing property context
|
|
||||||
- [resetprop] Support only printing persistent properties from storage
|
|
||||||
- [resetprop] Properly support setting persistent properties bypassing property_service
|
|
||||||
- [MagiskSU] Support `-g` and `-G` options
|
|
||||||
- [MagiskSU] Support switching mount namespace to PID with `-t`
|
|
||||||
- [MagiskPolicy] Fix patching extended permissions
|
|
||||||
- [MagiskPolicy] Support more syntax for extended permissions
|
|
||||||
- [MagiskPolicy] Support printing out the loaded sepolicy rules
|
|
||||||
- [App] Support patching boot image from ROM zips
|
|
||||||
- [App] Properly preserve `boot.img` when patching Samsung firmware with `init_boot.img`
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
## 2023.9.4 Magisk v26.3
|
|
||||||
|
|
||||||
### v26.3
|
|
||||||
|
|
||||||
- [General] Fix device information detection script
|
|
||||||
- [General] Update BusyBox to 1.36.1
|
|
||||||
- [General] Update toolchain that produces broken arm32 executables
|
|
||||||
- [App] Fix root service unable to bind on OnePlus devices
|
|
||||||
|
|
||||||
### v26.2
|
|
||||||
|
|
||||||
- [MagiskBoot] Support extracting boot image from `payload.bin`
|
|
||||||
- [MagiskBoot] Support cpio files containing character files
|
|
||||||
- [MagiskBoot] Support listing cpio content
|
|
||||||
- [MagiskBoot] Directly handle AVB 1.0 signing and verification without going through Java implementation
|
|
||||||
- [Daemon] Make daemon socket a fixed path in MAGISKTMP
|
|
||||||
- [resetprop] Support printing property context
|
|
||||||
- [resetprop] Support only printing persistent properties from storage
|
|
||||||
- [resetprop] Properly support setting persistent properties bypassing property_service
|
|
||||||
- [MagiskSU] Support `-g` and `-G` options
|
|
||||||
- [MagiskSU] Support switching mount namespace to PID with `-t`
|
|
||||||
- [MagiskPolicy] Fix patching extended permissions
|
|
||||||
- [MagiskPolicy] Support more syntax for extended permissions
|
|
||||||
- [MagiskPolicy] Support printing out the loaded sepolicy rules
|
|
||||||
- [App] Support patching boot image from ROM zips
|
|
||||||
- [App] Properly preserve `boot.img` when patching Samsung firmware with `init_boot.img`
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
## 2023.11.5 Magisk v26.4
|
|
||||||
|
|
||||||
- [MagiskBoot] Don't pad zeros if signed boot image is larger
|
|
||||||
- [MagiskPolicy] Fix `genfscon` and `filename_trans`
|
|
||||||
- [MagiskPolicy] Fix bug in `libsepol`
|
|
||||||
- [Zygisk] Fix and simplify file descriptor sanitization logic
|
|
||||||
- [App] Prevent OOM when patching AP tarfiles
|
|
||||||
- [App] Fix bug in device configuration detection
|
|
||||||
- [Daemon] Fix certificate parsing of APKs
|
|
||||||
- [General] Fix logging errors from C++ code being ignored
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
## 2024.2.3 Magisk v27.0
|
|
||||||
|
|
||||||
- [Zygisk] Introduce new code injection mechanism
|
|
||||||
- [Zygisk] Support new signature introduced in U QPR2
|
|
||||||
- [SEPolicy] Update libsepol to properly set some policy config bits
|
|
||||||
- [MagiskBoot] Support compressing `init` so Magisk is installable on devices with small boot partitions
|
|
||||||
- [ResetProp] Add new wait for property feature `resetprop -w`
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
## 2024.10.10 Magisk v28.0
|
|
||||||
|
|
||||||
- [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,33 +0,0 @@
|
|||||||
## 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,16 +0,0 @@
|
|||||||
## 2025.5.14 Magisk v29.0
|
|
||||||
|
|
||||||
This release looks minor at the surface, however, the entire codebase has gone through significant refactoring and migration. The native code in Magisk used to be mainly C++, but several contributors and I have been steadily rewriting parts of the code in Rust since April 2022. After years of effort, the Rust-ification of the project slowly began picking up steam, and at the moment of this release, over 40% of the native code has been rewritten in Rust, with several major subsystem rewrites in the PR queue, planned to be merged for the next release.
|
|
||||||
|
|
||||||
Many might wonder, why introduce a new language to the project? My reason is actually not to reduce memory safety issues (although it is a nice side benefit), but to be able to develop Magisk using a more modern programming language. After using Rust for a while, it's clear to me that using Rust allows me to write more correct code and makes me happier compared to dealing with C++. People share the [same sentiment as I do](https://threadreaderapp.com/thread/1577667445719912450.html).
|
|
||||||
|
|
||||||
## Changelog
|
|
||||||
|
|
||||||
- [General] Massive internal refactoring and code migration
|
|
||||||
- [App] Support downloading module zip files with XZ compression
|
|
||||||
- [App] Disable app animations when system animations are disabled
|
|
||||||
- [MagiskMount] Support systemlessly deleting files with modules using blank file nodes
|
|
||||||
- [MagiskInit] Redesign sepolicy patching and injection logic
|
|
||||||
- [MagiskSU] Better TTY/PTY support
|
|
||||||
|
|
||||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
# Release Notes
|
|
||||||
|
|
||||||
- [v29.0](29000.md)
|
|
||||||
- [v28.1](28100.md)
|
|
||||||
- [v28.0](28000.md)
|
|
||||||
- [v27.0](27000.md)
|
|
||||||
- [v26.4](26400.md)
|
|
||||||
- [v26.3](26300.md)
|
|
||||||
- [v26.2](26200.md)
|
|
||||||
- [v26.1](26100.md)
|
|
||||||
- [v26.0](26000.md)
|
|
||||||
- [v25.2](25200.md)
|
|
||||||
- [v25.1](25100.md)
|
|
||||||
- [v25.0](25000.md)
|
|
||||||
- [v24.3](24300.md)
|
|
||||||
- [v24.2](24200.md)
|
|
||||||
- [v24.1](24100.md)
|
|
||||||
- [v24.0](24000.md)
|
|
||||||
- [v23.0](23000.md)
|
|
||||||
- [v22.1](22100.md)
|
|
||||||
- [v22.0](22000.md)
|
|
||||||
- [v21.4](21400.md)
|
|
||||||
- [v21.2](21200.md)
|
|
||||||
- [v21.1](21100.md)
|
|
||||||
- [v21.0](21000.md)
|
|
||||||
- [v20.4](20400.md)
|
|
||||||
- [v20.3](20300.md)
|
|
||||||
- [v20.2](20200.md)
|
|
||||||
- [v20.1](20100.md)
|
|
||||||
- [v20.0](20000.md)
|
|
||||||
- [v19.4](19400.md)
|
|
||||||
- [v19.3](19300.md)
|
|
||||||
- [v19.2](19200.md)
|
|
||||||
- [v19.1](19100.md)
|
|
||||||
- [v19.0](19000.md)
|
|
||||||
- [v18.1](18100.md)
|
|
||||||
- [v18.0](18000.md)
|
|
||||||
@@ -20,7 +20,6 @@ LOCAL_SRC_FILES := \
|
|||||||
core/daemon.cpp \
|
core/daemon.cpp \
|
||||||
core/scripting.cpp \
|
core/scripting.cpp \
|
||||||
core/sqlite.cpp \
|
core/sqlite.cpp \
|
||||||
core/module.cpp \
|
|
||||||
core/thread.cpp \
|
core/thread.cpp \
|
||||||
core/core-rs.cpp \
|
core/core-rs.cpp \
|
||||||
core/resetprop/resetprop.cpp \
|
core/resetprop/resetprop.cpp \
|
||||||
|
|||||||
135
native/src/Cargo.lock
generated
135
native/src/Cargo.lock
generated
@@ -45,9 +45,9 @@ checksum = "a464143cc82dedcdc3928737445362466b7674b5db4e2eb8e869846d6d84f4f6"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base"
|
name = "base"
|
||||||
@@ -109,9 +109,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.18.1"
|
version = "3.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee"
|
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck"
|
name = "bytemuck"
|
||||||
@@ -124,9 +124,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck_derive"
|
name = "bytemuck_derive"
|
||||||
version = "1.9.3"
|
version = "1.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1"
|
checksum = "441473f2b4b0459a68628c744bc61d23e730fb00128b841d30fa4bb3972257e4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -141,29 +141,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bzip2"
|
name = "bzip2"
|
||||||
version = "0.5.2"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47"
|
checksum = "bea8dcd42434048e4f7a304411d9273a411f647446c1234a65ce0554923f4cff"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bzip2-sys",
|
|
||||||
"libbz2-rs-sys",
|
"libbz2-rs-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bzip2-sys"
|
|
||||||
version = "0.1.13+1.0.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"pkg-config",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.26"
|
version = "1.2.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac"
|
checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
@@ -176,18 +165,18 @@ checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.40"
|
version = "4.5.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
|
checksum = "ed87a9d530bb41a67537289bafcac159cb3ee28460e0a4571123d2a778a6a882"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.40"
|
version = "4.5.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
|
checksum = "64f4f3f3c77c94aff3c7e9aac9a2ca1974a5adf392a8bb751e827d6d127ab966"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
@@ -247,18 +236,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.4.2"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-bigint"
|
name = "crypto-bigint"
|
||||||
version = "0.7.0-pre.4"
|
version = "0.7.0-pre.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "edaae5fb9dac79a07260e0b2006799ff4f1d342ab243fd7d0892215113b27904"
|
checksum = "98dc20cae677f0af161d98f18463804b680f9af060f6dbe6d4249bd7e838bca1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hybrid-array",
|
"hybrid-array",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
@@ -336,9 +325,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.8.0-rc.4"
|
version = "0.8.0-rc.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c2e6107818886eff6b71fba7a2da3dd11025ebb80f0c9b94ff961168ef629f2"
|
checksum = "e2fe0a4fafae25053c19a03fefe040607bda956b4941d692ed9fb9d3c18a3193"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-oid",
|
"const-oid",
|
||||||
"der_derive",
|
"der_derive",
|
||||||
@@ -381,9 +370,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ecdsa"
|
name = "ecdsa"
|
||||||
version = "0.17.0-rc.1"
|
version = "0.17.0-rc.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ca18d8009d96ffc2a8b771c7432338233ffcfa05e4ca410ed77900a2a335a0b"
|
checksum = "112839e868b3376c2066506d42331023165d687a7ed38b2ed77f28763d9a7742"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"der",
|
"der",
|
||||||
"digest",
|
"digest",
|
||||||
@@ -396,9 +385,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "elliptic-curve"
|
name = "elliptic-curve"
|
||||||
version = "0.14.0-rc.5"
|
version = "0.14.0-rc.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "541598dba361b5ba0321caad955ba99ae82a604f4047c4f2743724996abf62f4"
|
checksum = "c28ecec37eea07ab976cea93c7ce8b36d561cf161f6767925c1edc51024b0ad3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base16ct",
|
"base16ct",
|
||||||
"crypto-bigint",
|
"crypto-bigint",
|
||||||
@@ -497,15 +486,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libbz2-rs-sys"
|
name = "libbz2-rs-sys"
|
||||||
version = "0.1.3"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0864a00c8d019e36216b69c2c4ce50b83b7bd966add3cf5ba554ec44f8bebcf5"
|
checksum = "775bf80d5878ab7c2b1080b5351a48b2f737d9f6f8b383574eebcc22be0dfccb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.172"
|
version = "0.2.174"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libm"
|
name = "libm"
|
||||||
@@ -621,9 +610,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.4"
|
version = "2.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
@@ -672,9 +661,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "p256"
|
name = "p256"
|
||||||
version = "0.14.0-pre.5"
|
version = "0.14.0-pre.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b42c06f1f28ff328cb76c95cb7aebd6734a8333b98bdac393bdc124d16561dcb"
|
checksum = "1be97a30a85c829fdac914cebb89ef05e109f9e5eb6510f46f623be91bc39ded"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ecdsa",
|
"ecdsa",
|
||||||
"elliptic-curve",
|
"elliptic-curve",
|
||||||
@@ -685,9 +674,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "p384"
|
name = "p384"
|
||||||
version = "0.14.0-pre.5"
|
version = "0.14.0-pre.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c7594e57ef1ce505538e5a8e3485a21b930e99701bb65c8ede899a3a8213174"
|
checksum = "ea9626bce3d0bf768a28778618e5095131cd32bfca5297b51bbcb4abe7fae62a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ecdsa",
|
"ecdsa",
|
||||||
"elliptic-curve",
|
"elliptic-curve",
|
||||||
@@ -698,9 +687,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "p521"
|
name = "p521"
|
||||||
version = "0.14.0-pre.5"
|
version = "0.14.0-pre.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9396e2414ace7de7e0f3d544a5a07f129e39b28b2f08a35b3b7febdea36fd8e9"
|
checksum = "ec1071ec0ddc9a8c198692acf5620176b0cd9c1db988acef030e101f851405f4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base16ct",
|
"base16ct",
|
||||||
"ecdsa",
|
"ecdsa",
|
||||||
@@ -731,36 +720,29 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkcs1"
|
name = "pkcs1"
|
||||||
version = "0.8.0-rc.2"
|
version = "0.8.0-rc.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24e16d93c725fa250577ffdec06ebbff4cae3625b0e2881ac43a5427797ee8d3"
|
checksum = "b2345503b65d9be13aac96ddbec3eed60def8bc83869f9a519789afbcf3c2bea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"der",
|
"der",
|
||||||
"pkcs8",
|
|
||||||
"spki",
|
"spki",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkcs8"
|
name = "pkcs8"
|
||||||
version = "0.11.0-rc.4"
|
version = "0.11.0-rc.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f1843d4345dfe1a55e487db747a04c01af50415b03e937410e0a41d8cc24ec7"
|
checksum = "c53e5d0804fa4070b1b2a5b320102f2c1c094920a7533d5d87c2630609bcbd34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"der",
|
"der",
|
||||||
"spki",
|
"spki",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pkg-config"
|
|
||||||
version = "0.3.32"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "primefield"
|
name = "primefield"
|
||||||
version = "0.14.0-pre.2"
|
version = "0.14.0-pre.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1bbeb92947a0d0d4b0cab5e2e6749acc44c81461eb3b1aff4dbb7acd0eb9f0ab"
|
checksum = "adc85f9f75dc05486f61bc61858535c0501a0ca81ca3117ab17befbead13c110"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crypto-bigint",
|
"crypto-bigint",
|
||||||
"ff",
|
"ff",
|
||||||
@@ -771,9 +753,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "primeorder"
|
name = "primeorder"
|
||||||
version = "0.14.0-pre.4"
|
version = "0.14.0-pre.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "979936340c6e8b108ad132b395a1682f02a0b179080ed3380320c2c888728429"
|
checksum = "af12dd34fc62d04416de85af032f4595369437fb7b0143d36ae60cecaf5cdddf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"elliptic-curve",
|
"elliptic-curve",
|
||||||
]
|
]
|
||||||
@@ -806,9 +788,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "r-efi"
|
name = "r-efi"
|
||||||
version = "5.2.0"
|
version = "5.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
@@ -831,9 +813,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rsa"
|
name = "rsa"
|
||||||
version = "0.10.0-rc.0"
|
version = "0.10.0-rc.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f30f0ad781aea19fe741d7a901b2ad8b4271ac3516e7045b8ecff74e201968fe"
|
checksum = "7e8cb237ca3624409eda7d73de0d423815c9d91175ed5a62a8dd6549d2408cc2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-oid",
|
"const-oid",
|
||||||
"crypto-bigint",
|
"crypto-bigint",
|
||||||
@@ -863,14 +845,13 @@ checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sec1"
|
name = "sec1"
|
||||||
version = "0.8.0-rc.5"
|
version = "0.8.0-rc.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e4855dd9b15e8e469fad23529698f7f7b7a6b250a81c88b1f9d7efe1abca7717"
|
checksum = "c54dee398d74b1d03d78ddc09c90e456bf906b5b7aa790ba4f48b025b2179e5d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base16ct",
|
"base16ct",
|
||||||
"der",
|
"der",
|
||||||
"hybrid-array",
|
"hybrid-array",
|
||||||
"pkcs8",
|
|
||||||
"subtle",
|
"subtle",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
@@ -935,9 +916,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signature"
|
name = "signature"
|
||||||
version = "3.0.0-rc.1"
|
version = "3.0.0-rc.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b8852cecbd17ba45978bbbe43061ebe36a2ae376058c5c172e09f72888f8f7de"
|
checksum = "4835c3b5ecb10171941a4998a95a3a76ecac1c5ae8e6954f2ad030acd1c7e8ab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"digest",
|
"digest",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
@@ -957,9 +938,9 @@ checksum = "1b6709c7b6754dca1311b3c73e79fcce40dd414c782c66d88e8823030093b02b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spki"
|
name = "spki"
|
||||||
version = "0.8.0-rc.2"
|
version = "0.8.0-rc.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2f0e2bdca9b00f5be6dd3bb6647d50fd0f24a508a95f78e3bb2fe98d0403c85"
|
checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64ct",
|
"base64ct",
|
||||||
"der",
|
"der",
|
||||||
@@ -979,9 +960,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.102"
|
version = "2.0.104"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462"
|
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1164,9 +1145,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x509-cert"
|
name = "x509-cert"
|
||||||
version = "0.3.0-rc.0"
|
version = "0.3.0-rc.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a5c645061d1dc562a65edda59c7f688f35403a4615adfc07460437442d6e8383"
|
checksum = "015655a524ab1db259a56aaaec614cf84952299f4081c2602881d556e2ed2838"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-oid",
|
"const-oid",
|
||||||
"der",
|
"der",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ edition = "2024"
|
|||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
cxx = { path = "external/cxx-rs" }
|
cxx = { path = "external/cxx-rs" }
|
||||||
cxx-gen = { path = "external/cxx-rs/gen/lib" }
|
cxx-gen = { path = "external/cxx-rs/gen/lib" }
|
||||||
libc = "0.2.172"
|
libc = "0.2.174"
|
||||||
cfg-if = "1.0.1"
|
cfg-if = "1.0.1"
|
||||||
num-traits = "0.2.19"
|
num-traits = "0.2.19"
|
||||||
num-derive = "0.4.2"
|
num-derive = "0.4.2"
|
||||||
@@ -21,14 +21,14 @@ bytemuck = "1.23.1"
|
|||||||
fdt = "0.1.5"
|
fdt = "0.1.5"
|
||||||
const_format = "0.2.34"
|
const_format = "0.2.34"
|
||||||
bit-set = "0.8.0"
|
bit-set = "0.8.0"
|
||||||
syn = "2.0.102"
|
syn = "2.0.104"
|
||||||
quote = "1.0.40"
|
quote = "1.0.40"
|
||||||
proc-macro2 = "1.0.95"
|
proc-macro2 = "1.0.95"
|
||||||
argh = { version = "0.1.13", default-features = false }
|
argh = { version = "0.1.13", default-features = false }
|
||||||
pb-rs = { version = "0.10.0", default-features = false }
|
pb-rs = { version = "0.10.0", default-features = false }
|
||||||
quick-protobuf = "0.8.1"
|
quick-protobuf = "0.8.1"
|
||||||
flate2 = { version = "1.1.2", default-features = false }
|
flate2 = { version = "1.1.2", default-features = false }
|
||||||
bzip2 = { version = "0.5.2", default-features = false }
|
bzip2 = { version = "0.6.0" }
|
||||||
zopfli = "0.8.2"
|
zopfli = "0.8.2"
|
||||||
lz4 = "1.28.1"
|
lz4 = "1.28.1"
|
||||||
xz2 = "0.1.7"
|
xz2 = "0.1.7"
|
||||||
@@ -37,12 +37,12 @@ xz2 = "0.1.7"
|
|||||||
sha1 = "0.11.0-rc.0"
|
sha1 = "0.11.0-rc.0"
|
||||||
sha2 = "0.11.0-rc.0"
|
sha2 = "0.11.0-rc.0"
|
||||||
digest = "0.11.0-rc.0"
|
digest = "0.11.0-rc.0"
|
||||||
p256 = "0.14.0-pre.5"
|
p256 = "0.14.0-pre.9"
|
||||||
p384 = "0.14.0-pre.5"
|
p384 = "0.14.0-pre.9"
|
||||||
p521 = "0.14.0-pre.5"
|
p521 = "0.14.0-pre.9"
|
||||||
rsa = "0.10.0-rc.0"
|
rsa = "0.10.0-rc.3"
|
||||||
x509-cert = "0.3.0-rc.0"
|
x509-cert = "0.3.0-rc.1"
|
||||||
der = "0.8.0-rc.4"
|
der = "0.8.0-rc.7"
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
pb-rs = { git = "https://github.com/tafia/quick-protobuf.git" }
|
pb-rs = { git = "https://github.com/tafia/quick-protobuf.git" }
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ impl Directory {
|
|||||||
self.pre_order_walk_impl(&mut f)
|
self.pre_order_walk_impl(&mut f)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_all(&mut self) -> OsResultStatic<()> {
|
pub fn remove_all(mut self) -> OsResultStatic<()> {
|
||||||
self.post_order_walk(|e| {
|
self.post_order_walk(|e| {
|
||||||
e.unlink()?;
|
e.unlink()?;
|
||||||
Ok(WalkResult::Continue)
|
Ok(WalkResult::Continue)
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ impl Utf8CStr {
|
|||||||
pub fn remove_all(&self) -> OsResultStatic<()> {
|
pub fn remove_all(&self) -> OsResultStatic<()> {
|
||||||
let attr = self.get_attr()?;
|
let attr = self.get_attr()?;
|
||||||
if attr.is_dir() {
|
if attr.is_dir() {
|
||||||
let mut dir = Directory::try_from(open_fd(self, O_RDONLY | O_CLOEXEC, 0)?)?;
|
let dir = Directory::try_from(open_fd(self, O_RDONLY | O_CLOEXEC, 0)?)?;
|
||||||
dir.remove_all()?;
|
dir.remove_all()?;
|
||||||
}
|
}
|
||||||
Ok(self.remove()?)
|
Ok(self.remove()?)
|
||||||
@@ -583,7 +583,7 @@ impl<S: Utf8CStrBuf + Sized> FsPathBuilder for S {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn append_path_fmt<T: Display>(&mut self, name: T) -> &mut Self {
|
fn append_path_fmt<T: Display>(&mut self, name: T) -> &mut Self {
|
||||||
self.write_fmt(format_args!("/{}", name)).ok();
|
self.write_fmt(format_args!("/{name}")).ok();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,7 +595,7 @@ impl FsPathBuilder for dyn Utf8CStrBuf + '_ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn append_path_fmt<T: Display>(&mut self, name: T) -> &mut Self {
|
fn append_path_fmt<T: Display>(&mut self, name: T) -> &mut Self {
|
||||||
self.write_fmt(format_args!("/{}", name)).ok();
|
self.write_fmt(format_args!("/{name}")).ok();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -846,7 +846,7 @@ fn parse_mount_info_line(line: &str) -> Option<MountInfo> {
|
|||||||
|
|
||||||
pub fn parse_mount_info(pid: &str) -> Vec<MountInfo> {
|
pub fn parse_mount_info(pid: &str) -> Vec<MountInfo> {
|
||||||
let mut res = vec![];
|
let mut res = vec![];
|
||||||
let mut path = format!("/proc/{}/mountinfo", pid);
|
let mut path = format!("/proc/{pid}/mountinfo");
|
||||||
if let Ok(file) = Utf8CStr::from_string(&mut path).open(O_RDONLY | O_CLOEXEC) {
|
if let Ok(file) = Utf8CStr::from_string(&mut path).open(O_RDONLY | O_CLOEXEC) {
|
||||||
BufReader::new(file).foreach_lines(|line| {
|
BufReader::new(file).foreach_lines(|line| {
|
||||||
parse_mount_info_line(line)
|
parse_mount_info_line(line)
|
||||||
|
|||||||
@@ -184,6 +184,10 @@ int parse_int(string_view s) {
|
|||||||
return parse_num<int, 10>(s);
|
return parse_num<int, 10>(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t parse_uint32_hex(string_view s) {
|
||||||
|
return parse_num<uint32_t, 16>(s);
|
||||||
|
}
|
||||||
|
|
||||||
int switch_mnt_ns(int pid) {
|
int switch_mnt_ns(int pid) {
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int fd = syscall(__NR_pidfd_open, pid, 0);
|
int fd = syscall(__NR_pidfd_open, pid, 0);
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ rust::Vec<size_t> mut_u8_patch(
|
|||||||
rust::Slice<const uint8_t> from,
|
rust::Slice<const uint8_t> from,
|
||||||
rust::Slice<const uint8_t> to);
|
rust::Slice<const uint8_t> to);
|
||||||
|
|
||||||
|
uint32_t parse_uint32_hex(std::string_view s);
|
||||||
int parse_int(std::string_view s);
|
int parse_int(std::string_view s);
|
||||||
|
|
||||||
using thread_entry = void *(*)(void *);
|
using thread_entry = void *(*)(void *);
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ impl<T> EarlyExitExt<T> for Result<T, EarlyExit> {
|
|||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("{}", output);
|
eprintln!("{output}");
|
||||||
print_help_msg();
|
print_help_msg();
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ impl<T, E: Display> Loggable<T> for Result<T, E> {
|
|||||||
write!(w, "[{}:{}] ", caller.file(), caller.line())?;
|
write!(w, "[{}:{}] ", caller.file(), caller.line())?;
|
||||||
}
|
}
|
||||||
f(w)?;
|
f(w)?;
|
||||||
writeln!(w, ": {:#}", e)
|
writeln!(w, ": {e:#}")
|
||||||
});
|
});
|
||||||
Err(LoggedError::default())
|
Err(LoggedError::default())
|
||||||
}
|
}
|
||||||
@@ -366,7 +366,7 @@ impl Display for OsError<'_> {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let error = self.as_io_error();
|
let error = self.as_io_error();
|
||||||
if self.name.is_empty() {
|
if self.name.is_empty() {
|
||||||
write!(f, "{:#}", error)
|
write!(f, "{error:#}")
|
||||||
} else {
|
} else {
|
||||||
match (self.arg1.ok(), self.arg2.ok()) {
|
match (self.arg1.ok(), self.arg2.ok()) {
|
||||||
(Some(arg1), Some(arg2)) => {
|
(Some(arg1), Some(arg2)) => {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ fdt = { workspace = true }
|
|||||||
bytemuck = { workspace = true, features = ["derive", "min_const_generics"] }
|
bytemuck = { workspace = true, features = ["derive", "min_const_generics"] }
|
||||||
num-traits = { workspace = true }
|
num-traits = { workspace = true }
|
||||||
flate2 = { workspace = true, features = ["zlib-rs"] }
|
flate2 = { workspace = true, features = ["zlib-rs"] }
|
||||||
bzip2 = { workspace = true, features = ["libbz2-rs-sys"] }
|
bzip2 = { workspace = true }
|
||||||
lz4 = { workspace = true }
|
lz4 = { workspace = true }
|
||||||
xz2 = { workspace = true }
|
xz2 = { workspace = true }
|
||||||
zopfli = { workspace = true, features = ["gzip"] }
|
zopfli = { workspace = true, features = ["gzip"] }
|
||||||
|
|||||||
@@ -523,10 +523,8 @@ bool boot_img::parse_image(const uint8_t *p, FileFormat type) {
|
|||||||
} else if (tail.sz() >= 16 && BUFFER_MATCH(tail.buf(), LG_BUMP_MAGIC)) {
|
} else if (tail.sz() >= 16 && BUFFER_MATCH(tail.buf(), LG_BUMP_MAGIC)) {
|
||||||
fprintf(stderr, "LG_BUMP_IMAGE\n");
|
fprintf(stderr, "LG_BUMP_IMAGE\n");
|
||||||
flags[LG_BUMP_FLAG] = true;
|
flags[LG_BUMP_FLAG] = true;
|
||||||
}
|
} else if (!(tail.sz() >= 4 && BUFFER_MATCH(tail.buf(), AVB_MAGIC)) && verify()) {
|
||||||
|
// Check if the image is avb 1.0 signed
|
||||||
// Check if the image is signed
|
|
||||||
if (verify()) {
|
|
||||||
fprintf(stderr, "AVB1_SIGNED\n");
|
fprintf(stderr, "AVB1_SIGNED\n");
|
||||||
flags[AVB1_SIGNED_FLAG] = true;
|
flags[AVB1_SIGNED_FLAG] = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,13 +269,13 @@ impl Cpio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_from_file(path: &Utf8CStr) -> LoggedResult<Self> {
|
fn load_from_file(path: &Utf8CStr) -> LoggedResult<Self> {
|
||||||
eprintln!("Loading cpio: [{}]", path);
|
eprintln!("Loading cpio: [{path}]");
|
||||||
let file = MappedFile::open(path)?;
|
let file = MappedFile::open(path)?;
|
||||||
Self::load_from_data(file.as_ref())
|
Self::load_from_data(file.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump(&self, path: &str) -> LoggedResult<()> {
|
fn dump(&self, path: &str) -> LoggedResult<()> {
|
||||||
eprintln!("Dumping cpio: [{}]", path);
|
eprintln!("Dumping cpio: [{path}]");
|
||||||
let mut file = File::create(path)?;
|
let mut file = File::create(path)?;
|
||||||
let mut pos = 0usize;
|
let mut pos = 0usize;
|
||||||
let mut inode = 300000i64;
|
let mut inode = 300000i64;
|
||||||
@@ -320,13 +320,13 @@ impl Cpio {
|
|||||||
fn rm(&mut self, path: &str, recursive: bool) {
|
fn rm(&mut self, path: &str, recursive: bool) {
|
||||||
let path = norm_path(path);
|
let path = norm_path(path);
|
||||||
if self.entries.remove(&path).is_some() {
|
if self.entries.remove(&path).is_some() {
|
||||||
eprintln!("Removed entry [{}]", path);
|
eprintln!("Removed entry [{path}]");
|
||||||
}
|
}
|
||||||
if recursive {
|
if recursive {
|
||||||
let path = path + "/";
|
let path = path + "/";
|
||||||
self.entries.retain(|k, _| {
|
self.entries.retain(|k, _| {
|
||||||
if k.starts_with(&path) {
|
if k.starts_with(&path) {
|
||||||
eprintln!("Removed entry [{}]", k);
|
eprintln!("Removed entry [{k}]");
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
@@ -340,7 +340,7 @@ impl Cpio {
|
|||||||
.entries
|
.entries
|
||||||
.get(path)
|
.get(path)
|
||||||
.ok_or_else(|| log_err!("No such file"))?;
|
.ok_or_else(|| log_err!("No such file"))?;
|
||||||
eprintln!("Extracting entry [{}] to [{}]", path, out);
|
eprintln!("Extracting entry [{path}] to [{out}]");
|
||||||
|
|
||||||
let out = Utf8CStr::from_string(out);
|
let out = Utf8CStr::from_string(out);
|
||||||
|
|
||||||
@@ -435,7 +435,7 @@ impl Cpio {
|
|||||||
data: content,
|
data: content,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
eprintln!("Add file [{}] ({:04o})", path, mode);
|
eprintln!("Add file [{path}] ({mode:04o})");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +451,7 @@ impl Cpio {
|
|||||||
data: vec![],
|
data: vec![],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
eprintln!("Create directory [{}] ({:04o})", dir, mode);
|
eprintln!("Create directory [{dir}] ({mode:04o})");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ln(&mut self, src: &str, dst: &str) {
|
fn ln(&mut self, src: &str, dst: &str) {
|
||||||
@@ -466,7 +466,7 @@ impl Cpio {
|
|||||||
data: norm_path(src).as_bytes().to_vec(),
|
data: norm_path(src).as_bytes().to_vec(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
eprintln!("Create symlink [{}] -> [{}]", dst, src);
|
eprintln!("Create symlink [{dst}] -> [{src}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mv(&mut self, from: &str, to: &str) -> LoggedResult<()> {
|
fn mv(&mut self, from: &str, to: &str) -> LoggedResult<()> {
|
||||||
@@ -475,7 +475,7 @@ impl Cpio {
|
|||||||
.remove(&norm_path(from))
|
.remove(&norm_path(from))
|
||||||
.ok_or_else(|| log_err!("no such entry {}", from))?;
|
.ok_or_else(|| log_err!("no such entry {}", from))?;
|
||||||
self.entries.insert(norm_path(to), entry);
|
self.entries.insert(norm_path(to), entry);
|
||||||
eprintln!("Move [{}] -> [{}]", from, to);
|
eprintln!("Move [{from}] -> [{to}]");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +498,7 @@ impl Cpio {
|
|||||||
if !recursive && !p.is_empty() && p.matches('/').count() > 1 {
|
if !recursive && !p.is_empty() && p.matches('/').count() > 1 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
println!("{}\t{}", entry, name);
|
println!("{entry}\t{name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -511,8 +511,7 @@ impl Cpio {
|
|||||||
let keep_verity = check_env("KEEPVERITY");
|
let keep_verity = check_env("KEEPVERITY");
|
||||||
let keep_force_encrypt = check_env("KEEPFORCEENCRYPT");
|
let keep_force_encrypt = check_env("KEEPFORCEENCRYPT");
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Patch with flag KEEPVERITY=[{}] KEEPFORCEENCRYPT=[{}]",
|
"Patch with flag KEEPVERITY=[{keep_verity}] KEEPFORCEENCRYPT=[{keep_force_encrypt}]"
|
||||||
keep_verity, keep_force_encrypt
|
|
||||||
);
|
);
|
||||||
self.entries.retain(|name, entry| {
|
self.entries.retain(|name, entry| {
|
||||||
let fstab = (!keep_verity || !keep_force_encrypt)
|
let fstab = (!keep_verity || !keep_force_encrypt)
|
||||||
@@ -523,7 +522,7 @@ impl Cpio {
|
|||||||
&& name.starts_with("fstab");
|
&& name.starts_with("fstab");
|
||||||
if !keep_verity {
|
if !keep_verity {
|
||||||
if fstab {
|
if fstab {
|
||||||
eprintln!("Found fstab file [{}]", name);
|
eprintln!("Found fstab file [{name}]");
|
||||||
let len = patch_verity(entry.data.as_mut_slice());
|
let len = patch_verity(entry.data.as_mut_slice());
|
||||||
if len != entry.data.len() {
|
if len != entry.data.len() {
|
||||||
entry.data.resize(len, 0);
|
entry.data.resize(len, 0);
|
||||||
@@ -581,7 +580,7 @@ impl Cpio {
|
|||||||
} else {
|
} else {
|
||||||
&name[8..]
|
&name[8..]
|
||||||
};
|
};
|
||||||
eprintln!("Restore [{}] -> [{}]", name, new_name);
|
eprintln!("Restore [{name}] -> [{new_name}]");
|
||||||
backups.insert(new_name.to_string(), entry);
|
backups.insert(new_name.to_string(), entry);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -658,16 +657,16 @@ impl Cpio {
|
|||||||
match action {
|
match action {
|
||||||
Action::Backup(name, mut entry) => {
|
Action::Backup(name, mut entry) => {
|
||||||
let backup = if !skip_compress && entry.compress() {
|
let backup = if !skip_compress && entry.compress() {
|
||||||
format!(".backup/{}.xz", name)
|
format!(".backup/{name}.xz")
|
||||||
} else {
|
} else {
|
||||||
format!(".backup/{}", name)
|
format!(".backup/{name}")
|
||||||
};
|
};
|
||||||
eprintln!("Backup [{}] -> [{}]", name, backup);
|
eprintln!("Backup [{name}] -> [{backup}]");
|
||||||
backups.insert(backup, entry);
|
backups.insert(backup, entry);
|
||||||
}
|
}
|
||||||
Action::Record(name) => {
|
Action::Record(name) => {
|
||||||
eprintln!("Record new entry: [{}] -> [.backup/.rmlist]", name);
|
eprintln!("Record new entry: [{name}] -> [.backup/.rmlist]");
|
||||||
rm_list.push_str(&format!("{}\0", name));
|
rm_list.push_str(&format!("{name}\0"));
|
||||||
}
|
}
|
||||||
Action::Noop => {}
|
Action::Noop => {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,9 +131,9 @@ fn print_node(node: &FdtNode) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else if size > MAX_PRINT_LEN {
|
} else if size > MAX_PRINT_LEN {
|
||||||
println!("[{}]: <bytes>({})", name, size);
|
println!("[{name}]: <bytes>({size})");
|
||||||
} else {
|
} else {
|
||||||
println!("[{}]: {:02x?}", name, value);
|
println!("[{name}]: {value:02x?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ fn for_each_fdt<F: FnMut(usize, Fdt) -> LoggedResult<()>>(
|
|||||||
rw: bool,
|
rw: bool,
|
||||||
mut f: F,
|
mut f: F,
|
||||||
) -> LoggedResult<()> {
|
) -> LoggedResult<()> {
|
||||||
eprintln!("Loading dtbs from [{}]", file);
|
eprintln!("Loading dtbs from [{file}]");
|
||||||
let file = if rw {
|
let file = if rw {
|
||||||
MappedFile::open_rw(file)?
|
MappedFile::open_rw(file)?
|
||||||
} else {
|
} else {
|
||||||
@@ -173,7 +173,7 @@ fn for_each_fdt<F: FnMut(usize, Fdt) -> LoggedResult<()>>(
|
|||||||
}
|
}
|
||||||
let fdt = match Fdt::new(slice) {
|
let fdt = match Fdt::new(slice) {
|
||||||
Err(FdtError::BufferTooSmall) => {
|
Err(FdtError::BufferTooSmall) => {
|
||||||
eprintln!("dtb.{:04} is truncated", dtb_num);
|
eprintln!("dtb.{dtb_num:04} is truncated");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Ok(fdt) => fdt,
|
Ok(fdt) => fdt,
|
||||||
@@ -198,11 +198,11 @@ fn dtb_print(file: &Utf8CStr, fstab: bool) -> LoggedResult<()> {
|
|||||||
for_each_fdt(file, false, |n, fdt| {
|
for_each_fdt(file, false, |n, fdt| {
|
||||||
if fstab {
|
if fstab {
|
||||||
if let Some(fstab) = find_fstab(&fdt) {
|
if let Some(fstab) = find_fstab(&fdt) {
|
||||||
eprintln!("Found fstab in dtb.{:04}", n);
|
eprintln!("Found fstab in dtb.{n:04}");
|
||||||
print_node(&fstab);
|
print_node(&fstab);
|
||||||
}
|
}
|
||||||
} else if let Some(mut root) = fdt.find_node("/") {
|
} else if let Some(mut root) = fdt.find_node("/") {
|
||||||
eprintln!("Printing dtb.{:04}", n);
|
eprintln!("Printing dtb.{n:04}");
|
||||||
if root.name.is_empty() {
|
if root.name.is_empty() {
|
||||||
root.name = "/";
|
root.name = "/";
|
||||||
}
|
}
|
||||||
@@ -248,7 +248,7 @@ fn dtb_patch(file: &Utf8CStr) -> LoggedResult<bool> {
|
|||||||
&mut *std::mem::transmute::<&[u8], &UnsafeCell<[u8]>>(w).get()
|
&mut *std::mem::transmute::<&[u8], &UnsafeCell<[u8]>>(w).get()
|
||||||
};
|
};
|
||||||
w[..=4].copy_from_slice(b"want");
|
w[..=4].copy_from_slice(b"want");
|
||||||
eprintln!("Patch [skip_initramfs] -> [want_initramfs] in dtb.{:04}", n);
|
eprintln!("Patch [skip_initramfs] -> [want_initramfs] in dtb.{n:04}");
|
||||||
patched = true;
|
patched = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ fn remove_pattern(buf: &mut [u8], pattern_matcher: unsafe fn(&[u8]) -> Option<us
|
|||||||
let skipped = buf.get_unchecked(read..(read + len));
|
let skipped = buf.get_unchecked(read..(read + len));
|
||||||
// SAFETY: all matching patterns are ASCII bytes
|
// SAFETY: all matching patterns are ASCII bytes
|
||||||
let skipped = std::str::from_utf8_unchecked(skipped);
|
let skipped = std::str::from_utf8_unchecked(skipped);
|
||||||
eprintln!("Remove pattern [{}]", skipped);
|
eprintln!("Remove pattern [{skipped}]");
|
||||||
sz -= len;
|
sz -= len;
|
||||||
read += len;
|
read += len;
|
||||||
} else {
|
} else {
|
||||||
@@ -114,7 +114,7 @@ pub fn hexpatch(file: &[u8], from: &[u8], to: &[u8]) -> bool {
|
|||||||
|
|
||||||
let v = map.patch(pattern.as_slice(), patch.as_slice());
|
let v = map.patch(pattern.as_slice(), patch.as_slice());
|
||||||
for off in &v {
|
for off in &v {
|
||||||
eprintln!("Patch @ {:#010X} [{}] -> [{}]", off, from, to);
|
eprintln!("Patch @ {off:#010X} [{from}] -> [{to}]");
|
||||||
}
|
}
|
||||||
!v.is_empty()
|
!v.is_empty()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ fn do_extract_boot_from_payload(
|
|||||||
let mut reader = BufReader::new(if in_path == "-" {
|
let mut reader = BufReader::new(if in_path == "-" {
|
||||||
unsafe { File::from_raw_fd(0) }
|
unsafe { File::from_raw_fd(0) }
|
||||||
} else {
|
} else {
|
||||||
File::open(in_path).log_with_msg(|w| write!(w, "Cannot open '{}'", in_path))?
|
File::open(in_path).log_with_msg(|w| write!(w, "Cannot open '{in_path}'"))?
|
||||||
});
|
});
|
||||||
|
|
||||||
let buf = &mut [0u8; 4];
|
let buf = &mut [0u8; 4];
|
||||||
@@ -107,7 +107,7 @@ fn do_extract_boot_from_payload(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut out_file =
|
let mut out_file =
|
||||||
File::create(out_path).log_with_msg(|w| write!(w, "Cannot write to '{}'", out_path))?;
|
File::create(out_path).log_with_msg(|w| write!(w, "Cannot write to '{out_path}'"))?;
|
||||||
|
|
||||||
// Skip the manifest signature
|
// Skip the manifest signature
|
||||||
reader.skip(manifest_sig_len as usize)?;
|
reader.skip(manifest_sig_len as usize)?;
|
||||||
|
|||||||
@@ -218,13 +218,7 @@ static void handle_request_sync(int client, int code) {
|
|||||||
denylist_handler(-1, nullptr);
|
denylist_handler(-1, nullptr);
|
||||||
|
|
||||||
// Restore native bridge property
|
// Restore native bridge property
|
||||||
auto nb = get_prop(NBPROP);
|
restore_zygisk_prop();
|
||||||
auto len = sizeof(ZYGISKLDR) - 1;
|
|
||||||
if (nb == ZYGISKLDR) {
|
|
||||||
set_prop(NBPROP, "0");
|
|
||||||
} else if (nb.size() > len) {
|
|
||||||
set_prop(NBPROP, nb.data() + len);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_int(client, 0);
|
write_int(client, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
use crate::consts::{MAGISK_FULL_VER, MAGISK_PROC_CON, MAIN_CONFIG, ROOTMNT, ROOTOVL, SECURE_DIR};
|
use crate::consts::{MAGISK_FULL_VER, MAGISK_PROC_CON, MAIN_CONFIG, ROOTMNT, ROOTOVL, SECURE_DIR};
|
||||||
use crate::db::Sqlite3;
|
use crate::db::Sqlite3;
|
||||||
use crate::ffi::{
|
use crate::ffi::{
|
||||||
DbEntryKey, ModuleInfo, RequestCode, check_key_combo, disable_modules, exec_common_scripts,
|
DbEntryKey, ModuleInfo, RequestCode, check_key_combo, exec_common_scripts, exec_module_scripts,
|
||||||
exec_module_scripts, get_magisk_tmp, initialize_denylist, setup_magisk_env,
|
get_magisk_tmp, get_prop, initialize_denylist, set_prop, setup_magisk_env,
|
||||||
};
|
};
|
||||||
use crate::logging::{magisk_logging, setup_logfile, start_log_daemon};
|
use crate::logging::{magisk_logging, setup_logfile, start_log_daemon};
|
||||||
use crate::mount::{clean_mounts, setup_module_mount, setup_preinit_dir};
|
use crate::module::disable_modules;
|
||||||
|
use crate::mount::{clean_mounts, setup_preinit_dir};
|
||||||
use crate::package::ManagerInfo;
|
use crate::package::ManagerInfo;
|
||||||
use crate::selinux::restore_tmpcon;
|
use crate::selinux::restore_tmpcon;
|
||||||
use crate::su::SuInfo;
|
use crate::su::SuInfo;
|
||||||
use crate::{get_prop, set_prop};
|
|
||||||
use base::libc::{O_APPEND, O_CLOEXEC, O_RDONLY, O_WRONLY};
|
use base::libc::{O_APPEND, O_CLOEXEC, O_RDONLY, O_WRONLY};
|
||||||
use base::{
|
use base::{
|
||||||
AtomicArc, BufReadExt, FsPathBuilder, ResultExt, Utf8CStr, Utf8CStrBuf, cstr, error, info, libc,
|
AtomicArc, BufReadExt, FsPathBuilder, ResultExt, Utf8CStr, Utf8CStrBuf, cstr, error, info, libc,
|
||||||
@@ -144,9 +144,7 @@ impl MagiskD {
|
|||||||
Ordering::Release,
|
Ordering::Release,
|
||||||
);
|
);
|
||||||
initialize_denylist();
|
initialize_denylist();
|
||||||
setup_module_mount();
|
self.handle_modules();
|
||||||
let modules = self.handle_modules();
|
|
||||||
self.module_list.set(modules).ok();
|
|
||||||
clean_mounts();
|
clean_mounts();
|
||||||
|
|
||||||
false
|
false
|
||||||
@@ -336,7 +334,7 @@ fn switch_cgroup(cgroup: &str, pid: i32) {
|
|||||||
}
|
}
|
||||||
if let Ok(mut file) = buf.open(O_WRONLY | O_APPEND | O_CLOEXEC) {
|
if let Ok(mut file) = buf.open(O_WRONLY | O_APPEND | O_CLOEXEC) {
|
||||||
buf.clear();
|
buf.clear();
|
||||||
buf.write_fmt(format_args!("{}", pid)).ok();
|
buf.write_fmt(format_args!("{pid}")).ok();
|
||||||
file.write_all(buf.as_bytes()).log_ok();
|
file.write_all(buf.as_bytes()).log_ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,14 +28,16 @@ enum class RespondCode : int {
|
|||||||
|
|
||||||
struct ModuleInfo;
|
struct ModuleInfo;
|
||||||
|
|
||||||
extern std::string native_bridge;
|
|
||||||
|
|
||||||
// Daemon
|
// Daemon
|
||||||
int connect_daemon(int req, bool create = false);
|
int connect_daemon(int req, bool create = false);
|
||||||
const char *get_magisk_tmp();
|
const char *get_magisk_tmp();
|
||||||
void unlock_blocks();
|
void unlock_blocks();
|
||||||
bool setup_magisk_env();
|
bool setup_magisk_env();
|
||||||
bool check_key_combo();
|
bool check_key_combo();
|
||||||
|
|
||||||
|
// Zygisk daemon
|
||||||
|
rust::Str get_zygisk_lib_name();
|
||||||
|
void set_zygisk_prop();
|
||||||
void restore_zygisk_prop();
|
void restore_zygisk_prop();
|
||||||
|
|
||||||
// Sockets
|
// Sockets
|
||||||
@@ -90,10 +92,6 @@ void exec_task(std::function<void()> &&task);
|
|||||||
// Daemon handlers
|
// Daemon handlers
|
||||||
void denylist_handler(int client, const sock_cred *cred);
|
void denylist_handler(int client, const sock_cred *cred);
|
||||||
|
|
||||||
// Module stuffs
|
|
||||||
void disable_modules();
|
|
||||||
void remove_modules();
|
|
||||||
|
|
||||||
// Scripting
|
// Scripting
|
||||||
void install_apk(rust::Utf8CStr apk);
|
void install_apk(rust::Utf8CStr apk);
|
||||||
void uninstall_pkg(rust::Utf8CStr pkg);
|
void uninstall_pkg(rust::Utf8CStr pkg);
|
||||||
@@ -123,3 +121,4 @@ static inline rust::Utf8CStr get_magisk_tmp_rs() { return get_magisk_tmp(); }
|
|||||||
static inline rust::String resolve_preinit_dir_rs(rust::Utf8CStr base_dir) {
|
static inline rust::String resolve_preinit_dir_rs(rust::Utf8CStr base_dir) {
|
||||||
return resolve_preinit_dir(base_dir.c_str());
|
return resolve_preinit_dir(base_dir.c_str());
|
||||||
}
|
}
|
||||||
|
static inline void exec_script_rs(rust::Utf8CStr script) { exec_script(script.data()); }
|
||||||
|
|||||||
@@ -20,12 +20,19 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// System properties
|
// System properties
|
||||||
rust::String get_prop_rs(const char *name, bool persist);
|
|
||||||
std::string get_prop(const char *name, bool persist = false);
|
std::string get_prop(const char *name, bool persist = false);
|
||||||
int delete_prop(const char *name, bool persist = false);
|
int delete_prop(const char *name, bool persist = false);
|
||||||
int set_prop(const char *name, const char *value, bool skip_svc = false);
|
int set_prop(const char *name, const char *value, bool skip_svc = false);
|
||||||
void load_prop_file(const char *filename, bool skip_svc = false);
|
void load_prop_file(const char *filename, bool skip_svc = false);
|
||||||
|
|
||||||
static inline void prop_cb_exec(prop_cb &cb, const char *name, const char *value, uint32_t serial) {
|
// Rust bindings
|
||||||
cb.exec(name, value, serial);
|
rust::String get_prop_rs(rust::Utf8CStr name, bool persist);
|
||||||
|
static inline int set_prop_rs(rust::Utf8CStr name, rust::Utf8CStr value, bool skip_svc) {
|
||||||
|
return set_prop(name.data(), value.data(), skip_svc);
|
||||||
}
|
}
|
||||||
|
static inline void load_prop_file_rs(rust::Utf8CStr filename, bool skip_svc) {
|
||||||
|
load_prop_file(filename.data(), skip_svc);
|
||||||
|
}
|
||||||
|
static inline void prop_cb_exec(prop_cb &cb, rust::Utf8CStr name, rust::Utf8CStr value, uint32_t serial) {
|
||||||
|
cb.exec(name.data(), value.data(), serial);
|
||||||
|
}
|
||||||
@@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
use crate::ffi::SuRequest;
|
use crate::ffi::SuRequest;
|
||||||
use crate::socket::Encodable;
|
use crate::socket::Encodable;
|
||||||
use base::{Utf8CStr, libc};
|
use base::libc;
|
||||||
use cxx::{ExternType, type_id};
|
use cxx::{ExternType, type_id};
|
||||||
use daemon::{MagiskD, daemon_entry};
|
use daemon::{MagiskD, daemon_entry};
|
||||||
use derive::Decodable;
|
use derive::Decodable;
|
||||||
use logging::{android_logging, setup_logfile, zygisk_close_logd, zygisk_get_logd, zygisk_logging};
|
use logging::{android_logging, setup_logfile, zygisk_close_logd, zygisk_get_logd, zygisk_logging};
|
||||||
use module::load_modules;
|
use module::remove_modules;
|
||||||
use mount::{find_preinit_device, revert_unmount};
|
use mount::{find_preinit_device, revert_unmount};
|
||||||
use resetprop::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop};
|
use resetprop::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop};
|
||||||
use selinux::{lgetfilecon, lsetfilecon, restorecon, setfilecon};
|
use selinux::{lgetfilecon, lsetfilecon, restorecon, setfilecon};
|
||||||
@@ -88,6 +88,7 @@ pub mod ffi {
|
|||||||
Query,
|
Query,
|
||||||
Deny,
|
Deny,
|
||||||
Allow,
|
Allow,
|
||||||
|
Restrict,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ModuleInfo {
|
struct ModuleInfo {
|
||||||
@@ -117,6 +118,7 @@ pub mod ffi {
|
|||||||
target_pid: i32,
|
target_pid: i32,
|
||||||
login: bool,
|
login: bool,
|
||||||
keep_env: bool,
|
keep_env: bool,
|
||||||
|
drop_cap: bool,
|
||||||
shell: String,
|
shell: String,
|
||||||
command: String,
|
command: String,
|
||||||
context: String,
|
context: String,
|
||||||
@@ -132,23 +134,6 @@ pub mod ffi {
|
|||||||
request: &'a SuRequest,
|
request: &'a SuRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C++" {
|
|
||||||
include!("include/resetprop.hpp");
|
|
||||||
|
|
||||||
#[cxx_name = "prop_cb"]
|
|
||||||
type PropCb;
|
|
||||||
unsafe fn get_prop_rs(name: *const c_char, persist: bool) -> String;
|
|
||||||
#[cxx_name = "set_prop"]
|
|
||||||
unsafe fn set_prop_rs(name: *const c_char, value: *const c_char, skip_svc: bool) -> i32;
|
|
||||||
unsafe fn prop_cb_exec(
|
|
||||||
cb: Pin<&mut PropCb>,
|
|
||||||
name: *const c_char,
|
|
||||||
value: *const c_char,
|
|
||||||
serial: u32,
|
|
||||||
);
|
|
||||||
unsafe fn load_prop_file(filename: *const c_char, skip_svc: bool);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe extern "C++" {
|
unsafe extern "C++" {
|
||||||
#[namespace = "rust"]
|
#[namespace = "rust"]
|
||||||
#[cxx_name = "Utf8CStr"]
|
#[cxx_name = "Utf8CStr"]
|
||||||
@@ -164,13 +149,16 @@ pub mod ffi {
|
|||||||
fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String;
|
fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String;
|
||||||
fn setup_magisk_env() -> bool;
|
fn setup_magisk_env() -> bool;
|
||||||
fn check_key_combo() -> bool;
|
fn check_key_combo() -> bool;
|
||||||
fn disable_modules();
|
#[cxx_name = "exec_script_rs"]
|
||||||
|
fn exec_script(script: Utf8CStrRef);
|
||||||
fn exec_common_scripts(stage: Utf8CStrRef);
|
fn exec_common_scripts(stage: Utf8CStrRef);
|
||||||
fn exec_module_scripts(state: Utf8CStrRef, modules: &Vec<ModuleInfo>);
|
fn exec_module_scripts(state: Utf8CStrRef, modules: &Vec<ModuleInfo>);
|
||||||
fn install_apk(apk: Utf8CStrRef);
|
fn install_apk(apk: Utf8CStrRef);
|
||||||
fn uninstall_pkg(apk: Utf8CStrRef);
|
fn uninstall_pkg(apk: Utf8CStrRef);
|
||||||
fn update_deny_flags(uid: i32, process: &str, flags: &mut u32);
|
fn update_deny_flags(uid: i32, process: &str, flags: &mut u32);
|
||||||
fn initialize_denylist();
|
fn initialize_denylist();
|
||||||
|
fn get_zygisk_lib_name() -> &'static str;
|
||||||
|
fn set_zygisk_prop();
|
||||||
fn restore_zygisk_prop();
|
fn restore_zygisk_prop();
|
||||||
fn switch_mnt_ns(pid: i32) -> i32;
|
fn switch_mnt_ns(pid: i32) -> i32;
|
||||||
fn app_request(req: &SuAppRequest) -> i32;
|
fn app_request(req: &SuAppRequest) -> i32;
|
||||||
@@ -191,6 +179,18 @@ pub mod ffi {
|
|||||||
fn get_text(self: &DbValues, index: i32) -> &str;
|
fn get_text(self: &DbValues, index: i32) -> &str;
|
||||||
fn bind_text(self: Pin<&mut DbStatement>, index: i32, val: &str) -> i32;
|
fn bind_text(self: Pin<&mut DbStatement>, index: i32, val: &str) -> i32;
|
||||||
fn bind_int64(self: Pin<&mut DbStatement>, index: i32, val: i64) -> i32;
|
fn bind_int64(self: Pin<&mut DbStatement>, index: i32, val: i64) -> i32;
|
||||||
|
|
||||||
|
include!("include/resetprop.hpp");
|
||||||
|
|
||||||
|
#[cxx_name = "prop_cb"]
|
||||||
|
type PropCb;
|
||||||
|
#[cxx_name = "get_prop_rs"]
|
||||||
|
fn get_prop(name: Utf8CStrRef, persist: bool) -> String;
|
||||||
|
#[cxx_name = "set_prop_rs"]
|
||||||
|
fn set_prop(name: Utf8CStrRef, value: Utf8CStrRef, skip_svc: bool) -> i32;
|
||||||
|
#[cxx_name = "load_prop_file_rs"]
|
||||||
|
fn load_prop_file(filename: Utf8CStrRef, skip_svc: bool);
|
||||||
|
fn prop_cb_exec(cb: Pin<&mut PropCb>, name: Utf8CStrRef, value: Utf8CStrRef, serial: u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
@@ -201,6 +201,7 @@ pub mod ffi {
|
|||||||
fn setup_logfile();
|
fn setup_logfile();
|
||||||
fn find_preinit_device() -> String;
|
fn find_preinit_device() -> String;
|
||||||
fn revert_unmount(pid: i32);
|
fn revert_unmount(pid: i32);
|
||||||
|
fn remove_modules();
|
||||||
fn zygisk_should_load_module(flags: u32) -> bool;
|
fn zygisk_should_load_module(flags: u32) -> bool;
|
||||||
unsafe fn persist_get_prop(name: Utf8CStrRef, prop_cb: Pin<&mut PropCb>);
|
unsafe fn persist_get_prop(name: Utf8CStrRef, prop_cb: Pin<&mut PropCb>);
|
||||||
unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>);
|
unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>);
|
||||||
@@ -221,8 +222,6 @@ pub mod ffi {
|
|||||||
|
|
||||||
#[namespace = "rust"]
|
#[namespace = "rust"]
|
||||||
fn daemon_entry();
|
fn daemon_entry();
|
||||||
#[namespace = "rust"]
|
|
||||||
fn load_modules(module_list: &[ModuleInfo], zygisk_name: &str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default constructors
|
// Default constructors
|
||||||
@@ -256,9 +255,6 @@ pub mod ffi {
|
|||||||
#[cxx_name = "Get"]
|
#[cxx_name = "Get"]
|
||||||
fn get() -> &'static MagiskD;
|
fn get() -> &'static MagiskD;
|
||||||
}
|
}
|
||||||
unsafe extern "C++" {
|
|
||||||
fn handle_modules(self: &MagiskD) -> Vec<ModuleInfo>;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
@@ -277,15 +273,3 @@ impl SuRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_prop(name: &Utf8CStr, persist: bool) -> String {
|
|
||||||
unsafe { ffi::get_prop_rs(name.as_ptr(), persist) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_prop(name: &Utf8CStr, value: &Utf8CStr, skip_svc: bool) -> bool {
|
|
||||||
unsafe { ffi::set_prop_rs(name.as_ptr(), value.as_ptr(), skip_svc) == 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_prop_file(filename: &Utf8CStr, skip_svc: bool) {
|
|
||||||
unsafe { ffi::load_prop_file(filename.as_ptr(), skip_svc) };
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ fn write_log_to_pipe(mut logd: &File, prio: i32, msg: &Utf8CStr) -> io::Result<u
|
|||||||
let result = logd.write_vectored(&[io1, io2]);
|
let result = logd.write_vectored(&[io1, io2]);
|
||||||
if let Err(ref e) = result {
|
if let Err(ref e) = result {
|
||||||
let mut buf = cstr::buf::default();
|
let mut buf = cstr::buf::default();
|
||||||
buf.write_fmt(format_args!("Cannot write_log_to_pipe: {}", e))
|
buf.write_fmt(format_args!("Cannot write_log_to_pipe: {e}"))
|
||||||
.ok();
|
.ok();
|
||||||
android_log_write(LogLevel::Error, &buf);
|
android_log_write(LogLevel::Error, &buf);
|
||||||
}
|
}
|
||||||
@@ -142,11 +142,11 @@ static MAGISK_LOGD_FD: Mutex<Option<Arc<File>>> = Mutex::new(None);
|
|||||||
|
|
||||||
fn with_logd_fd<R, F: FnOnce(&File) -> io::Result<R>>(f: F) {
|
fn with_logd_fd<R, F: FnOnce(&File) -> io::Result<R>>(f: F) {
|
||||||
let fd = MAGISK_LOGD_FD.lock().unwrap().clone();
|
let fd = MAGISK_LOGD_FD.lock().unwrap().clone();
|
||||||
if let Some(logd) = fd {
|
if let Some(logd) = fd
|
||||||
if f(&logd).is_err() {
|
&& f(&logd).is_err()
|
||||||
// If any error occurs, shut down the logd pipe
|
{
|
||||||
*MAGISK_LOGD_FD.lock().unwrap() = None;
|
// If any error occurs, shut down the logd pipe
|
||||||
}
|
*MAGISK_LOGD_FD.lock().unwrap() = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,197 +0,0 @@
|
|||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
|
|
||||||
#include <base.hpp>
|
|
||||||
#include <consts.hpp>
|
|
||||||
#include <core.hpp>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/************************
|
|
||||||
* Filesystem operations
|
|
||||||
************************/
|
|
||||||
|
|
||||||
static void prepare_modules() {
|
|
||||||
// Upgrade modules
|
|
||||||
if (auto dir = open_dir(MODULEUPGRADE); dir) {
|
|
||||||
int ufd = dirfd(dir.get());
|
|
||||||
int mfd = xopen(MODULEROOT, O_RDONLY | O_CLOEXEC);
|
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
|
||||||
if (entry->d_type == DT_DIR) {
|
|
||||||
// Cleanup old module if exists
|
|
||||||
if (faccessat(mfd, entry->d_name, F_OK, 0) == 0) {
|
|
||||||
int modfd = xopenat(mfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
|
||||||
if (faccessat(modfd, "disable", F_OK, 0) == 0) {
|
|
||||||
auto disable = entry->d_name + "/disable"s;
|
|
||||||
close(xopenat(ufd, disable.data(), O_RDONLY | O_CREAT | O_CLOEXEC, 0));
|
|
||||||
}
|
|
||||||
frm_rf(modfd);
|
|
||||||
unlinkat(mfd, entry->d_name, AT_REMOVEDIR);
|
|
||||||
}
|
|
||||||
LOGI("Upgrade / New module: %s\n", entry->d_name);
|
|
||||||
renameat(ufd, entry->d_name, mfd, entry->d_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(mfd);
|
|
||||||
rm_rf(MODULEUPGRADE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Func>
|
|
||||||
static void foreach_module(Func fn) {
|
|
||||||
auto dir = open_dir(MODULEROOT);
|
|
||||||
if (!dir)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int dfd = dirfd(dir.get());
|
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
|
||||||
if (entry->d_type == DT_DIR && entry->d_name != ".core"sv) {
|
|
||||||
int modfd = xopenat(dfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
|
||||||
fn(dfd, entry, modfd);
|
|
||||||
close(modfd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static rust::Vec<ModuleInfo> collect_modules(bool zygisk_enabled, bool open_zygisk) {
|
|
||||||
rust::Vec<ModuleInfo> modules;
|
|
||||||
foreach_module([&](int dfd, dirent *entry, int modfd) {
|
|
||||||
if (faccessat(modfd, "remove", F_OK, 0) == 0) {
|
|
||||||
LOGI("%s: remove\n", entry->d_name);
|
|
||||||
auto uninstaller = MODULEROOT + "/"s + entry->d_name + "/uninstall.sh";
|
|
||||||
if (access(uninstaller.data(), F_OK) == 0)
|
|
||||||
exec_script(uninstaller.data());
|
|
||||||
frm_rf(xdup(modfd));
|
|
||||||
unlinkat(dfd, entry->d_name, AT_REMOVEDIR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unlinkat(modfd, "update", 0);
|
|
||||||
if (faccessat(modfd, "disable", F_OK, 0) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ModuleInfo info{{}, -1, -1};
|
|
||||||
if (zygisk_enabled) {
|
|
||||||
// Riru and its modules are not compatible with zygisk
|
|
||||||
if (entry->d_name == "riru-core"sv || faccessat(modfd, "riru", F_OK, 0) == 0) {
|
|
||||||
LOGI("%s: ignore\n", entry->d_name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (open_zygisk) {
|
|
||||||
#if defined(__arm__)
|
|
||||||
info.z32 = openat(modfd, "zygisk/armeabi-v7a.so", O_RDONLY | O_CLOEXEC);
|
|
||||||
info.z64 = -1;
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
info.z32 = openat(modfd, "zygisk/armeabi-v7a.so", O_RDONLY | O_CLOEXEC);
|
|
||||||
info.z64 = openat(modfd, "zygisk/arm64-v8a.so", O_RDONLY | O_CLOEXEC);
|
|
||||||
#elif defined(__i386__)
|
|
||||||
info.z32 = openat(modfd, "zygisk/x86.so", O_RDONLY | O_CLOEXEC);
|
|
||||||
info.z64 = -1;
|
|
||||||
#elif defined(__x86_64__)
|
|
||||||
info.z32 = openat(modfd, "zygisk/x86.so", O_RDONLY | O_CLOEXEC);
|
|
||||||
info.z64 = openat(modfd, "zygisk/x86_64.so", O_RDONLY | O_CLOEXEC);
|
|
||||||
#elif defined(__riscv)
|
|
||||||
info.z32 = -1;
|
|
||||||
info.z64 = openat(modfd, "zygisk/riscv64.so", O_RDONLY | O_CLOEXEC);
|
|
||||||
#else
|
|
||||||
#error Unsupported ABI
|
|
||||||
#endif
|
|
||||||
unlinkat(modfd, "zygisk/unloaded", 0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Ignore zygisk modules when zygisk is not enabled
|
|
||||||
if (faccessat(modfd, "zygisk", F_OK, 0) == 0) {
|
|
||||||
LOGI("%s: ignore\n", entry->d_name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info.name = entry->d_name;
|
|
||||||
modules.push_back(std::move(info));
|
|
||||||
});
|
|
||||||
if (zygisk_enabled) {
|
|
||||||
bool use_memfd = true;
|
|
||||||
auto convert_to_memfd = [&](int fd) -> int {
|
|
||||||
if (fd < 0)
|
|
||||||
return -1;
|
|
||||||
if (use_memfd) {
|
|
||||||
int memfd = syscall(__NR_memfd_create, "jit-cache", MFD_CLOEXEC);
|
|
||||||
if (memfd >= 0) {
|
|
||||||
xsendfile(memfd, fd, nullptr, INT_MAX);
|
|
||||||
close(fd);
|
|
||||||
return memfd;
|
|
||||||
} else {
|
|
||||||
// memfd_create failed, just use what we had
|
|
||||||
use_memfd = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
};
|
|
||||||
std::for_each(modules.begin(),modules.end(), [&](ModuleInfo &info) {
|
|
||||||
info.z32 = convert_to_memfd(info.z32);
|
|
||||||
info.z64 = convert_to_memfd(info.z64);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return modules;
|
|
||||||
}
|
|
||||||
|
|
||||||
rust::Vec<ModuleInfo> MagiskD::handle_modules() const noexcept {
|
|
||||||
bool zygisk = zygisk_enabled();
|
|
||||||
prepare_modules();
|
|
||||||
exec_module_scripts("post-fs-data", collect_modules(zygisk, false));
|
|
||||||
// Recollect modules (module scripts could remove itself)
|
|
||||||
auto list = collect_modules(zygisk, true);
|
|
||||||
|
|
||||||
if (zygisk) {
|
|
||||||
string native_bridge_orig = get_prop(NBPROP);
|
|
||||||
if (native_bridge_orig.empty()) {
|
|
||||||
native_bridge_orig = "0";
|
|
||||||
}
|
|
||||||
native_bridge = native_bridge_orig != "0" ? ZYGISKLDR + native_bridge_orig : ZYGISKLDR;
|
|
||||||
set_prop(NBPROP, native_bridge.data());
|
|
||||||
// Whether Huawei's Maple compiler is enabled.
|
|
||||||
// If so, system server will be created by a special Zygote which ignores the native bridge
|
|
||||||
// and make system server out of our control. Avoid it by disabling.
|
|
||||||
if (get_prop("ro.maple.enable") == "1") {
|
|
||||||
set_prop("ro.maple.enable", "0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rust::load_modules(rust::Slice<const ModuleInfo>(list), zygisk ? native_bridge : "");
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int check_rules_dir(char *buf, size_t sz) {
|
|
||||||
int off = ssprintf(buf, sz, "%s/" PREINITMIRR, get_magisk_tmp());
|
|
||||||
struct stat st1{};
|
|
||||||
struct stat st2{};
|
|
||||||
if (xstat(buf, &st1) < 0 || xstat(MODULEROOT, &st2) < 0)
|
|
||||||
return 0;
|
|
||||||
if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
|
|
||||||
return 0;
|
|
||||||
return off;
|
|
||||||
}
|
|
||||||
|
|
||||||
void disable_modules() {
|
|
||||||
char buf[4096];
|
|
||||||
int off = check_rules_dir(buf, sizeof(buf));
|
|
||||||
foreach_module([&](int, dirent *entry, int modfd) {
|
|
||||||
close(xopenat(modfd, "disable", O_RDONLY | O_CREAT | O_CLOEXEC, 0));
|
|
||||||
if (off) {
|
|
||||||
ssprintf(buf + off, sizeof(buf) - off, "/%s/sepolicy.rule", entry->d_name);
|
|
||||||
unlink(buf);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_modules() {
|
|
||||||
char buf[4096];
|
|
||||||
int off = check_rules_dir(buf, sizeof(buf));
|
|
||||||
foreach_module([&](int, dirent *entry, int) {
|
|
||||||
auto uninstaller = MODULEROOT + "/"s + entry->d_name + "/uninstall.sh";
|
|
||||||
if (access(uninstaller.data(), F_OK) == 0)
|
|
||||||
exec_script(uninstaller.data());
|
|
||||||
if (off) {
|
|
||||||
ssprintf(buf + off, sizeof(buf) - off, "/%s/sepolicy.rule", entry->d_name);
|
|
||||||
unlink(buf);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
rm_rf(MODULEROOT);
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,28 @@
|
|||||||
use crate::consts::{MODULEMNT, WORKERDIR};
|
use crate::consts::{MODULEMNT, MODULEROOT, MODULEUPGRADE, WORKERDIR};
|
||||||
use crate::ffi::{ModuleInfo, get_magisk_tmp};
|
use crate::daemon::MagiskD;
|
||||||
use crate::load_prop_file;
|
use crate::ffi::{
|
||||||
use base::{
|
ModuleInfo, exec_module_scripts, exec_script, get_magisk_tmp, get_zygisk_lib_name,
|
||||||
Directory, FsPathBuilder, LoggedResult, OsResultStatic, ResultExt, Utf8CStr, Utf8CStrBuf,
|
load_prop_file, set_zygisk_prop,
|
||||||
Utf8CString, WalkResult, clone_attr, cstr, debug, error, info, libc, warn,
|
|
||||||
};
|
};
|
||||||
use libc::{MS_RDONLY, O_CLOEXEC, O_CREAT, O_RDONLY};
|
use crate::mount::setup_module_mount;
|
||||||
|
use base::{
|
||||||
|
DirEntry, Directory, FsPathBuilder, LibcReturn, LoggedResult, OsResultStatic, ResultExt,
|
||||||
|
Utf8CStr, Utf8CStrBuf, Utf8CString, WalkResult, clone_attr, cstr, debug, error, info, libc,
|
||||||
|
raw_cstr, warn,
|
||||||
|
};
|
||||||
|
use libc::{AT_REMOVEDIR, MS_RDONLY, O_CLOEXEC, O_CREAT, O_RDONLY};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
use std::os::fd::{AsRawFd, IntoRawFd};
|
||||||
use std::path::{Component, Path};
|
use std::path::{Component, Path};
|
||||||
|
use std::ptr;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
const MAGISK_BIN_INJECT_PARTITIONS: [&Utf8CStr; 4] =
|
const MAGISK_BIN_INJECT_PARTITIONS: [&Utf8CStr; 4] = [
|
||||||
[cstr!("/system/"), cstr!("/vendor/"), cstr!("/product/"), cstr!("/system_ext/")];
|
cstr!("/system/"),
|
||||||
|
cstr!("/vendor/"),
|
||||||
|
cstr!("/product/"),
|
||||||
|
cstr!("/system_ext/"),
|
||||||
|
];
|
||||||
|
|
||||||
const SECONDARY_READ_ONLY_PARTITIONS: [&Utf8CStr; 3] =
|
const SECONDARY_READ_ONLY_PARTITIONS: [&Utf8CStr; 3] =
|
||||||
[cstr!("/vendor"), cstr!("/product"), cstr!("/system_ext")];
|
[cstr!("/vendor"), cstr!("/product"), cstr!("/system_ext")];
|
||||||
@@ -24,11 +36,12 @@ macro_rules! module_log {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn bind_mount(reason: &str, src: &Utf8CStr, dest: &Utf8CStr, rec: bool) -> OsResultStatic<()> {
|
fn bind_mount(reason: &str, src: &Utf8CStr, dest: &Utf8CStr, rec: bool) {
|
||||||
module_log!(reason, dest, src);
|
module_log!(reason, dest, src);
|
||||||
src.bind_mount_to(dest, rec)?;
|
// Ignore any kind of error here. If a single bind mount fails due to selinux permissions or
|
||||||
dest.remount_mount_point_flags(MS_RDONLY)?;
|
// kernel limitations, don't let it break module mount entirely.
|
||||||
Ok(())
|
src.bind_mount_to(dest, rec).log_ok();
|
||||||
|
dest.remount_mount_point_flags(MS_RDONLY).log_ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mount_dummy(reason: &str, src: &Utf8CStr, dest: &Utf8CStr, is_dir: bool) -> OsResultStatic<()> {
|
fn mount_dummy(reason: &str, src: &Utf8CStr, dest: &Utf8CStr, is_dir: bool) -> OsResultStatic<()> {
|
||||||
@@ -37,65 +50,97 @@ fn mount_dummy(reason: &str, src: &Utf8CStr, dest: &Utf8CStr, is_dir: bool) -> O
|
|||||||
} else {
|
} else {
|
||||||
dest.create(O_CREAT | O_RDONLY | O_CLOEXEC, 0o000)?;
|
dest.create(O_CREAT | O_RDONLY | O_CLOEXEC, 0o000)?;
|
||||||
}
|
}
|
||||||
bind_mount(reason, src, dest, false)
|
bind_mount(reason, src, dest, false);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// File paths that act like a stack, popping out the last element
|
// File path that act like a stack, popping out the last element
|
||||||
// automatically when out of scope. Using Rust's lifetime mechanism,
|
// automatically when out of scope. Using Rust's lifetime mechanism,
|
||||||
// we can ensure the buffer will never be incorrectly copied or modified.
|
// we can ensure the buffer will never be incorrectly copied or modified.
|
||||||
// After calling append or clone, the mutable reference's lifetime is
|
// After calling append or reborrow, the mutable reference's lifetime is
|
||||||
// "transferred" to the returned object, and the compiler will guarantee
|
// "transferred" to the returned object, and the compiler will guarantee
|
||||||
// that the original mutable reference can only be reused if and only if
|
// that the original mutable reference can only be reused if and only if
|
||||||
// the newly created instance is destroyed.
|
// the newly created instance is destroyed.
|
||||||
struct PathTracker<'a> {
|
struct PathTracker<'a> {
|
||||||
real: &'a mut dyn Utf8CStrBuf,
|
path: &'a mut dyn Utf8CStrBuf,
|
||||||
tmp: &'a mut dyn Utf8CStrBuf,
|
len: usize,
|
||||||
real_len: usize,
|
|
||||||
tmp_len: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PathTracker<'_> {
|
impl PathTracker<'_> {
|
||||||
fn from<'a>(real: &'a mut dyn Utf8CStrBuf, tmp: &'a mut dyn Utf8CStrBuf) -> PathTracker<'a> {
|
fn from<'a>(path: &'a mut dyn Utf8CStrBuf) -> PathTracker<'a> {
|
||||||
let real_len = real.len();
|
let len = path.len();
|
||||||
let tmp_len = tmp.len();
|
PathTracker { path, len }
|
||||||
PathTracker {
|
|
||||||
real,
|
|
||||||
tmp,
|
|
||||||
real_len,
|
|
||||||
tmp_len,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append(&mut self, name: &str) -> PathTracker {
|
fn append(&mut self, name: &str) -> PathTracker {
|
||||||
let real_len = self.real.len();
|
let len = self.path.len();
|
||||||
let tmp_len = self.tmp.len();
|
self.path.append_path(name);
|
||||||
self.real.append_path(name);
|
|
||||||
self.tmp.append_path(name);
|
|
||||||
PathTracker {
|
PathTracker {
|
||||||
real: self.real,
|
path: self.path,
|
||||||
tmp: self.tmp,
|
len,
|
||||||
real_len,
|
|
||||||
tmp_len,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone(&mut self) -> PathTracker {
|
fn reborrow(&mut self) -> PathTracker {
|
||||||
Self::from(self.real, self.tmp)
|
Self::from(self.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for PathTracker<'_> {
|
impl Drop for PathTracker<'_> {
|
||||||
// Revert back to the original state after finish using the buffer
|
// Revert back to the original state after finish using the buffer
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.real.truncate(self.real_len);
|
self.path.truncate(self.len);
|
||||||
self.tmp.truncate(self.tmp_len);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FilePaths<'a> {
|
||||||
|
real: PathTracker<'a>,
|
||||||
|
worker: PathTracker<'a>,
|
||||||
|
module_mnt: PathTracker<'a>,
|
||||||
|
module_root: PathTracker<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FilePaths<'_> {
|
||||||
|
fn append(&mut self, name: &str) -> FilePaths {
|
||||||
|
FilePaths {
|
||||||
|
real: self.real.append(name),
|
||||||
|
worker: self.worker.append(name),
|
||||||
|
module_mnt: self.module_mnt.append(name),
|
||||||
|
module_root: self.module_root.append(name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reborrow(&mut self) -> FilePaths {
|
||||||
|
FilePaths {
|
||||||
|
real: self.real.reborrow(),
|
||||||
|
worker: self.worker.reborrow(),
|
||||||
|
module_mnt: self.module_mnt.reborrow(),
|
||||||
|
module_root: self.module_root.reborrow(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn real(&self) -> &Utf8CStr {
|
||||||
|
self.real.path
|
||||||
|
}
|
||||||
|
|
||||||
|
fn worker(&self) -> &Utf8CStr {
|
||||||
|
self.worker.path
|
||||||
|
}
|
||||||
|
|
||||||
|
fn module_mnt(&self) -> &Utf8CStr {
|
||||||
|
self.module_mnt.path
|
||||||
|
}
|
||||||
|
|
||||||
|
fn module(&self) -> &Utf8CStr {
|
||||||
|
self.module_root.path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FsNode {
|
enum FsNode {
|
||||||
Directory { children: FsNodeMap },
|
Directory { children: FsNodeMap },
|
||||||
File { src: Utf8CString },
|
File { src: Utf8CString },
|
||||||
Symlink { target: Utf8CString, is_magisk_bin: bool },
|
Symlink { target: Utf8CString },
|
||||||
|
MagiskLink,
|
||||||
Whiteout,
|
Whiteout,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,21 +151,20 @@ impl FsNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_from_path(&mut self, path: &mut dyn Utf8CStrBuf) -> LoggedResult<()> {
|
fn collect(&mut self, mut paths: FilePaths) -> LoggedResult<()> {
|
||||||
let FsNode::Directory { children } = self else {
|
let FsNode::Directory { children } = self else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
let mut dir = Directory::open(path)?;
|
let mut dir = Directory::open(paths.module())?;
|
||||||
let path_len = path.len();
|
|
||||||
|
|
||||||
while let Some(entry) = dir.read()? {
|
while let Some(entry) = dir.read()? {
|
||||||
path.truncate(path_len);
|
let entry_paths = paths.append(entry.name());
|
||||||
path.append_path(entry.name());
|
let path = entry_paths.module();
|
||||||
if entry.is_dir() {
|
if entry.is_dir() {
|
||||||
let node = children
|
let node = children
|
||||||
.entry(entry.name().to_string())
|
.entry(entry.name().to_string())
|
||||||
.or_insert_with(FsNode::new_dir);
|
.or_insert_with(FsNode::new_dir);
|
||||||
node.build_from_path(path)?;
|
node.collect(entry_paths)?;
|
||||||
} else if entry.is_symlink() {
|
} else if entry.is_symlink() {
|
||||||
let mut link = cstr::buf::default();
|
let mut link = cstr::buf::default();
|
||||||
path.read_link(&mut link)?;
|
path.read_link(&mut link)?;
|
||||||
@@ -128,7 +172,6 @@ impl FsNode {
|
|||||||
.entry(entry.name().to_string())
|
.entry(entry.name().to_string())
|
||||||
.or_insert_with(|| FsNode::Symlink {
|
.or_insert_with(|| FsNode::Symlink {
|
||||||
target: link.to_owned(),
|
target: link.to_owned(),
|
||||||
is_magisk_bin: false,
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if entry.is_char_device() {
|
if entry.is_char_device() {
|
||||||
@@ -140,10 +183,14 @@ impl FsNode {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if entry_paths.real().exists() {
|
||||||
|
clone_attr(entry_paths.real(), path)?;
|
||||||
|
}
|
||||||
children
|
children
|
||||||
.entry(entry.name().to_string())
|
.entry(entry.name().to_string())
|
||||||
.or_insert_with(|| FsNode::File {
|
.or_insert_with(|| FsNode::File {
|
||||||
src: path.to_owned(),
|
// Make sure to mount from module_mnt, not module
|
||||||
|
src: entry_paths.module_mnt().to_owned(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,7 +211,7 @@ impl FsNode {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FsNode::Symlink { .. } | FsNode::Whiteout => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +222,7 @@ impl FsNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit(&mut self, mut path: PathTracker, is_root_dir: bool) -> LoggedResult<()> {
|
fn commit(&mut self, mut path: FilePaths, is_root_dir: bool) -> LoggedResult<()> {
|
||||||
match self {
|
match self {
|
||||||
FsNode::Directory { children } => {
|
FsNode::Directory { children } => {
|
||||||
let mut is_tmpfs = false;
|
let mut is_tmpfs = false;
|
||||||
@@ -184,7 +231,7 @@ impl FsNode {
|
|||||||
children.retain(|name, node| {
|
children.retain(|name, node| {
|
||||||
if name == ".replace" {
|
if name == ".replace" {
|
||||||
return if is_root_dir {
|
return if is_root_dir {
|
||||||
warn!("Unable to replace '{}', ignore request", path.real);
|
warn!("Unable to replace '{}', ignore request", path.real());
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
is_tmpfs = true;
|
is_tmpfs = true;
|
||||||
@@ -193,10 +240,10 @@ impl FsNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let path = path.append(name);
|
let path = path.append(name);
|
||||||
if node.parent_should_be_tmpfs(path.real) {
|
if node.parent_should_be_tmpfs(path.real()) {
|
||||||
if is_root_dir {
|
if is_root_dir {
|
||||||
// Ignore the unsupported child node
|
// Ignore the unsupported child node
|
||||||
warn!("Unable to add '{}', skipped", path.real);
|
warn!("Unable to add '{}', skipped", path.real());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
is_tmpfs = true;
|
is_tmpfs = true;
|
||||||
@@ -205,10 +252,10 @@ impl FsNode {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if is_tmpfs {
|
if is_tmpfs {
|
||||||
self.commit_tmpfs(path.clone())?;
|
self.commit_tmpfs(path.reborrow())?;
|
||||||
// Transitioning from non-tmpfs to tmpfs, we need to actually mount the
|
// Transitioning from non-tmpfs to tmpfs, we need to actually mount the
|
||||||
// worker dir to dest after all children are committed.
|
// worker dir to dest after all children are committed.
|
||||||
bind_mount("move", path.tmp, path.real, true)?;
|
bind_mount("move", path.worker(), path.real(), true);
|
||||||
} else {
|
} else {
|
||||||
for (name, node) in children {
|
for (name, node) in children {
|
||||||
let path = path.append(name);
|
let path = path.append(name);
|
||||||
@@ -217,26 +264,25 @@ impl FsNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
FsNode::File { src } => {
|
FsNode::File { src } => {
|
||||||
clone_attr(path.real, src)?;
|
bind_mount("mount", src, path.real(), false);
|
||||||
bind_mount("mount", src, path.real, false)?;
|
|
||||||
}
|
}
|
||||||
FsNode::Symlink { .. } | FsNode::Whiteout => {
|
_ => {
|
||||||
error!("Unable to handle '{}': parent should be tmpfs", path.real);
|
error!("Unable to handle '{}': parent should be tmpfs", path.real());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit_tmpfs(&mut self, mut path: PathTracker) -> LoggedResult<()> {
|
fn commit_tmpfs(&mut self, mut path: FilePaths) -> LoggedResult<()> {
|
||||||
match self {
|
match self {
|
||||||
FsNode::Directory { children } => {
|
FsNode::Directory { children } => {
|
||||||
path.tmp.mkdirs(0o000)?;
|
path.worker().mkdirs(0o000)?;
|
||||||
if path.real.exists() {
|
if path.real().exists() {
|
||||||
clone_attr(path.real, path.tmp)?;
|
clone_attr(path.real(), path.worker())?;
|
||||||
} else if let Some(p) = path.tmp.parent_dir() {
|
} else if let Some(p) = path.worker().parent_dir() {
|
||||||
let parent = Utf8CString::from(p);
|
let parent = Utf8CString::from(p);
|
||||||
clone_attr(&parent, path.tmp)?;
|
clone_attr(&parent, path.worker())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether a file name '.replace' exist
|
// Check whether a file name '.replace' exist
|
||||||
@@ -248,10 +294,10 @@ impl FsNode {
|
|||||||
match node {
|
match node {
|
||||||
FsNode::Directory { .. } | FsNode::File { .. } => {
|
FsNode::Directory { .. } | FsNode::File { .. } => {
|
||||||
let src = Utf8CString::from(base_dir).join_path(name);
|
let src = Utf8CString::from(base_dir).join_path(name);
|
||||||
bind_mount(
|
mount_dummy(
|
||||||
"mount",
|
"mount",
|
||||||
&src,
|
&src,
|
||||||
path.real,
|
path.worker(),
|
||||||
matches!(node, FsNode::Directory { .. }),
|
matches!(node, FsNode::Directory { .. }),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
@@ -264,7 +310,7 @@ impl FsNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Traverse the real directory and mount mirrors
|
// Traverse the real directory and mount mirrors
|
||||||
if let Ok(mut dir) = Directory::open(path.real) {
|
if let Ok(mut dir) = Directory::open(path.real()) {
|
||||||
while let Ok(Some(entry)) = dir.read() {
|
while let Ok(Some(entry)) = dir.read() {
|
||||||
if children.contains_key(entry.name().as_str()) {
|
if children.contains_key(entry.name().as_str()) {
|
||||||
// Should not be mirrored, next
|
// Should not be mirrored, next
|
||||||
@@ -281,11 +327,10 @@ impl FsNode {
|
|||||||
entry.name().to_string(),
|
entry.name().to_string(),
|
||||||
FsNode::Symlink {
|
FsNode::Symlink {
|
||||||
target: link.to_owned(),
|
target: link.to_owned(),
|
||||||
is_magisk_bin: false,
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
mount_dummy("mirror", path.real, path.tmp, entry.is_dir())?;
|
mount_dummy("mirror", path.real(), path.worker(), entry.is_dir())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,21 +342,28 @@ impl FsNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
FsNode::File { src } => {
|
FsNode::File { src } => {
|
||||||
if path.real.exists() {
|
mount_dummy("mount", src, path.worker(), false)?;
|
||||||
clone_attr(path.real, src)?;
|
|
||||||
}
|
|
||||||
mount_dummy("mount", src, path.tmp, false)?;
|
|
||||||
}
|
}
|
||||||
FsNode::Symlink { target, is_magisk_bin } => {
|
FsNode::Symlink { target } => {
|
||||||
module_log!("mklink", path.tmp, target);
|
module_log!("mklink", path.worker(), target);
|
||||||
path.tmp.create_symlink_to(target)?;
|
path.worker().create_symlink_to(target)?;
|
||||||
// Avoid cloneing existing su attributes to our su
|
if path.real().exists() {
|
||||||
if !*is_magisk_bin && path.real.exists() {
|
clone_attr(path.real(), path.worker())?;
|
||||||
clone_attr(path.real, path.tmp)?;
|
}
|
||||||
|
}
|
||||||
|
FsNode::MagiskLink => {
|
||||||
|
if let Some(name) = path.real().file_name()
|
||||||
|
&& name == "supolicy"
|
||||||
|
{
|
||||||
|
module_log!("mklink", path.worker(), "./magiskpolicy");
|
||||||
|
path.worker().create_symlink_to(cstr!("./magiskpolicy"))?;
|
||||||
|
} else {
|
||||||
|
module_log!("mklink", path.worker(), "./magisk");
|
||||||
|
path.worker().create_symlink_to(cstr!("./magisk"))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FsNode::Whiteout => {
|
FsNode::Whiteout => {
|
||||||
module_log!("delete", path.real, "null");
|
module_log!("delete", path.real(), "null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -349,34 +401,15 @@ fn inject_magisk_bins(system: &mut FsNode) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Inject applet symlinks
|
// Inject applet symlinks
|
||||||
|
children.insert("su".to_string(), FsNode::MagiskLink);
|
||||||
children.insert(
|
children.insert("resetprop".to_string(), FsNode::MagiskLink);
|
||||||
"su".to_string(),
|
children.insert("supolicy".to_string(), FsNode::MagiskLink);
|
||||||
FsNode::Symlink {
|
|
||||||
target: Utf8CString::from("./magisk"),
|
|
||||||
is_magisk_bin: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
children.insert(
|
|
||||||
"resetprop".to_string(),
|
|
||||||
FsNode::Symlink {
|
|
||||||
target: Utf8CString::from("./magisk"),
|
|
||||||
is_magisk_bin: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
children.insert(
|
|
||||||
"supolicy".to_string(),
|
|
||||||
FsNode::Symlink {
|
|
||||||
target: Utf8CString::from("./magiskpolicy"),
|
|
||||||
is_magisk_bin: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strip /system prefix to insert correct node
|
// Strip /system prefix to insert correct node
|
||||||
fn strip_system_prefix(orig_item: &str) -> String {
|
fn strip_system_prefix(orig_item: &str) -> String {
|
||||||
match orig_item.strip_prefix("/system/") {
|
match orig_item.strip_prefix("/system/") {
|
||||||
Some(rest) => format!("/{}", rest),
|
Some(rest) => format!("/{rest}"),
|
||||||
None => orig_item.to_string(),
|
None => orig_item.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,7 +419,10 @@ fn inject_magisk_bins(system: &mut FsNode) {
|
|||||||
|
|
||||||
for orig_item in path_env.split(':') {
|
for orig_item in path_env.split(':') {
|
||||||
// Filter not suitbale paths
|
// Filter not suitbale paths
|
||||||
if !MAGISK_BIN_INJECT_PARTITIONS.iter().any(|p| orig_item.starts_with(p.as_str())) {
|
if !MAGISK_BIN_INJECT_PARTITIONS
|
||||||
|
.iter()
|
||||||
|
.any(|p| orig_item.starts_with(p.as_str()))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Flatten apex path is not suitable too
|
// Flatten apex path is not suitable too
|
||||||
@@ -395,7 +431,7 @@ fn inject_magisk_bins(system: &mut FsNode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Override existing su first
|
// Override existing su first
|
||||||
let su_path = Utf8CString::from(format!("{}/su", orig_item));
|
let su_path = Utf8CString::from(format!("{orig_item}/su"));
|
||||||
if su_path.exists() {
|
if su_path.exists() {
|
||||||
let item = strip_system_prefix(orig_item);
|
let item = strip_system_prefix(orig_item);
|
||||||
candidates.push((item, 0));
|
candidates.push((item, 0));
|
||||||
@@ -403,21 +439,25 @@ fn inject_magisk_bins(system: &mut FsNode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let path = Utf8CString::from(orig_item);
|
let path = Utf8CString::from(orig_item);
|
||||||
if let Ok(attr) = path.get_attr() && (attr.st.st_mode & 0x0001) != 0 {
|
if let Ok(attr) = path.get_attr()
|
||||||
if let Ok(mut dir) = Directory::open(&path) {
|
&& (attr.st.st_mode & 0x0001) != 0
|
||||||
let mut count = 0;
|
&& let Ok(mut dir) = Directory::open(&path)
|
||||||
if let Err(_) = dir.pre_order_walk(|e| {
|
{
|
||||||
|
let mut count = 0;
|
||||||
|
if dir
|
||||||
|
.pre_order_walk(|e| {
|
||||||
if e.is_file() {
|
if e.is_file() {
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
Ok(WalkResult::Continue)
|
Ok(WalkResult::Continue)
|
||||||
}) {
|
})
|
||||||
// Skip, we cannot ensure the result is correct
|
.is_err()
|
||||||
continue;
|
{
|
||||||
}
|
// Skip, we cannot ensure the result is correct
|
||||||
let item = strip_system_prefix(orig_item);
|
continue;
|
||||||
candidates.push((item, count));
|
|
||||||
}
|
}
|
||||||
|
let item = strip_system_prefix(orig_item);
|
||||||
|
candidates.push((item, count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,7 +497,9 @@ fn inject_magisk_bins(system: &mut FsNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inject_zygisk_bins(system: &mut FsNode, name: &str) {
|
fn inject_zygisk_bins(system: &mut FsNode) {
|
||||||
|
let name = get_zygisk_lib_name();
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
let has_32_bit = cstr!("/system/bin/linker").exists();
|
let has_32_bit = cstr!("/system/bin/linker").exists();
|
||||||
|
|
||||||
@@ -477,7 +519,7 @@ fn inject_zygisk_bins(system: &mut FsNode, name: &str) {
|
|||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
bin_path.append_path("magisk");
|
bin_path.append_path("magisk");
|
||||||
|
|
||||||
// There are some devices that announce ABI as 64 bit only, but ship with linker64
|
// There are some devices that announce ABI as 64 bit only, but ship with linker
|
||||||
// because they make use of a special 32 bit to 64 bit translator (such as tango).
|
// because they make use of a special 32 bit to 64 bit translator (such as tango).
|
||||||
// In this case, magisk32 does not exist, so inserting it will cause bind mount
|
// In this case, magisk32 does not exist, so inserting it will cause bind mount
|
||||||
// failure and affect module mount. Native bridge injection does not support these
|
// failure and affect module mount. Native bridge injection does not support these
|
||||||
@@ -513,43 +555,59 @@ fn inject_zygisk_bins(system: &mut FsNode, name: &str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_modules(module_list: &[ModuleInfo], zygisk_name: &str) {
|
fn apply_modules(zygisk: bool, module_list: &[ModuleInfo]) {
|
||||||
let mut system = FsNode::new_dir();
|
let mut system = FsNode::new_dir();
|
||||||
|
|
||||||
|
// Build all the base "prefix" paths
|
||||||
|
let mut root = cstr::buf::default().join_path("/");
|
||||||
|
|
||||||
|
let mut module_dir = cstr::buf::default().join_path(MODULEROOT);
|
||||||
|
|
||||||
|
let mut module_mnt = cstr::buf::default()
|
||||||
|
.join_path(get_magisk_tmp())
|
||||||
|
.join_path(MODULEMNT);
|
||||||
|
|
||||||
|
let mut worker = cstr::buf::default()
|
||||||
|
.join_path(get_magisk_tmp())
|
||||||
|
.join_path(WORKERDIR);
|
||||||
|
|
||||||
|
// Create a collection of all relevant paths
|
||||||
|
let mut root_paths = FilePaths {
|
||||||
|
real: PathTracker::from(&mut root),
|
||||||
|
worker: PathTracker::from(&mut worker),
|
||||||
|
module_mnt: PathTracker::from(&mut module_mnt),
|
||||||
|
module_root: PathTracker::from(&mut module_dir),
|
||||||
|
};
|
||||||
|
|
||||||
// Step 1: Create virtual filesystem tree
|
// Step 1: Create virtual filesystem tree
|
||||||
//
|
//
|
||||||
// In this step, there is zero logic applied during tree construction; we simply collect
|
// In this step, there is zero logic applied during tree construction; we simply collect and
|
||||||
// and record the union of all module filesystem trees under each of their /system directory.
|
// record the union of all module filesystem trees under each of their /system directory.
|
||||||
|
|
||||||
let mut path = cstr::buf::default()
|
|
||||||
.join_path(get_magisk_tmp())
|
|
||||||
.join_path(MODULEMNT);
|
|
||||||
let len = path.len();
|
|
||||||
for info in module_list {
|
for info in module_list {
|
||||||
path.truncate(len);
|
let mut module_paths = root_paths.append(&info.name);
|
||||||
path.append_path(&info.name);
|
{
|
||||||
|
// Read props
|
||||||
// Read props
|
let prop = module_paths.append("system.prop");
|
||||||
let module_path_len = path.len();
|
if prop.module().exists() {
|
||||||
path.append_path("system.prop");
|
// Do NOT go through property service as it could cause boot lock
|
||||||
if path.exists() {
|
load_prop_file(prop.module(), true);
|
||||||
// Do NOT go through property service as it could cause boot lock
|
}
|
||||||
load_prop_file(&path, true);
|
|
||||||
}
|
}
|
||||||
|
{
|
||||||
// Check whether skip mounting
|
// Check whether skip mounting
|
||||||
path.truncate(module_path_len);
|
let skip = module_paths.append("skip_mount");
|
||||||
path.append_path("skip_mount");
|
if skip.module().exists() {
|
||||||
if path.exists() {
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
// Double check whether the system folder exists
|
// Double check whether the system folder exists
|
||||||
path.truncate(module_path_len);
|
let sys = module_paths.append("system");
|
||||||
path.append_path("system");
|
if sys.module().exists() {
|
||||||
if path.exists() {
|
info!("{}: loading module files", &info.name);
|
||||||
info!("{}: loading module files", &info.name);
|
system.collect(sys).log_ok();
|
||||||
system.build_from_path(&mut path).log_ok();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,8 +622,8 @@ pub fn load_modules(module_list: &[ModuleInfo], zygisk_name: &str) {
|
|||||||
if get_magisk_tmp() != "/sbin" || get_path_env().split(":").all(|s| s != "/sbin") {
|
if get_magisk_tmp() != "/sbin" || get_path_env().split(":").all(|s| s != "/sbin") {
|
||||||
inject_magisk_bins(&mut system);
|
inject_magisk_bins(&mut system);
|
||||||
}
|
}
|
||||||
if !zygisk_name.is_empty() {
|
if zygisk {
|
||||||
inject_zygisk_bins(&mut system, zygisk_name);
|
inject_zygisk_bins(&mut system);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Extract all supported read-only partition roots
|
// Step 3: Extract all supported read-only partition roots
|
||||||
@@ -592,16 +650,6 @@ pub fn load_modules(module_list: &[ModuleInfo], zygisk_name: &str) {
|
|||||||
}
|
}
|
||||||
roots.insert("system", system);
|
roots.insert("system", system);
|
||||||
|
|
||||||
// Reuse the path buffer
|
|
||||||
path.clear();
|
|
||||||
path.push_str("/");
|
|
||||||
|
|
||||||
// Build the base worker directory path
|
|
||||||
let mut tmp = cstr::buf::default()
|
|
||||||
.join_path(get_magisk_tmp())
|
|
||||||
.join_path(WORKERDIR);
|
|
||||||
|
|
||||||
let mut tracker = PathTracker::from(&mut path, &mut tmp);
|
|
||||||
for (dir, mut root) in roots {
|
for (dir, mut root) in roots {
|
||||||
// Step 4: Convert virtual filesystem tree into concrete operations
|
// Step 4: Convert virtual filesystem tree into concrete operations
|
||||||
//
|
//
|
||||||
@@ -610,7 +658,225 @@ pub fn load_modules(module_list: &[ModuleInfo], zygisk_name: &str) {
|
|||||||
// The "core" of the logic is to decide which directories need to be rebuilt in the
|
// The "core" of the logic is to decide which directories need to be rebuilt in the
|
||||||
// tmpfs worker directory, and real sub-nodes need to be mirrored inside it.
|
// tmpfs worker directory, and real sub-nodes need to be mirrored inside it.
|
||||||
|
|
||||||
let path = tracker.append(dir);
|
let path = root_paths.append(dir);
|
||||||
root.commit(path, true).log_ok();
|
root.commit(path, true).log_ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn upgrade_modules() -> LoggedResult<()> {
|
||||||
|
let mut upgrade = Directory::open(cstr!(MODULEUPGRADE))?;
|
||||||
|
let ufd = upgrade.as_raw_fd();
|
||||||
|
let root = Directory::open(cstr!(MODULEROOT))?;
|
||||||
|
while let Some(e) = upgrade.read()? {
|
||||||
|
if !e.is_dir() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let module_name = e.name();
|
||||||
|
let mut disable = false;
|
||||||
|
// Cleanup old module if exists
|
||||||
|
if root.contains_path(module_name) {
|
||||||
|
let module = root.open_as_dir_at(module_name)?;
|
||||||
|
// If the old module is disabled, we need to also disable the new one
|
||||||
|
disable = module.contains_path(cstr!("disable"));
|
||||||
|
module.remove_all()?;
|
||||||
|
root.unlink_at(module_name, AT_REMOVEDIR)?;
|
||||||
|
}
|
||||||
|
info!("Upgrade / New module: {module_name}");
|
||||||
|
unsafe {
|
||||||
|
libc::renameat(
|
||||||
|
ufd,
|
||||||
|
module_name.as_ptr(),
|
||||||
|
root.as_raw_fd(),
|
||||||
|
module_name.as_ptr(),
|
||||||
|
)
|
||||||
|
.check_os_err("renameat", Some(module_name), None)?;
|
||||||
|
}
|
||||||
|
if disable {
|
||||||
|
let path = cstr::buf::default()
|
||||||
|
.join_path(module_name)
|
||||||
|
.join_path("disable");
|
||||||
|
let _ = root.open_as_file_at(&path, O_RDONLY | O_CREAT | O_CLOEXEC, 0)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
upgrade.remove_all()?;
|
||||||
|
cstr!(MODULEUPGRADE).remove()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn for_each_module(mut func: impl FnMut(&DirEntry) -> LoggedResult<()>) -> LoggedResult<()> {
|
||||||
|
let mut root = Directory::open(cstr!(MODULEROOT))?;
|
||||||
|
while let Some(ref e) = root.read()? {
|
||||||
|
if e.is_dir() && e.name() != ".core" {
|
||||||
|
func(e)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable_modules() {
|
||||||
|
for_each_module(|e| {
|
||||||
|
let dir = e.open_as_dir()?;
|
||||||
|
dir.open_as_file_at(cstr!("disable"), O_RDONLY | O_CREAT | O_CLOEXEC, 0)?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.log_ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_uninstall_script(module_name: &Utf8CStr) {
|
||||||
|
let script = cstr::buf::default()
|
||||||
|
.join_path(MODULEROOT)
|
||||||
|
.join_path(module_name)
|
||||||
|
.join_path("uninstall.sh");
|
||||||
|
exec_script(&script);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_modules() {
|
||||||
|
for_each_module(|e| {
|
||||||
|
let dir = e.open_as_dir()?;
|
||||||
|
if dir.contains_path(cstr!("uninstall.sh")) {
|
||||||
|
run_uninstall_script(e.name());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.log_ok();
|
||||||
|
cstr!(MODULEROOT).remove_all().log_ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_modules(zygisk_enabled: bool, open_zygisk: bool) -> Vec<ModuleInfo> {
|
||||||
|
let mut modules = Vec::new();
|
||||||
|
|
||||||
|
#[allow(unused_mut)] // It's possible that z32 and z64 are unused
|
||||||
|
for_each_module(|e| {
|
||||||
|
let name = e.name();
|
||||||
|
let dir = e.open_as_dir()?;
|
||||||
|
if dir.contains_path(cstr!("remove")) {
|
||||||
|
info!("{name}: remove");
|
||||||
|
if dir.contains_path(cstr!("uninstall.sh")) {
|
||||||
|
run_uninstall_script(name);
|
||||||
|
}
|
||||||
|
dir.remove_all()?;
|
||||||
|
e.unlink()?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
dir.unlink_at(cstr!("update"), 0).ok();
|
||||||
|
if dir.contains_path(cstr!("disable")) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut z32 = -1;
|
||||||
|
let mut z64 = -1;
|
||||||
|
|
||||||
|
let is_zygisk = dir.contains_path(cstr!("zygisk"));
|
||||||
|
|
||||||
|
if zygisk_enabled {
|
||||||
|
// Riru and its modules are not compatible with zygisk
|
||||||
|
if name == "riru-core" || dir.contains_path(cstr!("riru")) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn open_fd_safe(dir: &Directory, name: &Utf8CStr) -> i32 {
|
||||||
|
dir.open_as_file_at(name, O_RDONLY | O_CLOEXEC, 0)
|
||||||
|
.log()
|
||||||
|
.map(IntoRawFd::into_raw_fd)
|
||||||
|
.unwrap_or(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if open_zygisk && is_zygisk {
|
||||||
|
#[cfg(target_arch = "arm")]
|
||||||
|
{
|
||||||
|
z32 = open_fd_safe(&dir, cstr!("zygisk/armeabi-v7a.so"));
|
||||||
|
}
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
{
|
||||||
|
z32 = open_fd_safe(&dir, cstr!("zygisk/armeabi-v7a.so"));
|
||||||
|
z64 = open_fd_safe(&dir, cstr!("zygisk/arm64-v8a.so"));
|
||||||
|
}
|
||||||
|
#[cfg(target_arch = "x86")]
|
||||||
|
{
|
||||||
|
z32 = open_fd_safe(&dir, cstr!("zygisk/x86.so"));
|
||||||
|
}
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
{
|
||||||
|
z32 = open_fd_safe(&dir, cstr!("zygisk/x86.so"));
|
||||||
|
z64 = open_fd_safe(&dir, cstr!("zygisk/x86_64.so"));
|
||||||
|
}
|
||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
{
|
||||||
|
z64 = open_fd_safe(&dir, cstr!("zygisk/riscv64.so"));
|
||||||
|
}
|
||||||
|
dir.unlink_at(cstr!("zygisk/unloaded"), 0).ok();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Ignore zygisk modules when zygisk is not enabled
|
||||||
|
if is_zygisk {
|
||||||
|
info!("{name}: ignore");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modules.push(ModuleInfo {
|
||||||
|
name: name.to_string(),
|
||||||
|
z32,
|
||||||
|
z64,
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.log_ok();
|
||||||
|
|
||||||
|
if zygisk_enabled && open_zygisk {
|
||||||
|
let mut use_memfd = true;
|
||||||
|
let mut convert_to_memfd = |fd: i32| -> i32 {
|
||||||
|
if fd < 0 {
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
if use_memfd {
|
||||||
|
let memfd = unsafe {
|
||||||
|
libc::syscall(
|
||||||
|
libc::SYS_memfd_create,
|
||||||
|
raw_cstr!("jit-cache"),
|
||||||
|
libc::MFD_CLOEXEC,
|
||||||
|
) as i32
|
||||||
|
};
|
||||||
|
if memfd >= 0 {
|
||||||
|
unsafe {
|
||||||
|
if libc::sendfile(memfd, fd, ptr::null_mut(), i32::MAX as usize) < 0 {
|
||||||
|
libc::close(memfd);
|
||||||
|
} else {
|
||||||
|
libc::close(fd);
|
||||||
|
return memfd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Some error occurred, don't try again
|
||||||
|
use_memfd = false;
|
||||||
|
}
|
||||||
|
fd
|
||||||
|
};
|
||||||
|
|
||||||
|
modules.iter_mut().for_each(|m| {
|
||||||
|
m.z32 = convert_to_memfd(m.z32);
|
||||||
|
m.z64 = convert_to_memfd(m.z64);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
modules
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MagiskD {
|
||||||
|
pub fn handle_modules(&self) {
|
||||||
|
setup_module_mount();
|
||||||
|
upgrade_modules().ok();
|
||||||
|
|
||||||
|
let zygisk = self.zygisk_enabled.load(Ordering::Acquire);
|
||||||
|
let modules = collect_modules(zygisk, false);
|
||||||
|
exec_module_scripts(cstr!("post-fs-data"), &modules);
|
||||||
|
|
||||||
|
// Recollect modules (module scripts could remove itself)
|
||||||
|
let modules = collect_modules(zygisk, true);
|
||||||
|
if zygisk {
|
||||||
|
set_zygisk_prop();
|
||||||
|
}
|
||||||
|
apply_modules(zygisk, &modules);
|
||||||
|
|
||||||
|
self.module_list.set(modules).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ use base::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::consts::{MODULEMNT, MODULEROOT, PREINITDEV, PREINITMIRR, WORKERDIR};
|
use crate::consts::{MODULEMNT, MODULEROOT, PREINITDEV, PREINITMIRR, WORKERDIR};
|
||||||
use crate::ffi::{get_magisk_tmp, resolve_preinit_dir, switch_mnt_ns};
|
use crate::ffi::{get_magisk_tmp, get_prop, resolve_preinit_dir, switch_mnt_ns};
|
||||||
use crate::get_prop;
|
|
||||||
|
|
||||||
pub fn setup_preinit_dir() {
|
pub fn setup_preinit_dir() {
|
||||||
let magisk_tmp = get_magisk_tmp();
|
let magisk_tmp = get_magisk_tmp();
|
||||||
@@ -22,37 +21,37 @@ pub fn setup_preinit_dir() {
|
|||||||
let dev_path = cstr::buf::new::<64>()
|
let dev_path = cstr::buf::new::<64>()
|
||||||
.join_path(magisk_tmp)
|
.join_path(magisk_tmp)
|
||||||
.join_path(PREINITDEV);
|
.join_path(PREINITDEV);
|
||||||
if let Ok(attr) = dev_path.get_attr() {
|
if let Ok(attr) = dev_path.get_attr()
|
||||||
if attr.st.st_mode & libc::S_IFMT as c_uint == libc::S_IFBLK.as_() {
|
&& attr.st.st_mode & libc::S_IFMT as c_uint == libc::S_IFBLK.as_()
|
||||||
// DO NOT mount the block device directly, as we do not know the flags and configs
|
{
|
||||||
// to properly mount the partition; mounting block devices directly as rw could cause
|
// DO NOT mount the block device directly, as we do not know the flags and configs
|
||||||
// crashes if the filesystem driver is crap (e.g. some broken F2FS drivers).
|
// to properly mount the partition; mounting block devices directly as rw could cause
|
||||||
// What we do instead is to scan through the current mountinfo and find a pre-existing
|
// crashes if the filesystem driver is crap (e.g. some broken F2FS drivers).
|
||||||
// mount point mounting our desired partition, and then bind mount the target folder.
|
// What we do instead is to scan through the current mountinfo and find a pre-existing
|
||||||
let preinit_dev = attr.st.st_rdev;
|
// mount point mounting our desired partition, and then bind mount the target folder.
|
||||||
let mnt_path = cstr::buf::default()
|
let preinit_dev = attr.st.st_rdev;
|
||||||
.join_path(magisk_tmp)
|
let mnt_path = cstr::buf::default()
|
||||||
.join_path(PREINITMIRR);
|
.join_path(magisk_tmp)
|
||||||
for info in parse_mount_info("self") {
|
.join_path(PREINITMIRR);
|
||||||
if info.root == "/" && info.device == preinit_dev {
|
for info in parse_mount_info("self") {
|
||||||
if !info.fs_option.split(',').any(|s| s == "rw") {
|
if info.root == "/" && info.device == preinit_dev {
|
||||||
// Only care about rw mounts
|
if !info.fs_option.split(',').any(|s| s == "rw") {
|
||||||
continue;
|
// Only care about rw mounts
|
||||||
}
|
continue;
|
||||||
let mut target = info.target;
|
}
|
||||||
let target = Utf8CStr::from_string(&mut target);
|
let mut target = info.target;
|
||||||
let mut preinit_dir = resolve_preinit_dir(target);
|
let target = Utf8CStr::from_string(&mut target);
|
||||||
let preinit_dir = Utf8CStr::from_string(&mut preinit_dir);
|
let mut preinit_dir = resolve_preinit_dir(target);
|
||||||
let r: LoggedResult<()> = try {
|
let preinit_dir = Utf8CStr::from_string(&mut preinit_dir);
|
||||||
preinit_dir.mkdir(0o700)?;
|
let r: LoggedResult<()> = try {
|
||||||
mnt_path.mkdirs(0o755)?;
|
preinit_dir.mkdir(0o700)?;
|
||||||
mnt_path.remove().ok();
|
mnt_path.mkdirs(0o755)?;
|
||||||
mnt_path.create_symlink_to(preinit_dir)?;
|
mnt_path.remove().ok();
|
||||||
};
|
mnt_path.create_symlink_to(preinit_dir)?;
|
||||||
if r.is_ok() {
|
};
|
||||||
info!("* Found preinit dir: {}", preinit_dir);
|
if r.is_ok() {
|
||||||
return;
|
info!("* Found preinit dir: {}", preinit_dir);
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,10 +237,10 @@ pub fn revert_unmount(pid: i32) {
|
|||||||
let mut prev: Option<PathBuf> = None;
|
let mut prev: Option<PathBuf> = None;
|
||||||
targets.sort();
|
targets.sort();
|
||||||
targets.retain(|target| {
|
targets.retain(|target| {
|
||||||
if let Some(prev) = &prev {
|
if let Some(prev) = &prev
|
||||||
if Path::new(target).starts_with(prev) {
|
&& Path::new(target).starts_with(prev)
|
||||||
return false;
|
{
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
prev = Some(PathBuf::from(target.clone()));
|
prev = Some(PathBuf::from(target.clone()));
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ trait PropCbExec {
|
|||||||
|
|
||||||
impl PropCbExec for Pin<&mut PropCb> {
|
impl PropCbExec for Pin<&mut PropCb> {
|
||||||
fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr) {
|
fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr) {
|
||||||
unsafe { prop_cb_exec(self.as_mut(), name.as_ptr(), value.as_ptr(), u32::MAX) }
|
prop_cb_exec(self.as_mut(), name, value, u32::MAX)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,10 +167,10 @@ pub fn persist_get_props(mut prop_cb: Pin<&mut PropCb>) {
|
|||||||
} else {
|
} else {
|
||||||
let mut dir = Directory::open(cstr!(PERSIST_PROP_DIR))?;
|
let mut dir = Directory::open(cstr!(PERSIST_PROP_DIR))?;
|
||||||
dir.pre_order_walk(|e| {
|
dir.pre_order_walk(|e| {
|
||||||
if e.is_file() {
|
if e.is_file()
|
||||||
if let Ok(mut value) = file_get_prop(e.name()) {
|
&& let Ok(mut value) = file_get_prop(e.name())
|
||||||
prop_cb.exec(e.name(), Utf8CStr::from_string(&mut value));
|
{
|
||||||
}
|
prop_cb.exec(e.name(), Utf8CStr::from_string(&mut value));
|
||||||
}
|
}
|
||||||
// Do not traverse recursively
|
// Do not traverse recursively
|
||||||
Ok(WalkResult::Skip)
|
Ok(WalkResult::Skip)
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
#include <core.hpp>
|
#include <core.hpp>
|
||||||
#include <resetprop.hpp>
|
#include <resetprop.hpp>
|
||||||
|
|
||||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
#include <api/system_properties.h>
|
||||||
#include <api/_system_properties.h>
|
|
||||||
#include <system_properties/prop_info.h>
|
#include <system_properties/prop_info.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -430,8 +429,8 @@ static StringType get_prop_impl(const char *name, bool persist) {
|
|||||||
return get_prop<StringType>(name, flags);
|
return get_prop<StringType>(name, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
rust::String get_prop_rs(const char *name, bool persist) {
|
rust::String get_prop_rs(rust::Utf8CStr name, bool persist) {
|
||||||
return get_prop_impl<rust::String>(name, persist);
|
return get_prop_impl<rust::String>(name.data(), persist);
|
||||||
}
|
}
|
||||||
|
|
||||||
string get_prop(const char *name, bool persist) {
|
string get_prop(const char *name, bool persist) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user