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

Commit c0e306bf authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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

parents 312e0697 37dd1ba0
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
@@ -351,7 +351,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 {
@@ -667,11 +677,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();
@@ -696,7 +701,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();
@@ -730,18 +737,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.
@@ -762,11 +784,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()) {
@@ -778,8 +795,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);
            }

@@ -1539,6 +1562,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());