Use java BpfMap in BpfNetMaps#addUidInterfaceRules
Bug: 217624062 Test: atest BpfNetMapsTest HostsideVpnTests#testBlockIncomingPacket Change-Id: I8aeb4712c852167d553eb331f32d770582199b13
This commit is contained in:
@@ -25,6 +25,7 @@ import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
|
|||||||
import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
|
import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
|
||||||
import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
|
import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
|
||||||
import static android.system.OsConstants.EINVAL;
|
import static android.system.OsConstants.EINVAL;
|
||||||
|
import static android.system.OsConstants.ENODEV;
|
||||||
import static android.system.OsConstants.ENOENT;
|
import static android.system.OsConstants.ENOENT;
|
||||||
import static android.system.OsConstants.EOPNOTSUPP;
|
import static android.system.OsConstants.EOPNOTSUPP;
|
||||||
|
|
||||||
@@ -60,6 +61,7 @@ public class BpfNetMaps {
|
|||||||
|
|
||||||
private static final String TAG = "BpfNetMaps";
|
private static final String TAG = "BpfNetMaps";
|
||||||
private final INetd mNetd;
|
private final INetd mNetd;
|
||||||
|
private final Dependencies mDeps;
|
||||||
// Use legacy netd for releases before T.
|
// Use legacy netd for releases before T.
|
||||||
private static boolean sInitialized = false;
|
private static boolean sInitialized = false;
|
||||||
|
|
||||||
@@ -163,6 +165,19 @@ public class BpfNetMaps {
|
|||||||
sInitialized = true;
|
sInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dependencies of BpfNetMaps, for injection in tests.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static class Dependencies {
|
||||||
|
/**
|
||||||
|
* Get interface index.
|
||||||
|
*/
|
||||||
|
public int getIfIndex(final String ifName) {
|
||||||
|
return Os.if_nametoindex(ifName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Constructor used after T that doesn't need to use netd anymore. */
|
/** Constructor used after T that doesn't need to use netd anymore. */
|
||||||
public BpfNetMaps() {
|
public BpfNetMaps() {
|
||||||
this(null);
|
this(null);
|
||||||
@@ -171,10 +186,16 @@ public class BpfNetMaps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BpfNetMaps(final INetd netd) {
|
public BpfNetMaps(final INetd netd) {
|
||||||
|
this(netd, new Dependencies());
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public BpfNetMaps(final INetd netd, final Dependencies deps) {
|
||||||
if (!PRE_T) {
|
if (!PRE_T) {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
}
|
}
|
||||||
mNetd = netd;
|
mNetd = netd;
|
||||||
|
mDeps = deps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -419,9 +440,24 @@ public class BpfNetMaps {
|
|||||||
mNetd.firewallAddUidInterfaceRules(ifName, uids);
|
mNetd.firewallAddUidInterfaceRules(ifName, uids);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
synchronized (sUidOwnerMap) {
|
// Null ifName is a wildcard to allow apps to receive packets on all interfaces and ifIndex
|
||||||
final int err = native_addUidInterfaceRules(ifName, uids);
|
// is set to 0.
|
||||||
maybeThrow(err, "Unable to add uid interface rules");
|
final int ifIndex;
|
||||||
|
if (ifName == null) {
|
||||||
|
ifIndex = 0;
|
||||||
|
} else {
|
||||||
|
ifIndex = mDeps.getIfIndex(ifName);
|
||||||
|
if (ifIndex == 0) {
|
||||||
|
throw new ServiceSpecificException(ENODEV,
|
||||||
|
"Failed to get index of interface " + ifName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (final int uid: uids) {
|
||||||
|
try {
|
||||||
|
addRule(uid, IIF_MATCH, ifIndex, "addUidInterfaceRules");
|
||||||
|
} catch (ServiceSpecificException e) {
|
||||||
|
Log.e(TAG, "addRule failed uid=" + uid + " ifName=" + ifName + ", " + e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import static org.junit.Assert.assertNull;
|
|||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assume.assumeFalse;
|
import static org.junit.Assume.assumeFalse;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.net.INetd;
|
import android.net.INetd;
|
||||||
@@ -81,6 +82,7 @@ public final class BpfNetMapsTest {
|
|||||||
private static final String TEST_IF_NAME = "wlan0";
|
private static final String TEST_IF_NAME = "wlan0";
|
||||||
private static final int TEST_IF_INDEX = 7;
|
private static final int TEST_IF_INDEX = 7;
|
||||||
private static final int NO_IIF = 0;
|
private static final int NO_IIF = 0;
|
||||||
|
private static final int NULL_IIF = 0;
|
||||||
private static final String CHAINNAME = "fw_dozable";
|
private static final String CHAINNAME = "fw_dozable";
|
||||||
private static final U32 UID_RULES_CONFIGURATION_KEY = new U32(0);
|
private static final U32 UID_RULES_CONFIGURATION_KEY = new U32(0);
|
||||||
private static final List<Integer> FIREWALL_CHAINS = List.of(
|
private static final List<Integer> FIREWALL_CHAINS = List.of(
|
||||||
@@ -97,6 +99,7 @@ public final class BpfNetMapsTest {
|
|||||||
private BpfNetMaps mBpfNetMaps;
|
private BpfNetMaps mBpfNetMaps;
|
||||||
|
|
||||||
@Mock INetd mNetd;
|
@Mock INetd mNetd;
|
||||||
|
@Mock BpfNetMaps.Dependencies mDeps;
|
||||||
private final BpfMap<U32, U32> mConfigurationMap = new TestBpfMap<>(U32.class, U32.class);
|
private final BpfMap<U32, U32> mConfigurationMap = new TestBpfMap<>(U32.class, U32.class);
|
||||||
private final BpfMap<U32, UidOwnerValue> mUidOwnerMap =
|
private final BpfMap<U32, UidOwnerValue> mUidOwnerMap =
|
||||||
new TestBpfMap<>(U32.class, UidOwnerValue.class);
|
new TestBpfMap<>(U32.class, UidOwnerValue.class);
|
||||||
@@ -104,9 +107,10 @@ public final class BpfNetMapsTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
doReturn(TEST_IF_INDEX).when(mDeps).getIfIndex(TEST_IF_NAME);
|
||||||
BpfNetMaps.setConfigurationMapForTest(mConfigurationMap);
|
BpfNetMaps.setConfigurationMapForTest(mConfigurationMap);
|
||||||
BpfNetMaps.setUidOwnerMapForTest(mUidOwnerMap);
|
BpfNetMaps.setUidOwnerMapForTest(mUidOwnerMap);
|
||||||
mBpfNetMaps = new BpfNetMaps(mNetd);
|
mBpfNetMaps = new BpfNetMaps(mNetd, mDeps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -458,4 +462,72 @@ public final class BpfNetMapsTest {
|
|||||||
assertThrows(UnsupportedOperationException.class,
|
assertThrows(UnsupportedOperationException.class,
|
||||||
() -> mBpfNetMaps.updateUidLockdownRule(TEST_UID, true /* add */));
|
() -> mBpfNetMaps.updateUidLockdownRule(TEST_UID, true /* add */));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||||
|
public void testAddUidInterfaceRules() throws Exception {
|
||||||
|
final int uid0 = TEST_UIDS[0];
|
||||||
|
final int uid1 = TEST_UIDS[1];
|
||||||
|
|
||||||
|
mBpfNetMaps.addUidInterfaceRules(TEST_IF_NAME, TEST_UIDS);
|
||||||
|
|
||||||
|
checkUidOwnerValue(uid0, TEST_IF_INDEX, IIF_MATCH);
|
||||||
|
checkUidOwnerValue(uid1, TEST_IF_INDEX, IIF_MATCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||||
|
public void testAddUidInterfaceRulesWithOtherMatch() throws Exception {
|
||||||
|
final int uid0 = TEST_UIDS[0];
|
||||||
|
final int uid1 = TEST_UIDS[1];
|
||||||
|
final long match0 = DOZABLE_MATCH;
|
||||||
|
final long match1 = DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH;
|
||||||
|
mUidOwnerMap.updateEntry(new U32(uid0), new UidOwnerValue(NO_IIF, match0));
|
||||||
|
mUidOwnerMap.updateEntry(new U32(uid1), new UidOwnerValue(NO_IIF, match1));
|
||||||
|
|
||||||
|
mBpfNetMaps.addUidInterfaceRules(TEST_IF_NAME, TEST_UIDS);
|
||||||
|
|
||||||
|
checkUidOwnerValue(uid0, TEST_IF_INDEX, match0 | IIF_MATCH);
|
||||||
|
checkUidOwnerValue(uid1, TEST_IF_INDEX, match1 | IIF_MATCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||||
|
public void testAddUidInterfaceRulesWithExistingIifMatch() throws Exception {
|
||||||
|
final int uid0 = TEST_UIDS[0];
|
||||||
|
final int uid1 = TEST_UIDS[1];
|
||||||
|
final long match0 = IIF_MATCH;
|
||||||
|
final long match1 = IIF_MATCH | DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH;
|
||||||
|
mUidOwnerMap.updateEntry(new U32(uid0), new UidOwnerValue(TEST_IF_INDEX + 1, match0));
|
||||||
|
mUidOwnerMap.updateEntry(new U32(uid1), new UidOwnerValue(NULL_IIF, match1));
|
||||||
|
|
||||||
|
mBpfNetMaps.addUidInterfaceRules(TEST_IF_NAME, TEST_UIDS);
|
||||||
|
|
||||||
|
checkUidOwnerValue(uid0, TEST_IF_INDEX, match0);
|
||||||
|
checkUidOwnerValue(uid1, TEST_IF_INDEX, match1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||||
|
public void testAddUidInterfaceRulesGetIfIndexFail() {
|
||||||
|
doReturn(0).when(mDeps).getIfIndex(TEST_IF_NAME);
|
||||||
|
assertThrows(ServiceSpecificException.class,
|
||||||
|
() -> mBpfNetMaps.addUidInterfaceRules(TEST_IF_NAME, TEST_UIDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||||
|
public void testAddUidInterfaceRulesWithNullInterface() throws Exception {
|
||||||
|
final int uid0 = TEST_UIDS[0];
|
||||||
|
final int uid1 = TEST_UIDS[1];
|
||||||
|
final long match0 = IIF_MATCH;
|
||||||
|
final long match1 = IIF_MATCH | DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH;
|
||||||
|
mUidOwnerMap.updateEntry(new U32(uid0), new UidOwnerValue(TEST_IF_INDEX, match0));
|
||||||
|
mUidOwnerMap.updateEntry(new U32(uid1), new UidOwnerValue(NULL_IIF, match1));
|
||||||
|
|
||||||
|
mBpfNetMaps.addUidInterfaceRules(null /* ifName */, TEST_UIDS);
|
||||||
|
|
||||||
|
checkUidOwnerValue(uid0, NULL_IIF, match0);
|
||||||
|
checkUidOwnerValue(uid1, NULL_IIF, match1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user