Skip to content
Snippets Groups Projects
Commit 5c0b66ed authored by Motomu Utsumi's avatar Motomu Utsumi Committed by Mohammad Hasan Keramat J
Browse files

Drop packets to VPN address ingressing via non-VPN interface

Cherry-pick of aosp/2795711 to backport VPN security fix to non-mainline
U devices.
Since isTetheringFeatureNotChickenedOut is not available on U branch,
this feature is enabled on T+ devices without kill switch.
Also, this CL removes test changes since CSTest utilities are not
available on u branches.

When there are addresses that are used by a single VPN interface,
ConnectivityService sets ingress discard rules to drop packets to this
address from the non-Vpn interfaces

Bug: 193031925
Test: TH
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d493a3aa7dcca3219b139616c9de3c6ee8181f86)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1027bc813ea6a5b97bc0f55401e01f5eec91e94a)
Merged-In: I5933d42f3fd257139fb803ede1391e10d9d1211b
Change-Id: I5933d42f3fd257139fb803ede1391e10d9d1211b
parent 741ed0b4
No related branches found
No related tags found
No related merge requests found
...@@ -1332,6 +1332,9 @@ public class ConnectivityService extends IConnectivityManager.Stub ...@@ -1332,6 +1332,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Uids that ConnectivityService is pending to close sockets of. // Uids that ConnectivityService is pending to close sockets of.
private final Set<Integer> mPendingFrozenUids = new ArraySet<>(); private final Set<Integer> mPendingFrozenUids = new ArraySet<>();
   
// Flag to drop packets to VPN addresses ingressing via non-VPN interfaces.
private final boolean mIngressToVpnAddressFiltering;
/** /**
* Implements support for the legacy "one network per network type" model. * Implements support for the legacy "one network per network type" model.
* *
...@@ -2320,6 +2323,7 @@ public class ConnectivityService extends IConnectivityManager.Stub ...@@ -2320,6 +2323,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (mDeps.isFeatureNotChickenedOut(mContext, LOG_BPF_RC)) { if (mDeps.isFeatureNotChickenedOut(mContext, LOG_BPF_RC)) {
mHandler.post(BpfLoaderRcUtils::checkBpfLoaderRc); mHandler.post(BpfLoaderRcUtils::checkBpfLoaderRc);
} }
mIngressToVpnAddressFiltering = mDeps.isAtLeastT();
} }
   
/** /**
...@@ -5712,6 +5716,7 @@ public class ConnectivityService extends IConnectivityManager.Stub ...@@ -5712,6 +5716,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// was is being disconnected the callbacks have already been sent, and if it is being // was is being disconnected the callbacks have already been sent, and if it is being
// destroyed pending replacement they will be sent when it is disconnected. // destroyed pending replacement they will be sent when it is disconnected.
maybeDisableForwardRulesForDisconnectingNai(nai, false /* sendCallbacks */); maybeDisableForwardRulesForDisconnectingNai(nai, false /* sendCallbacks */);
updateIngressToVpnAddressFiltering(null, nai.linkProperties, nai);
try { try {
mNetd.networkDestroy(nai.network.getNetId()); mNetd.networkDestroy(nai.network.getNetId());
} catch (RemoteException | ServiceSpecificException e) { } catch (RemoteException | ServiceSpecificException e) {
...@@ -9071,6 +9076,8 @@ public class ConnectivityService extends IConnectivityManager.Stub ...@@ -9071,6 +9076,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
// new interface (the interface name -> index map becomes initialized) // new interface (the interface name -> index map becomes initialized)
updateVpnFiltering(newLp, oldLp, networkAgent, shouldForceUpdateVpnFiltering); updateVpnFiltering(newLp, oldLp, networkAgent, shouldForceUpdateVpnFiltering);
   
updateIngressToVpnAddressFiltering(newLp, oldLp, networkAgent);
updateMtu(newLp, oldLp); updateMtu(newLp, oldLp);
// TODO - figure out what to do for clat // TODO - figure out what to do for clat
// for (LinkProperties lp : newLp.getStackedLinks()) { // for (LinkProperties lp : newLp.getStackedLinks()) {
...@@ -9368,6 +9375,87 @@ public class ConnectivityService extends IConnectivityManager.Stub ...@@ -9368,6 +9375,87 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
} }
   
