Merge "Verify INSTALL_PACKAGES permissions when adding installer package" into rvc-dev

This commit is contained in:
Winson Chiu
2020-06-03 18:34:30 +00:00
committed by Android (Google) Code Review

View File

@@ -148,6 +148,8 @@ import android.app.ResourcesManager;
import android.app.admin.IDevicePolicyManager; import android.app.admin.IDevicePolicyManager;
import android.app.admin.SecurityLog; import android.app.admin.SecurityLog;
import android.app.backup.IBackupManager; import android.app.backup.IBackupManager;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.ContentResolver; import android.content.ContentResolver;
@@ -639,6 +641,19 @@ public class PackageManagerService extends IPackageManager.Stub
*/ */
private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW; private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
/**
* Adding an installer package name to a package that does not have one set requires the
* INSTALL_PACKAGES permission.
*
* If the caller targets R, this will throw a SecurityException. Otherwise the request will
* fail silently. In both cases, and regardless of whether this change is enabled, the
* installer package will remain unchanged.
*/
@ChangeId
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
private static final long THROW_EXCEPTION_ON_REQUIRE_INSTALL_PACKAGES_TO_ADD_INSTALLER_PACKAGE =
150857253;
public static final String PLATFORM_PACKAGE_NAME = "android"; public static final String PLATFORM_PACKAGE_NAME = "android";
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
@@ -14172,19 +14187,38 @@ public class PackageManagerService extends IPackageManager.Stub
// be signed with the same cert as the caller. // be signed with the same cert as the caller.
String targetInstallerPackageName = String targetInstallerPackageName =
targetPackageSetting.installSource.installerPackageName; targetPackageSetting.installSource.installerPackageName;
if (targetInstallerPackageName != null) { PackageSetting targetInstallerPkgSetting = targetInstallerPackageName == null ? null :
PackageSetting setting = mSettings.mPackages.get( mSettings.mPackages.get(targetInstallerPackageName);
targetInstallerPackageName);
// If the currently set package isn't valid, then it's always if (targetInstallerPkgSetting != null) {
// okay to change it.
if (setting != null) {
if (compareSignatures(callerSignature, if (compareSignatures(callerSignature,
setting.signatures.mSigningDetails.signatures) targetInstallerPkgSetting.signatures.mSigningDetails.signatures)
!= PackageManager.SIGNATURE_MATCH) { != PackageManager.SIGNATURE_MATCH) {
throw new SecurityException( throw new SecurityException(
"Caller does not have same cert as old installer package " "Caller does not have same cert as old installer package "
+ targetInstallerPackageName); + targetInstallerPackageName);
} }
} else if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)
!= PackageManager.PERMISSION_GRANTED) {
// This is probably an attempt to exploit vulnerability b/150857253 of taking
// privileged installer permissions when the installer has been uninstalled or
// was never set.
EventLog.writeEvent(0x534e4554, "150857253", callingUid, "");
long binderToken = Binder.clearCallingIdentity();
try {
if (mInjector.getCompatibility().isChangeEnabledByUid(
THROW_EXCEPTION_ON_REQUIRE_INSTALL_PACKAGES_TO_ADD_INSTALLER_PACKAGE,
callingUid)) {
throw new SecurityException("Neither user " + callingUid
+ " nor current process has "
+ Manifest.permission.INSTALL_PACKAGES);
} else {
// If change disabled, fail silently for backwards compatibility
return;
}
} finally {
Binder.restoreCallingIdentity(binderToken);
} }
} }