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

Commit 40522200 authored by Benedict Wong's avatar Benedict Wong
Browse files

Only use SIM certificates for determining Carrier Provisioning package

This change closes a loophole potentially introduced during the
migration of carrier config packages to CarrierPrivilegesTracker, where
any carrier privileged application could be marked as a carrier
provisioning service, which would potentially allow chaining of
certificates and associated privileges infinitely.

Bug: 267809568
Test: atest CarrierPrivilegesTrackerTest
Change-Id: I16a80428c378a3c555722ca0349e4047d84abe10
Merged-In: I16a80428c378a3c555722ca0349e4047d84abe10
(cherry picked from commit 5f2cc3b8)
parent 4e92361e
Loading
Loading
Loading
Loading
+32 −16
Original line number Diff line number Diff line
@@ -108,6 +108,10 @@ public class CarrierPrivilegesTracker extends Handler {
    private static final String SHA_1 = "SHA-1";
    private static final String SHA_256 = "SHA-256";

    private static final int PACKAGE_NOT_PRIVILEGED = 0;
    private static final int PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG = 1;
    private static final int PACKAGE_PRIVILEGED_FROM_SIM = 2;

    // TODO(b/232273884): Turn feature on when find solution to handle the inter-carriers switching
    /**
     * Time delay to clear UICC rules after UICC is gone.
@@ -757,23 +761,35 @@ public class CarrierPrivilegesTracker extends Handler {

    @NonNull
    private PrivilegedPackageInfo getCurrentPrivilegedPackagesForAllUsers() {
        Set<String> carrierServiceEligiblePackages = new ArraySet<>();
        Set<String> privilegedPackageNames = new ArraySet<>();
        Set<Integer> privilegedUids = new ArraySet<>();
        for (Map.Entry<String, Set<String>> e : mInstalledPackageCerts.entrySet()) {
            if (isPackagePrivileged(e.getKey(), e.getValue())) {
            final int priv = getPackagePrivilegedStatus(e.getKey(), e.getValue());
            switch (priv) {
                case PACKAGE_PRIVILEGED_FROM_SIM:
                    carrierServiceEligiblePackages.add(e.getKey());
                    // fallthrough
                case PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG:
                    privilegedPackageNames.add(e.getKey());
                privilegedUids.addAll(getUidsForPackage(e.getKey(), /* invalidateCache= */ false));
                    privilegedUids.addAll(
                            getUidsForPackage(e.getKey(), /* invalidateCache= */ false));
            }
        }
        return new PrivilegedPackageInfo(privilegedPackageNames, privilegedUids,
                getCarrierService(privilegedPackageNames));

        return new PrivilegedPackageInfo(
                privilegedPackageNames,
                privilegedUids,
                getCarrierService(carrierServiceEligiblePackages));
    }

    /**
     * Returns true iff there is an overlap between the provided certificate hashes and the
     * certificate hashes stored in mTestOverrideRules, mCarrierConfigRules and mUiccRules.
     * Returns the privilege status of the provided package.
     *
     * <p>Returned privilege status depends on whether a package matches the certificates from
     * carrier config, from test overrides or from certificates stored on the SIM.
     */
    private boolean isPackagePrivileged(@NonNull String pkgName, @NonNull Set<String> certs) {
    private int getPackagePrivilegedStatus(@NonNull String pkgName, @NonNull Set<String> certs) {
        // Double-nested for loops, but each collection should contain at most 2 elements in nearly
        // every case.
        // TODO(b/184382310) find a way to speed this up
@@ -782,23 +798,23 @@ public class CarrierPrivilegesTracker extends Handler {
            if (mTestOverrideRules != null) {
                for (UiccAccessRule rule : mTestOverrideRules) {
                    if (rule.matches(cert, pkgName)) {
                        return true;
                        return PACKAGE_PRIVILEGED_FROM_SIM;
                    }
                }
            } else {
                for (UiccAccessRule rule : mCarrierConfigRules) {
                for (UiccAccessRule rule : mUiccRules) {
                    if (rule.matches(cert, pkgName)) {
                        return true;
                        return PACKAGE_PRIVILEGED_FROM_SIM;
                    }
                }
                for (UiccAccessRule rule : mUiccRules) {
                for (UiccAccessRule rule : mCarrierConfigRules) {
                    if (rule.matches(cert, pkgName)) {
                        return true;
                        return PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG;
                    }
                }
            }
        }
        return false;
        return PACKAGE_NOT_PRIVILEGED;
    }

    @NonNull
@@ -1067,13 +1083,13 @@ public class CarrierPrivilegesTracker extends Handler {
    }

    @NonNull
    private Pair<String, Integer> getCarrierService(@NonNull Set<String> privilegedPackageNames) {
    private Pair<String, Integer> getCarrierService(@NonNull Set<String> simPrivilegedPackages) {
        List<ResolveInfo> carrierServiceResolveInfos = mPackageManager.queryIntentServices(
                new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), /* flags= */ 0);
        String carrierServicePackageName = null;
        for (ResolveInfo resolveInfo : carrierServiceResolveInfos) {
            String packageName = getPackageName(resolveInfo);
            if (privilegedPackageNames.contains(packageName)) {
            if (simPrivilegedPackages.contains(packageName)) {
                carrierServicePackageName = packageName;
                break;
            }
+20 −13
Original line number Diff line number Diff line
@@ -889,7 +889,7 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    @Test
    public void testPackageDisabledAndThenEnabled() throws Exception {
        // Start with certs and packages installed
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1)));
        setupSimLoadedRules(ruleWithHashOnly(getHash(CERT_1)));
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
@@ -1032,9 +1032,12 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    }

    @Test
    public void testGetCarrierService_haveCarrierServiceWithCarrierPrivileges() throws Exception {
        // Only packages with CERT_1 have carrier privileges
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1)));
    public void testGetCarrierService_haveCarrierServiceWithSimCarrierPrivileges()
            throws Exception {
        // Package 1 has SIM loaded rules, making it eligible for carrier service bindings
        setupSimLoadedRules(ruleWithHashOnly(getHash(CERT_1)));
        // Package 2 has only carrier-config based rules, which is insufficient for carrier services
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_2)));
        // Setup all odd packages privileged, even packages not
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
@@ -1061,7 +1064,6 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        assertEquals(PACKAGE_1, carrierServicePackageName);
        assertEquals(UID_1, carrierServiceUid);


        reset(mPackageManager);
        // Get CS again
        carrierServicePackageName = mCarrierPrivilegesTracker.getCarrierServicePackageName();
