Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7fb07438 authored by Chad Brubaker's avatar Chad Brubaker Committed by Android Git Automerger
Browse files

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

* commit '674f85af':
  Only allow System apps to make VPN exempt routes
parents 1011960c 674f85af
Loading
Loading
Loading
Loading
+70 −6
Original line number Diff line number Diff line
@@ -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);
    }

    /**
@@ -1526,6 +1533,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
     *
@@ -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,
+14 −0
Original line number Diff line number Diff line
@@ -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;
    }