am 7fb07438: am 674f85af: Merge "Only allow System apps to make VPN exempt routes" into klp-dev

* commit '7fb074389370ac93afc5830189371dc3ec26265c':
  Only allow System apps to make VPN exempt routes
This commit is contained in:
Chad Brubaker
2014-03-13 18:18:40 +00:00
committed by Android Git Automerger

View File

@@ -33,6 +33,7 @@ import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
@@ -44,7 +45,9 @@ import android.content.Context;
import android.content.ContextWrapper; import android.content.ContextWrapper;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.ContentObserver; import android.database.ContentObserver;
@@ -414,6 +417,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private SettingsObserver mSettingsObserver; private SettingsObserver mSettingsObserver;
private AppOpsManager mAppOpsManager;
NetworkConfig[] mNetConfigs; NetworkConfig[] mNetConfigs;
int mNetworksDefined; int mNetworksDefined;
@@ -697,6 +702,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
filter = new IntentFilter(); filter = new IntentFilter();
filter.addAction(CONNECTED_TO_PROVISIONING_NETWORK_ACTION); filter.addAction(CONNECTED_TO_PROVISIONING_NETWORK_ACTION);
mContext.registerReceiver(mProvisioningReceiver, filter); mContext.registerReceiver(mProvisioningReceiver, filter);
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
} }
/** /**
@@ -1530,6 +1537,40 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} }
} }
/**
* Check if the address falls into any of currently running VPN's route's.
*/
private boolean isAddressUnderVpn(InetAddress address) {
synchronized (mVpns) {
synchronized (mRoutesLock) {
int uid = UserHandle.getCallingUserId();
Vpn vpn = mVpns.get(uid);
if (vpn == null) {
return false;
}
// Check if an exemption exists for this address.
for (LinkAddress destination : mExemptAddresses) {
if (!NetworkUtils.addressTypeMatches(address, destination.getAddress())) {
continue;
}
int prefix = destination.getNetworkPrefixLength();
InetAddress addrMasked = NetworkUtils.getNetworkPart(address, prefix);
InetAddress destMasked = NetworkUtils.getNetworkPart(destination.getAddress(),
prefix);
if (addrMasked.equals(destMasked)) {
return false;
}
}
// Finally check if the address is covered by the VPN.
return vpn.isAddressCovered(address);
}
}
}
/** /**
* @deprecated use requestRouteToHostAddress instead * @deprecated use requestRouteToHostAddress instead
* *
@@ -1566,6 +1607,34 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (mProtectedNetworks.contains(networkType)) { if (mProtectedNetworks.contains(networkType)) {
enforceConnectivityInternalPermission(); enforceConnectivityInternalPermission();
} }
boolean exempt;
InetAddress addr;
try {
addr = InetAddress.getByAddress(hostAddress);
} catch (UnknownHostException e) {
if (DBG) log("requestRouteToHostAddress got " + e.toString());
return false;
}
// System apps may request routes bypassing the VPN to keep other networks working.
if (Binder.getCallingUid() == Process.SYSTEM_UID) {
exempt = true;
} else {
mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
try {
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(packageName,
0);
exempt = (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
} catch (NameNotFoundException e) {
throw new IllegalArgumentException("Failed to find calling package details", e);
}
}
// Non-exempt routeToHost's can only be added if the host is not covered by the VPN.
// This can be either because the VPN's routes do not cover the destination or a
// system application added an exemption that covers this destination.
if (!exempt && isAddressUnderVpn(addr)) {
return false;
}
if (!ConnectivityManager.isNetworkTypeValid(networkType)) { if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType); if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
@@ -1592,18 +1661,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} }
final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity();
try { try {
InetAddress addr = InetAddress.getByAddress(hostAddress);
LinkProperties lp = tracker.getLinkProperties(); LinkProperties lp = tracker.getLinkProperties();
boolean ok = addRouteToAddress(lp, addr, EXEMPT); boolean ok = addRouteToAddress(lp, addr, exempt);
if (DBG) log("requestRouteToHostAddress ok=" + ok); if (DBG) log("requestRouteToHostAddress ok=" + ok);
return ok; return ok;
} catch (UnknownHostException e) {
if (DBG) log("requestRouteToHostAddress got " + e.toString());
} finally { } finally {
Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token);
} }
if (DBG) log("requestRouteToHostAddress X bottom return false");
return false;
} }
private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable, private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable,