manager: support setting selinux rules profile
This commit is contained in:
@@ -93,6 +93,7 @@ object Natives {
|
|||||||
|
|
||||||
val nonRootUseDefault: Boolean = true,
|
val nonRootUseDefault: Boolean = true,
|
||||||
val umountModules: Boolean = true,
|
val umountModules: Boolean = true,
|
||||||
|
var rules: String = "", // this field is save in ksud!!
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
enum class Namespace {
|
enum class Namespace {
|
||||||
Inherited,
|
Inherited,
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ fun RootProfileConfig(
|
|||||||
onProfileChange(
|
onProfileChange(
|
||||||
profile.copy(
|
profile.copy(
|
||||||
context = domain,
|
context = domain,
|
||||||
|
rules = rules,
|
||||||
rootUseDefault = false
|
rootUseDefault = false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -357,11 +358,14 @@ private fun UidPanel(uid: Int, label: String, onUidChange: (Int) -> Unit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SELinuxPanel(profile: Natives.Profile, onSELinuxChange: (domain: String, rules: String) -> Unit) {
|
private fun SELinuxPanel(
|
||||||
|
profile: Natives.Profile,
|
||||||
|
onSELinuxChange: (domain: String, rules: String) -> Unit
|
||||||
|
) {
|
||||||
var showDialog by remember { mutableStateOf(false) }
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
var domain by remember { mutableStateOf(profile.context) }
|
var domain by remember { mutableStateOf(profile.context) }
|
||||||
var rules by remember { mutableStateOf("") }
|
var rules by remember { mutableStateOf(profile.rules) }
|
||||||
|
|
||||||
val inputOptions = listOf(
|
val inputOptions = listOf(
|
||||||
InputTextField(
|
InputTextField(
|
||||||
@@ -382,7 +386,7 @@ private fun SELinuxPanel(profile: Natives.Profile, onSELinuxChange: (domain: Str
|
|||||||
// value can be a-zA-Z0-9_
|
// value can be a-zA-Z0-9_
|
||||||
val regex = Regex("^[a-z_]+:[a-z0-9_]+:[a-z0-9_]+(:[a-z0-9_]+)?$")
|
val regex = Regex("^[a-z_]+:[a-z0-9_]+:[a-z0-9_]+(:[a-z0-9_]+)?$")
|
||||||
if (value?.matches(regex) == true) ValidationResult.Valid
|
if (value?.matches(regex) == true) ValidationResult.Valid
|
||||||
else ValidationResult.Invalid("Domain must be valid sepolicy")
|
else ValidationResult.Invalid("Domain must be in the format of \"user:role:type:level\"")
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
InputTextField(
|
InputTextField(
|
||||||
@@ -393,7 +397,6 @@ private fun SELinuxPanel(profile: Natives.Profile, onSELinuxChange: (domain: Str
|
|||||||
type = InputTextFieldType.OUTLINED,
|
type = InputTextFieldType.OUTLINED,
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
keyboardType = KeyboardType.Ascii,
|
keyboardType = KeyboardType.Ascii,
|
||||||
imeAction = ImeAction.Done
|
|
||||||
),
|
),
|
||||||
singleLine = false,
|
singleLine = false,
|
||||||
resultListener = {
|
resultListener = {
|
||||||
@@ -401,8 +404,8 @@ private fun SELinuxPanel(profile: Natives.Profile, onSELinuxChange: (domain: Str
|
|||||||
},
|
},
|
||||||
validationListener = { value ->
|
validationListener = { value ->
|
||||||
if (isSepolicyValid(value)) ValidationResult.Valid
|
if (isSepolicyValid(value)) ValidationResult.Valid
|
||||||
else ValidationResult.Invalid("Rules must be valid sepolicy")
|
else ValidationResult.Invalid("SELinux rules is invalid!")
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package me.weishu.kernelsu.ui.screen
|
package me.weishu.kernelsu.ui.screen
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
@@ -64,8 +63,10 @@ import me.weishu.kernelsu.ui.component.profile.AppProfileConfig
|
|||||||
import me.weishu.kernelsu.ui.component.profile.RootProfileConfig
|
import me.weishu.kernelsu.ui.component.profile.RootProfileConfig
|
||||||
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
||||||
import me.weishu.kernelsu.ui.util.forceStopApp
|
import me.weishu.kernelsu.ui.util.forceStopApp
|
||||||
|
import me.weishu.kernelsu.ui.util.getSepolicy
|
||||||
import me.weishu.kernelsu.ui.util.launchApp
|
import me.weishu.kernelsu.ui.util.launchApp
|
||||||
import me.weishu.kernelsu.ui.util.restartApp
|
import me.weishu.kernelsu.ui.util.restartApp
|
||||||
|
import me.weishu.kernelsu.ui.util.setSepolicy
|
||||||
import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel
|
import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,10 +84,16 @@ fun AppProfileScreen(
|
|||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val failToUpdateAppProfile =
|
val failToUpdateAppProfile =
|
||||||
stringResource(R.string.failed_to_update_app_profile).format(appInfo.label)
|
stringResource(R.string.failed_to_update_app_profile).format(appInfo.label)
|
||||||
|
val failToUpdateSepolicy =
|
||||||
|
stringResource(R.string.failed_to_update_sepolicy).format(appInfo.label)
|
||||||
|
|
||||||
val packageName = appInfo.packageName
|
val packageName = appInfo.packageName
|
||||||
|
val initialProfile = Natives.getAppProfile(packageName, appInfo.uid)
|
||||||
|
if (initialProfile.allowSu) {
|
||||||
|
initialProfile.rules = getSepolicy(packageName)
|
||||||
|
}
|
||||||
var profile by rememberSaveable {
|
var profile by rememberSaveable {
|
||||||
mutableStateOf(Natives.getAppProfile(packageName, appInfo.uid))
|
mutableStateOf(initialProfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -114,6 +121,12 @@ fun AppProfileScreen(
|
|||||||
profile = profile,
|
profile = profile,
|
||||||
onProfileChange = {
|
onProfileChange = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
if (it.allowSu && !it.rootUseDefault && it.rules.isNotEmpty()) {
|
||||||
|
if (!setSepolicy(profile.name, it.rules)) {
|
||||||
|
snackbarHost.showSnackbar(failToUpdateSepolicy)
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!Natives.setAppProfile(it)) {
|
if (!Natives.setAppProfile(it)) {
|
||||||
snackbarHost.showSnackbar(failToUpdateAppProfile.format(appInfo.uid))
|
snackbarHost.showSnackbar(failToUpdateAppProfile.format(appInfo.uid))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -147,7 +147,23 @@ fun isSepolicyValid(rules: String?): Boolean {
|
|||||||
}
|
}
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
val result =
|
val result =
|
||||||
shell.newJob().add("ksud sepolicy check '$rules'").to(ArrayList(), null).exec()
|
shell.newJob().add("${getKsuDaemonPath()} sepolicy check '$rules'").to(ArrayList(), null).exec()
|
||||||
|
return result.isSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSepolicy(pkg: String): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val result =
|
||||||
|
shell.newJob().add("${getKsuDaemonPath()} profile get-sepolicy $pkg").to(ArrayList(), null).exec()
|
||||||
|
Log.i(TAG, "code: ${result.code}, out: ${result.out}, err: ${result.err}")
|
||||||
|
return result.out.joinToString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSepolicy(pkg: String, rules: String): Boolean {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val result =
|
||||||
|
shell.newJob().add("${getKsuDaemonPath()} profile set-sepolicy $pkg '$rules'").to(ArrayList(), null).exec()
|
||||||
|
Log.i(TAG, "set sepolicy result: ${result.code}")
|
||||||
return result.isSuccess
|
return result.isSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,4 +83,5 @@
|
|||||||
<string name="launch_app">Launch</string>
|
<string name="launch_app">Launch</string>
|
||||||
<string name="force_stop_app">Force Stop</string>
|
<string name="force_stop_app">Force Stop</string>
|
||||||
<string name="restart_app">Restart</string>
|
<string name="restart_app">Restart</string>
|
||||||
|
<string name="failed_to_update_sepolicy">Failed to update SELinux rules for: %s</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user