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 1253875af..015562660 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Config.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Config.kt @@ -6,9 +6,9 @@ import android.util.Xml import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.edit import com.topjohnwu.magisk.BuildConfig -import com.topjohnwu.magisk.core.utils.BiometricHelper import com.topjohnwu.magisk.core.utils.refreshLocale import com.topjohnwu.magisk.data.preference.PreferenceModel +import com.topjohnwu.magisk.data.repository.DBBoolSettingsNoWrite import com.topjohnwu.magisk.data.repository.DBConfig import com.topjohnwu.magisk.di.ServiceLocator import com.topjohnwu.magisk.ui.theme.Theme @@ -38,6 +38,7 @@ object Config : PreferenceModel, DBConfig { const val SU_MNT_NS = "mnt_ns" const val SU_BIOMETRIC = "su_biometric" const val ZYGISK = "zygisk" + const val DENYLIST = "denylist" const val SU_MANAGER = "requester" const val KEYSTORE = "keystore" @@ -145,6 +146,7 @@ object Config : PreferenceModel, DBConfig { 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 denyList by DBBoolSettingsNoWrite(Key.DENYLIST, false) var suManager by dbStrings(Key.SU_MANAGER, "", true) var keyStoreRaw by dbStrings(Key.KEYSTORE, "", true) @@ -169,12 +171,6 @@ object Config : PreferenceModel, DBConfig { else if (it.toInt() > Value.CANARY_CHANNEL) putString(Key.UPDATE_CHANNEL, Value.CANARY_CHANNEL.toString()) } - - // Write database configs - putString(Key.ROOT_ACCESS, rootMode.toString()) - putString(Key.SU_MNT_NS, suMntNamespaceMode.toString()) - putString(Key.SU_MULTIUSER_MODE, suMultiuserMode.toString()) - putBoolean(Key.SU_BIOMETRIC, BiometricHelper.isEnabled) } } diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Info.kt b/app/src/main/java/com/topjohnwu/magisk/core/Info.kt index 98816dea8..8e3198c37 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Info.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Info.kt @@ -64,9 +64,5 @@ object Info { } val isUnsupported = code > 0 && code < Const.Version.MIN_VERCODE val isActive = magiskVersionCode >= 0 - var denyListEnforced = if (Const.Version.isCanary(code)) - Shell.su("magisk --denylist status").exec().isSuccess - else - false } } diff --git a/app/src/main/java/com/topjohnwu/magisk/data/repository/DBConfig.kt b/app/src/main/java/com/topjohnwu/magisk/data/repository/DBConfig.kt index 954b86bb0..66bcd5671 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/repository/DBConfig.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/repository/DBConfig.kt @@ -35,14 +35,12 @@ class DBSettingsValue( private val default: Int ) : ReadWriteProperty { - private var value: Int? = null + var value: Int? = null @Synchronized override fun getValue(thisRef: DBConfig, property: KProperty<*>): Int { if (value == null) - value = runBlocking { - thisRef.settingsDB.fetch(name, default) - } + value = runBlocking { thisRef.settingsDB.fetch(name, default) } return value as Int } @@ -56,7 +54,7 @@ class DBSettingsValue( } } -class DBBoolSettings( +open class DBBoolSettings( name: String, default: Boolean ) : ReadWriteProperty { @@ -70,6 +68,17 @@ class DBBoolSettings( base.setValue(thisRef, property, if (value) 1 else 0) } +class DBBoolSettingsNoWrite( + name: String, + default: Boolean +) : DBBoolSettings(name, default) { + override fun setValue(thisRef: DBConfig, property: KProperty<*>, value: Boolean) { + synchronized(base) { + base.value = if (value) 1 else 0 + } + } +} + class DBStringsValue( private val name: String, private val default: String, 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 9d4c47019..3a75266e0 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 @@ -251,11 +251,11 @@ object DenyList : BaseSettingsItem.Toggle() { 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 + override var value = Config.denyList set(value) = setV(value, field, { field = it }) { val cmd = if (it) "enable" else "disable" Shell.su("magisk --denylist $cmd").submit { result -> - if (result.isSuccess) Info.env.denyListEnforced = it + if (result.isSuccess) Config.denyList = it else field = !it } DenyListConfig.isEnabled = it diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 73806dfab..22f142326 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -304,10 +304,8 @@ void post_fs_data(int client) { exec_common_scripts("post-fs-data"); db_settings dbs; get_db_settings(dbs, ZYGISK_CONFIG); - if (dbs[ZYGISK_CONFIG]) { - zygisk_enabled = true; - check_enforce_denylist(); - } + zygisk_enabled = dbs[ZYGISK_CONFIG]; + initialize_denylist(); handle_modules(); } diff --git a/native/jni/core/core.hpp b/native/jni/core/core.hpp index 70a85ed4e..0620a064f 100644 --- a/native/jni/core/core.hpp +++ b/native/jni/core/core.hpp @@ -6,7 +6,15 @@ extern bool RECOVERY_MODE; extern int DAEMON_STATE; -extern bool zygisk_enabled; + +// Daemon state +enum : int { + STATE_NONE, + STATE_POST_FS_DATA, + STATE_POST_FS_DATA_DONE, + STATE_LATE_START_DONE, + STATE_BOOT_COMPLETE +}; void unlock_blocks(); void reboot(); diff --git a/native/jni/core/module.cpp b/native/jni/core/module.cpp index 5dc69b519..019c3fbcf 100644 --- a/native/jni/core/module.cpp +++ b/native/jni/core/module.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include diff --git a/native/jni/deny/cli.cpp b/native/jni/deny/cli.cpp index 97ee93c09..2d387fe68 100644 --- a/native/jni/deny/cli.cpp +++ b/native/jni/deny/cli.cpp @@ -35,11 +35,10 @@ void denylist_handler(int client, ucred *cred) { int res = DAEMON_ERROR; switch (req) { - case DISABLE_DENY: case ADD_LIST: case RM_LIST: case LS_LIST: - if (!deny_enforced()) { + if (!denylist_enabled) { write_int(client, DENY_NOT_ENFORCED); close(client); return; @@ -48,7 +47,7 @@ void denylist_handler(int client, ucred *cred) { switch (req) { case ENFORCE_DENY: - res = enable_hide(); + res = enable_deny(); break; case DISABLE_DENY: res = disable_deny(); @@ -63,7 +62,7 @@ void denylist_handler(int client, ucred *cred) { ls_list(client); return; case DENY_STATUS: - res = deny_enforced() ? DENY_IS_ENFORCED : DENY_NOT_ENFORCED; + res = (zygisk_enabled && denylist_enabled) ? DENY_IS_ENFORCED : DENY_NOT_ENFORCED; break; } diff --git a/native/jni/deny/deny.hpp b/native/jni/deny/deny.hpp index eb3cc9abc..f7a6e57b6 100644 --- a/native/jni/deny/deny.hpp +++ b/native/jni/deny/deny.hpp @@ -4,26 +4,28 @@ #include #include #include +#include #include #define ISOLATED_MAGIC "isolated" // CLI entries -int enable_hide(); +int enable_deny(); int disable_deny(); int add_list(int client); int rm_list(int client); void ls_list(int client); // Utility functions -bool deny_enforced(); bool is_deny_target(int uid, std::string_view process); // Revert void revert_daemon(int pid, int client); void revert_unmount(int pid = -1); +extern std::atomic denylist_enabled; + enum : int { ENFORCE_DENY, DISABLE_DENY, diff --git a/native/jni/deny/utils.cpp b/native/jni/deny/utils.cpp index 2f1d44ee0..77ce1d516 100644 --- a/native/jni/deny/utils.cpp +++ b/native/jni/deny/utils.cpp @@ -19,7 +19,7 @@ static map> *uid_proc_map; /* uid -> list of process * // Locks the variables above static pthread_mutex_t data_lock = PTHREAD_MUTEX_INITIALIZER; -static atomic enforcement_status = false; +atomic denylist_enabled = false; static void rebuild_uid_map() { uid_proc_map->clear(); @@ -147,7 +147,6 @@ static int add_list(const char *pkg, const char *proc) { return DENYLIST_INVALID_PKG; { - // Critical region mutex_guard lock(data_lock); for (const auto &hide : *deny_set) if (hide.first == pkg && hide.second == proc) @@ -172,9 +171,8 @@ int add_list(int client) { } static int rm_list(const char *pkg, const char *proc) { - bool remove = false; { - // Critical region + bool remove = false; mutex_guard lock(data_lock); for (auto it = deny_set->begin(); it != deny_set->end();) { if (it->first == pkg && (proc[0] == '\0' || it->second == proc)) { @@ -248,63 +246,68 @@ void ls_list(int client) { close(client); } -static void update_hide_config() { +static void update_deny_config() { char sql[64]; sprintf(sql, "REPLACE INTO settings (key,value) VALUES('%s',%d)", - DB_SETTING_KEYS[DENYLIST_CONFIG], enforcement_status.load()); + DB_SETTING_KEYS[DENYLIST_CONFIG], denylist_enabled.load()); char *err = db_exec(sql); db_err(err); } -int enable_hide() { - if (enforcement_status) - return DENY_IS_ENFORCED; +int enable_deny() { + if (denylist_enabled) { + return DAEMON_SUCCESS; + } else { + mutex_guard lock(data_lock); - if (access("/proc/self/ns/mnt", F_OK) != 0) - return DENY_NO_NS; + if (access("/proc/self/ns/mnt", F_OK) != 0) { + LOGW("The kernel does not support mount namespace\n"); + return DENY_NO_NS; + } - if (procfp == nullptr && (procfp = opendir("/proc")) == nullptr) - return DAEMON_ERROR; + if (procfp == nullptr && (procfp = opendir("/proc")) == nullptr) + return DAEMON_ERROR; - LOGI("* Enforce DenyList\n"); + LOGI("* Enable DenyList\n"); - mutex_guard lock(data_lock); - default_new(deny_set); - default_new(uid_proc_map); + default_new(deny_set); + if (!init_list()) { + delete deny_set; + deny_set = nullptr; + return DAEMON_ERROR; + } - // Initialize the hide list - if (!init_list()) - return DAEMON_ERROR; + denylist_enabled = true; - enforcement_status = true; - update_hide_config(); + default_new(uid_proc_map); + rebuild_uid_map(); + } - rebuild_uid_map(); + update_deny_config(); return DAEMON_SUCCESS; } int disable_deny() { - mutex_guard lock(data_lock); - - if (enforcement_status) { + if (denylist_enabled) { + denylist_enabled = false; LOGI("* Disable DenyList\n"); + + mutex_guard lock(data_lock); delete uid_proc_map; delete deny_set; uid_proc_map = nullptr; deny_set = nullptr; } - - enforcement_status = false; - update_hide_config(); + update_deny_config(); return DAEMON_SUCCESS; } -void check_enforce_denylist() { - if (!enforcement_status) { +void initialize_denylist() { + if (!denylist_enabled) { db_settings dbs; get_db_settings(dbs, DENYLIST_CONFIG); if (dbs[DENYLIST_CONFIG]) - enable_hide(); + enable_deny(); } } @@ -333,7 +336,3 @@ bool is_deny_target(int uid, string_view process) { } return false; } - -bool deny_enforced() { - return enforcement_status; -} diff --git a/native/jni/include/daemon.hpp b/native/jni/include/daemon.hpp index 8c77b8f7f..acc57b4be 100644 --- a/native/jni/include/daemon.hpp +++ b/native/jni/include/daemon.hpp @@ -39,14 +39,7 @@ enum : int { DAEMON_LAST }; -// Daemon state -enum : int { - STATE_NONE, - STATE_POST_FS_DATA, - STATE_POST_FS_DATA_DONE, - STATE_LATE_START_DONE, - STATE_BOOT_COMPLETE -}; +extern bool zygisk_enabled; int connect_daemon(bool create = false); @@ -63,6 +56,6 @@ void su_daemon_handler(int client, ucred *credential); void zygisk_handler(int client, ucred *cred); // Denylist -void check_enforce_denylist(); +void initialize_denylist(); int disable_deny(); int denylist_cli(int argc, char **argv); diff --git a/native/jni/utils/files.cpp b/native/jni/utils/files.cpp index bd3fafe8f..cbb8bd669 100644 --- a/native/jni/utils/files.cpp +++ b/native/jni/utils/files.cpp @@ -26,7 +26,7 @@ int fd_pathat(int dirfd, const char *name, char *path, size_t size) { return 0; } -int mkdirs(string_view path, mode_t mode) { +int mkdirs(string path, mode_t mode) { errno = 0; for (char *p = path.data() + 1; *p; ++p) { if (*p == '/') { diff --git a/native/jni/utils/files.hpp b/native/jni/utils/files.hpp index 8948535ae..e5e38f898 100644 --- a/native/jni/utils/files.hpp +++ b/native/jni/utils/files.hpp @@ -32,7 +32,7 @@ struct raw_file { ssize_t fd_path(int fd, char *path, size_t size); int fd_pathat(int dirfd, const char *name, char *path, size_t size); -int mkdirs(std::string_view path, mode_t mode); +int mkdirs(std::string path, mode_t mode); void rm_rf(const char *path); void mv_path(const char *src, const char *dest); void mv_dir(int src, int dest); diff --git a/native/jni/zygisk/entry.cpp b/native/jni/zygisk/entry.cpp index c1a04bd5c..609a2872a 100644 --- a/native/jni/zygisk/entry.cpp +++ b/native/jni/zygisk/entry.cpp @@ -255,7 +255,7 @@ static void setup_files(int client, ucred *cred) { } static void check_denylist(int client) { - if (!deny_enforced()) { + if (!denylist_enabled) { write_int(client, DENY_NOT_ENFORCED); return; } @@ -266,7 +266,7 @@ static void check_denylist(int client) { } static void do_unmount(int client, ucred *cred) { - if (deny_enforced()) { + if (denylist_enabled) { LOGD("zygisk: cleanup mount namespace for pid=[%d]\n", cred->pid); revert_daemon(cred->pid, client); } else {