[BR02] Implement isUidNetworkingBlocked
This is needed for data stall detection mechanism in NetworkStack to get the information about whether the network is blocked for a given uid and conditions. Because the API will be called frequently from NetworkStack to resolve all status for all uids on the device, the API cannot call into the service which creates IPC. Instead, the API need to directly access bpf maps in the user process to retrieve the status. In this case the user process is the network stack, the access control is provided by linux file permission and selinux. Test: atest FrameworksNetTests:android.net.connectivity.android.net.BpfNetMapsReaderTest Test: atest FrameworksNetTests:android.net.connectivity.android.net.ConnectivityManagerTest NO_IFTTT=Refactor only change for firewall chains definitions Bug: 297836825 Change-Id: Iaf983b71ec98cbfe5152dcfade8a3120f938f135
This commit is contained in:
@@ -16,23 +16,31 @@
|
||||
|
||||
package android.net
|
||||
|
||||
import android.net.BpfNetMapsConstants.DOZABLE_MATCH
|
||||
import android.net.BpfNetMapsConstants.STANDBY_MATCH
|
||||
import android.net.BpfNetMapsConstants.UID_RULES_CONFIGURATION_KEY
|
||||
import android.net.BpfNetMapsUtils.getMatchByFirewallChain
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION_CODES
|
||||
import com.android.net.module.util.IBpfMap
|
||||
import com.android.net.module.util.Struct.S32
|
||||
import com.android.net.module.util.Struct.U32
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import com.android.testutils.TestBpfMap
|
||||
import java.lang.reflect.Modifier
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
private const val TEST_UID1 = 1234
|
||||
private const val TEST_UID2 = TEST_UID1 + 1
|
||||
private const val NO_IIF = 0
|
||||
|
||||
// pre-T devices does not support Bpf.
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
@IgnoreUpTo(VERSION_CODES.S_V2)
|
||||
class BpfNetMapsReaderTest {
|
||||
private val testConfigurationMap: IBpfMap<S32, U32> = TestBpfMap()
|
||||
private val testUidOwnerMap: IBpfMap<S32, UidOwnerValue> = TestBpfMap()
|
||||
@@ -66,4 +74,75 @@ class BpfNetMapsReaderTest {
|
||||
doTestIsChainEnabled(ConnectivityManager.FIREWALL_CHAIN_RESTRICTED)
|
||||
doTestIsChainEnabled(ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFirewallChainList() {
|
||||
// Verify that when a firewall chain constant is added, it should also be included in
|
||||
// firewall chain list.
|
||||
val declaredChains = ConnectivityManager::class.java.declaredFields.filter {
|
||||
Modifier.isStatic(it.modifiers) && it.name.startsWith("FIREWALL_CHAIN_")
|
||||
}
|
||||
// Verify the size matches, this also verifies no common item in allow and deny chains.
|
||||
assertEquals(BpfNetMapsConstants.ALLOW_CHAINS.size +
|
||||
BpfNetMapsConstants.DENY_CHAINS.size, declaredChains.size)
|
||||
declaredChains.forEach {
|
||||
assertTrue(BpfNetMapsConstants.ALLOW_CHAINS.contains(it.get(null)) ||
|
||||
BpfNetMapsConstants.DENY_CHAINS.contains(it.get(null)))
|
||||
}
|
||||
}
|
||||
|
||||
private fun mockChainEnabled(chain: Int, enabled: Boolean) {
|
||||
val config = testConfigurationMap.getValue(UID_RULES_CONFIGURATION_KEY).`val`
|
||||
val newConfig = if (enabled) {
|
||||
config or getMatchByFirewallChain(chain)
|
||||
} else {
|
||||
config and getMatchByFirewallChain(chain).inv()
|
||||
}
|
||||
testConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, U32(newConfig))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsUidNetworkingBlockedByFirewallChains_allowChain() {
|
||||
// With everything disabled by default, verify the return value is false.
|
||||
testConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, U32(0))
|
||||
assertFalse(bpfNetMapsReader.isUidBlockedByFirewallChains(TEST_UID1))
|
||||
|
||||
// Enable dozable chain but does not provide allowed list. Verify the network is blocked
|
||||
// for all uids.
|
||||
mockChainEnabled(ConnectivityManager.FIREWALL_CHAIN_DOZABLE, true)
|
||||
assertTrue(bpfNetMapsReader.isUidBlockedByFirewallChains(TEST_UID1))
|
||||
assertTrue(bpfNetMapsReader.isUidBlockedByFirewallChains(TEST_UID2))
|
||||
|
||||
// Add uid1 to dozable allowed list. Verify the network is not blocked for uid1, while
|
||||
// uid2 is blocked.
|
||||
testUidOwnerMap.updateEntry(S32(TEST_UID1), UidOwnerValue(NO_IIF, DOZABLE_MATCH))
|
||||
assertFalse(bpfNetMapsReader.isUidBlockedByFirewallChains(TEST_UID1))
|
||||
assertTrue(bpfNetMapsReader.isUidBlockedByFirewallChains(TEST_UID2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsUidNetworkingBlockedByFirewallChains_denyChain() {
|
||||
// Enable standby chain but does not provide denied list. Verify the network is allowed
|
||||
// for all uids.
|
||||
testConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, U32(0))
|
||||
mockChainEnabled(ConnectivityManager.FIREWALL_CHAIN_STANDBY, true)
|
||||
assertFalse(bpfNetMapsReader.isUidBlockedByFirewallChains(TEST_UID1))
|
||||
assertFalse(bpfNetMapsReader.isUidBlockedByFirewallChains(TEST_UID2))
|
||||
|
||||
// Add uid1 to standby allowed list. Verify the network is blocked for uid1, while
|
||||
// uid2 is not blocked.
|
||||
testUidOwnerMap.updateEntry(S32(TEST_UID1), UidOwnerValue(NO_IIF, STANDBY_MATCH))
|
||||
assertTrue(bpfNetMapsReader.isUidBlockedByFirewallChains(TEST_UID1))
|
||||
assertFalse(bpfNetMapsReader.isUidBlockedByFirewallChains(TEST_UID2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsUidNetworkingBlockedByFirewallChains_blockedWithAllowed() {
|
||||
// Uids blocked by powersave chain but allowed by standby chain, verify the blocking
|
||||
// takes higher priority.
|
||||
testConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, U32(0))
|
||||
mockChainEnabled(ConnectivityManager.FIREWALL_CHAIN_POWERSAVE, true)
|
||||
mockChainEnabled(ConnectivityManager.FIREWALL_CHAIN_STANDBY, true)
|
||||
assertTrue(bpfNetMapsReader.isUidBlockedByFirewallChains(TEST_UID1))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user