Merge "Sealed sessions need to be destroyed or validated" into oc-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c0e306bf03
@@ -319,9 +319,15 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
|
|||||||
if (type == START_TAG) {
|
if (type == START_TAG) {
|
||||||
final String tag = in.getName();
|
final String tag = in.getName();
|
||||||
if (PackageInstallerSession.TAG_SESSION.equals(tag)) {
|
if (PackageInstallerSession.TAG_SESSION.equals(tag)) {
|
||||||
final PackageInstallerSession session = PackageInstallerSession.
|
final PackageInstallerSession session;
|
||||||
readFromXml(in, mInternalCallback, mContext, mPm,
|
try {
|
||||||
mInstallThread.getLooper(), mSessionsDir);
|
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 long age = System.currentTimeMillis() - session.createdMillis;
|
||||||
|
|
||||||
final boolean valid;
|
final boolean valid;
|
||||||
|
|||||||
@@ -351,7 +351,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mPrepared = prepared;
|
mPrepared = prepared;
|
||||||
mSealed = sealed;
|
|
||||||
|
if (sealed) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
try {
|
||||||
|
sealAndValidateLocked();
|
||||||
|
} catch (PackageManagerException | IOException e) {
|
||||||
|
destroyInternal();
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final long identity = Binder.clearCallingIdentity();
|
final long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -667,11 +677,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
|
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
|
||||||
Preconditions.checkNotNull(statusReceiver);
|
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;
|
final boolean wasSealed;
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
assertCallerIsOwnerOrRootLocked();
|
assertCallerIsOwnerOrRootLocked();
|
||||||
@@ -696,7 +701,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
wasSealed = mSealed;
|
wasSealed = mSealed;
|
||||||
if (!mSealed) {
|
if (!mSealed) {
|
||||||
try {
|
try {
|
||||||
sealAndValidateLocked(installedPkgInfo);
|
sealAndValidateLocked();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
} catch (PackageManagerException e) {
|
} catch (PackageManagerException e) {
|
||||||
// Do now throw an exception here to stay compatible with O and older
|
// Do now throw an exception here to stay compatible with O and older
|
||||||
destroyInternal();
|
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.
|
* <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)
|
private void sealAndValidateLocked() throws PackageManagerException, IOException {
|
||||||
throws PackageManagerException {
|
|
||||||
assertNoWriteFileTransfersOpenLocked();
|
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;
|
mSealed = true;
|
||||||
|
|
||||||
// Verify that stage looks sane with respect to existing application.
|
// Verify that stage looks sane with respect to existing application.
|
||||||
// This currently only ensures packageName, versionCode, and certificate
|
// This currently only ensures packageName, versionCode, and certificate
|
||||||
// consistency.
|
// 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
|
// Read transfers from the original owner stay open, but as the session's data
|
||||||
// cannot be modified anymore, there is no leak of information.
|
// 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");
|
+ "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
|
// 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.
|
// allowed. The parameters can be read via PackageInstaller.SessionInfo.
|
||||||
if (!params.areHiddenOptionsSet()) {
|
if (!params.areHiddenOptionsSet()) {
|
||||||
@@ -778,8 +795,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
assertPreparedAndNotSealedLocked("transfer");
|
assertPreparedAndNotSealedLocked("transfer");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sealAndValidateLocked(installedPkgInfo);
|
sealAndValidateLocked();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
} catch (PackageManagerException 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);
|
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 {
|
void write(@NonNull XmlSerializer out, @NonNull File sessionsDir) throws IOException {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
if (mDestroyed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
out.startTag(null, TAG_SESSION);
|
out.startTag(null, TAG_SESSION);
|
||||||
|
|
||||||
writeIntAttribute(out, ATTR_SESSION_ID, sessionId);
|
writeIntAttribute(out, ATTR_SESSION_ID, sessionId);
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ public class PackageManagerException extends Exception {
|
|||||||
this.error = error;
|
this.error = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PackageManagerException(Throwable e) {
|
||||||
|
super(e);
|
||||||
|
this.error = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
public static PackageManagerException from(PackageParserException e)
|
public static PackageManagerException from(PackageParserException e)
|
||||||
throws PackageManagerException {
|
throws PackageManagerException {
|
||||||
throw new PackageManagerException(e.error, e.getMessage(), e.getCause());
|
throw new PackageManagerException(e.error, e.getMessage(), e.getCause());
|
||||||
|
|||||||
Reference in New Issue
Block a user