Propagate Zygisk state to Magisk app

This commit is contained in:
topjohnwu 2021-09-18 02:38:53 -07:00
parent 7b25e74418
commit db590091b3
11 changed files with 99 additions and 85 deletions

View File

@ -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

View File

@ -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) }

View File

@ -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 }) {

View File

@ -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
}
}

View File

@ -127,11 +127,28 @@
</LinearLayout>
<LinearLayout
android:id="@+id/home_device_details_zygisk"
style="@style/W.Home.Item"
app:layout_constraintStart_toStartOf="@+id/home_magisk_installed_version"
app:layout_constraintTop_toBottomOf="@+id/home_magisk_installed_version">
<TextView
style="@style/W.Home.ItemContent"
android:text="@string/zygisk" />
<TextView
style="@style/W.Home.ItemContent.Right"
android:text="@{Info.isZygiskEnabled ? @string/yes : @string/no}"
tools:text="Yes" />
</LinearLayout>
<LinearLayout
android:id="@+id/home_device_details_ramdisk"
style="@style/W.Home.Item.Bottom"
app:layout_constraintStart_toStartOf="@+id/home_magisk_installed_version"
app:layout_constraintTop_toBottomOf="@+id/home_magisk_installed_version">
app:layout_constraintTop_toBottomOf="@+id/home_device_details_zygisk">
<TextView
style="@style/W.Home.ItemContent"
@ -144,48 +161,6 @@
</LinearLayout>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/home_magisk_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:referencedIds="@{viewModel.magiskDetailBarrierIds}"
tools:constraint_referenced_ids="home_magisk_installed_version,home_device_details_ramdisk"/>
<LinearLayout
android:id="@+id/home_device_details_ab"
style="@style/W.Home.Item.Top"
app:layout_constraintStart_toStartOf="@id/home_magisk_barrier"
app:layout_constraintTop_toTopOf="parent">
<TextView
style="@style/W.Home.ItemContent"
android:text="A/B" />
<TextView
style="@style/W.Home.ItemContent.Right"
android:text="@{Info.isAB ? @string/yes : @string/no}"
tools:text="Yes" />
</LinearLayout>
<LinearLayout
android:id="@+id/home_device_details_sar"
style="@style/W.Home.Item.Bottom"
app:layout_constraintStart_toStartOf="@+id/home_device_details_ab"
app:layout_constraintTop_toBottomOf="@+id/home_device_details_ab">
<TextView
style="@style/W.Home.ItemContent"
android:text="SAR" />
<TextView
style="@style/W.Home.ItemContent.Right"
android:text="@{Info.isSAR ? @string/yes : @string/no}"
tools:text="Yes" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View File

@ -242,5 +242,6 @@
<string name="add_shortcut_title">Add shortcut to home screen</string>
<string name="add_shortcut_msg">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?</string>
<string name="app_not_found">No application found to handle this action</string>
<string name="reboot_apply_change">Reboot to apply changes</string>
</resources>

View File

@ -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);

View File

@ -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);

View File

@ -8,6 +8,7 @@
#include <utils.hpp>
#include <daemon.hpp>
#include <magisk.hpp>
#include <db.hpp>
#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);

View File

@ -43,8 +43,9 @@ struct HookContext {
const char *process;
int pid;
bitset<FLAG_MAX> 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;
}

View File

@ -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();