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

Commit 8e42276a authored by Malcolm Chen's avatar Malcolm Chen Committed by android-build-merger
Browse files

Don't allow reading IMSI of one active sub if only has carrier privilege on the other.

am: 8c1ee3bb

Change-Id: Ic0f7b1b6b14826b4f429b3ded66b0250ffaa56f0
parents a4bd9e02 8c1ee3bb
Loading
Loading
Loading
Loading
+98 −24
Original line number Original line Diff line number Diff line
@@ -32,8 +32,11 @@ import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build;
import android.os.Build;
import android.os.Bundle;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ServiceManager;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager;
@@ -50,14 +53,15 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations;


import java.lang.reflect.Field;
import java.lang.reflect.Field;
import java.util.Map;


@SmallTest
@SmallTest
public class TelephonyPermissionsTest {
public class TelephonyPermissionsTest {


    private static final int SUB_ID = 55555;
    private static final int SUB_ID = 55555;
    private static final int SUB_ID_2 = 22222;
    private static final int SUB_ID_2 = 22222;
    private static final int PID = 12345;
    private static final int PID = Binder.getCallingPid();
    private static final int UID = 54321;
    private static final int UID = Binder.getCallingUid();
    private static final String PACKAGE = "com.example";
    private static final String PACKAGE = "com.example";
    private static final String MSG = "message";
    private static final String MSG = "message";


@@ -70,6 +74,8 @@ public class TelephonyPermissionsTest {
    @Mock
    @Mock
    private ITelephony mMockTelephony;
    private ITelephony mMockTelephony;
    @Mock
    @Mock
    private IBinder mMockTelephonyBinder;
    @Mock
    private PackageManager mMockPackageManager;
    private PackageManager mMockPackageManager;
    @Mock
    @Mock
    private ApplicationInfo mMockApplicationInfo;
    private ApplicationInfo mMockApplicationInfo;
@@ -101,10 +107,13 @@ public class TelephonyPermissionsTest {
                AppOpsManager.MODE_ERRORED);
                AppOpsManager.MODE_ERRORED);
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID)))
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID)))
                .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
                .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), eq(UID)))
                .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
        when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
        when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
                PID, UID)).thenReturn(PackageManager.PERMISSION_DENIED);
                PID, UID)).thenReturn(PackageManager.PERMISSION_DENIED);
        when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID),
        when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID),
                eq(UID))).thenReturn(false);
                eq(UID))).thenReturn(false);
        setTelephonyMockAsService();
    }
    }


    @Test
    @Test
@@ -243,8 +252,8 @@ public class TelephonyPermissionsTest {
    public void testCheckReadDeviceIdentifiers_noPermissions() throws Exception {
    public void testCheckReadDeviceIdentifiers_noPermissions() throws Exception {
        setupMocksForDeviceIdentifiersErrorPath();
        setupMocksForDeviceIdentifiersErrorPath();
        try {
        try {
            TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
            TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                    SUB_ID, PID, UID, PACKAGE, MSG);
                    SUB_ID, PACKAGE, MSG);
            fail("Should have thrown SecurityException");
            fail("Should have thrown SecurityException");
        } catch (SecurityException e) {
        } catch (SecurityException e) {
            // expected
            // expected
@@ -256,8 +265,8 @@ public class TelephonyPermissionsTest {
        when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
        when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
                PID, UID)).thenReturn(PackageManager.PERMISSION_GRANTED);
                PID, UID)).thenReturn(PackageManager.PERMISSION_GRANTED);
        assertTrue(
        assertTrue(
                TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
                TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                        SUB_ID, PID, UID, PACKAGE, MSG));
                        SUB_ID, PACKAGE, MSG));
    }
    }


    @Test
    @Test
@@ -265,8 +274,8 @@ public class TelephonyPermissionsTest {
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID)))
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID)))
                .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
                .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
        assertTrue(
        assertTrue(
                TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
                TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                        SUB_ID, PID, UID, PACKAGE, MSG));
                        SUB_ID, PACKAGE, MSG));
    }
    }


    @Test
    @Test
@@ -274,8 +283,8 @@ public class TelephonyPermissionsTest {
        when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID,
        when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID,
                PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);
                PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);
        assertTrue(
        assertTrue(
                TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
                TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                        SUB_ID, PID, UID, PACKAGE, MSG));
                        SUB_ID, PACKAGE, MSG));
    }
    }


    @Test
    @Test
@@ -283,8 +292,8 @@ public class TelephonyPermissionsTest {
        when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID),
        when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID),
                eq(UID))).thenReturn(true);
                eq(UID))).thenReturn(true);
        assertTrue(
        assertTrue(
                TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
                TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                        SUB_ID, PID, UID, PACKAGE, MSG));
                        SUB_ID, PACKAGE, MSG));
    }
    }


    @Test
    @Test
