Populating local addresses to local_net_access_map
Whenever LinkProperties is added/modified/removes, we are updating local network prefixes for the modified interface/addresses. These prefixes are used by BPF egress and ingress cgroup hooks to disallow local network packets if the calling application do not have required permission. Bug: 369815823 Test: Manually tested Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.BpfNetMapsTest Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.CSLocalNetworkProtectionTest Change-Id: Ie592ecb948ae05a0a73f47d0573560eb705f6bcf
This commit is contained in:
parent
f2ae113d53
commit
18b7262f60
1 changed files with 665 additions and 15 deletions
|
|
@ -109,8 +109,8 @@ import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_5;
|
|||
import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
|
||||
import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS;
|
||||
import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
|
||||
import static android.net.NetworkCapabilities.RES_ID_UNSET;
|
||||
import static android.net.NetworkCapabilities.RES_ID_MATCH_ALL_RESERVATIONS;
|
||||
import static android.net.NetworkCapabilities.RES_ID_UNSET;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
||||
|
|
@ -146,6 +146,8 @@ import static com.android.net.module.util.BpfUtils.BPF_CGROUP_UDP4_SENDMSG;
|
|||
import static com.android.net.module.util.BpfUtils.BPF_CGROUP_UDP6_RECVMSG;
|
||||
import static com.android.net.module.util.BpfUtils.BPF_CGROUP_UDP6_SENDMSG;
|
||||
import static com.android.net.module.util.NetworkMonitorUtils.isPrivateDnsValidationRequired;
|
||||
import static com.android.net.module.util.NetworkStackConstants.IPV4_LOCAL_PREFIXES;
|
||||
import static com.android.net.module.util.NetworkStackConstants.MULTICAST_AND_BROADCAST_PREFIXES;
|
||||
import static com.android.net.module.util.PermissionUtils.enforceAnyPermissionOf;
|
||||
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermission;
|
||||
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermissionOr;
|
||||
|
|
@ -214,6 +216,7 @@ import android.net.ISocketKeepaliveCallback;
|
|||
import android.net.InetAddresses;
|
||||
import android.net.IpMemoryStore;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.LocalNetworkConfig;
|
||||
import android.net.LocalNetworkInfo;
|
||||
|
|
@ -5683,6 +5686,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
// destroyed pending replacement they will be sent when it is disconnected.
|
||||
maybeDisableForwardRulesForDisconnectingNai(nai, false /* sendCallbacks */);
|
||||
updateIngressToVpnAddressFiltering(null, nai.linkProperties, nai);
|
||||
updateLocalNetworkAddresses(null, nai.linkProperties);
|
||||
try {
|
||||
mNetd.networkDestroy(nai.network.getNetId());
|
||||
} catch (RemoteException | ServiceSpecificException e) {
|
||||
|
|
@ -9583,6 +9587,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
|
||||
updateIngressToVpnAddressFiltering(newLp, oldLp, networkAgent);
|
||||
|
||||
updateLocalNetworkAddresses(newLp, oldLp);
|
||||
|
||||
updateMtu(newLp, oldLp);
|
||||
// TODO - figure out what to do for clat
|
||||
// for (LinkProperties lp : newLp.getStackedLinks()) {
|
||||
|
|
@ -9761,6 +9767,134 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Local Network Addresses to LocalNetAccess BPF map.
|
||||
* @param newLp new link properties
|
||||
* @param oldLp old link properties
|
||||
*/
|
||||
private void updateLocalNetworkAddresses(@Nullable final LinkProperties newLp,
|
||||
@NonNull final LinkProperties oldLp) {
|
||||
|
||||
// The maps are available only after 25Q2 release
|
||||
if (!BpfNetMaps.isAtLeast25Q2()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final CompareResult<String> interfaceDiff = new CompareResult<>(
|
||||
oldLp != null ? oldLp.getAllInterfaceNames() : null,
|
||||
newLp != null ? newLp.getAllInterfaceNames() : null);
|
||||
|
||||
for (final String iface : interfaceDiff.added) {
|
||||
addLocalAddressesToBpfMap(iface, MULTICAST_AND_BROADCAST_PREFIXES);
|
||||
}
|
||||
for (final String iface : interfaceDiff.removed) {
|
||||
removeLocalAddressesFromBpfMap(iface, MULTICAST_AND_BROADCAST_PREFIXES);
|
||||
}
|
||||
|
||||
final CompareResult<LinkAddress> linkAddressDiff = new CompareResult<>(
|
||||
oldLp != null ? oldLp.getLinkAddresses() : null,
|
||||
newLp != null ? newLp.getLinkAddresses() : null);
|
||||
|
||||
List<IpPrefix> unicastLocalPrefixesToBeAdded = new ArrayList<>();
|
||||
List<IpPrefix> unicastLocalPrefixesToBeRemoved = new ArrayList<>();
|
||||
|
||||
// Finding the list of local network prefixes that needs to be added
|
||||
if (newLp != null) {
|
||||
for (LinkAddress linkAddress : newLp.getLinkAddresses()) {
|
||||
unicastLocalPrefixesToBeAdded.addAll(
|
||||
getLocalNetworkPrefixesForAddress(linkAddress));
|
||||
}
|
||||
}
|
||||
|
||||
for (LinkAddress linkAddress : linkAddressDiff.removed) {
|
||||
unicastLocalPrefixesToBeRemoved.addAll(getLocalNetworkPrefixesForAddress(linkAddress));
|
||||
}
|
||||
|
||||
// If newLp is not null, adding local network prefixes using interface name of newLp
|
||||
if (newLp != null) {
|
||||
addLocalAddressesToBpfMap(newLp.getInterfaceName(),
|
||||
new ArrayList<>(unicastLocalPrefixesToBeAdded));
|
||||
}
|
||||
if (oldLp != null) {
|
||||
// excluding removal of ip prefixes that needs to be added for newLp, but also
|
||||
// removed for oldLp.
|
||||
if (newLp != null && Objects.equals(oldLp.getInterfaceName(),
|
||||
newLp.getInterfaceName())) {
|
||||
unicastLocalPrefixesToBeRemoved.removeAll(unicastLocalPrefixesToBeAdded);
|
||||
}
|
||||
// removing ip local network prefixes because of change in link addresses.
|
||||
removeLocalAddressesFromBpfMap(oldLp.getInterfaceName(),
|
||||
new ArrayList<>(unicastLocalPrefixesToBeRemoved));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters IpPrefix that are local prefixes and LinkAddress is part of them.
|
||||
* @param linkAddress link address used for filtering
|
||||
* @return list of IpPrefix that are local addresses.
|
||||
*/
|
||||
private List<IpPrefix> getLocalNetworkPrefixesForAddress(LinkAddress linkAddress) {
|
||||
List<IpPrefix> localPrefixes = new ArrayList<>();
|
||||
if (linkAddress.isIpv6()) {
|
||||
// For IPv6, if the prefix length is greater than zero then they are part of local
|
||||
// network
|
||||
if (linkAddress.getPrefixLength() != 0) {
|
||||
localPrefixes.add(
|
||||
new IpPrefix(linkAddress.getAddress(), linkAddress.getPrefixLength()));
|
||||
}
|
||||
} else {
|
||||
// For IPv4, if the linkAddress is part of IpPrefix adding prefix to result.
|
||||
for (IpPrefix ipv4LocalPrefix : IPV4_LOCAL_PREFIXES) {
|
||||
if (ipv4LocalPrefix.containsPrefix(
|
||||
new IpPrefix(linkAddress.getAddress(), linkAddress.getPrefixLength()))) {
|
||||
localPrefixes.add(ipv4LocalPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
return localPrefixes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds list of prefixes(addresses) to local network access map.
|
||||
* @param iface interface name
|
||||
* @param prefixes list of prefixes/addresses
|
||||
*/
|
||||
private void addLocalAddressesToBpfMap(final String iface, final List<IpPrefix> prefixes) {
|
||||
if (!BpfNetMaps.isAtLeast25Q2()) return;
|
||||
for (IpPrefix prefix : prefixes) {
|
||||
/*
|
||||
Prefix length is used by LPM trie map(local_net_access_map) for performing longest
|
||||
prefix matching, this length represents the maximum number of bits used for matching.
|
||||
The interface index should always be matched which is 32-bit integer. For IPv6, prefix
|
||||
length is calculated by adding the ip address prefix length along with interface index
|
||||
making it (32 + length). IPv4 addresses are stored as ipv4-mapped-ipv6 which implies
|
||||
first 96 bits are common for all ipv4 addresses. Hence, prefix length is calculated as
|
||||
32(interface index) + 96 (common for ipv4-mapped-ipv6) + length.
|
||||
*/
|
||||
final int prefixLengthConstant = (prefix.isIPv4() ? (32 + 96) : 32);
|
||||
mBpfNetMaps.addLocalNetAccess(prefixLengthConstant + prefix.getPrefixLength(),
|
||||
iface, prefix.getAddress(), 0, 0, false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes list of prefixes(addresses) from local network access map.
|
||||
* @param iface interface name
|
||||
* @param prefixes list of prefixes/addresses
|
||||
*/
|
||||
private void removeLocalAddressesFromBpfMap(final String iface, final List<IpPrefix> prefixes) {
|
||||
if (!BpfNetMaps.isAtLeast25Q2()) return;
|
||||
for (IpPrefix prefix : prefixes) {
|
||||
// The reasoning for prefix length is explained in addLocalAddressesToBpfMap()
|
||||
final int prefixLengthConstant = (prefix.isIPv4() ? (32 + 96) : 32);
|
||||
mBpfNetMaps.removeLocalNetAccess(prefixLengthConstant
|
||||
+ prefix.getPrefixLength(), iface, prefix.getAddress(), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Have netd update routes from oldLp to newLp.
|
||||
* @return true if routes changed between oldLp and newLp
|
||||
|
|
|
|||
Loading…
Reference in a new issue