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

Commit b22e916a authored by Patrick Baumann's avatar Patrick Baumann
Browse files

Fixes incorrect app id cleanup on failure

This change makes sure that we track the creation of app IDs so that we
only delete when we actually created something new.

Fixes: 130209119
Test: atest SharedUserIdTest
Change-Id: I03e38b4dc16e9ccccd7d10bfe78bcaedc317d0cb
parent d81cd262
Loading
Loading
Loading
Loading
+28 −18
Original line number Diff line number Diff line
@@ -9329,6 +9329,7 @@ public class PackageManagerService extends IPackageManager.Stub
                | SCAN_UPDATE_SIGNATURE, currentTime, user);
        if (scanResult.success) {
            synchronized (mPackages) {
                boolean appIdCreated = false;
                try {
                    final String pkgName = scanResult.pkgSetting.name;
                    final Map<String, ReconciledPackage> reconcileResult = reconcilePackagesLocked(
@@ -9341,11 +9342,12 @@ public class PackageManagerService extends IPackageManager.Stub
                                    Collections.singletonMap(pkgName,
                                            getSharedLibLatestVersionSetting(scanResult))),
                            mSettings.mKeySetManagerService);
                    prepareScanResultLocked(scanResult);
                    commitReconciledScanResultLocked(
                            reconcileResult.get(pkgName));
                    appIdCreated = optimisticallyRegisterAppId(scanResult);
                    commitReconciledScanResultLocked(reconcileResult.get(pkgName));
                } catch (PackageManagerException e) {
                    unprepareScanResultLocked(scanResult);
                    if (appIdCreated) {
                        cleanUpAppIdCreation(scanResult);
                    }
                    throw e;
                }
            }
@@ -10832,29 +10834,34 @@ public class PackageManagerService extends IPackageManager.Stub
    }
    /** Prepares the system to commit a {@link ScanResult} in a way that will not fail. */
    private void prepareScanResultLocked(@NonNull ScanResult result)
    /**
     * Prepares the system to commit a {@link ScanResult} in a way that will not fail by registering
     * the app ID required for reconcile.
     * @return {@code true} if a new app ID was registered and will need to be cleaned up on
     *         failure.
     */
    private boolean optimisticallyRegisterAppId(@NonNull ScanResult result)
            throws PackageManagerException {
        if (!result.existingSettingCopied) {
            // THROWS: when we can't allocate a user id. add call to check if there's
            // enough space to ensure we won't throw; otherwise, don't modify state
            mSettings.registerAppIdLPw(result.pkgSetting);
            return mSettings.registerAppIdLPw(result.pkgSetting);
        }
        return false;
    }
    /**
     * Reverts any changes to the system that were made by
     * {@link #prepareScanResultLocked(ScanResult)}
     * Reverts any app ID creation that were made by
     * {@link #optimisticallyRegisterAppId(ScanResult)}. Note: this is only necessary if the
     * referenced method returned true.
     */
    private void unprepareScanResultLocked(@NonNull ScanResult result) {
        if (!result.existingSettingCopied) {
    private void cleanUpAppIdCreation(@NonNull ScanResult result) {
        // iff we've acquired an app ID for a new package setting, remove it so that it can be
        // acquired by another request.
        if (result.pkgSetting.appId > 0) {
            mSettings.removeAppIdLPw(result.pkgSetting.appId);
        }
    }
    }
    /**
     * Commits the package scan and modifies system state.
@@ -16696,6 +16703,7 @@ public class PackageManagerService extends IPackageManager.Stub
        final Map<String, VersionInfo> versionInfos = new ArrayMap<>(requests.size());
        final Map<String, PackageSetting> lastStaticSharedLibSettings =
                new ArrayMap<>(requests.size());
        final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
        boolean success = false;
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
@@ -16735,7 +16743,7 @@ public class PackageManagerService extends IPackageManager.Stub
                                            + " in multi-package install request.");
                            return;
                        }
                        prepareScanResultLocked(result);
                        createdAppId.put(packageName, optimisticallyRegisterAppId(result));
                        versionInfos.put(result.pkgSetting.pkg.packageName,
                                getSettingsVersionForPackage(result.pkgSetting.pkg));
                        if (result.staticSharedLibraryInfo != null) {
@@ -16792,7 +16800,9 @@ public class PackageManagerService extends IPackageManager.Stub
        } finally {
            if (!success) {
                for (ScanResult result : preparedScans.values()) {
                    unprepareScanResultLocked(result);
                    if (createdAppId.getOrDefault(result.request.pkg.packageName, false)) {
                        cleanUpAppIdCreation(result);
                    }
                }
            }
            for (PrepareResult result : prepareResults.values()) {
+8 −2
Original line number Diff line number Diff line
@@ -810,15 +810,20 @@ public final class Settings {

    /**
     * Registers a user ID with the system. Potentially allocates a new user ID.
     * @return {@code true} if a new app ID was created in the process. {@code false} can be
     *         returned in the case that a shared user ID already exists or the explicit app ID is
     *         already registered.
     * @throws PackageManagerException If a user ID could not be allocated.
     */
    void registerAppIdLPw(PackageSetting p) throws PackageManagerException {
    boolean registerAppIdLPw(PackageSetting p) throws PackageManagerException {
        final boolean createdNew;
        if (p.appId == 0) {
            // Assign new user ID
            p.appId = acquireAndRegisterNewAppIdLPw(p);
            createdNew = true;
        } else {
            // Add new setting to list of user IDs
            registerExistingAppIdLPw(p.appId, p, p.name);
            createdNew = registerExistingAppIdLPw(p.appId, p, p.name);
        }
        if (p.appId < 0) {
            PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -826,6 +831,7 @@ public final class Settings {
            throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                    "Package " + p.name + " could not be assigned a valid UID");
        }
        return createdNew;
    }

    /**