diff --git a/app/src/main/java/com/mrbimc/selinux/MainActivity.kt b/app/src/main/java/com/mrbimc/selinux/MainActivity.kt index 8db2181..9007b8c 100644 --- a/app/src/main/java/com/mrbimc/selinux/MainActivity.kt +++ b/app/src/main/java/com/mrbimc/selinux/MainActivity.kt @@ -46,17 +46,11 @@ class MainActivity : AppCompatActivity() { } fun setEnforcing(v: View) = setSELinuxState(SELinuxState.ENFORCING) { - runOnUiThread { - buttonEnforcing.isEnabled = false - buttonPermissive.isEnabled = true - } + handleButtons(it) } fun setPermissive(v: View) = setSELinuxState(SELinuxState.PERMISSIVE) { - runOnUiThread { - buttonEnforcing.isEnabled = true - buttonPermissive.isEnabled = false - } + handleButtons(it) } private fun checkContext() { @@ -124,29 +118,33 @@ class MainActivity : AppCompatActivity() { getSELinuxState() { ad.cancel() + handleButtons(it) + } + } - when (it) { - SELinuxState.UNKNOWN -> { - runOnUiThread { - buttonEnforcing.isEnabled = false - buttonPermissive.isEnabled = false - } + private fun handleButtons(state: SELinuxState) = when (state) { + SELinuxState.PERMISSIVE -> { + runOnUiThread { + buttonEnforcing.isEnabled = true + buttonPermissive.isEnabled = false } - SELinuxState.PERMISSIVE -> { - runOnUiThread { - buttonEnforcing.isEnabled = true - buttonPermissive.isEnabled = false - } + } + SELinuxState.ENFORCING -> { + runOnUiThread { + buttonEnforcing.isEnabled = false + buttonPermissive.isEnabled = true } - SELinuxState.ENFORCING -> { - runOnUiThread { - buttonEnforcing.isEnabled = false - buttonPermissive.isEnabled = true - } + } + SELinuxState.NOROOT -> { + runOnUiThread { + buttonEnforcing.isEnabled = false + buttonPermissive.isEnabled = false } } + SELinuxState.UNSWITCHABLE -> { + // do nothing + } } - } private fun showInfoDialog(): Boolean { LovelyStandardDialog(this) diff --git a/app/src/main/java/com/mrbimc/selinux/SELinuxBroadcastReceiver.kt b/app/src/main/java/com/mrbimc/selinux/SELinuxBroadcastReceiver.kt index 6888925..74e9701 100644 --- a/app/src/main/java/com/mrbimc/selinux/SELinuxBroadcastReceiver.kt +++ b/app/src/main/java/com/mrbimc/selinux/SELinuxBroadcastReceiver.kt @@ -18,11 +18,12 @@ class SELinuxBroadcastReceiver : BroadcastReceiver() { return } - val selinuxState = sp.getInt(KEY_SELINUX_STATE, SELinuxState.UNKNOWN.value) - when (selinuxState) { - 0 -> context.setSELinuxState(SELinuxState.PERMISSIVE) - 1 -> context.setSELinuxState(SELinuxState.ENFORCING) - else -> context.createNotification(context.getString(R.string.no_root_access)) + val selinuxInt = sp.getInt(KEY_SELINUX_STATE, SELinuxState.NOROOT.value) + when (selinuxInt) { + SELinuxState.PERMISSIVE.value -> context.setSELinuxState(SELinuxState.PERMISSIVE) + SELinuxState.ENFORCING.value -> context.setSELinuxState(SELinuxState.ENFORCING) + SELinuxState.NOROOT.value -> context.createNotification(context.getString(R.string.no_root_access)) + SELinuxState.UNSWITCHABLE.value -> context.createNotification(context.getString(R.string.unswitchable_context)) } } } diff --git a/app/src/main/java/com/mrbimc/selinux/util/ContextUtil.kt b/app/src/main/java/com/mrbimc/selinux/util/ContextUtil.kt index 57ab438..bff9de2 100644 --- a/app/src/main/java/com/mrbimc/selinux/util/ContextUtil.kt +++ b/app/src/main/java/com/mrbimc/selinux/util/ContextUtil.kt @@ -22,19 +22,9 @@ import kotlinx.coroutines.experimental.launch fun Context.getSELinuxState(callback: (SELinuxState) -> Unit) = launch(CommonPool) { val sp = PreferenceManager.getDefaultSharedPreferences(this@getSELinuxState) - when(executeGetSELinuxState().get()) { - SELinuxState.ENFORCING -> { - sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.ENFORCING.value).apply() - callback(SELinuxState.ENFORCING) - } - SELinuxState.PERMISSIVE -> { - sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.PERMISSIVE.value).apply() - callback(SELinuxState.PERMISSIVE) - } - else -> { // SELinuxState.UNKNOWN && black magic cases - sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.UNKNOWN.value).apply() - callback(SELinuxState.UNKNOWN) - } + executeGetSELinuxState().whenCompleteAsync { state, _ -> + sp.edit().putInt(KEY_SELINUX_STATE, state.value).apply() + callback(state) } } @@ -53,22 +43,24 @@ fun Context.setSELinuxState(state: SELinuxState, callback: (SELinuxState) -> Uni commandToExecute = "su --context $context -c \"$command\"" } - when(executeSetSELinuxState(state, commandToExecute).get()) { - SELinuxState.ENFORCING -> { - createNotification(getString(R.string.selinux_set_to_enforcing)) - sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.ENFORCING.value).apply() - callback(SELinuxState.ENFORCING) - } - SELinuxState.PERMISSIVE -> { - createNotification(getString(R.string.selinux_set_to_permissive)) - sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.PERMISSIVE.value).apply() - callback(SELinuxState.PERMISSIVE) - } - else -> { // SELinuxState.UNKNOWN && black magic cases - createNotification(getString(R.string.no_root_access)) - sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.UNKNOWN.value).apply() - callback(SELinuxState.UNKNOWN) + executeSetSELinuxState(state, commandToExecute).whenCompleteAsync { (realState, desiredState), _ -> + when(realState) { + SELinuxState.ENFORCING -> { + createNotification(getString(R.string.selinux_set_to_enforcing)) + } + SELinuxState.PERMISSIVE -> { + createNotification(getString(R.string.selinux_set_to_permissive)) + } + SELinuxState.NOROOT -> { + createNotification(getString(R.string.no_root_access)) + } + SELinuxState.UNSWITCHABLE -> { + createNotification(getString(R.string.unswitchable_context)) + } } + + sp.edit().putInt(KEY_SELINUX_STATE, realState.value).apply() + callback(realState) } } diff --git a/app/src/main/java/com/mrbimc/selinux/util/ShellUtil.kt b/app/src/main/java/com/mrbimc/selinux/util/ShellUtil.kt index b407503..738f3df 100644 --- a/app/src/main/java/com/mrbimc/selinux/util/ShellUtil.kt +++ b/app/src/main/java/com/mrbimc/selinux/util/ShellUtil.kt @@ -7,7 +7,7 @@ import java8.util.concurrent.CompletableFuture * Created by Pavel Sikun on 23.07.17. */ -enum class SELinuxState(val value: Int) { PERMISSIVE(0), ENFORCING(1), UNKNOWN(3) } +enum class SELinuxState(val value: Int) { PERMISSIVE(0), ENFORCING(1), NOROOT(3), UNSWITCHABLE(4) } private val shell by lazy { Shell.Builder() .setShell("su") @@ -18,28 +18,28 @@ fun executeGetSELinuxState(): CompletableFuture { val future = CompletableFuture() if (Shell.SU.available()) { - future.complete(if (Shell.SU.isSELinuxEnforcing()) SELinuxState.ENFORCING else SELinuxState.PERMISSIVE) + shell.addCommand("/system/bin/getenforce", 1) { _, _, output: MutableList? -> + val outputString = output?.joinToString() ?: "enforcing" + val isEnforcing = outputString.toLowerCase().contains("enforcing") + future.complete(if (isEnforcing) SELinuxState.ENFORCING else SELinuxState.PERMISSIVE) + } } else { - future.complete(SELinuxState.UNKNOWN) + future.complete(SELinuxState.NOROOT) } return future } -fun executeSetSELinuxState(state: SELinuxState, command: String): CompletableFuture { - val future = CompletableFuture() +fun executeSetSELinuxState(state: SELinuxState, command: String): CompletableFuture> { + val future = CompletableFuture>() //returning (RealState, DesiredState) - if (Shell.SU.available()) { - shell.addCommand(command, 1) { _, _, output: MutableList -> - val outputString = output.joinToString() - val isError = outputString.trim().isNotEmpty() - future.complete(if (isError) SELinuxState.UNKNOWN else state) + shell.addCommand(command, 1) { _, _, _: MutableList? -> + executeGetSELinuxState().whenCompleteAsync { systemState, _ -> + val resultState = if (systemState == state) systemState else SELinuxState.UNSWITCHABLE + future.complete(resultState to state) } } - else { - future.complete(SELinuxState.UNKNOWN) - } return future } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cb69230..3f8f8ae 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,6 +12,7 @@ SELinux mode changed to permissive! App was unable to gain root access + App was unable switch SELinux state Show notification after mode changed Automatically start on boot