diff options
author | Chad Brubaker <cbrubaker@google.com> | 2014-03-11 17:51:50 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-03-11 17:51:50 +0000 |
commit | 674f85af4c04970ec8875669b3f08eaf0465ba4b (patch) | |
tree | 972345d7b4faa8a92af95bd488e902657a035e6e | |
parent | decfd7079b622f9135aeb8f7b2ec48005c844c38 (diff) | |
parent | fb5800ed9ccefc1110800e91632dda930fc66151 (diff) | |
download | frameworks_base-674f85af4c04970ec8875669b3f08eaf0465ba4b.zip frameworks_base-674f85af4c04970ec8875669b3f08eaf0465ba4b.tar.gz frameworks_base-674f85af4c04970ec8875669b3f08eaf0465ba4b.tar.bz2 |
Merge "Only allow System apps to make VPN exempt routes" into klp-dev
-rw-r--r-- | services/java/com/android/server/ConnectivityService.java | 76 | ||||
-rw-r--r-- | services/java/com/android/server/connectivity/Vpn.java | 14 |
2 files changed, 84 insertions, 6 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index af6433a..83a3bfd 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -32,6 +32,7 @@ import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import android.app.AlarmManager; +import android.app.AppOpsManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -43,7 +44,9 @@ import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; @@ -412,6 +415,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { private SettingsObserver mSettingsObserver; + private AppOpsManager mAppOpsManager; + NetworkConfig[] mNetConfigs; int mNetworksDefined; @@ -695,6 +700,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { filter = new IntentFilter(); filter.addAction(CONNECTED_TO_PROVISIONING_NETWORK_ACTION); mContext.registerReceiver(mProvisioningReceiver, filter); + + mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); } /** @@ -1527,6 +1534,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 * * Ensure that a network route exists to deliver traffic to the specified @@ -1562,6 +1603,34 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (mProtectedNetworks.contains(networkType)) { 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 (DBG) log("requestRouteToHostAddress on invalid network: " + networkType); @@ -1585,18 +1654,13 @@ public class ConnectivityService extends IConnectivityManager.Stub { } final long token = Binder.clearCallingIdentity(); try { - InetAddress addr = InetAddress.getByAddress(hostAddress); LinkProperties lp = tracker.getLinkProperties(); - boolean ok = addRouteToAddress(lp, addr, EXEMPT); + boolean ok = addRouteToAddress(lp, addr, exempt); if (DBG) log("requestRouteToHostAddress ok=" + ok); return ok; - } catch (UnknownHostException e) { - if (DBG) log("requestRouteToHostAddress got " + e.toString()); } finally { Binder.restoreCallingIdentity(token); } - if (DBG) log("requestRouteToHostAddress X bottom return false"); - return false; } private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable, diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java index f5a7039..9ed3eaa 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/java/com/android/server/connectivity/Vpn.java @@ -45,6 +45,7 @@ import android.net.LinkProperties; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.net.NetworkInfo; +import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.NetworkInfo.DetailedState; import android.os.Binder; @@ -77,6 +78,7 @@ import com.android.server.net.BaseNetworkObserver; import java.io.File; import java.io.InputStream; import java.io.OutputStream; +import java.net.InetAddress; import java.net.Inet4Address; import java.net.InetAddress; import java.nio.charset.StandardCharsets; @@ -435,6 +437,18 @@ public class Vpn extends BaseNetworkStateTracker { return tun; } + /** + * Check if a given address is covered by the VPN's routing rules. + */ + public boolean isAddressCovered(InetAddress address) { + synchronized (Vpn.this) { + if (!isRunningLocked()) { + return false; + } + return RouteInfo.selectBestRoute(mConfig.routes, address) != null; + } + } + private boolean isRunningLocked() { return mVpnUsers != null; } |