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 8e3198c37..821253f5f 100644
--- a/app/src/main/java/com/topjohnwu/magisk/core/Info.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/core/Info.kt
@@ -28,9 +28,10 @@ object Info {
// Device state
@JvmStatic val env by lazy { loadState() }
- @JvmField var isSAR = false
- @JvmField var isAB = false
- @JvmField val isVirtualAB = getProperty("ro.virtual_ab.enabled", "false") == "true"
+ @JvmStatic var isSAR = false
+ var isAB = false
+ val isVirtualAB = getProperty("ro.virtual_ab.enabled", "false") == "true"
+ @JvmField val isZygiskEnabled = System.getenv("ZYGISK_ENABLED") == "1"
@JvmStatic val isFDE get() = crypto == "block"
@JvmField var ramdisk = false
@JvmField var hasGMS = true
diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
index bee42cad3..b4a23aab5 100644
--- a/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
@@ -62,7 +62,12 @@ class LogViewModel(
val filename = "magisk_log_%s.log".format(now.toTime(timeFormatStandard))
val logFile = MediaStoreUtils.getFile(filename, true)
logFile.uri.outputStream().bufferedWriter().use { file ->
- file.write("---System Properties---\n\n")
+ file.write("---Detected Device Info---\n\n")
+ file.write("isAB=${Info.isAB}\n")
+ file.write("isSAR=${Info.isSAR}\n")
+ file.write("ramdisk=${Info.ramdisk}\n")
+
+ file.write("\n\n---System Properties---\n\n")
ProcessBuilder("getprop").start()
.inputStream.reader().use { it.copyTo(file) }
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 3a75266e0..ca51108a0 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
@@ -236,20 +236,30 @@ object Magisk : BaseSettingsItem.Section() {
object Zygisk : BaseSettingsItem.Toggle() {
override val title = R.string.zygisk.asText()
- override val description = R.string.settings_zygisk_summary.asText()
+ override val description get() =
+ if (mismatch) R.string.reboot_apply_change.asText()
+ else 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
+ DenyList.notifyPropertyChanged(BR.description)
}
+ val mismatch get() = value != Info.isZygiskEnabled
}
object DenyList : BaseSettingsItem.Toggle() {
override val title = R.string.settings_denylist_title.asText()
override val description get() =
- if (isEnabled) R.string.settings_denylist_summary.asText()
- else R.string.settings_denylist_error.asText(R.string.zygisk.asText())
+ if (isEnabled) {
+ if (Zygisk.mismatch)
+ R.string.reboot_apply_change.asText()
+ else
+ R.string.settings_denylist_summary.asText()
+ } else {
+ R.string.settings_denylist_error.asText(R.string.zygisk.asText())
+ }
override var value = Config.denyList
set(value) = setV(value, field, { field = it }) {
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 8afc4ba22..7f3c363c9 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
@@ -18,6 +18,7 @@ import com.topjohnwu.magisk.databinding.itemBindingOf
import com.topjohnwu.magisk.di.AppContext
import com.topjohnwu.magisk.events.AddHomeIconEvent
import com.topjohnwu.magisk.events.RecreateEvent
+import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.events.dialog.BiometricEvent
import com.topjohnwu.magisk.ktx.activity
import com.topjohnwu.magisk.utils.Utils
@@ -97,15 +98,19 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Callback {
return list
}
- override fun onItemPressed(view: View, item: BaseSettingsItem, callback: () -> Unit) = when (item) {
- is DownloadPath -> withExternalRW(callback)
- is Biometrics -> authenticate(callback)
- is Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().navigate()
- is DenyListConfig -> SettingsFragmentDirections.actionSettingsFragmentToDenyFragment().navigate()
- is SystemlessHosts -> createHosts()
- is Restore -> HideAPK.restore(view.activity)
- is AddShortcut -> AddHomeIconEvent().publish()
- else -> callback()
+ override fun onItemPressed(view: View, item: BaseSettingsItem, callback: () -> Unit) {
+ when (item) {
+ is DownloadPath -> withExternalRW(callback)
+ is Biometrics -> authenticate(callback)
+ is Theme ->
+ SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().navigate()
+ is DenyListConfig ->
+ SettingsFragmentDirections.actionSettingsFragmentToDenyFragment().navigate()
+ is SystemlessHosts -> createHosts()
+ is Restore -> HideAPK.restore(view.activity)
+ is AddShortcut -> AddHomeIconEvent().publish()
+ else -> callback()
+ }
}
override fun onItemChanged(view: View, item: BaseSettingsItem) {
@@ -113,6 +118,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Callback {
is Language -> RecreateEvent().publish()
is UpdateChannel -> openUrlIfNecessary(view)
is Hide -> viewModelScope.launch { HideAPK.hide(view.activity, item.value) }
+ is Zygisk -> if (Zygisk.mismatch) SnackbarEvent(R.string.reboot_apply_change).publish()
else -> Unit
}
}
diff --git a/app/src/main/res/layout/include_home_magisk.xml b/app/src/main/res/layout/include_home_magisk.xml
index 20eeec4bd..343d869b8 100644
--- a/app/src/main/res/layout/include_home_magisk.xml
+++ b/app/src/main/res/layout/include_home_magisk.xml
@@ -127,11 +127,28 @@
+
+
+
+
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@+id/home_device_details_zygisk">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 144aba5bf..0088fa32f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -242,5 +242,6 @@
Add shortcut to home screen
After hiding this app, its name and icon might become difficult to recognize. Do you want to add a pretty shortcut to the home screen?
No application found to handle this action
+ Reboot to apply changes
diff --git a/native/jni/core/db.cpp b/native/jni/core/db.cpp
index 3e7bbda98..4949538f9 100644
--- a/native/jni/core/db.cpp
+++ b/native/jni/core/db.cpp
@@ -376,6 +376,13 @@ bool get_manager(string *pkg) {
return get_manager(0, pkg, &st);
}
+int get_manager_app_id() {
+ struct stat st;
+ if (get_manager(0, nullptr, &st))
+ return to_app_id(st.st_uid);
+ return -1;
+}
+
void exec_sql(int client) {
run_finally f([=]{ close(client); });
string sql = read_string(client);
diff --git a/native/jni/include/db.hpp b/native/jni/include/db.hpp
index ca7f4ee3b..3491382df 100644
--- a/native/jni/include/db.hpp
+++ b/native/jni/include/db.hpp
@@ -128,6 +128,7 @@ int get_db_strings(db_strings &str, int key = -1);
int get_uid_policy(su_access &su, int uid);
bool get_manager(int user_id, std::string *pkg, struct stat *st);
bool get_manager(std::string *pkg = nullptr);
+int get_manager_app_id();
void exec_sql(int client);
char *db_exec(const char *sql);
char *db_exec(const char *sql, const db_row_cb &fn);
diff --git a/native/jni/zygisk/entry.cpp b/native/jni/zygisk/entry.cpp
index 609a2872a..26a38e892 100644
--- a/native/jni/zygisk/entry.cpp
+++ b/native/jni/zygisk/entry.cpp
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include "inject.hpp"
#include "../deny/deny.hpp"
@@ -205,21 +206,17 @@ static int zygisk_log(int prio, const char *fmt, va_list ap) {
return ret;
}
-bool remote_check_denylist(int uid, const char *process) {
+void remote_get_app_info(int uid, const char *process, AppInfo *info) {
if (int fd = connect_daemon(); fd >= 0) {
write_int(fd, ZYGISK_REQUEST);
- write_int(fd, ZYGISK_CHECK_DENYLIST);
+ write_int(fd, ZYGISK_GET_APPINFO);
+
+ write_int(fd, uid);
+ write_string(fd, process);
+ xxread(fd, info, sizeof(*info));
- int ret = -1;
- if (read_int(fd) == 0) {
- write_int(fd, uid);
- write_string(fd, process);
- ret = read_int(fd);
- }
close(fd);
- return ret >= 0 && ret;
}
- return false;
}
int remote_request_unmount() {
@@ -254,15 +251,16 @@ static void setup_files(int client, ucred *cred) {
write_string(client, path);
}
-static void check_denylist(int client) {
- if (!denylist_enabled) {
- write_int(client, DENY_NOT_ENFORCED);
- return;
- }
- write_int(client, 0);
+static void get_app_info(int client) {
+ AppInfo info{};
int uid = read_int(client);
string process = read_string(client);
- write_int(client, is_deny_target(uid, process));
+ if (to_app_id(uid) == get_manager_app_id()) {
+ info.is_magisk_app = true;
+ } else if (denylist_enabled) {
+ info.on_denylist = is_deny_target(uid, process);
+ }
+ xwrite(client, &info, sizeof(info));
}
static void do_unmount(int client, ucred *cred) {
@@ -290,8 +288,8 @@ void zygisk_handler(int client, ucred *cred) {
case ZYGISK_SETUP:
setup_files(client, cred);
break;
- case ZYGISK_CHECK_DENYLIST:
- check_denylist(client);
+ case ZYGISK_GET_APPINFO:
+ get_app_info(client);
break;
case ZYGISK_UNMOUNT:
do_unmount(client, cred);
diff --git a/native/jni/zygisk/hook.cpp b/native/jni/zygisk/hook.cpp
index 529e77f50..61c6c48af 100644
--- a/native/jni/zygisk/hook.cpp
+++ b/native/jni/zygisk/hook.cpp
@@ -43,8 +43,9 @@ struct HookContext {
const char *process;
int pid;
bitset flags;
+ AppInfo info;
- HookContext() : pid(-1) {}
+ HookContext() : pid(-1), info{} {}
static void close_fds();
@@ -139,7 +140,7 @@ DCL_HOOK_FUNC(int, fork) {
// This is the latest point where we can still connect to the magiskd main socket
DCL_HOOK_FUNC(int, selinux_android_setcontext,
uid_t uid, int isSystemServer, const char *seinfo, const char *pkgname) {
- if (g_ctx && g_ctx->flags[DENY_FLAG]) {
+ if (g_ctx && g_ctx->info.on_denylist) {
if (remote_request_unmount() == 0) {
LOGD("zygisk: mount namespace cleaned up\n");
}
@@ -241,9 +242,10 @@ void HookContext::nativeSpecializeAppProcess_pre() {
VLOG("zygisk: pre specialize [%s]\n", process);
}
+ remote_get_app_info(args->uid, process, &info);
+
/* TODO: Handle MOUNT_EXTERNAL_NONE */
- if (args->mount_external != 0 && remote_check_denylist(args->uid, process)) {
- flags[DENY_FLAG] = true;
+ if (args->mount_external != 0 && info.on_denylist) {
LOGI("zygisk: [%s] is on the denylist\n", process);
} else {
run_modules_pre();
@@ -258,11 +260,14 @@ void HookContext::nativeSpecializeAppProcess_post() {
}
env->ReleaseStringUTFChars(args->nice_name, process);
- if (flags[DENY_FLAG]) {
+ if (info.on_denylist) {
self_unload();
} else {
run_modules_post();
}
+ if (info.is_magisk_app) {
+ setenv("ZYGISK_ENABLED", "1", 1);
+ }
g_ctx = nullptr;
}
diff --git a/native/jni/zygisk/inject.hpp b/native/jni/zygisk/inject.hpp
index e33f9cc59..e88d4fee6 100644
--- a/native/jni/zygisk/inject.hpp
+++ b/native/jni/zygisk/inject.hpp
@@ -8,7 +8,7 @@
enum : int {
ZYGISK_SETUP,
- ZYGISK_CHECK_DENYLIST,
+ ZYGISK_GET_APPINFO,
ZYGISK_UNMOUNT,
ZYGISK_GET_LOG_PIPE,
};
@@ -22,8 +22,13 @@ uintptr_t get_function_off(int pid, uintptr_t addr, char *lib);
// Get function address, given library name + offset
uintptr_t get_function_addr(int pid, const char *lib, uintptr_t off);
+struct AppInfo {
+ bool is_magisk_app;
+ bool on_denylist;
+};
+
void self_unload();
void hook_functions();
bool unhook_functions();
-bool remote_check_denylist(int uid, const char *process);
+void remote_get_app_info(int uid, const char *process, AppInfo *info);
int remote_request_unmount();