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

Commit eae314a6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Check location permission for ConnDiags last." into sc-dev

parents 1dc89984 314ff0dc
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -713,7 +713,9 @@ public class ConnectivityDiagnosticsManager {
     * <p>Callbacks registered by apps not meeting the above criteria will not be invoked.
     *
     * <p>If a registering app loses its relevant permissions, any callbacks it registered will
     * silently stop receiving callbacks.
     * silently stop receiving callbacks. Note that registering apps must also have location
     * permissions to receive callbacks as some Networks may be location-bound (such as WiFi
     * networks).
     *
     * <p>Each register() call <b>MUST</b> use a ConnectivityDiagnosticsCallback instance that is
     * not currently registered. If a ConnectivityDiagnosticsCallback instance is registered with
+24 −11
Original line number Diff line number Diff line
@@ -9162,36 +9162,49 @@ public class ConnectivityService extends IConnectivityManager.Stub
        return results;
    }

    @VisibleForTesting
    boolean checkConnectivityDiagnosticsPermissions(
            int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName) {
        if (checkNetworkStackPermission(callbackPid, callbackUid)) {
            return true;
        }

    private boolean hasLocationPermission(String packageName, int uid) {
        // LocationPermissionChecker#checkLocationPermission can throw SecurityException if the uid
        // and package name don't match. Throwing on the CS thread is not acceptable, so wrap the
        // call in a try-catch.
        try {
            if (!mLocationPermissionChecker.checkLocationPermission(
                    callbackPackageName, null /* featureId */, callbackUid, null /* message */)) {
                        packageName, null /* featureId */, uid, null /* message */)) {
                return false;
            }
        } catch (SecurityException e) {
            return false;
        }

        return true;
    }

    private boolean ownsVpnRunningOverNetwork(int uid, Network network) {
        for (NetworkAgentInfo virtual : mNetworkAgentInfos) {
            if (virtual.supportsUnderlyingNetworks()
                    && virtual.networkCapabilities.getOwnerUid() == callbackUid
                    && CollectionUtils.contains(virtual.declaredUnderlyingNetworks, nai.network)) {
                    && virtual.networkCapabilities.getOwnerUid() == uid
                    && CollectionUtils.contains(virtual.declaredUnderlyingNetworks, network)) {
                return true;
            }
        }

        return false;
    }

    @VisibleForTesting
    boolean checkConnectivityDiagnosticsPermissions(
            int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName) {
        if (checkNetworkStackPermission(callbackPid, callbackUid)) {
            return true;
        }

        // Administrator UIDs also contains the Owner UID
        final int[] administratorUids = nai.networkCapabilities.getAdministratorUids();
        return CollectionUtils.contains(administratorUids, callbackUid);
        if (!CollectionUtils.contains(administratorUids, callbackUid)
                && !ownsVpnRunningOverNetwork(callbackUid, nai.network)) {
            return false;
        }

        return hasLocationPermission(callbackPackageName, callbackUid);
    }

    @Override
+10 −6
Original line number Diff line number Diff line
@@ -9940,28 +9940,32 @@ public class ConnectivityServiceTest {
    @Test
    public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
        final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
        final int wrongUid = Process.myUid() + 1;
        final NetworkCapabilities nc = new NetworkCapabilities();
        nc.setAdministratorUids(new int[] {wrongUid});
        final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
        mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
        assertFalse(
                "Mismatched uid/package name should not pass the location permission check",
                mService.checkConnectivityDiagnosticsPermissions(
                        Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid,
                        mContext.getOpPackageName()));
                        Process.myPid() + 1, wrongUid, naiWithUid, mContext.getOpPackageName()));
    }
    @Test
    public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
        final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
        final NetworkCapabilities nc = new NetworkCapabilities();
        nc.setAdministratorUids(new int[] {Process.myUid()});
        final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
        mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
        assertFalse(
                "ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics",
                mService.checkConnectivityDiagnosticsPermissions(
                        Process.myPid(), Process.myUid(), naiWithoutUid,
                        mContext.getOpPackageName()));
                        Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
    }
    @Test