@@ -296,8 +305,8 @@ public class TelephonyPermissionsTest {
                UID)).thenReturn(PackageManager.PERMISSION_GRANTED);
                UID)).thenReturn(PackageManager.PERMISSION_GRANTED);
        setupMocksForDeviceIdentifiersErrorPath();
        setupMocksForDeviceIdentifiersErrorPath();
        try {
        try {
            TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
            TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                    SUB_ID, PID, UID, PACKAGE, MSG);
                    SUB_ID, PACKAGE, MSG);
            fail("Should have thrown SecurityException");
            fail("Should have thrown SecurityException");
        } catch (SecurityException e) {
        } catch (SecurityException e) {
            // expected
            // expected
@@ -314,8 +323,8 @@ public class TelephonyPermissionsTest {
        setupMocksForDeviceIdentifiersErrorPath();
        setupMocksForDeviceIdentifiersErrorPath();
        mMockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
        mMockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
        assertFalse(
        assertFalse(
                TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
                TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                        SUB_ID, PID, UID, PACKAGE, MSG));
                        SUB_ID, PACKAGE, MSG));
    }
    }


    @Test
    @Test
@@ -326,8 +335,8 @@ public class TelephonyPermissionsTest {
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), eq(UID))).thenReturn(
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), eq(UID))).thenReturn(
                TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
                TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
        assertTrue(
        assertTrue(
                TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
                TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                        SUB_ID, PID, UID, PACKAGE, MSG));
                        SUB_ID, PACKAGE, MSG));
    }
    }


    @Test
    @Test
@@ -340,8 +349,8 @@ public class TelephonyPermissionsTest {
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), eq(UID)))
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), eq(UID)))
                .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
                .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
        assertTrue(
        assertTrue(
                TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
                TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                        SUB_ID_2, PID, UID, PACKAGE, MSG));
                        SUB_ID, PACKAGE, MSG));
    }
    }


    @Test
    @Test
@@ -354,8 +363,8 @@ public class TelephonyPermissionsTest {
        when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID,
        when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID,
                PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);
                PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);
        assertTrue(
        assertTrue(
                TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
                TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                        SUB_ID, PID, UID, PACKAGE, MSG));
                        SUB_ID, PACKAGE, MSG));
    }
    }


    @Test
    @Test
@@ -365,14 +374,79 @@ public class TelephonyPermissionsTest {
        // case.
        // case.
        setupMocksForDeviceIdentifiersErrorPath();
        setupMocksForDeviceIdentifiersErrorPath();
        try {
        try {
            TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
            TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                    SUB_ID, PID, UID, null, MSG);
                    SUB_ID, null, MSG);
            fail("Should have thrown SecurityException");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testCheckCallingOrSelfReadSubscriberIdentifiers_noPermissions() throws Exception {
        setupMocksForDeviceIdentifiersErrorPath();
        setTelephonyMockAsService();
        when(mMockContext.checkPermission(
                eq(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE),
                anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
        when(mMockAppOps.noteOpNoThrow(anyString(), anyInt(), eq(PACKAGE))).thenReturn(
                AppOpsManager.MODE_ERRORED);
        when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), anyInt(),
                anyInt())).thenReturn(false);
        try {
            TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(mMockContext,
                    SUB_ID, PACKAGE, MSG);
            fail("Should have thrown SecurityException");
            fail("Should have thrown SecurityException");
        } catch (SecurityException e) {
        } catch (SecurityException e) {
            // expected
            // expected
        }
        }
    }
    }


    @Test
    public void testCheckCallingOrSelfReadSubscriberIdentifiers_carrierPrivileges()
            throws Exception {
        setTelephonyMockAsService();
        when(mMockContext.checkPermission(
                eq(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE),
                anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), anyInt()))
                .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
        assertTrue(
                TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(mMockContext,
                        SUB_ID, PACKAGE, MSG));
    }

    @Test
    public void testCheckCallingOrSelfReadSubscriberIdentifiers_carrierPrivilegesOnOtherSub()
            throws Exception {
        setupMocksForDeviceIdentifiersErrorPath();
        setTelephonyMockAsService();
        when(mMockContext.checkPermission(
                eq(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE),
                anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
        when(mMockSubscriptionManager.getActiveSubscriptionIdList(anyBoolean())).thenReturn(
                new int[]{SUB_ID, SUB_ID_2});
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), anyInt())).thenReturn(
                TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
        // Carrier privilege on the other active sub shouldn't allow access to this sub.
        try {
            TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(mMockContext,
                    SUB_ID, PACKAGE, MSG);
            fail("Should have thrown SecurityException");
        } catch (SecurityException e) {
            // expected
        }
    }

    // Put mMockTelephony into service cache so that TELEPHONY_SUPPLIER will get it.
    private void setTelephonyMockAsService() throws Exception {
        when(mMockTelephonyBinder.queryLocalInterface(anyString())).thenReturn(mMockTelephony);
        Field field = ServiceManager.class.getDeclaredField("sCache");
        field.setAccessible(true);
        ((Map<String, IBinder>) field.get(null)).put(Context.TELEPHONY_SERVICE,
                mMockTelephonyBinder);
    }

    public static class FakeSettingsConfigProvider extends FakeSettingsProvider {
    public static class FakeSettingsConfigProvider extends FakeSettingsProvider {
        private static final String PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED =
        private static final String PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED =
                DeviceConfig.NAMESPACE_PRIVACY + "/"
                DeviceConfig.NAMESPACE_PRIVACY + "/"