summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/provider/Settings.java6
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--services/core/java/com/android/server/pm/DomainVerificationConnection.java2
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java57
-rw-r--r--services/core/java/com/android/server/pm/PackageHandler.java90
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java18
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java42
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java9
-rw-r--r--services/core/java/com/android/server/pm/VerificationParams.java383
-rw-r--r--services/core/java/com/android/server/pm/VerificationUtils.java31
10 files changed, 386 insertions, 253 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ad6d85f2712b..7228b5ab7feb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11558,6 +11558,12 @@ public final class Settings {
@Readable
public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
+ /** Timeout for package verification during streaming installations.
+ * @hide */
+ @Readable
+ public static final String PACKAGE_STREAMING_VERIFIER_TIMEOUT =
+ "streaming_verifier_timeout";
+
/** Timeout for app integrity verification.
* @hide */
@Readable
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index fb8ffbd476a6..0dfad172ec5b 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -396,6 +396,7 @@ public class SettingsBackupTest {
Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE,
Settings.Global.OVERLAY_DISPLAY_DEVICES,
Settings.Global.PAC_CHANGE_DELAY,
+ Settings.Global.PACKAGE_STREAMING_VERIFIER_TIMEOUT,
Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE,
diff --git a/services/core/java/com/android/server/pm/DomainVerificationConnection.java b/services/core/java/com/android/server/pm/DomainVerificationConnection.java
index 4ddf2ff51dd1..d24435e12593 100644
--- a/services/core/java/com/android/server/pm/DomainVerificationConnection.java
+++ b/services/core/java/com/android/server/pm/DomainVerificationConnection.java
@@ -76,7 +76,7 @@ public final class DomainVerificationConnection implements DomainVerificationSer
@Override
public long getPowerSaveTempWhitelistAppDuration() {
- return VerificationUtils.getVerificationTimeout(mPm.mContext);
+ return VerificationUtils.getDefaultVerificationTimeout(mPm.mContext);
}
@Override
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 24052532dfa3..c8594eba69a6 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -56,7 +56,6 @@ import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
-import static com.android.server.pm.PackageManagerService.DEBUG_VERIFY;
import static com.android.server.pm.PackageManagerService.EMPTY_INT_ARRAY;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.PackageManagerService.POST_INSTALL;
@@ -90,7 +89,6 @@ import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
-import android.app.AppOpsManager;
import android.app.ApplicationPackageManager;
import android.app.backup.IBackupManager;
import android.content.ContentResolver;
@@ -190,11 +188,6 @@ import java.util.Set;
import java.util.concurrent.ExecutorService;
final class InstallPackageHelper {
- /**
- * Whether verification is enabled by default.
- */
- private static final boolean DEFAULT_VERIFY_ENABLE = true;
-
private final PackageManagerService mPm;
private final AppDataHelper mAppDataHelper;
private final PackageManagerServiceInjector mInjector;
@@ -2835,56 +2828,6 @@ final class InstallPackageHelper {
}
}
- /**
- * Check whether or not package verification has been enabled.
- *
- * @return true if verification should be performed
- */
- boolean isVerificationEnabled(PackageInfoLite pkgInfoLite, int userId, int installFlags,
- int installerUid) {
- if (!DEFAULT_VERIFY_ENABLE) {
- return false;
- }
-
- // Check if installing from ADB
- if ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
- if (mPm.isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS)) {
- return true;
- }
- // Check if the developer wants to skip verification for ADB installs
- if ((installFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0) {
- synchronized (mPm.mLock) {
- if (mPm.mSettings.getPackageLPr(pkgInfoLite.packageName) == null) {
- // Always verify fresh install
- return true;
- }
- }
- // Only skip when apk is debuggable
- return !pkgInfoLite.debuggable;
- }
- return android.provider.Settings.Global.getInt(mPm.mContext.getContentResolver(),
- android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0;
- }
-
- // only when not installed from ADB, skip verification for instant apps when
- // the installer and verifier are the same.
- if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
- if (mPm.mInstantAppInstallerActivity != null
- && mPm.mInstantAppInstallerActivity.packageName.equals(
- mPm.mRequiredVerifierPackage)) {
- try {
- mPm.mInjector.getSystemService(AppOpsManager.class)
- .checkPackage(installerUid, mPm.mRequiredVerifierPackage);
- if (DEBUG_VERIFY) {
- Slog.i(TAG, "disable verification for instant app");
- }
- return false;
- } catch (SecurityException ignore) { }
- }
- }
- return true;
- }
-
public void sendPendingBroadcasts() {
String[] packages;
ArrayList<String>[] components;
diff --git a/services/core/java/com/android/server/pm/PackageHandler.java b/services/core/java/com/android/server/pm/PackageHandler.java
index 1a9c7a994fea..217bc2397f29 100644
--- a/services/core/java/com/android/server/pm/PackageHandler.java
+++ b/services/core/java/com/android/server/pm/PackageHandler.java
@@ -22,7 +22,6 @@ import static com.android.server.pm.PackageManagerService.CHECK_PENDING_INTEGRIT
import static com.android.server.pm.PackageManagerService.CHECK_PENDING_VERIFICATION;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEFAULT_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD;
-import static com.android.server.pm.PackageManagerService.DEFAULT_VERIFICATION_RESPONSE;
import static com.android.server.pm.PackageManagerService.DEFERRED_NO_KILL_INSTALL_OBSERVER;
import static com.android.server.pm.PackageManagerService.DEFERRED_NO_KILL_POST_DELETE;
import static com.android.server.pm.PackageManagerService.DOMAIN_VERIFICATION;
@@ -47,14 +46,12 @@ import android.content.pm.InstantAppRequest;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.net.Uri;
-import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.Trace;
import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
@@ -154,45 +151,50 @@ final class PackageHandler extends Handler {
} break;
case CHECK_PENDING_VERIFICATION: {
final int verificationId = msg.arg1;
+ final boolean streaming = msg.arg2 != 0;
final PackageVerificationState state = mPm.mPendingVerification.get(verificationId);
- if ((state != null) && !state.isVerificationComplete()
- && !state.timeoutExtended()) {
- final VerificationParams params = state.getVerificationParams();
- final Uri originUri = Uri.fromFile(params.mOriginInfo.mResolvedFile);
+ if (state == null || state.isVerificationComplete()) {
+ // Not found or complete.
+ break;
+ }
+ if (!streaming && state.timeoutExtended()) {
+ // Timeout extended.
+ break;
+ }
- String errorMsg = "Verification timed out for " + originUri;
- Slog.i(TAG, errorMsg);
+ final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
- final UserHandle user = params.getUser();
- if (getDefaultVerificationResponse(user)
- == PackageManager.VERIFICATION_ALLOW) {
- Slog.i(TAG, "Continuing with installation of " + originUri);
- state.setVerifierResponse(Binder.getCallingUid(),
- PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
- VerificationUtils.broadcastPackageVerified(verificationId, originUri,
- PackageManager.VERIFICATION_ALLOW, null, params.mDataLoaderType,
- user, mPm.mContext);
- } else {
- VerificationUtils.broadcastPackageVerified(verificationId, originUri,
- PackageManager.VERIFICATION_REJECT, null,
- params.mDataLoaderType, user, mPm.mContext);
- params.setReturnCode(
- PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, errorMsg);
- state.setVerifierResponse(Binder.getCallingUid(),
- PackageManager.VERIFICATION_REJECT);
- }
+ final VerificationParams params = state.getVerificationParams();
+ final Uri originUri = Uri.fromFile(params.mOriginInfo.mResolvedFile);
- if (state.areAllVerificationsComplete()) {
- mPm.mPendingVerification.remove(verificationId);
- }
+ String errorMsg = "Verification timed out for " + originUri;
+ Slog.i(TAG, errorMsg);
- Trace.asyncTraceEnd(
- TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
-
- params.handleVerificationFinished();
+ final UserHandle user = params.getUser();
+ if (response.code != PackageManager.VERIFICATION_REJECT) {
+ Slog.i(TAG, "Continuing with installation of " + originUri);
+ state.setVerifierResponse(response.callerUid, response.code);
+ VerificationUtils.broadcastPackageVerified(verificationId, originUri,
+ PackageManager.VERIFICATION_ALLOW, null, params.mDataLoaderType,
+ user, mPm.mContext);
+ } else {
+ VerificationUtils.broadcastPackageVerified(verificationId, originUri,
+ PackageManager.VERIFICATION_REJECT, null,
+ params.mDataLoaderType, user, mPm.mContext);
+ params.setReturnCode(
+ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, errorMsg);
+ state.setVerifierResponse(response.callerUid, response.code);
+ }
+ if (state.areAllVerificationsComplete()) {
+ mPm.mPendingVerification.remove(verificationId);
}
+
+ Trace.asyncTraceEnd(
+ TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
+
+ params.handleVerificationFinished();
break;
}
case CHECK_PENDING_INTEGRITY_VERIFICATION: {
@@ -241,9 +243,12 @@ final class PackageHandler extends Handler {
+ " It may be invalid or overridden by integrity verification");
break;
}
+ if (state.isVerificationComplete()) {
+ Slog.w(TAG, "Verification with id " + verificationId + " already complete.");
+ break;
+ }
final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
-
state.setVerifierResponse(response.callerUid, response.code);
if (state.isVerificationComplete()) {
@@ -397,21 +402,6 @@ final class PackageHandler extends Handler {
}
/**
- * Get the default verification agent response code.
- *
- * @return default verification response code
- */
- private int getDefaultVerificationResponse(UserHandle user) {
- if (mPm.mUserManager.hasUserRestriction(UserManager.ENSURE_VERIFY_APPS,
- user.getIdentifier())) {
- return PackageManager.VERIFICATION_REJECT;
- }
- return android.provider.Settings.Global.getInt(mPm.mContext.getContentResolver(),
- android.provider.Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
- DEFAULT_VERIFICATION_RESPONSE);
- }
-
- /**
* Get the default integrity verification response code.
*/
private int getDefaultIntegrityVerificationResponse() {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 356d6c93ae84..f4740448b8a9 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -916,10 +916,26 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
}
+ private boolean checkOpenSessionAccess(final PackageInstallerSession session) {
+ if (session == null) {
+ return false;
+ }
+ if (isCallingUidOwner(session)) {
+ return true;
+ }
+ // Package verifiers have access to openSession for sealed sessions.
+ if (session.isSealed() && mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)
+ == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ return false;
+ }
+
private IPackageInstallerSession openSessionInternal(int sessionId) throws IOException {
synchronized (mSessions) {
final PackageInstallerSession session = mSessions.get(sessionId);
- if (session == null || !isCallingUidOwner(session)) {
+ if (!checkOpenSessionAccess(session)) {
throw new SecurityException("Caller has no access to session " + sessionId);
}
session.open();
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 28204eadd394..a94985c226ea 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1303,22 +1303,30 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@Override
public String[] getNames() {
- assertCallerIsOwnerOrRoot();
+ assertCallerIsOwnerRootOrVerifier();
synchronized (mLock) {
- assertPreparedAndNotCommittedOrDestroyedLocked("getNames");
+ assertPreparedAndNotDestroyedLocked("getNames");
+ if (!mCommitted.get()) {
+ return getNamesLocked();
+ } else {
+ return getStageDirContentsLocked();
+ }
+ }
+ }
- return getNamesLocked();
+ @GuardedBy("mLock")
+ private String[] getStageDirContentsLocked() {
+ String[] result = stageDir.list();
+ if (result == null) {
+ result = EmptyArray.STRING;
}
+ return result;
}
@GuardedBy("mLock")
private String[] getNamesLocked() {
if (!isDataLoaderInstallation()) {
- String[] result = stageDir.list();
- if (result == null) {
- result = EmptyArray.STRING;
- }
- return result;
+ return getStageDirContentsLocked();
}
InstallationFile[] files = getInstallationFilesLocked();
@@ -1403,6 +1411,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public void requestChecksums(@NonNull String name, @Checksum.TypeMask int optional,
@Checksum.TypeMask int required, @Nullable List trustedInstallers,
@NonNull IOnChecksumsReadyListener onChecksumsReadyListener) {
+ assertCallerIsOwnerRootOrVerifier();
final File file = new File(stageDir, name);
final String installerPackageName = getInstallSource().initiatingPackageName;
try {
@@ -1670,6 +1679,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
/**
+ * Check if the caller is the owner of this session or a verifier.
+ * Otherwise throw a {@link SecurityException}.
+ */
+ private void assertCallerIsOwnerRootOrVerifier() {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid == Process.ROOT_UID || callingUid == mInstallerUid) {
+ return;
+ }
+ if (isSealed() && mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ throw new SecurityException("Session does not belong to uid " + callingUid);
+ }
+
+ /**
* Check if the caller is the owner of this session. Otherwise throw a
* {@link SecurityException}.
*/
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7ceae61f8726..8f6ac0744574 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1289,9 +1289,6 @@ public class PackageManagerService extends IPackageManager.Stub
if (!file.exists()) {
throw new FileNotFoundException(file.getAbsolutePath());
}
- if (TextUtils.isEmpty(installerPackageName)) {
- throw new FileNotFoundException(file.getAbsolutePath());
- }
final Executor executor = mInjector.getBackgroundExecutor();
final Handler handler = mInjector.getBackgroundHandler();
@@ -5223,10 +5220,11 @@ public class PackageManagerService extends IPackageManager.Stub
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
"Only package verification agents can verify applications");
+ final int callingUid = Binder.getCallingUid();
final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
final PackageVerificationResponse response = new PackageVerificationResponse(
- verificationCode, Binder.getCallingUid());
+ verificationCode, callingUid);
msg.arg1 = id;
msg.obj = response;
mHandler.sendMessage(msg);
@@ -5238,11 +5236,12 @@ public class PackageManagerService extends IPackageManager.Stub
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
"Only package verification agents can extend verification timeouts");
+ final int callingUid = Binder.getCallingUid();
mHandler.post(() -> {
final PackageVerificationState state = mPendingVerification.get(id);
final PackageVerificationResponse response = new PackageVerificationResponse(
- verificationCodeAtTimeout, Binder.getCallingUid());
+ verificationCodeAtTimeout, callingUid);
long delay = millisecondsToDelay;
if (delay > PackageManager.MAXIMUM_VERIFICATION_TIMEOUT) {
diff --git a/services/core/java/com/android/server/pm/VerificationParams.java b/services/core/java/com/android/server/pm/VerificationParams.java
index 6d681399460e..e1442dd080f5 100644
--- a/services/core/java/com/android/server/pm/VerificationParams.java
+++ b/services/core/java/com/android/server/pm/VerificationParams.java
@@ -30,6 +30,7 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static com.android.server.pm.PackageManagerService.CHECK_PENDING_INTEGRITY_VERIFICATION;
import static com.android.server.pm.PackageManagerService.CHECK_PENDING_VERIFICATION;
import static com.android.server.pm.PackageManagerService.DEBUG_VERIFY;
+import static com.android.server.pm.PackageManagerService.DEFAULT_VERIFICATION_RESPONSE;
import static com.android.server.pm.PackageManagerService.ENABLE_ROLLBACK_TIMEOUT;
import static com.android.server.pm.PackageManagerService.PACKAGE_MIME_TYPE;
import static com.android.server.pm.PackageManagerService.TAG;
@@ -59,10 +60,13 @@ import android.os.Bundle;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
@@ -76,6 +80,11 @@ import java.util.Set;
final class VerificationParams extends HandlerParams {
/**
+ * Whether verification is enabled by default.
+ */
+ private static final boolean DEFAULT_VERIFY_ENABLE = true;
+
+ /**
* Whether integrity verification is enabled by default.
*/
private static final boolean DEFAULT_INTEGRITY_VERIFY_ENABLE = true;
@@ -333,157 +342,273 @@ final class VerificationParams extends HandlerParams {
if (verifierUser == UserHandle.ALL) {
verifierUser = UserHandle.SYSTEM;
}
+ final int verifierUserId = verifierUser.getIdentifier();
+
+ String requiredVerifierPackage = mPm.mRequiredVerifierPackage;
+ boolean requiredVerifierPackageOverridden = false;
+
+ // Allow verifier override for ADB installations which could already be unverified using
+ // PackageManager.INSTALL_DISABLE_VERIFICATION flag.
+ if ((mInstallFlags & PackageManager.INSTALL_FROM_ADB) != 0
+ && (mInstallFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) == 0) {
+ final String adbVerifierOverridePackage = SystemProperties.get(
+ "debug.pm.adb_verifier_override_package", "");
+ // Check if the package installed.
+ if (!TextUtils.isEmpty(adbVerifierOverridePackage)
+ && packageExists(adbVerifierOverridePackage)) {
+ // Pretend we requested to disable verification from command line.
+ boolean requestedDisableVerification = true;
+ // If this returns false then the caller can already skip verification, so we are
+ // not adding a new way to disable verifications.
+ if (!isAdbVerificationEnabled(pkgLite, verifierUserId,
+ requestedDisableVerification)) {
+ requiredVerifierPackage = adbVerifierOverridePackage;
+ requiredVerifierPackageOverridden = true;
+ }
+ }
+ }
/*
* Determine if we have any installed package verifiers. If we
* do, then we'll defer to them to verify the packages.
*/
- final int requiredUid = mPm.mRequiredVerifierPackage == null ? -1
- : mPm.getPackageUid(mPm.mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
- verifierUser.getIdentifier());
+ final int requiredUid = requiredVerifierPackage == null ? -1
+ : mPm.getPackageUid(requiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+ verifierUserId);
verificationState.setRequiredVerifierUid(requiredUid);
- final int installerUid =
- mVerificationInfo == null ? -1 : mVerificationInfo.mInstallerUid;
- final boolean isVerificationEnabled = mInstallPackageHelper.isVerificationEnabled(
- pkgLite, verifierUser.getIdentifier(), mInstallFlags, installerUid);
- final boolean isV4Signed =
- (mSigningDetails.getSignatureSchemeVersion() == SIGNING_BLOCK_V4);
- final boolean isIncrementalInstall =
- (mDataLoaderType == DataLoaderType.INCREMENTAL);
- // NOTE: We purposefully skip verification for only incremental installs when there's
- // a v4 signature block. Otherwise, proceed with verification as usual.
- if (!mOriginInfo.mExisting
- && isVerificationEnabled
- && (!isIncrementalInstall || !isV4Signed)) {
- final Intent verification = new Intent(
- Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
- verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- verification.setDataAndType(Uri.fromFile(new File(mOriginInfo.mResolvedPath)),
- PACKAGE_MIME_TYPE);
- verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Query all live verifiers based on current user state
- final ParceledListSlice<ResolveInfo> receivers = mPm.queryIntentReceivers(verification,
- PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier());
+ final boolean isVerificationEnabled = isVerificationEnabled(pkgLite,
+ verifierUserId);
- if (DEBUG_VERIFY) {
- Slog.d(TAG, "Found " + receivers.getList().size() + " verifiers for intent "
- + verification.toString() + " with " + pkgLite.verifiers.length
- + " optional verifiers");
- }
+ if (mOriginInfo.mExisting || !isVerificationEnabled) {
+ verificationState.setVerifierResponse(requiredUid, PackageManager.VERIFICATION_ALLOW);
+ return;
+ }
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
+ final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+ verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ verification.setDataAndType(Uri.fromFile(new File(mOriginInfo.mResolvedPath)),
+ PACKAGE_MIME_TYPE);
+ verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- verification.putExtra(
- PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, mInstallFlags);
+ // Query all live verifiers based on current user state
+ final ParceledListSlice<ResolveInfo> receivers = mPm.queryIntentReceivers(verification,
+ PACKAGE_MIME_TYPE, 0, verifierUserId);
- verification.putExtra(
- PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME, pkgLite.packageName);
+ if (DEBUG_VERIFY) {
+ Slog.d(TAG, "Found " + receivers.getList().size() + " verifiers for intent "
+ + verification.toString() + " with " + pkgLite.verifiers.length
+ + " optional verifiers");
+ }
- verification.putExtra(
- PackageManager.EXTRA_VERIFICATION_VERSION_CODE, pkgLite.versionCode);
+ verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
- verification.putExtra(
- PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
- pkgLite.getLongVersionCode());
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, mInstallFlags);
- final String baseCodePath = mPackageLite.getBaseApkPath();
- final String[] splitCodePaths = mPackageLite.getSplitApkPaths();
- final String rootHashString =
- PackageManagerServiceUtils.buildVerificationRootHashString(baseCodePath,
- splitCodePaths);
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME, pkgLite.packageName);
- if (rootHashString != null) {
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_ROOT_HASH, rootHashString);
- }
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_VERSION_CODE, pkgLite.versionCode);
- verification.putExtra(PackageInstaller.EXTRA_DATA_LOADER_TYPE, mDataLoaderType);
-
- verification.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
-
- populateInstallerExtras(verification);
-
- final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
- receivers.getList(), verificationState);
-
- DeviceIdleInternal idleController =
- mPm.mInjector.getLocalService(DeviceIdleInternal.class);
- final long idleDuration = VerificationUtils.getVerificationTimeout(mPm.mContext);
- final BroadcastOptions options = BroadcastOptions.makeBasic();
- options.setTemporaryAppAllowlist(idleDuration,
- TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
- REASON_PACKAGE_VERIFIER, "");
-
- /*
- * If any sufficient verifiers were listed in the package
- * manifest, attempt to ask them.
- */
- if (sufficientVerifiers != null) {
- final int n = sufficientVerifiers.size();
- if (n == 0) {
- String errorMsg = "Additional verifiers required, but none installed.";
- Slog.i(TAG, errorMsg);
- setReturnCode(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, errorMsg);
- } else {
- for (int i = 0; i < n; i++) {
- final ComponentName verifierComponent = sufficientVerifiers.get(i);
- idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
- verifierComponent.getPackageName(), idleDuration,
- verifierUser.getIdentifier(), false,
- REASON_PACKAGE_VERIFIER, "package verifier");
-
- final Intent sufficientIntent = new Intent(verification);
- sufficientIntent.setComponent(verifierComponent);
- mPm.mContext.sendBroadcastAsUser(sufficientIntent, verifierUser,
- /* receiverPermission= */ null,
- options.toBundle());
- }
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
+ pkgLite.getLongVersionCode());
+
+ final String baseCodePath = mPackageLite.getBaseApkPath();
+ final String[] splitCodePaths = mPackageLite.getSplitApkPaths();
+ final String rootHashString = PackageManagerServiceUtils.buildVerificationRootHashString(
+ baseCodePath, splitCodePaths);
+
+ if (rootHashString != null) {
+ verification.putExtra(PackageManager.EXTRA_VERIFICATION_ROOT_HASH, rootHashString);
+ }
+
+ verification.putExtra(PackageInstaller.EXTRA_DATA_LOADER_TYPE, mDataLoaderType);
+
+ verification.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
+
+ populateInstallerExtras(verification);
+
+ // Streaming installation timeout schema is enabled only for:
+ // 1. Incremental installs with v4,
+ // 2. If device/policy allow unverified app installs by default.
+ final boolean streaming = (mDataLoaderType == DataLoaderType.INCREMENTAL)
+ && (mSigningDetails.getSignatureSchemeVersion() == SIGNING_BLOCK_V4)
+ && (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW);
+
+ final long verificationTimeout = VerificationUtils.getVerificationTimeout(mPm.mContext,
+ streaming);
+
+ final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
+ receivers.getList(), verificationState);
+
+ DeviceIdleInternal idleController =
+ mPm.mInjector.getLocalService(DeviceIdleInternal.class);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setTemporaryAppAllowlist(verificationTimeout,
+ TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ REASON_PACKAGE_VERIFIER, "");
+
+ /*
+ * If any sufficient verifiers were listed in the package
+ * manifest, attempt to ask them.
+ */
+ if (sufficientVerifiers != null) {
+ final int n = sufficientVerifiers.size();
+ if (n == 0) {
+ String errorMsg = "Additional verifiers required, but none installed.";
+ Slog.i(TAG, errorMsg);
+ setReturnCode(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, errorMsg);
+ } else {
+ for (int i = 0; i < n; i++) {
+ final ComponentName verifierComponent = sufficientVerifiers.get(i);
+ idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
+ verifierComponent.getPackageName(), verificationTimeout,
+ verifierUserId, false,
+ REASON_PACKAGE_VERIFIER, "package verifier");
+
+ final Intent sufficientIntent = new Intent(verification);
+ sufficientIntent.setComponent(verifierComponent);
+ mPm.mContext.sendBroadcastAsUser(sufficientIntent, verifierUser,
+ /* receiverPermission= */ null,
+ options.toBundle());
}
}
+ }
- if (mPm.mRequiredVerifierPackage != null) {
- final ComponentName requiredVerifierComponent = matchComponentForVerifier(
- mPm.mRequiredVerifierPackage, receivers.getList());
- /*
- * Send the intent to the required verification agent,
- * but only start the verification timeout after the
- * target BroadcastReceivers have run.
- */
- verification.setComponent(requiredVerifierComponent);
- idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
- mPm.mRequiredVerifierPackage, idleDuration,
- verifierUser.getIdentifier(), false,
- REASON_PACKAGE_VERIFIER, "package verifier");
- mPm.mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
- android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
- /* appOp= */ AppOpsManager.OP_NONE,
- /* options= */ options.toBundle(),
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final Message msg = mPm.mHandler
- .obtainMessage(CHECK_PENDING_VERIFICATION);
- msg.arg1 = verificationId;
- mPm.mHandler.sendMessageDelayed(msg,
- VerificationUtils.getVerificationTimeout(mPm.mContext));
- }
- }, null, 0, null, null);
-
- Trace.asyncTraceBegin(
- TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
-
- /*
- * We don't want the copy to proceed until verification
- * succeeds.
- */
- mWaitForVerificationToComplete = true;
- }
+ if (requiredVerifierPackage == null) {
+ Slog.e(TAG, "Required verifier is null");
+ return;
+ }
+
+ final int verificationCodeAtTimeout;
+ if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
+ verificationCodeAtTimeout = PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT;
+ } else {
+ verificationCodeAtTimeout = PackageManager.VERIFICATION_REJECT;
+ }
+ final PackageVerificationResponse response = new PackageVerificationResponse(
+ verificationCodeAtTimeout, requiredUid);
+
+ /*
+ * Send the intent to the required verification agent,
+ * but only start the verification timeout after the
+ * target BroadcastReceivers have run.
+ */
+ if (!requiredVerifierPackageOverridden) {
+ final ComponentName requiredVerifierComponent = matchComponentForVerifier(
+ requiredVerifierPackage, receivers.getList());
+ verification.setComponent(requiredVerifierComponent);
} else {
- verificationState.setVerifierResponse(
- requiredUid, PackageManager.VERIFICATION_ALLOW);
+ verification.setPackage(requiredVerifierPackage);
}
+ idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
+ requiredVerifierPackage, verificationTimeout,
+ verifierUserId, false,
+ REASON_PACKAGE_VERIFIER, "package verifier");
+ mPm.mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
+ android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+ /* appOp= */ AppOpsManager.OP_NONE,
+ /* options= */ options.toBundle(),
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final Message msg = mPm.mHandler
+ .obtainMessage(CHECK_PENDING_VERIFICATION);
+ msg.arg1 = verificationId;
+ msg.arg2 = streaming ? 1 : 0;
+ msg.obj = response;
+ mPm.mHandler.sendMessageDelayed(msg, verificationTimeout);
+ }
+ }, null, 0, null, null);
+
+ Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
+
+ /*
+ * We don't want the copy to proceed until verification
+ * succeeds.
+ */
+ mWaitForVerificationToComplete = true;
}
+ /**
+ * Get the default verification agent response code.
+ *
+ * @return default verification response code
+ */
+ int getDefaultVerificationResponse() {
+ if (mPm.mUserManager.hasUserRestriction(UserManager.ENSURE_VERIFY_APPS,
+ getUser().getIdentifier())) {
+ return PackageManager.VERIFICATION_REJECT;
+ }
+ return android.provider.Settings.Global.getInt(mPm.mContext.getContentResolver(),
+ android.provider.Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
+ DEFAULT_VERIFICATION_RESPONSE);
+ }
+
+ private boolean packageExists(String packageName) {
+ synchronized (mPm.mLock) {
+ return mPm.mSettings.getPackageLPr(packageName) != null;
+ }
+ }
+
+ private boolean isAdbVerificationEnabled(PackageInfoLite pkgInfoLite, int userId,
+ boolean requestedDisableVerification) {
+ if (mPm.isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS)) {
+ return true;
+ }
+ // Check if the developer wants to skip verification for ADB installs
+ if (requestedDisableVerification) {
+ if (!packageExists(pkgInfoLite.packageName)) {
+ // Always verify fresh install
+ return true;
+ }
+ // Only skip when apk is debuggable
+ return !pkgInfoLite.debuggable;
+ }
+ return android.provider.Settings.Global.getInt(mPm.mContext.getContentResolver(),
+ android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0;
+ }
+
+ /**
+ * Check whether package verification has been enabled.
+ *
+ * @return true if verification should be performed
+ */
+ private boolean isVerificationEnabled(PackageInfoLite pkgInfoLite, int userId) {
+ if (!DEFAULT_VERIFY_ENABLE) {
+ return false;
+ }
+
+ final int installerUid = mVerificationInfo == null ? -1 : mVerificationInfo.mInstallerUid;
+ final int installFlags = mInstallFlags;
+
+ // Check if installing from ADB
+ if ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
+ boolean requestedDisableVerification =
+ (mInstallFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0;
+ return isAdbVerificationEnabled(pkgInfoLite, userId, requestedDisableVerification);
+ }
+
+ // only when not installed from ADB, skip verification for instant apps when
+ // the installer and verifier are the same.
+ if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
+ if (mPm.mInstantAppInstallerActivity != null
+ && mPm.mInstantAppInstallerActivity.packageName.equals(
+ mPm.mRequiredVerifierPackage)) {
+ try {
+ mPm.mInjector.getSystemService(AppOpsManager.class)
+ .checkPackage(installerUid, mPm.mRequiredVerifierPackage);
+ if (DEBUG_VERIFY) {
+ Slog.i(TAG, "disable verification for instant app");
+ }
+ return false;
+ } catch (SecurityException ignore) { }
+ }
+ }
+ return true;
+ }
private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
diff --git a/services/core/java/com/android/server/pm/VerificationUtils.java b/services/core/java/com/android/server/pm/VerificationUtils.java
index 4392b4720fcb..c132028a4dae 100644
--- a/services/core/java/com/android/server/pm/VerificationUtils.java
+++ b/services/core/java/com/android/server/pm/VerificationUtils.java
@@ -35,12 +35,25 @@ final class VerificationUtils {
private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
/**
- * Get the verification agent timeout. Used for both the APK verifier and the
+ * The default maximum time to wait for the verification agent to return in
+ * milliseconds.
+ */
+ private static final long DEFAULT_STREAMING_VERIFICATION_TIMEOUT = 3 * 1000;
+
+ public static long getVerificationTimeout(Context context, boolean streaming) {
+ if (streaming) {
+ return getDefaultStreamingVerificationTimeout(context);
+ }
+ return getDefaultVerificationTimeout(context);
+ }
+
+ /**
+ * Get the default verification agent timeout. Used for both the APK verifier and the
* intent filter verifier.
*
* @return verification timeout in milliseconds
*/
- public static long getVerificationTimeout(Context context) {
+ public static long getDefaultVerificationTimeout(Context context) {
long timeout = Settings.Global.getLong(context.getContentResolver(),
Settings.Global.PACKAGE_VERIFIER_TIMEOUT, DEFAULT_VERIFICATION_TIMEOUT);
// The setting can be used to increase the timeout but not decrease it, since that is
@@ -48,6 +61,20 @@ final class VerificationUtils {
return Math.max(timeout, DEFAULT_VERIFICATION_TIMEOUT);
}
+ /**
+ * Get the default verification agent timeout for streaming installations.
+ *
+ * @return verification timeout in milliseconds
+ */
+ public static long getDefaultStreamingVerificationTimeout(Context context) {
+ long timeout = Settings.Global.getLong(context.getContentResolver(),
+ Settings.Global.PACKAGE_STREAMING_VERIFIER_TIMEOUT,
+ DEFAULT_STREAMING_VERIFICATION_TIMEOUT);
+ // The setting can be used to increase the timeout but not decrease it, since that is
+ // equivalent to disabling the verifier.
+ return Math.max(timeout, DEFAULT_STREAMING_VERIFICATION_TIMEOUT);
+ }
+
public static void broadcastPackageVerified(int verificationId, Uri packageUri,
int verificationCode, @Nullable String rootHashString, int dataLoaderType,
UserHandle user, Context context) {