Fix systemless hosts installation

This commit is contained in:
topjohnwu
2025-08-05 02:22:39 -07:00
committed by John Wu
parent 2923c8ccd1
commit 959430e030
6 changed files with 48 additions and 34 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -123,7 +123,9 @@ class Environment : BaseTest {
} }
private fun setupSystemlessHost() { private fun setupSystemlessHost() {
assertTrue("hosts setup failed", Shell.cmd("add_hosts_module").exec().isSuccess) 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) {

View File

@@ -118,24 +118,6 @@ EOF
cd / cd /
} }
add_hosts_module() {
# Do not touch existing hosts module
[ -d /data/adb/modules/hosts ] && return
cd /data/adb/modules
mkdir -p hosts/system/etc
cat << EOF > hosts/module.prop
id=hosts
name=Systemless Hosts
version=1.0
versionCode=1
author=Magisk
description=Magisk app built-in systemless hosts module
EOF
magisk --clone /system/etc/hosts hosts/system/etc/hosts
touch hosts/update
cd /
}
# $1 = APK # $1 = APK
# $2 = package name # $2 = package name
adb_pm_install() { adb_pm_install() {