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()); |