tunnel: remove kernel module downloader

Nathan Chance dropped the ball repeatedly and never maintained this in a
consistent way that anybody could use. With Android 12 out now, just
drop it all together. A bummer, but I don't see much of a choice.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld
2021-10-29 16:42:36 +02:00
parent 447b06ec2c
commit a03ad51622
35 changed files with 122 additions and 2938 deletions
@@ -21,7 +21,6 @@ import com.wireguard.android.backend.GoBackend
import com.wireguard.android.backend.WgQuickBackend
import com.wireguard.android.configStore.FileConfigStore
import com.wireguard.android.model.TunnelManager
import com.wireguard.android.util.ModuleLoader
import com.wireguard.android.util.RootShell
import com.wireguard.android.util.ToolsInstaller
import com.wireguard.android.util.UserKnobs
@@ -42,7 +41,6 @@ class Application : android.app.Application() {
private val futureBackend = CompletableDeferred<Backend>()
private val coroutineScope = CoroutineScope(Job() + Dispatchers.Main.immediate)
private var backend: Backend? = null
private lateinit var moduleLoader: ModuleLoader
private lateinit var rootShell: RootShell
private lateinit var preferencesDataStore: DataStore<Preferences>
private lateinit var toolsInstaller: ToolsInstaller
@@ -67,15 +65,7 @@ class Application : android.app.Application() {
private suspend fun determineBackend(): Backend {
var backend: Backend? = null
var didStartRootShell = false
if (!ModuleLoader.isModuleLoaded() && moduleLoader.moduleMightExist()) {
try {
rootShell.start()
didStartRootShell = true
moduleLoader.loadModule()
} catch (ignored: Exception) {
}
}
if (!UserKnobs.disableKernelModule.first() && ModuleLoader.isModuleLoaded()) {
if (UserKnobs.enableKernelModule.first() && WgQuickBackend.hasKernelSupport()) {
try {
if (!didStartRootShell)
rootShell.start()
@@ -100,7 +90,6 @@ class Application : android.app.Application() {
super.onCreate()
rootShell = RootShell(applicationContext)
toolsInstaller = ToolsInstaller(applicationContext, rootShell)
moduleLoader = ModuleLoader(applicationContext, rootShell, USER_AGENT)
preferencesDataStore = PreferenceDataStoreFactory.create { applicationContext.preferencesDataStoreFile("settings") }
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
coroutineScope.launch {
@@ -140,9 +129,6 @@ class Application : android.app.Application() {
@JvmStatic
suspend fun getBackend() = get().futureBackend.await()
@JvmStatic
fun getModuleLoader() = get().moduleLoader
@JvmStatic
fun getRootShell() = get().rootShell
@@ -17,7 +17,6 @@ import com.wireguard.android.R
import com.wireguard.android.backend.WgQuickBackend
import com.wireguard.android.preference.PreferencesPreferenceDataStore
import com.wireguard.android.util.AdminKnobs
import com.wireguard.android.util.ModuleLoader
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -79,30 +78,19 @@ class SettingsActivity : ThemeChangeAwareActivity() {
startActivity(Intent(requireContext(), LogViewerActivity::class.java))
true
}
val moduleInstaller = preferenceManager.findPreference<Preference>("module_downloader")
val kernelModuleDisabler = preferenceManager.findPreference<Preference>("kernel_module_disabler")
moduleInstaller?.isVisible = false
if (ModuleLoader.isModuleLoaded()) {
moduleInstaller?.parent?.removePreference(moduleInstaller)
val kernelModuleEnabler = preferenceManager.findPreference<Preference>("kernel_module_enabler")
if (WgQuickBackend.hasKernelSupport()) {
lifecycleScope.launch {
if (Application.getBackend() !is WgQuickBackend) {
try {
withContext(Dispatchers.IO) { Application.getRootShell().start() }
} catch (_: Throwable) {
kernelModuleDisabler?.parent?.removePreference(kernelModuleDisabler)
kernelModuleEnabler?.parent?.removePreference(kernelModuleEnabler)
}
}
}
} else {
kernelModuleDisabler?.parent?.removePreference(kernelModuleDisabler)
lifecycleScope.launch {
try {
withContext(Dispatchers.IO) { Application.getRootShell().start() }
moduleInstaller?.isVisible = true
} catch (_: Throwable) {
moduleInstaller?.parent?.removePreference(moduleInstaller)
}
}
kernelModuleEnabler?.parent?.removePreference(kernelModuleEnabler)
}
}
}
@@ -26,7 +26,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.system.exitProcess
class KernelModuleDisablerPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
class KernelModuleEnablerPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
private var state = State.UNKNOWN
init {
@@ -44,10 +44,10 @@ class KernelModuleDisablerPreference(context: Context, attrs: AttributeSet?) : P
activity.lifecycleScope.launch {
if (state == State.DISABLED) {
setState(State.ENABLING)
UserKnobs.setDisableKernelModule(false)
UserKnobs.setEnableKernelModule(true)
} else if (state == State.ENABLED) {
setState(State.DISABLING)
UserKnobs.setDisableKernelModule(true)
UserKnobs.setEnableKernelModule(false)
}
val observableTunnels = Application.getTunnelManager().getTunnels()
val downings = observableTunnels.map { async(SupervisorJob()) { it.setStateAsync(Tunnel.State.DOWN) } }
@@ -76,13 +76,13 @@ class KernelModuleDisablerPreference(context: Context, attrs: AttributeSet?) : P
private enum class State(val titleResourceId: Int, val summaryResourceId: Int, val shouldEnableView: Boolean, val visible: Boolean) {
UNKNOWN(0, 0, false, false),
ENABLED(R.string.module_disabler_enabled_title, R.string.module_disabler_enabled_summary, true, true),
DISABLED(R.string.module_disabler_disabled_title, R.string.module_disabler_disabled_summary, true, true),
ENABLING(R.string.module_disabler_disabled_title, R.string.success_application_will_restart, false, true),
DISABLING(R.string.module_disabler_enabled_title, R.string.success_application_will_restart, false, true);
ENABLED(R.string.module_enabler_enabled_title, R.string.module_enabler_enabled_summary, true, true),
DISABLED(R.string.module_enabler_disabled_title, R.string.module_enabler_disabled_summary, true, true),
ENABLING(R.string.module_enabler_disabled_title, R.string.success_application_will_restart, false, true),
DISABLING(R.string.module_enabler_enabled_title, R.string.success_application_will_restart, false, true);
}
companion object {
private const val TAG = "WireGuard/KernelModuleDisablerPreference"
private const val TAG = "WireGuard/KernelModuleEnablerPreference"
}
}
@@ -1,70 +0,0 @@
/*
* Copyright © 2019 WireGuard LLC. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.preference
import android.content.Context
import android.content.Intent
import android.system.OsConstants
import android.util.AttributeSet
import android.widget.Toast
import androidx.preference.Preference
import com.wireguard.android.Application
import com.wireguard.android.R
import com.wireguard.android.activity.SettingsActivity
import com.wireguard.android.util.ErrorMessages
import com.wireguard.android.util.UserKnobs
import com.wireguard.android.util.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.system.exitProcess
class ModuleDownloaderPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
private var state = State.INITIAL
override fun getSummary() = context.getString(state.messageResourceId)
override fun getTitle() = context.getString(R.string.module_installer_title)
override fun onClick() {
setState(State.WORKING)
lifecycleScope.launch {
try {
when (withContext(Dispatchers.IO) { Application.getModuleLoader().download() }) {
OsConstants.ENOENT -> setState(State.NOTFOUND)
OsConstants.EXIT_SUCCESS -> {
setState(State.SUCCESS)
UserKnobs.setDisableKernelModule(null)
withContext(Dispatchers.IO) {
val restartIntent = Intent(context, SettingsActivity::class.java)
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
Application.get().startActivity(restartIntent)
exitProcess(0)
}
}
else -> setState(State.FAILURE)
}
} catch (e: Throwable) {
setState(State.FAILURE)
Toast.makeText(context, ErrorMessages[e], Toast.LENGTH_LONG).show()
}
}
}
private fun setState(state: State) {
if (this.state == state) return
this.state = state
if (isEnabled != state.shouldEnableView) isEnabled = state.shouldEnableView
notifyChanged()
}
private enum class State(val messageResourceId: Int, val shouldEnableView: Boolean) {
INITIAL(R.string.module_installer_initial, true),
FAILURE(R.string.module_installer_error, true),
WORKING(R.string.module_installer_working, false),
SUCCESS(R.string.success_application_will_restart, false),
NOTFOUND(R.string.module_installer_not_found, false);
}
}
@@ -14,18 +14,18 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
object UserKnobs {
private val DISABLE_KERNEL_MODULE = booleanPreferencesKey("disable_kernel_module")
val disableKernelModule: Flow<Boolean>
private val ENABLE_KERNEL_MODULE = booleanPreferencesKey("enable_kernel_module")
val enableKernelModule: Flow<Boolean>
get() = Application.getPreferencesDataStore().data.map {
it[DISABLE_KERNEL_MODULE] ?: false
it[ENABLE_KERNEL_MODULE] ?: false
}
suspend fun setDisableKernelModule(disable: Boolean?) {
suspend fun setEnableKernelModule(enable: Boolean?) {
Application.getPreferencesDataStore().edit {
if (disable == null)
it.remove(DISABLE_KERNEL_MODULE)
if (enable == null)
it.remove(ENABLE_KERNEL_MODULE)
else
it[DISABLE_KERNEL_MODULE] = disable
it[ENABLE_KERNEL_MODULE] = enable
}
}