From c0be5383de776073130241f7772e8e90a531c15a Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Wed, 15 Sep 2021 02:49:54 -0700 Subject: [PATCH] Support enable/disable Zygisk --- .../java/com/topjohnwu/magisk/core/Config.kt | 2 ++ .../magisk/ui/settings/BaseSettingsItem.kt | 2 +- .../magisk/ui/settings/SettingsItems.kt | 27 ++++++++++++++++--- .../magisk/ui/settings/SettingsViewModel.kt | 2 +- .../com/topjohnwu/magisk/utils/TextHolder.kt | 23 ++++++++++------ app/src/main/res/values/resources.xml | 1 + app/src/main/res/values/strings.xml | 2 ++ native/jni/core/bootstages.cpp | 10 ++++--- native/jni/core/core.hpp | 1 + native/jni/core/db.cpp | 1 + native/jni/core/module.cpp | 10 ++++--- native/jni/include/db.hpp | 6 +++-- 12 files changed, 65 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Config.kt b/app/src/main/java/com/topjohnwu/magisk/core/Config.kt index c42c67443..1253875af 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Config.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Config.kt @@ -37,6 +37,7 @@ object Config : PreferenceModel, DBConfig { const val SU_MULTIUSER_MODE = "multiuser_mode" const val SU_MNT_NS = "mnt_ns" const val SU_BIOMETRIC = "su_biometric" + const val ZYGISK = "zygisk" const val SU_MANAGER = "requester" const val KEYSTORE = "keystore" @@ -143,6 +144,7 @@ object Config : PreferenceModel, DBConfig { var suMntNamespaceMode by dbSettings(Key.SU_MNT_NS, Value.NAMESPACE_MODE_REQUESTER) var suMultiuserMode by dbSettings(Key.SU_MULTIUSER_MODE, Value.MULTIUSER_MODE_OWNER_ONLY) var suBiometric by dbSettings(Key.SU_BIOMETRIC, false) + var zygisk by dbSettings(Key.ZYGISK, false) var suManager by dbStrings(Key.SU_MANAGER, "", true) var keyStoreRaw by dbStrings(Key.KEYSTORE, "", true) diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/BaseSettingsItem.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/BaseSettingsItem.kt index ad216f42f..812aeac49 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/BaseSettingsItem.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/BaseSettingsItem.kt @@ -34,7 +34,7 @@ sealed class BaseSettingsItem : ObservableRvItem() { @get:Bindable var isEnabled = true - set(value) = set(value, field, { field = it }, BR.enabled) + set(value) = set(value, field, { field = it }, BR.enabled, BR.description) open fun onPressed(view: View, callback: Callback) { callback.onItemPressed(view, this) diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt index 54a268717..9d4c47019 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt @@ -234,23 +234,44 @@ object Magisk : BaseSettingsItem.Section() { override val title = R.string.magisk.asText() } +object Zygisk : BaseSettingsItem.Toggle() { + override val title = R.string.zygisk.asText() + override val description = R.string.settings_zygisk_summary.asText() + override var value = Config.zygisk + set(value) = setV(value, field, { field = it }) { + Config.zygisk = it + DenyList.isEnabled = it + DenyListConfig.isEnabled = it + } +} + object DenyList : BaseSettingsItem.Toggle() { override val title = R.string.settings_denylist_title.asText() - override val description = R.string.settings_denylist_summary.asText() + override val description get() = + if (isEnabled) R.string.settings_denylist_summary.asText() + else R.string.settings_denylist_error.asText(R.string.zygisk.asText()) + override var value = Info.env.denyListEnforced set(value) = setV(value, field, { field = it }) { val cmd = if (it) "enable" else "disable" - Shell.su("magisk --denylist $cmd").submit { cb -> - if (cb.isSuccess) Info.env.denyListEnforced = it + Shell.su("magisk --denylist $cmd").submit { result -> + if (result.isSuccess) Info.env.denyListEnforced = it else field = !it } DenyListConfig.isEnabled = it } + + override fun refresh() { + isEnabled = Zygisk.value + } } object DenyListConfig : BaseSettingsItem.Blank() { override val title = R.string.settings_denylist_config_title.asText() override val description = R.string.settings_denylist_config_summary.asText() + override fun refresh() { + isEnabled = Zygisk.value + } } // --- Superuser diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt index 1340360ff..8afc4ba22 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt @@ -69,7 +69,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Callback { SystemlessHosts )) if (Const.Version.isCanary()) { - list.addAll(listOf(DenyList, DenyListConfig)) + list.addAll(listOf(Zygisk, DenyList, DenyListConfig)) } } diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/TextHolder.kt b/app/src/main/java/com/topjohnwu/magisk/utils/TextHolder.kt index 7f3404228..3cf52ee51 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/TextHolder.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/TextHolder.kt @@ -14,20 +14,26 @@ abstract class TextHolder { class String( private val value: CharSequence ) : TextHolder() { - override val isEmpty get() = value.isEmpty() override fun getText(resources: Resources) = value - } - class Resource( - private val value: Int, - private vararg val params: Any + open class Resource( + protected val value: Int ) : TextHolder() { - override val isEmpty get() = value == 0 - override fun getText(resources: Resources) = resources.getString(value, *params) + override fun getText(resources: Resources) = resources.getString(value) + } + class ResourceArgs( + value: Int, + private vararg val params: Any + ) : Resource(value) { + override fun getText(resources: Resources): kotlin.String { + // Replace TextHolder with strings + val args = params.map { if (it is TextHolder) it.getText(resources) else it } + return resources.getString(value, *args.toTypedArray()) + } } // --- @@ -37,7 +43,8 @@ abstract class TextHolder { } } -fun Int.asText(vararg params: Any): TextHolder = TextHolder.Resource(this, *params) +fun Int.asText(): TextHolder = TextHolder.Resource(this) +fun Int.asText(vararg params: Any): TextHolder = TextHolder.ResourceArgs(this, *params) fun CharSequence.asText(): TextHolder = TextHolder.String(this) diff --git a/app/src/main/res/values/resources.xml b/app/src/main/res/values/resources.xml index 16d5d048e..00d5c51d0 100644 --- a/app/src/main/res/values/resources.xml +++ b/app/src/main/res/values/resources.xml @@ -3,6 +3,7 @@ Magisk + Zygisk \@topjohnwu diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 263b361b0..144aba5bf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -145,8 +145,10 @@ Beta Custom Channel Insert a custom URL + Run parts of Magisk in the zygote daemon Enforce DenyList Processes on the denylist will have all Magisk modifications reverted + This feature requires %1$s to be enabled Configure DenyList Select the processes to be included on the denylist Systemless hosts diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 361bbacb8..73806dfab 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -18,6 +18,7 @@ using namespace std; static bool safe_mode = false; +bool zygisk_enabled = false; /********* * Setup * @@ -301,7 +302,12 @@ void post_fs_data(int client) { disable_deny(); } else { exec_common_scripts("post-fs-data"); - check_enforce_denylist(); + db_settings dbs; + get_db_settings(dbs, ZYGISK_CONFIG); + if (dbs[ZYGISK_CONFIG]) { + zygisk_enabled = true; + check_enforce_denylist(); + } handle_modules(); } @@ -350,8 +356,6 @@ void boot_complete(int client) { if (access(SECURE_DIR, F_OK) != 0) xmkdir(SECURE_DIR, 0700); - check_enforce_denylist(); - if (!check_manager()) { if (access(MANAGERAPK, F_OK) == 0) { // Only try to install APK when no manager is installed diff --git a/native/jni/core/core.hpp b/native/jni/core/core.hpp index 73777ffd0..70a85ed4e 100644 --- a/native/jni/core/core.hpp +++ b/native/jni/core/core.hpp @@ -6,6 +6,7 @@ extern bool RECOVERY_MODE; extern int DAEMON_STATE; +extern bool zygisk_enabled; void unlock_blocks(); void reboot(); diff --git a/native/jni/core/db.cpp b/native/jni/core/db.cpp index 82d9a4ff1..4667fd629 100644 --- a/native/jni/core/db.cpp +++ b/native/jni/core/db.cpp @@ -113,6 +113,7 @@ db_settings::db_settings() { data[SU_MULTIUSER_MODE] = MULTIUSER_MODE_OWNER_ONLY; data[SU_MNT_NS] = NAMESPACE_MODE_REQUESTER; data[DENYLIST_CONFIG] = false; + data[ZYGISK_CONFIG] = false; } int db_settings::get_idx(string_view key) const { diff --git a/native/jni/core/module.cpp b/native/jni/core/module.cpp index f9e882799..5dc69b519 100644 --- a/native/jni/core/module.cpp +++ b/native/jni/core/module.cpp @@ -616,10 +616,12 @@ void magic_mount() { root->mount(); // Mount on top of modules to enable zygisk - string zygisk_bin = MAGISKTMP + "/" ZYGISKBIN; - mkdir(zygisk_bin.data(), 0); - mount_zygisk(32) - mount_zygisk(64) + if (zygisk_enabled) { + string zygisk_bin = MAGISKTMP + "/" ZYGISKBIN; + mkdir(zygisk_bin.data(), 0); + mount_zygisk(32) + mount_zygisk(64) + } } static void prepare_modules() { diff --git a/native/jni/include/db.hpp b/native/jni/include/db.hpp index 69df70353..59cc9d6e6 100644 --- a/native/jni/include/db.hpp +++ b/native/jni/include/db.hpp @@ -38,7 +38,8 @@ constexpr const char *DB_SETTING_KEYS[] = { "root_access", "multiuser_mode", "mnt_ns", - "denylist" + "denylist", + "zygisk" }; // Settings key indices @@ -46,7 +47,8 @@ enum { ROOT_ACCESS = 0, SU_MULTIUSER_MODE, SU_MNT_NS, - DENYLIST_CONFIG + DENYLIST_CONFIG, + ZYGISK_CONFIG }; // Values for root_access