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

Commit e68b1275 authored by Jeff Davidson's avatar Jeff Davidson
Browse files

Disable preinstalled carrier apps earlier in boot.

Preinstalled carrier apps start in state DEFAULT (== ENABLED); the
telephony stack marks them as DISABLED_UNTIL_USED during
initialization, and eventually ENABLED once a SIM for that carrier is
inserted.

However, this can cause a race as telephony initialization may happen
after the carrier app is started, while it is still in the DEFAULT
state. In this case, the app is disabled, and though PackageManager
will subsequently kill it, this may lead to a race as the app will
briefly remain running while disabled. In this state, crashes are
likely to occur in the app.

So, make sure we perform the first disable as soon as PackageManager
is ready. This ensures the app is not started until it has been
explicitly enabled.

Bug: 27821069
Change-Id: I771d7dde7880fd98b1df3d011be44164abf402f4
parent b7e26fb1
Loading
Loading
Loading
Loading
+12 −2
Original line number Original line Diff line number Diff line
@@ -232,6 +232,7 @@ import com.android.internal.os.IParcelFileDescriptorFactory;
import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.os.Zygote;
import com.android.internal.telephony.CarrierAppUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FastXmlSerializer;
@@ -2016,6 +2017,10 @@ public class PackageManagerService extends IPackageManager.Stub {
        PackageManagerService m = new PackageManagerService(context, installer,
        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
                factoryTest, onlyCore);
        m.enableSystemUserPackages();
        m.enableSystemUserPackages();
        // Disable any carrier apps. We do this very early in boot to prevent the apps from being
        // disabled after already being started.
        CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m,
                UserHandle.USER_SYSTEM);
        ServiceManager.addService("package", m);
        ServiceManager.addService("package", m);
        return m;
        return m;
    }
    }
@@ -17076,8 +17081,13 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
        }
        }
        PackageSetting pkgSetting;
        PackageSetting pkgSetting;
        final int uid = Binder.getCallingUid();
        final int uid = Binder.getCallingUid();
        final int permission = mContext.checkCallingOrSelfPermission(
        final int permission;
        if (uid == Process.SYSTEM_UID) {
            permission = PackageManager.PERMISSION_GRANTED;
        } else {
            permission = mContext.checkCallingOrSelfPermission(
                    android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
                    android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
        }
        enforceCrossUserPermission(uid, userId,
        enforceCrossUserPermission(uid, userId,
                false /* requireFullPermission */, true /* checkShell */, "set enabled");
                false /* requireFullPermission */, true /* checkShell */, "set enabled");
        final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
        final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
+25 −2
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.internal.telephony;
package com.android.internal.telephony;


import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
@@ -69,10 +70,32 @@ public final class CarrierAppUtils {
                systemCarrierAppsDisabledUntilUsed);
                systemCarrierAppsDisabledUntilUsed);
    }
    }


    /**
     * Like {@link #disableCarrierAppsUntilPrivileged(String, IPackageManager, TelephonyManager,
     * int)}, but assumes that no carrier apps have carrier privileges.
     *
     * This prevents a potential race condition on first boot - since the app's default state is
     * enabled, we will initially disable it when the telephony stack is first initialized as it has
     * not yet read the carrier privilege rules. However, since telephony is initialized later on
     * late in boot, the app being disabled may have already been started in response to certain
     * broadcasts. The app will continue to run (briefly) after being disabled, before the Package
     * Manager can kill it, and this can lead to crashes as the app is in an unexpected state.
     */
    public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
            IPackageManager packageManager, int userId) {
        if (DEBUG) {
            Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
        }
        String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
                com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
        disableCarrierAppsUntilPrivileged(callingPackage, packageManager,
                null /* telephonyManager */, userId, systemCarrierAppsDisabledUntilUsed);
    }

    // Must be public b/c framework unit tests can't access package-private methods.
    // Must be public b/c framework unit tests can't access package-private methods.
    @VisibleForTesting
    @VisibleForTesting
    public static void disableCarrierAppsUntilPrivileged(String callingPackage,
    public static void disableCarrierAppsUntilPrivileged(String callingPackage,
            IPackageManager packageManager, TelephonyManager telephonyManager, int userId,
            IPackageManager packageManager, @Nullable TelephonyManager telephonyManager, int userId,
            String[] systemCarrierAppsDisabledUntilUsed) {
            String[] systemCarrierAppsDisabledUntilUsed) {
        List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(packageManager,
        List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(packageManager,
                userId, systemCarrierAppsDisabledUntilUsed);
                userId, systemCarrierAppsDisabledUntilUsed);
@@ -85,7 +108,7 @@ public final class CarrierAppUtils {
        try {
        try {
            for (ApplicationInfo ai : candidates) {
            for (ApplicationInfo ai : candidates) {
                String packageName = ai.packageName;
                String packageName = ai.packageName;
                boolean hasPrivileges =
                boolean hasPrivileges = telephonyManager != null &&
                        telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
                        telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
                                TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
                                TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;