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

Commit 276cd075 authored by Dario Freni's avatar Dario Freni
Browse files

Verify apex files on staged sessions.

Contact apexservice to submit the staged session, which will return the
result of the verification.

Bug: 118865310
Test: m apex_e2e_tests; Verified with an app that the broadcasts are
sent properly. I tried submitting an apk disguised as an apex and
verification failed, and also tried the successful case.
Change-Id: I8e47541d19c066d6b4945427d4e6a77f40c28f5a
parent 0b4d5db4
Loading
Loading
Loading
Loading
+46 −18
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.pm;

import android.annotation.NonNull;
import android.apex.ApexInfo;
import android.apex.ApexInfoList;
import android.apex.IApexService;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
@@ -127,28 +128,55 @@ public class StagingManager {
        return false;
    }

    void commitSession(@NonNull PackageInstallerSession sessionInfo) {
        updateStoredSession(sessionInfo);
    private static boolean submitSessionToApexService(int sessionId, ApexInfoList apexInfoList) {
        final IApexService apex = IApexService.Stub.asInterface(
                ServiceManager.getService("apexservice"));
        boolean success;
        try {
            success = apex.submitStagedSession(sessionId, apexInfoList);
        } catch (RemoteException re) {
            Slog.e(TAG, "Unable to contact apexservice", re);
            return false;
        }
        return success;
    }

    void preRebootVerification(@NonNull PackageInstallerSession session) {
        boolean success = true;
        if ((session.params.installFlags & PackageManager.INSTALL_APEX) != 0) {

        mBgHandler.post(() -> {
            sessionInfo.setStagedSessionReady();
            final ApexInfoList apexInfoList = new ApexInfoList();

            SessionInfo session = sessionInfo.generateInfo(false);
            // For APEXes, we validate the signature here before we write the package to the
            // staging directory. For APKs, the signature verification will be done by the package
            // manager at the point at which it applies the staged install.
            if (!submitSessionToApexService(session.sessionId, apexInfoList)) {
                success = false;
            } else {
                // For APEXes, we validate the signature here before we mark the session as ready,
                // so we fail the session early if there is a signature mismatch. For APKs, the
                // signature verification will be done by the package manager at the point at which
                // it applies the staged install.
                //
                // TODO: Decide whether we want to fail fast by detecting signature mismatches right
                // away.
            if ((sessionInfo.params.installFlags & PackageManager.INSTALL_APEX) != 0) {
                if (!validateApexSignatureLocked(session.resolvedBaseCodePath,
                        session.appPackageName)) {
                    sessionInfo.setStagedSessionFailed(SessionInfo.VERIFICATION_FAILED);
                for (ApexInfo apexPackage : apexInfoList.apexInfos) {
                    if (!validateApexSignatureLocked(apexPackage.packagePath,
                            apexPackage.packageName)) {
                        success = false;
                        break;
                    }
                }
            }
        }
        if (success) {
            session.setStagedSessionReady();
        } else {
            session.setStagedSessionFailed(SessionInfo.VERIFICATION_FAILED);
        }
        mPm.sendSessionUpdatedBroadcast(session.generateInfo(false), session.userId);
    }

            mPm.sendSessionUpdatedBroadcast(sessionInfo.generateInfo(false), sessionInfo.userId);
        });
    void commitSession(@NonNull PackageInstallerSession session) {
        updateStoredSession(session);
        mBgHandler.post(() -> preRebootVerification(session));
    }

    void createSession(@NonNull PackageInstallerSession sessionInfo) {