@@ -1072,27 +1074,32 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        verify(mPackageManager, never()).queryIntentServices(any(), anyInt());
        assertEquals(PACKAGE_1, carrierServicePackageName);
        assertEquals(UID_1, carrierServiceUid);

    }

    @Test
    public void testGetCarrierService_haveCarrierServiceWithNoCarrierPrivileges() throws Exception {
        // Only packages with CERT_1 have carrier privileges
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1)));
    public void testGetCarrierService_haveCarrierServiceWithoutSimCarrierPrivileges()
            throws Exception {
        // Package 1 has no carrier privileges, package 2 has carrier-config based privileges, but
        // no matching certificate on the SIM.
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_2)));
        // Setup all odd packages privileged, even packages not
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2),
                new PackageCertInfo(PACKAGE_3, CERT_1, USER_1, UID_1));
        // One declared CarrierService which has no carrier privileges
        ResolveInfo noPrivilegeService = new ResolveInfoBuilder().setService(PACKAGE_2).build();
        // Two declared CarrierService, only PACKAGE_1 has carrier privileges
        ResolveInfo service1 = new ResolveInfoBuilder().setService(PACKAGE_1).build();
        ResolveInfo service2 = new ResolveInfoBuilder().setService(PACKAGE_2).build();
        // Use doReturn instead of when/thenReturn which has NPE with unknown reason
        doReturn(List.of(noPrivilegeService)).when(
                mPackageManager).queryIntentServices(any(), anyInt());
        doReturn(List.of(service1, service2))
                .when(mPackageManager)
                .queryIntentServices(any(), anyInt());
        when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
        when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
        when(mPackageManager.getPackageUid(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);

        // Verify that neither carrier service (no privileges, or carrier-config based privileges)
        // are accepted.
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
        String carrierServicePackageName = mCarrierPrivilegesTracker.getCarrierServicePackageName();
        int carrierServiceUid = mCarrierPrivilegesTracker.getCarrierServicePackageUid();