kernel: Bump susfs binary version to 1.5.12
- Removed functionally coupled versions 1.5.10-1.5.11 - Removed `statusMagicMount` status retrieval - Use `getSuSFSFeatures` to replace `CMD_GET_SUSFS_FEATURE_STATUS` for obtaining SUSFS status.
This commit is contained in:
@@ -106,7 +106,6 @@ object Natives {
|
||||
* Get SUSFS feature status from kernel
|
||||
* @return SusfsFeatureStatus object containing all feature states, or null if failed
|
||||
*/
|
||||
external fun getSusfsFeatureStatus(): SusfsFeatureStatus?
|
||||
|
||||
/**
|
||||
* Set dynamic managerature configuration
|
||||
@@ -183,27 +182,6 @@ object Natives {
|
||||
return isVersionLessThan(getFullVersion(), MINIMAL_SUPPORTED_KERNEL_FULL)
|
||||
}
|
||||
|
||||
@Immutable
|
||||
@Parcelize
|
||||
@Keep
|
||||
data class SusfsFeatureStatus(
|
||||
val statusSusPath: Boolean = false,
|
||||
val statusSusMount: Boolean = false,
|
||||
val statusAutoDefaultMount: Boolean = false,
|
||||
val statusAutoBindMount: Boolean = false,
|
||||
val statusSusKstat: Boolean = false,
|
||||
val statusTryUmount: Boolean = false,
|
||||
val statusAutoTryUmountBind: Boolean = false,
|
||||
val statusSpoofUname: Boolean = false,
|
||||
val statusEnableLog: Boolean = false,
|
||||
val statusHideSymbols: Boolean = false,
|
||||
val statusSpoofCmdline: Boolean = false,
|
||||
val statusOpenRedirect: Boolean = false,
|
||||
val statusMagicMount: Boolean = false,
|
||||
val statusOverlayfsAutoKstat: Boolean = false,
|
||||
val statusSusSu: Boolean = false
|
||||
) : Parcelable
|
||||
|
||||
@Immutable
|
||||
@Parcelize
|
||||
@Keep
|
||||
|
||||
@@ -42,6 +42,7 @@ import com.sukisu.ultra.ui.theme.CardConfig
|
||||
import com.sukisu.ultra.ui.susfs.util.SuSFSManager
|
||||
import com.sukisu.ultra.ui.susfs.util.SuSFSManager.isSusVersion158
|
||||
import com.sukisu.ultra.ui.susfs.util.SuSFSManager.isSusVersion159
|
||||
import com.sukisu.ultra.ui.util.getSuSFSVersion
|
||||
import com.sukisu.ultra.ui.util.isAbDevice
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
@@ -168,6 +169,38 @@ fun SuSFSConfigScreen(
|
||||
}
|
||||
}
|
||||
|
||||
var showVersionMismatchDialog by remember { mutableStateOf(false) }
|
||||
|
||||
if (showVersionMismatchDialog) {
|
||||
AlertDialog(
|
||||
onDismissRequest = { showVersionMismatchDialog = false },
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(R.string.warning),
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Text(
|
||||
stringResource(
|
||||
R.string.susfs_version_mismatch,
|
||||
try { getSuSFSVersion() } catch (_: Exception) { "unknown" },
|
||||
SuSFSManager.MAX_SUSFS_VERSION
|
||||
)
|
||||
)
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = { showVersionMismatchDialog = false },
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) {
|
||||
Text(stringResource(R.string.confirm))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 文件选择器
|
||||
val backupFileLauncher = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.CreateDocument("application/json")
|
||||
@@ -253,25 +286,41 @@ fun SuSFSConfigScreen(
|
||||
|
||||
// 加载当前配置
|
||||
LaunchedEffect(Unit) {
|
||||
unameValue = SuSFSManager.getUnameValue(context)
|
||||
buildTimeValue = SuSFSManager.getBuildTimeValue(context)
|
||||
autoStartEnabled = SuSFSManager.isAutoStartEnabled(context)
|
||||
executeInPostFsData = SuSFSManager.getExecuteInPostFsData(context)
|
||||
susPaths = SuSFSManager.getSusPaths(context)
|
||||
susLoopPaths = SuSFSManager.getSusLoopPaths(context)
|
||||
susMounts = SuSFSManager.getSusMounts(context)
|
||||
tryUmounts = SuSFSManager.getTryUmounts(context)
|
||||
androidDataPath = SuSFSManager.getAndroidDataPath(context)
|
||||
sdcardPath = SuSFSManager.getSdcardPath(context)
|
||||
kstatConfigs = SuSFSManager.getKstatConfigs(context)
|
||||
addKstatPaths = SuSFSManager.getAddKstatPaths(context)
|
||||
hideSusMountsForAllProcs = SuSFSManager.getHideSusMountsForAllProcs(context)
|
||||
enableHideBl = SuSFSManager.getEnableHideBl(context)
|
||||
enableCleanupResidue = SuSFSManager.getEnableCleanupResidue(context)
|
||||
umountForZygoteIsoService = SuSFSManager.getUmountForZygoteIsoService(context)
|
||||
enableAvcLogSpoofing = SuSFSManager.getEnableAvcLogSpoofing(context)
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
val version = getSuSFSVersion()
|
||||
val binaryName = "ksu_susfs_${version.removePrefix("v")}"
|
||||
|
||||
loadSlotInfo()
|
||||
val isBinaryAvailable = try {
|
||||
context.assets.open(binaryName).use { true }
|
||||
} catch (_: Exception) { false }
|
||||
|
||||
if (!isBinaryAvailable) {
|
||||
showVersionMismatchDialog = true
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
|
||||
unameValue = SuSFSManager.getUnameValue(context)
|
||||
buildTimeValue = SuSFSManager.getBuildTimeValue(context)
|
||||
autoStartEnabled = SuSFSManager.isAutoStartEnabled(context)
|
||||
executeInPostFsData = SuSFSManager.getExecuteInPostFsData(context)
|
||||
susPaths = SuSFSManager.getSusPaths(context)
|
||||
susLoopPaths = SuSFSManager.getSusLoopPaths(context)
|
||||
susMounts = SuSFSManager.getSusMounts(context)
|
||||
tryUmounts = SuSFSManager.getTryUmounts(context)
|
||||
androidDataPath = SuSFSManager.getAndroidDataPath(context)
|
||||
sdcardPath = SuSFSManager.getSdcardPath(context)
|
||||
kstatConfigs = SuSFSManager.getKstatConfigs(context)
|
||||
addKstatPaths = SuSFSManager.getAddKstatPaths(context)
|
||||
hideSusMountsForAllProcs = SuSFSManager.getHideSusMountsForAllProcs(context)
|
||||
enableHideBl = SuSFSManager.getEnableHideBl(context)
|
||||
enableCleanupResidue = SuSFSManager.getEnableCleanupResidue(context)
|
||||
umountForZygoteIsoService = SuSFSManager.getUmountForZygoteIsoService(context)
|
||||
enableAvcLogSpoofing = SuSFSManager.getEnableAvcLogSpoofing(context)
|
||||
|
||||
loadSlotInfo()
|
||||
}
|
||||
}
|
||||
|
||||
// 当切换到启用功能状态标签页时加载数据
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.os.Build
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import com.dergoogler.mmrl.platform.Platform.Companion.context
|
||||
import com.sukisu.ultra.Natives
|
||||
import com.sukisu.ultra.R
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -22,6 +21,7 @@ import java.io.IOException
|
||||
import androidx.core.content.edit
|
||||
import com.sukisu.ultra.ui.util.getRootShell
|
||||
import com.sukisu.ultra.ui.util.getSuSFSVersion
|
||||
import com.sukisu.ultra.ui.util.getSuSFSFeatures
|
||||
import com.sukisu.ultra.ui.viewmodel.SuperUserViewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.async
|
||||
@@ -65,6 +65,7 @@ object SuSFSManager {
|
||||
private const val MODULE_PATH = "/data/adb/modules/$MODULE_ID"
|
||||
private const val MIN_VERSION_FOR_HIDE_MOUNT = "1.5.8"
|
||||
private const val MIN_VERSION_FOR_LOOP_PATH = "1.5.9"
|
||||
const val MAX_SUSFS_VERSION = "1.5.12"
|
||||
private const val BACKUP_FILE_EXTENSION = ".susfs_backup"
|
||||
private const val MEDIA_DATA_PATH = "/data/media/0/Android/data"
|
||||
private const val CGROUP_UID_PATH_PREFIX = "/sys/fs/cgroup/uid_"
|
||||
@@ -185,11 +186,23 @@ object SuSFSManager {
|
||||
private fun getPrefs(context: Context): SharedPreferences =
|
||||
context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||
|
||||
private fun getSuSFSVersionUse(): String = try {
|
||||
getSuSFSVersion()
|
||||
} catch (_: Exception) { MIN_VERSION_FOR_HIDE_MOUNT }
|
||||
private fun getSuSFSVersionUse(context: Context): String = try {
|
||||
val version = getSuSFSVersion()
|
||||
val binaryName = "${SUSFS_BINARY_TARGET_NAME}_${version.removePrefix("v")}"
|
||||
if (isBinaryAvailable(context, binaryName)) {
|
||||
version
|
||||
} else {
|
||||
MAX_SUSFS_VERSION
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
MAX_SUSFS_VERSION
|
||||
}
|
||||
|
||||
private fun getSuSFSBinaryName(): String = "${SUSFS_BINARY_TARGET_NAME}_${getSuSFSVersionUse().removePrefix("v")}"
|
||||
fun isBinaryAvailable(context: Context, binaryName: String): Boolean = try {
|
||||
context.assets.open(binaryName).use { true }
|
||||
} catch (_: IOException) { false }
|
||||
|
||||
private fun getSuSFSBinaryName(context: Context): String = "${SUSFS_BINARY_TARGET_NAME}_${getSuSFSVersionUse(context).removePrefix("v")}"
|
||||
|
||||
private fun getSuSFSTargetPath(): String = "/data/adb/ksu/bin/$SUSFS_BINARY_TARGET_NAME"
|
||||
|
||||
@@ -715,7 +728,7 @@ object SuSFSManager {
|
||||
// 二进制文件管理
|
||||
private suspend fun copyBinaryFromAssets(context: Context): String? = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val binaryName = getSuSFSBinaryName()
|
||||
val binaryName = getSuSFSBinaryName(context)
|
||||
val targetPath = getSuSFSTargetPath()
|
||||
val tempFile = File(context.cacheDir, binaryName)
|
||||
|
||||
@@ -736,7 +749,7 @@ object SuSFSManager {
|
||||
}
|
||||
|
||||
fun isBinaryAvailable(context: Context): Boolean = try {
|
||||
context.assets.open(getSuSFSBinaryName()).use { true }
|
||||
context.assets.open(getSuSFSBinaryName(context)).use { true }
|
||||
} catch (_: IOException) { false }
|
||||
|
||||
// 命令执行
|
||||
@@ -823,9 +836,10 @@ object SuSFSManager {
|
||||
// 功能状态获取
|
||||
suspend fun getEnabledFeatures(context: Context): List<EnabledFeature> = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val status = Natives.getSusfsFeatureStatus()
|
||||
if (status != null) {
|
||||
parseEnabledFeaturesFromStatus(context, status)
|
||||
val featuresOutput = getSuSFSFeatures()
|
||||
|
||||
if (featuresOutput.isNotBlank() && featuresOutput != "Invalid") {
|
||||
parseEnabledFeaturesFromOutput(context, featuresOutput)
|
||||
} else {
|
||||
getDefaultDisabledFeatures(context)
|
||||
}
|
||||
@@ -835,10 +849,47 @@ object SuSFSManager {
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseEnabledFeaturesFromOutput(context: Context, featuresOutput: String): List<EnabledFeature> {
|
||||
val enabledConfigs = featuresOutput.lines()
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotEmpty() }
|
||||
.toSet()
|
||||
|
||||
val featureMap = mapOf(
|
||||
"CONFIG_KSU_SUSFS_SUS_PATH" to context.getString(R.string.sus_path_feature_label),
|
||||
"CONFIG_KSU_SUSFS_SUS_MOUNT" to context.getString(R.string.sus_mount_feature_label),
|
||||
"CONFIG_KSU_SUSFS_TRY_UMOUNT" to context.getString(R.string.try_umount_feature_label),
|
||||
"CONFIG_KSU_SUSFS_SPOOF_UNAME" to context.getString(R.string.spoof_uname_feature_label),
|
||||
"CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG" to context.getString(R.string.spoof_cmdline_feature_label),
|
||||
"CONFIG_KSU_SUSFS_OPEN_REDIRECT" to context.getString(R.string.open_redirect_feature_label),
|
||||
"CONFIG_KSU_SUSFS_ENABLE_LOG" to context.getString(R.string.enable_log_feature_label),
|
||||
"CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT" to context.getString(R.string.auto_default_mount_feature_label),
|
||||
"CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT" to context.getString(R.string.auto_bind_mount_feature_label),
|
||||
"CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT" to context.getString(R.string.auto_try_umount_bind_feature_label),
|
||||
"CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS" to context.getString(R.string.hide_symbols_feature_label),
|
||||
"CONFIG_KSU_SUSFS_SUS_KSTAT" to context.getString(R.string.sus_kstat_feature_label),
|
||||
"CONFIG_KSU_SUSFS_SUS_SU" to context.getString(R.string.sus_su_feature_label)
|
||||
)
|
||||
|
||||
|
||||
return featureMap.map { (configKey, displayName) ->
|
||||
val isEnabled = enabledConfigs.contains(configKey)
|
||||
|
||||
val statusText = if (isEnabled) {
|
||||
context.getString(R.string.susfs_feature_enabled)
|
||||
} else {
|
||||
context.getString(R.string.susfs_feature_disabled)
|
||||
}
|
||||
|
||||
val canConfigure = displayName == context.getString(R.string.enable_log_feature_label)
|
||||
|
||||
EnabledFeature(displayName, isEnabled, statusText, canConfigure)
|
||||
}.sortedBy { it.name }
|
||||
}
|
||||
|
||||
private fun getDefaultDisabledFeatures(context: Context): List<EnabledFeature> {
|
||||
val defaultFeatures = listOf(
|
||||
"sus_path_feature_label" to context.getString(R.string.sus_path_feature_label),
|
||||
"sus_loop_path_feature_label" to context.getString(R.string.sus_loop_path_feature_label),
|
||||
"sus_mount_feature_label" to context.getString(R.string.sus_mount_feature_label),
|
||||
"try_umount_feature_label" to context.getString(R.string.try_umount_feature_label),
|
||||
"spoof_uname_feature_label" to context.getString(R.string.spoof_uname_feature_label),
|
||||
@@ -850,7 +901,6 @@ object SuSFSManager {
|
||||
"auto_try_umount_bind_feature_label" to context.getString(R.string.auto_try_umount_bind_feature_label),
|
||||
"hide_symbols_feature_label" to context.getString(R.string.hide_symbols_feature_label),
|
||||
"sus_kstat_feature_label" to context.getString(R.string.sus_kstat_feature_label),
|
||||
"magic_mount_feature_label" to context.getString(R.string.magic_mount_feature_label),
|
||||
"sus_su_feature_label" to context.getString(R.string.sus_su_feature_label)
|
||||
)
|
||||
|
||||
@@ -864,31 +914,6 @@ object SuSFSManager {
|
||||
}.sortedBy { it.name }
|
||||
}
|
||||
|
||||
private fun parseEnabledFeaturesFromStatus(context: Context, status: Natives.SusfsFeatureStatus): List<EnabledFeature> {
|
||||
val featureList = listOf(
|
||||
Triple("status_sus_path", context.getString(R.string.sus_path_feature_label), status.statusSusPath),
|
||||
Triple("status_sus_mount", context.getString(R.string.sus_mount_feature_label), status.statusSusMount),
|
||||
Triple("status_try_umount", context.getString(R.string.try_umount_feature_label), status.statusTryUmount),
|
||||
Triple("status_spoof_uname", context.getString(R.string.spoof_uname_feature_label), status.statusSpoofUname),
|
||||
Triple("status_spoof_cmdline", context.getString(R.string.spoof_cmdline_feature_label), status.statusSpoofCmdline),
|
||||
Triple("status_open_redirect", context.getString(R.string.open_redirect_feature_label), status.statusOpenRedirect),
|
||||
Triple("status_enable_log", context.getString(R.string.enable_log_feature_label), status.statusEnableLog),
|
||||
Triple("status_auto_default_mount", context.getString(R.string.auto_default_mount_feature_label), status.statusAutoDefaultMount),
|
||||
Triple("status_auto_bind_mount", context.getString(R.string.auto_bind_mount_feature_label), status.statusAutoBindMount),
|
||||
Triple("status_auto_try_umount_bind", context.getString(R.string.auto_try_umount_bind_feature_label), status.statusAutoTryUmountBind),
|
||||
Triple("status_hide_symbols", context.getString(R.string.hide_symbols_feature_label), status.statusHideSymbols),
|
||||
Triple("status_sus_kstat", context.getString(R.string.sus_kstat_feature_label), status.statusSusKstat),
|
||||
Triple("status_magic_mount", context.getString(R.string.magic_mount_feature_label), status.statusMagicMount),
|
||||
Triple("status_sus_su", context.getString(R.string.sus_su_feature_label), status.statusSusSu)
|
||||
)
|
||||
|
||||
return featureList.map { (id, displayName, isEnabled) ->
|
||||
val statusText = if (isEnabled) context.getString(R.string.susfs_feature_enabled) else context.getString(R.string.susfs_feature_disabled)
|
||||
val canConfigure = id == "status_enable_log"
|
||||
EnabledFeature(displayName, isEnabled, statusText, canConfigure)
|
||||
}.sortedBy { it.name }
|
||||
}
|
||||
|
||||
// sus日志开关
|
||||
suspend fun setEnableLog(context: Context, enabled: Boolean): Boolean {
|
||||
val success = executeSusfsCommand(context, "enable_log ${if (enabled) 1 else 0}")
|
||||
|
||||
@@ -528,8 +528,8 @@ fun getSuSFSVariant(): String {
|
||||
|
||||
fun getSuSFSFeatures(): String {
|
||||
val shell = getRootShell()
|
||||
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} features")
|
||||
return result
|
||||
val cmd = "${getSuSFSDaemonPath()} features"
|
||||
return runCmd(shell, cmd)
|
||||
}
|
||||
|
||||
fun susfsSUS_SU_0(): String {
|
||||
|
||||
Reference in New Issue
Block a user