diff options
3 files changed, 58 insertions, 20 deletions
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index c3b93b428cb5..1fa37b91b8e8 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -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; diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index fddbd670d1a2..810c399e9f8d 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -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. -        validateInstallLocked(pkgInfo); +        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); diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java index 0e3f17360e7b..0793b091265e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerException.java +++ b/services/core/java/com/android/server/pm/PackageManagerException.java @@ -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());  |