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

Commit 4466373e authored by Philip P. Moltmann's avatar Philip P. Moltmann Committed by android-build-merger
Browse files

Merge "Sealed sessions need to be destroyed or validated" into oc-mr1-dev am: c0e306bf

am: 2da5f3f0

Change-Id: I83f2668f3f93eb869c97711cdc9fa5c52dbb22d7
parents 3d003521 2da5f3f0
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -319,9 +319,15 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
                if (type == START_TAG) {
                    final String tag = in.getName();
                    if (PackageInstallerSession.TAG_SESSION.equals(tag)) {
                        final PackageInstallerSession session = PackageInstallerSession.
                                readFromXml(in, mInternalCallback, mContext, mPm,
                                        mInstallThread.getLooper(), mSessionsDir);
                        final PackageInstallerSession session;
                        try {
                            session = PackageInstallerSession.readFromXml(in, mInternalCallback,
                                    mContext, mPm, mInstallThread.getLooper(), mSessionsDir);
                        } catch (Exception e) {
                            Slog.e(TAG, "Could not read session", e);
                            continue;
                        }

                        final long age = System.currentTimeMillis() - session.createdMillis;

                        final boolean valid;
+44 −17
Original line number Diff line number Diff line
@@ -357,7 +357,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        }

        mPrepared = prepared;
        mSealed = sealed;

        if (sealed) {
            synchronized (mLock) {
                try {
                    sealAndValidateLocked();
                } catch (PackageManagerException | IOException e) {
                    destroyInternal();
                    throw new IllegalArgumentException(e);
                }
            }
        }

        final long identity = Binder.clearCallingIdentity();
        try {
@@ -673,11 +683,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
        Preconditions.checkNotNull(statusReceiver);

        // Cache package manager data without the lock held
        final PackageInfo installedPkgInfo = mPm.getPackageInfo(
                params.appPackageName, PackageManager.GET_SIGNATURES
                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);

        final boolean wasSealed;
        synchronized (mLock) {
            assertCallerIsOwnerOrRootLocked();
@@ -702,7 +707,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            wasSealed = mSealed;
            if (!mSealed) {
                try {
                    sealAndValidateLocked(installedPkgInfo);
                    sealAndValidateLocked();
                } catch (IOException e) {
                    throw new IllegalArgumentException(e);
                } catch (PackageManagerException e) {
                    // Do now throw an exception here to stay compatible with O and older
                    destroyInternal();
@@ -736,18 +743,33 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
     *
     * <p>The session will be sealed after calling this method even if it failed.
     *
     * @param pkgInfo The package info for {@link #params}.packagename
     * @throws PackageManagerException if the session was sealed but something went wrong. If the
     *                                 session was sealed this is the only possible exception.
     */
    private void sealAndValidateLocked(@Nullable PackageInfo pkgInfo)
            throws PackageManagerException {
    private void sealAndValidateLocked() throws PackageManagerException, IOException {
        assertNoWriteFileTransfersOpenLocked();
        assertPreparedAndNotDestroyedLocked("sealing of session");

        final PackageInfo pkgInfo = mPm.getPackageInfo(
                params.appPackageName, PackageManager.GET_SIGNATURES
                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);

        resolveStageDirLocked();

        mSealed = true;

        // Verify that stage looks sane with respect to existing application.
        // This currently only ensures packageName, versionCode, and certificate
        // consistency.
        try {
            validateInstallLocked(pkgInfo);
        } catch (PackageManagerException e) {
            throw e;
        } catch (Throwable e) {
            // Convert all exceptions into package manager exceptions as only those are handled
            // in the code above
            throw new PackageManagerException(e);
        }

        // Read transfers from the original owner stay open, but as the session's data
        // cannot be modified anymore, there is no leak of information.
@@ -768,11 +790,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                    + "the " + Manifest.permission.INSTALL_PACKAGES + " permission");
        }

        // Cache package manager data without the lock held
        final PackageInfo installedPkgInfo = mPm.getPackageInfo(
                params.appPackageName, PackageManager.GET_SIGNATURES
                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);

        // Only install flags that can be verified by the app the session is transferred to are
        // allowed. The parameters can be read via PackageInstaller.SessionInfo.
        if (!params.areHiddenOptionsSet()) {
@@ -784,8 +801,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            assertPreparedAndNotSealedLocked("transfer");

            try {
                sealAndValidateLocked(installedPkgInfo);
                sealAndValidateLocked();
            } catch (IOException e) {
                throw new IllegalStateException(e);
            } catch (PackageManagerException e) {
                // Session is sealed but could not be verified, we need to destroy it
                destroyInternal();
                dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);

                throw new IllegalArgumentException("Package is not valid", e);
            }

@@ -1545,6 +1568,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
     */
    void write(@NonNull XmlSerializer out, @NonNull File sessionsDir) throws IOException {
        synchronized (mLock) {
            if (mDestroyed) {
                return;
            }

            out.startTag(null, TAG_SESSION);

            writeIntAttribute(out, ATTR_SESSION_ID, sessionId);
+5 −0
Original line number Diff line number Diff line
@@ -40,6 +40,11 @@ public class PackageManagerException extends Exception {
        this.error = error;
    }

    public PackageManagerException(Throwable e) {
        super(e);
        this.error = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
    }

    public static PackageManagerException from(PackageParserException e)
            throws PackageManagerException {
        throw new PackageManagerException(e.error, e.getMessage(), e.getCause());