Skip to content

Commit

Permalink
Merge branch 'main' into patch-actions
Browse files Browse the repository at this point in the history
  • Loading branch information
tinyboxvk authored Nov 26, 2024
2 parents b91bf35 + 9e0b4f1 commit 03d5bfb
Show file tree
Hide file tree
Showing 87 changed files with 2,530 additions and 1,214 deletions.
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
**/osv-scanner.toml @faern @raksooo @pinkisemils @albin-mullvad
/.github/workflows/osv-scanner*.yml @faern @raksooo @pinkisemils @albin-mullvad

# GitHub actions workflow that verifies that commits are signed if they are required to be
/.github/workflows/verify-locked-down-signatures.yml @faern @raksooo @pinkisemils @albin-mullvad

# The CODEOWNERS itself must be protected from unauthorized changes,
# otherwise the protection becomes quite moot.
# Keep this entry last, so it is sure to override any existing previous wildcard match
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/ios-rust-ffi.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: iOS - Build and test Rust FFI (mullvad-ios)
name: iOS - Build and test Rust FFI (mullvad-ios and mullvad-api)
on:
pull_request:
paths:
Expand Down Expand Up @@ -40,8 +40,8 @@ jobs:
# handy.
run: |
source env.sh
time cargo build --locked --verbose --lib -p mullvad-ios --target ${{ matrix.target }}
time cargo test --locked --verbose --lib -p mullvad-ios
time cargo build --locked --verbose --lib -p mullvad-ios -p mullvad-api --target ${{ matrix.target }}
time cargo test --locked --verbose --lib -p mullvad-ios -p mullvad-api
clippy-check-ios:
runs-on: macos-latest
Expand Down Expand Up @@ -70,5 +70,7 @@ jobs:
RUSTFLAGS: --deny warnings
run: |
source env.sh
time cargo clippy --locked --all-targets --no-default-features -p mullvad-ios --target ${{ matrix.target }}
time cargo clippy --locked --all-targets --all-features -p mullvad-ios --target ${{ matrix.target }}
time cargo clippy --locked --all-targets --no-default-features -p mullvad-ios -p mullvad-api \
--target ${{ matrix.target }}
time cargo clippy --locked --all-targets --all-features -p mullvad-ios -p mullvad-api \
--target ${{ matrix.target }}
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ Line wrap the file at 100 chars. Th
(WFP) filters normally do not apply for VMs. This mitigates the issue by ensuring that it does not
leak (as easily) when the VPN tunnel is up. Previously, WSL would leak while in the blocked or
connecting state, or while lockdown mode was active.
- Fix issue where the installer would allow any executable named `taskkill.exe` in the working
directory to run as admin. This fixes audit issue `MLLVD-CR-24-06`.

#### Linux
- Prevent attackers able to send ARP requests to the device running Mullvad from figuring out
Expand Down
15 changes: 9 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ single_use_lifetimes = "warn"
unused_async = "deny"

[workspace.dependencies]
hickory-proto = "0.24.1"
hickory-resolver = "0.24.1"
hickory-server = { version = "0.24.1", features = ["resolver"] }
tokio = { version = "1.8" }
parity-tokio-ipc = "0.9"
futures = "0.3.15"
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ See [this](Release.md) for instructions on how to make a new release.
interface UDS socket to users in the specified group. This means that only users in that group can
use the CLI and GUI. By default, everyone has access to the socket.

* `MULLVAD_BACKTRACE_ON_FAULT` - When enabled, if the daemon encounters a fault (e.g. `SIGSEGV`),
it will log a backtrace to stdout, and to `daemon.log`. By default, this is disabled in
release-builds and enabled in debug-builds. Set variable to `1` or `0` to explicitly enable or
disable this feature. Logging the backtrace cause heap allocation. Allocation is not signal safe,
but here it runs in the signal handler. This in technically undefined behavior and therefore
disabled by default. This usually works, but enable at your own risk.

### Development builds only

* `MULLVAD_API_HOST` - Set the hostname to use in API requests. E.g. `api.mullvad.net`.
Expand Down
1 change: 1 addition & 0 deletions android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Line wrap the file at 100 chars. Th
### Fixed
- Fix a bug where the Android account expiry notifications would not be updated if the app was
running in the background for a long time.
- Fix ANR due to the tokio runtime being blocked by `getaddrinfo` when dropped.