/**
* Returns ingress discard rules to drop packets to VPN addresses ingressing via non-VPN
* interfaces.
* Ingress discard rule is added to the address iff
* 1. The address is not a link local address
* 2. The address is used by a single VPN interface and not used by any other
* interfaces even non-VPN ones
* This method can be called during network disconnects, when nai has already been removed from
* mNetworkAgentInfos.
*
* @param nai This method generates rules assuming lp of this nai is the lp at the second
* argument.
* @param lp This method generates rules assuming lp of nai at the first argument is this lp.
* Caller passes old lp to generate old rules and new lp to generate new rules.
* @return ingress discard rules. Set of pairs of addresses and interface names
*/
private Set<Pair<InetAddress, String>> generateIngressDiscardRules(
@NonNull final NetworkAgentInfo nai, @Nullable final LinkProperties lp) {
Set<NetworkAgentInfo> nais = new ArraySet<>(mNetworkAgentInfos);
nais.add(nai);
// Determine how many networks each IP address is currently configured on.
// Ingress rules are added only for IP addresses that are configured on single interface.
final Map<InetAddress, Integer> addressOwnerCounts = new ArrayMap<>();
for (final NetworkAgentInfo agent : nais) {
if (agent.isDestroyed()) {
continue;
}
final LinkProperties agentLp = (nai == agent) ? lp : agent.linkProperties;
if (agentLp == null) {
continue;
}
for (final InetAddress addr: agentLp.getAllAddresses()) {
addressOwnerCounts.put(addr, addressOwnerCounts.getOrDefault(addr, 0) + 1);
}
}
// Iterates all networks instead of only generating rule for nai that was passed in since
// lp of the nai change could cause/resolve address collision and result in affecting rule
// for different network.
final Set<Pair<InetAddress, String>> ingressDiscardRules = new ArraySet<>();
for (final NetworkAgentInfo agent : nais) {
if (!agent.isVPN() || agent.isDestroyed()) {
continue;
}
final LinkProperties agentLp = (nai == agent) ? lp : agent.linkProperties;
if (agentLp == null || agentLp.getInterfaceName() == null) {
continue;
}
for (final InetAddress addr: agentLp.getAllAddresses()) {
if (addressOwnerCounts.get(addr) == 1 && !addr.isLinkLocalAddress()) {
ingressDiscardRules.add(new Pair<>(addr, agentLp.getInterfaceName()));
}
}
}
return ingressDiscardRules;
}
private void updateIngressToVpnAddressFiltering(@Nullable LinkProperties newLp,
@Nullable LinkProperties oldLp, @NonNull NetworkAgentInfo nai) {
// Having isAtleastT to avoid NewApi linter error (b/303382209)
if (!mIngressToVpnAddressFiltering || !mDeps.isAtLeastT()) {
return;
}
final CompareOrUpdateResult<InetAddress, Pair<InetAddress, String>> ruleDiff =
new CompareOrUpdateResult<>(
generateIngressDiscardRules(nai, oldLp),
generateIngressDiscardRules(nai, newLp),
(rule) -> rule.first);
for (Pair<InetAddress, String> rule: ruleDiff.removed) {
mBpfNetMaps.removeIngressDiscardRule(rule.first);
}
for (Pair<InetAddress, String> rule: ruleDiff.added) {
mBpfNetMaps.setIngressDiscardRule(rule.first, rule.second);
}
// setIngressDiscardRule overrides the existing rule
for (Pair<InetAddress, String> rule: ruleDiff.updated) {
mBpfNetMaps.setIngressDiscardRule(rule.first, rule.second);
}
}
private void updateWakeOnLan(@NonNull LinkProperties lp) { private void updateWakeOnLan(@NonNull LinkProperties lp) {
if (mWolSupportedInterfaces == null) { if (mWolSupportedInterfaces == null) {
mWolSupportedInterfaces = new ArraySet<>(mResources.get().getStringArray( mWolSupportedInterfaces = new ArraySet<>(mResources.get().getStringArray(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment