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

Commit 8c1ee3bb authored by Malcolm Chen's avatar Malcolm Chen
Browse files

Don't allow reading IMSI of one active sub if only has carrier privilege

on the other.

Bug: 136123413
Test: unittest
Change-Id: I24983ac66092c3571cc0f35ead49259587576492
parent 6c8f450d
Loading
Loading
Loading
Loading
+98 −24
Original line number Diff line number Diff line
@@ -31,8 +31,11 @@ import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ServiceManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
@@ -49,14 +52,15 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

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

@SmallTest
public class TelephonyPermissionsTest {

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

@@ -69,6 +73,8 @@ public class TelephonyPermissionsTest {
    @Mock
    private ITelephony mMockTelephony;
    @Mock
    private IBinder mMockTelephonyBinder;
    @Mock
    private PackageManager mMockPackageManager;
    @Mock
    private ApplicationInfo mMockApplicationInfo;
@@ -100,10 +106,13 @@ public class TelephonyPermissionsTest {
                AppOpsManager.MODE_ERRORED);
        when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID)))
                .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,
                PID, UID)).thenReturn(PackageManager.PERMISSION_DENIED);
        when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID),
                eq(UID))).thenReturn(false);
        setTelephonyMockAsService();
    }

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

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

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

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

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

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

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

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

    @Test
@@ -364,14 +373,79 @@ public class TelephonyPermissionsTest {
        // case.
        setupMocksForDeviceIdentifiersErrorPath();
        try {
            TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
                    SUB_ID, PID, UID, null, MSG);
            TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
                    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");
        } catch (SecurityException e) {
            // 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 {
        private static final String PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED =
                DeviceConfig.NAMESPACE_PRIVACY + "/"