## [android/2024.8] - 2024-11-01
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ fun ServerIpOverridesScreen(
ServerIpOverridesCell(active = state.overridesActive)

Spacer(modifier = Modifier.weight(1f))
SnackbarHost(hostState = snackbarHostState) { MullvadSnackbar(snackbarData = it) }
PrimaryButton(
onClick = { showBottomSheet = true },
text = stringResource(R.string.server_ip_overrides_import_button),
Expand All @@ -211,9 +212,6 @@ fun ServerIpOverridesScreen(
.padding(bottom = Dimens.screenVerticalMargin)
.testTag(SERVER_IP_OVERRIDE_IMPORT_TEST_TAG),
)
SnackbarHost(hostState = snackbarHostState, modifier = Modifier.animateContentSize()) {
MullvadSnackbar(snackbarData = it)
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions android/config/dependency-check-suppression-agp-fixes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<cve>CVE-2022-24823</cve>
<cve>CVE-2024-29025</cve>
<cve>CVE-2022-41915</cve>
<cve>CVE-2024-47535</cve>
</suppress>
<suppress until="2024-12-01Z">
<notes><![CDATA[
Expand Down
1 change: 1 addition & 0 deletions android/lib/talpid/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ android {
dependencies {
implementation(projects.lib.model)

implementation(libs.androidx.ktx)
implementation(libs.androidx.lifecycle.service)
implementation(libs.kermit)
implementation(libs.kotlin.stdlib)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,70 +1,79 @@
package net.mullvad.talpid

import android.content.Context
import android.net.ConnectivityManager
import android.net.ConnectivityManager.NetworkCallback
import android.net.LinkProperties
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import kotlin.properties.Delegates.observable
import java.net.InetAddress
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.flow.stateIn
import net.mullvad.talpid.util.NetworkEvent
import net.mullvad.talpid.util.defaultNetworkFlow
import net.mullvad.talpid.util.networkFlow

class ConnectivityListener {
private val availableNetworks = HashSet<Network>()
class ConnectivityListener(val connectivityManager: ConnectivityManager) {
private lateinit var _isConnected: StateFlow<Boolean>
// Used by JNI
val isConnected
get() = _isConnected.value

private val callback =
object : NetworkCallback() {
override fun onAvailable(network: Network) {
availableNetworks.add(network)
isConnected = true
}
private lateinit var _currentDnsServers: StateFlow<List<InetAddress>>
// Used by JNI
val currentDnsServers
get() = ArrayList(_currentDnsServers.value)

override fun onLost(network: Network) {
availableNetworks.remove(network)
isConnected = availableNetworks.isNotEmpty()
}
}
fun register(scope: CoroutineScope) {
_currentDnsServers =
dnsServerChanges().stateIn(scope, SharingStarted.Eagerly, currentDnsServers())

private lateinit var connectivityManager: ConnectivityManager
_isConnected =
hasInternetCapability()
.onEach { notifyConnectivityChange(it) }
.stateIn(scope, SharingStarted.Eagerly, false)
}

// Used by JNI
var isConnected by
observable(false) { _, oldValue, newValue ->
if (newValue != oldValue) {
if (senderAddress != 0L) {
notifyConnectivityChange(newValue, senderAddress)
}
}
}
private fun dnsServerChanges(): Flow<List<InetAddress>> =
connectivityManager
.defaultNetworkFlow()
.filterIsInstance<NetworkEvent.LinkPropertiesChanged>()
.map { it.linkProperties.dnsServersWithoutFallback() }

private fun currentDnsServers(): List<InetAddress> =
connectivityManager
.getLinkProperties(connectivityManager.activeNetwork)
?.dnsServersWithoutFallback() ?: emptyList()

var senderAddress = 0L
private fun LinkProperties.dnsServersWithoutFallback(): List<InetAddress> =
dnsServers.filter { it.hostAddress != TalpidVpnService.FALLBACK_DUMMY_DNS_SERVER }

fun register(context: Context) {
private fun hasInternetCapability(): Flow<Boolean> {
val request =
NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.build()

connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

connectivityManager.registerNetworkCallback(request, callback)
}

fun unregister() {
connectivityManager.unregisterNetworkCallback(callback)
}

// DROID-1401
// This function has never been used and should most likely be merged into unregister(),
// along with ensuring that the lifecycle of it is correct.
@Suppress("UnusedPrivateMember")
private fun finalize() {
destroySender(senderAddress)
senderAddress = 0L
return connectivityManager
.networkFlow(request)
.scan(setOf<Network>()) { networks, event ->
when (event) {
is NetworkEvent.Available -> networks + event.network
is NetworkEvent.Lost -> networks - event.network
else -> networks
}
}
.map { it.isNotEmpty() }
.distinctUntilChanged()
}

private external fun notifyConnectivityChange(isConnected: Boolean, senderAddress: Long)

private external fun destroySender(senderAddress: Long)
private external fun notifyConnectivityChange(isConnected: Boolean)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package net.mullvad.talpid

import android.net.ConnectivityManager
import android.os.ParcelFileDescriptor
import androidx.annotation.CallSuper
import androidx.core.content.getSystemService
import androidx.lifecycle.lifecycleScope
import co.touchlab.kermit.Logger
import java.net.Inet4Address
import java.net.Inet6Address
Expand Down Expand Up @@ -29,18 +32,13 @@ open class TalpidVpnService : LifecycleVpnService() {
private var currentTunConfig: TunConfig? = null

// Used by JNI
val connectivityListener = ConnectivityListener()
lateinit var connectivityListener: ConnectivityListener

@CallSuper
override fun onCreate() {
super.onCreate()
connectivityListener.register(this)
}

@CallSuper
override fun onDestroy() {
super.onDestroy()
connectivityListener.unregister()
connectivityListener = ConnectivityListener(getSystemService<ConnectivityManager>()!!)
connectivityListener.register(lifecycleScope)
}

fun openTun(config: TunConfig): CreateTunResult {
Expand Down Expand Up @@ -161,7 +159,7 @@ open class TalpidVpnService : LifecycleVpnService() {
private external fun waitForTunnelUp(tunFd: Int, isIpv6Enabled: Boolean)

companion object {
private const val FALLBACK_DUMMY_DNS_SERVER = "192.0.2.1"
const val FALLBACK_DUMMY_DNS_SERVER = "192.0.2.1"

private const val IPV4_PREFIX_LENGTH = 32
private const val IPV6_PREFIX_LENGTH = 128
Expand Down
Loading

0 comments on commit 03d5bfb

Please sign in to comment.