Add a one-off shell command to disable verification

The package verification is provided by Play whose behavior
is not controlled by framework. For CTS, such verification
is unnecessary because we have dedicated GTS for that. We add
a shell command to disable verification when installing packages
in CTS to avoid unexpected behavior caused by external entities
to improve stableness of tests.

There is no reduction in safety:
1. This feature is only available to apps with shell
   permissions. Such apps can already skip verification
   by changing a settings value.
2. The command works in a one-off manner. This command
   will only allow the next created session to bypass verification.
   This command requires a uid which prevents accidentally granting
   the ability to other apps.

Bug: 264963480
Test: atest CtsStagedInstallHostTestCases
Change-Id: I26e60837139007e98e99f44aeb0eb13716d91523
This commit is contained in:
JW Wang
2023-01-10 14:48:47 +08:00
parent 18bd9c45cf
commit 0bfcc6562b
4 changed files with 51 additions and 3 deletions

View File

@@ -65,6 +65,8 @@ interface IPackageInstaller {
void bypassNextAllowedApexUpdateCheck(boolean value);
void disableVerificationForUid(int uid);
void setAllowUnlimitedSilentUpdates(String installerPackageName);
void setSilentUpdatesThrottleTime(long throttleTimeInSeconds);
void checkInstallConstraints(String installerPackageName, in List<String> packageNames,

View File

@@ -184,6 +184,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
private volatile boolean mOkToSendBroadcasts = false;
private volatile boolean mBypassNextStagedInstallerCheck = false;
private volatile boolean mBypassNextAllowedApexUpdateCheck = false;
private volatile int mDisableVerificationForUid = INVALID_UID;
/**
* File storing persisted {@link #mSessions} metadata.
@@ -712,7 +713,16 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
params.installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
}
if ((params.installFlags & ADB_DEV_MODE) != ADB_DEV_MODE) {
if (mDisableVerificationForUid != INVALID_UID) {
if (callingUid == mDisableVerificationForUid) {
params.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
} else {
// Clear the flag if current calling uid doesn't match the requested uid.
params.installFlags &= ~PackageManager.INSTALL_DISABLE_VERIFICATION;
}
// Reset the field as this is a one-off request.
mDisableVerificationForUid = INVALID_UID;
} else if ((params.installFlags & ADB_DEV_MODE) != ADB_DEV_MODE) {
// Only tools under specific conditions (test app installed through ADB, and
// verification disabled flag specified) can disable verification.
params.installFlags &= ~PackageManager.INSTALL_DISABLE_VERIFICATION;
@@ -1367,6 +1377,14 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
mBypassNextAllowedApexUpdateCheck = value;
}
@Override
public void disableVerificationForUid(int uid) {
if (!isCalledBySystemOrShell(Binder.getCallingUid())) {
throw new SecurityException("Operation not allowed for caller");
}
mDisableVerificationForUid = uid;
}
/**
* Set an installer to allow for the unlimited silent updates.
*/

View File

@@ -342,6 +342,8 @@ class PackageManagerShellCommand extends ShellCommand {
return runBypassStagedInstallerCheck();
case "bypass-allowed-apex-update-check":
return runBypassAllowedApexUpdateCheck();
case "disable-verification-for-uid":
return runDisableVerificationForUid();
case "set-silent-updates-policy":
return runSetSilentUpdatesPolicy();
default: {
@@ -514,6 +516,29 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
private int runDisableVerificationForUid() {
final PrintWriter pw = getOutPrintWriter();
try {
int uid = Integer.parseInt(getNextArgRequired());
var amInternal = LocalServices.getService(ActivityManagerInternal.class);
boolean isInstrumented =
amInternal.getInstrumentationSourceUid(uid) != Process.INVALID_UID;
if (isInstrumented) {
mInterface.getPackageInstaller().disableVerificationForUid(uid);
return 0;
} else {
// Only available for testing
pw.println("Error: must specify an instrumented uid");
return -1;
}
} catch (RemoteException e) {
pw.println("Failure ["
+ e.getClass().getName() + " - "
+ e.getMessage() + "]");
return -1;
}
}
private int uninstallSystemUpdates(String packageName) {
final PrintWriter pw = getOutPrintWriter();
boolean failedUninstalls = false;

View File

@@ -680,12 +680,15 @@ final class VerifyingSession {
}
final int installerUid = mVerificationInfo == null ? -1 : mVerificationInfo.mInstallerUid;
final boolean requestedDisableVerification =
(mInstallFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0;
// Check if installing from ADB
if ((mInstallFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
boolean requestedDisableVerification =
(mInstallFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0;
return isAdbVerificationEnabled(pkgInfoLite, userId, requestedDisableVerification);
} else if (requestedDisableVerification) {
// Skip verification for non-adb installs
return false;
}
// only when not installed from ADB, skip verification for instant apps when