From 25e26d905530af917717267aff234871ab0e6e7c Mon Sep 17 00:00:00 2001 From: Alex Johnston Date: Mon, 5 Oct 2020 11:01:47 +0000 Subject: [PATCH] Revert "Replace remaining enforceXXX methods" This reverts commit 2cc14d046eacce9816d4e1afba081ad625080fe0. Reason for revert: Factory reset function can not work This was caused by the method getCallerIdentityOptionalAdmin(). When the component name is null and no active admin is found, getCallerIdentity() should be called instead of throwing a security exception. Bug: 170057677 Change-Id: I46f181a5be5bf6cff7be6ea0f8965c4cd7be1f01 --- .../DevicePolicyManagerService.java | 837 +++++++++--------- 1 file changed, 443 insertions(+), 394 deletions(-) diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 09ba6efcfab82..282cee0ea2538 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -2128,10 +2128,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle, boolean parent) { ensureLocked(); - Preconditions.checkCallAuthorization(!parent || isManagedProfile(userHandle), - String.format("You can not call APIs on the parent profile outside a " - + "managed profile, userId = %d", userHandle)); - + if (parent) { + Preconditions.checkCallAuthorization(isManagedProfile(userHandle), String.format( + "You can not call APIs on the parent profile outside a managed profile, " + + "userId = %d", userHandle)); + } ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); if (admin != null && parent) { admin = admin.getParentActiveAdmin(); @@ -2301,9 +2302,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { boolean parent, @Nullable String permission) throws SecurityException { ensureLocked(); - Preconditions.checkCallingUser(!parent - || isManagedProfile(getCallerIdentity().getUserId())); - + if (parent) { + Preconditions.checkCallingUser(isManagedProfile(getCallerIdentity().getUserId())); + } ActiveAdmin admin = getActiveAdminOrCheckPermissionForCallerLocked( who, reqPolicy, permission); return parent ? admin.getParentActiveAdmin() : admin; @@ -3178,10 +3179,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(adminReceiver, "ComponentName is null"); - - Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()), - "Non-shell user attempted to call forceRemoveActiveAdmin"); - + enforceShell("forceRemoveActiveAdmin"); mInjector.binderWithCleanCallingIdentity(() -> { synchronized (getLockObject()) { if (!isAdminTestOnlyLocked(adminReceiver, userHandle)) { @@ -3260,6 +3258,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return (admin != null) && admin.testOnlyAdmin; } + private void enforceShell(String method) { + final int callingUid = mInjector.binderGetCallingUid(); + if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) { + throw new SecurityException("Non-shell user attempted to call " + method); + } + } + @Override public void removeActiveAdmin(ComponentName adminReceiver, int userHandle) { if (!mHasFeature) { @@ -3269,8 +3274,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); - Preconditions.checkState(mUserManager.isUserUnlocked(userHandle), - "User must be running and unlocked"); + enforceUserUnlocked(userHandle); synchronized (getLockObject()) { ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle); @@ -3284,8 +3288,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { adminReceiver); return; } - Preconditions.checkCallAuthorization((admin.getUid() == caller.getUid()) - || hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS)); + if (admin.getUid() != mInjector.binderGetCallingUid()) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_DEVICE_ADMINS, null); + } mInjector.binderWithCleanCallingIdentity(() -> removeActiveAdminLocked(adminReceiver, userHandle)); } @@ -3293,8 +3299,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean isSeparateProfileChallengeAllowed(int userHandle) { - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can query separate challenge support"); + enforceSystemCaller("query separate challenge support"); ComponentName profileOwner = getProfileOwner(userHandle); // Profile challenge is supported on N or newer release. @@ -4066,9 +4071,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); - Preconditions.checkState( - mUserManager.isUserUnlocked(parent ? getProfileParentId(userHandle) : userHandle), - "User must be running and unlocked"); + enforceUserUnlocked(userHandle, parent); synchronized (getLockObject()) { // This API can only be called by an active device admin, @@ -4109,15 +4112,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Preconditions.checkCallAuthorization(isManagedProfile(userHandle), String.format( "can not call APIs refering to the parent profile outside a managed profile, " + "userId = %d", userHandle)); - Preconditions.checkState(mUserManager.isUserUnlocked(getProfileParentId(userHandle)), - "User must be running and unlocked"); synchronized (getLockObject()) { + final int targetUser = getProfileParentId(userHandle); + enforceUserUnlocked(targetUser, false); int credentialOwner = getCredentialOwner(userHandle, false); DevicePolicyData policy = getUserDataUnchecked(credentialOwner); PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(credentialOwner); - return isActivePasswordSufficientForUserLocked(policy.mPasswordValidAtLastCheckpoint, - metrics, getProfileParentId(userHandle), false); + return isActivePasswordSufficientForUserLocked( + policy.mPasswordValidAtLastCheckpoint, metrics, targetUser, false); } } @@ -4133,8 +4136,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Preconditions.checkCallAuthorization(!isManagedProfile(userHandle), String.format( "You can not check password sufficiency for a managed profile, userId = %d", userHandle)); - Preconditions.checkState(mUserManager.isUserUnlocked(userHandle), - "User must be running and unlocked"); + enforceUserUnlocked(userHandle); synchronized (getLockObject()) { PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(userHandle); @@ -4192,22 +4194,24 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override @PasswordComplexity public int getPasswordComplexity(boolean parent) { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkState(mUserManager.isUserUnlocked(caller.getUserId()), - "User must be running and unlocked"); - Preconditions.checkCallAuthorization(!parent || isCallerDeviceOwner(caller.getUid()) - || isCallerProfileOwner(caller.getUid()) || isSystemUid(caller)); - Preconditions.checkCallAuthorization( - hasCallingOrSelfPermission(REQUEST_PASSWORD_COMPLEXITY)); - DevicePolicyEventLogger .createEvent(DevicePolicyEnums.GET_USER_PASSWORD_COMPLEXITY_LEVEL) .setStrings(parent ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT, - mInjector.getPackageManager().getPackagesForUid(caller.getUid())) + mInjector.getPackageManager().getPackagesForUid( + mInjector.binderGetCallingUid())) .write(); + final int callingUserId = mInjector.userHandleGetCallingUserId(); + + if (parent) { + enforceProfileOwnerOrSystemUser(); + } + enforceUserUnlocked(callingUserId); + mContext.enforceCallingOrSelfPermission( + REQUEST_PASSWORD_COMPLEXITY, + "Must have " + REQUEST_PASSWORD_COMPLEXITY + " permission."); synchronized (getLockObject()) { - final int credentialOwner = getCredentialOwner(caller.getUserId(), parent); + final int credentialOwner = getCredentialOwner(callingUserId, parent); PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(credentialOwner); return metrics == null ? PASSWORD_COMPLEXITY_NONE : metrics.determineComplexity(); } @@ -4356,24 +4360,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Slog.w(LOG_TAG, "Cannot reset password when the device has no lock screen"); return false; } + if (password == null) password = ""; + final int callingUid = mInjector.binderGetCallingUid(); + final int userHandle = mInjector.userHandleGetCallingUserId(); - final CallerIdentity caller = getCallerIdentity(); - // As of R, only privileged caller holding RESET_PASSWORD can call resetPassword() to + // As of R, only privlleged caller holding RESET_PASSWORD can call resetPassword() to // set password to an unsecured user. if (hasCallingPermission(permission.RESET_PASSWORD)) { - if (password == null) { - password = ""; - } - return setPasswordPrivileged(password, flags, caller.getUid()); + return setPasswordPrivileged(password, flags, callingUid); } synchronized (getLockObject()) { // If caller has PO (or DO) throw or fail silently depending on its target SDK level. ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked( - null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, caller.getUid()); + null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid); if (admin != null) { - if (getTargetSdk(admin.info.getPackageName(), - caller.getUserId()) < Build.VERSION_CODES.O) { + if (getTargetSdk(admin.info.getPackageName(), userHandle) < Build.VERSION_CODES.O) { Slog.e(LOG_TAG, "DPC can no longer call resetPassword()"); return false; } @@ -4384,7 +4386,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { admin = getActiveAdminForCallerLocked( null, DeviceAdminInfo.USES_POLICY_RESET_PASSWORD, false); if (getTargetSdk(admin.info.getPackageName(), - caller.getUserId()) <= android.os.Build.VERSION_CODES.M) { + userHandle) <= android.os.Build.VERSION_CODES.M) { Slog.e(LOG_TAG, "Device admin can no longer call resetPassword()"); return false; } @@ -4480,9 +4482,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean getDoNotAskCredentialsOnBoot() { - Preconditions.checkCallAuthorization(hasCallingOrSelfPermission( - permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT)); - + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT, null); synchronized (getLockObject()) { DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM); return policyData.mDoNotAskCredentialsOnBoot; @@ -5224,13 +5225,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void choosePrivateKeyAlias(final int uid, final Uri uri, final String alias, final IBinder response) { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization(isSystemUid(caller), - "Only the system can choose private key alias"); + enforceSystemCaller("choose private key alias"); + final UserHandle caller = mInjector.binderGetCallingUserHandle(); // If there is a profile owner, redirect to that; otherwise query the device owner. - ComponentName aliasChooser = getProfileOwner(caller.getUserId()); - if (aliasChooser == null && caller.getUserHandle().isSystem()) { + ComponentName aliasChooser = getProfileOwner(caller.getIdentifier()); + if (aliasChooser == null && caller.isSystem()) { synchronized (getLockObject()) { final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked(); if (deviceOwnerAdmin != null) { @@ -5252,7 +5252,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final ComponentName delegateReceiver; delegateReceiver = resolveDelegateReceiver(DELEGATION_CERT_SELECTION, - DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS, caller.getUserId()); + DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS, caller.getIdentifier()); final boolean isDelegate; if (delegateReceiver != null) { @@ -5264,8 +5264,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } mInjector.binderWithCleanCallingIdentity(() -> { - mContext.sendOrderedBroadcastAsUser(intent, caller.getUserHandle(), null, - new BroadcastReceiver() { + mContext.sendOrderedBroadcastAsUser(intent, caller, null, new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String chosenAlias = getResultData(); @@ -5429,14 +5428,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { String delegatePackage) throws SecurityException { Objects.requireNonNull(delegatePackage, "Delegate package is null"); - final CallerIdentity caller = getCallerIdentity(who, delegatePackage); - Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isDeviceOwner(caller) - || isProfileOwner(caller))) || (caller.hasPackage() && isCallingFromPackage( - delegatePackage, caller.getUid()))); - // Retrieve the user ID of the calling process. + final int callingUid = mInjector.binderGetCallingUid(); + final int userId = UserHandle.getUserId(callingUid); synchronized (getLockObject()) { - final DevicePolicyData policy = getUserData(caller.getUserId()); + // Ensure calling process is device/profile owner. + if (who != null) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + // Or ensure calling process is delegatePackage itself. + } else { + if (!isCallingFromPackage(delegatePackage, callingUid)) { + throw new SecurityException("Caller with uid " + callingUid + " is not " + + delegatePackage); + } + } + final DevicePolicyData policy = getUserData(userId); // Retrieve the scopes assigned to delegatePackage, or null if no scope was given. final List scopes = policy.mDelegationMap.get(delegatePackage); return scopes == null ? Collections.EMPTY_LIST : scopes; @@ -5715,9 +5721,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public String getAlwaysOnVpnPackageForUser(int userHandle) { - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can get always on VPN package for user"); - + enforceSystemCaller("getAlwaysOnVpnPackageForUser"); synchronized (getLockObject()) { ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userHandle); return admin != null ? admin.mAlwaysOnVpnPackage : null; @@ -5738,9 +5742,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean isAlwaysOnVpnLockdownEnabledForUser(int userHandle) { - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can query always on VPN lockdown enabled for user"); - + enforceSystemCaller("isAlwaysOnVpnLockdownEnabledForUser"); synchronized (getLockObject()) { ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userHandle); return admin != null ? admin.mAlwaysOnVpnLockdown : null; @@ -5971,18 +5973,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return null; } - final CallerIdentity caller = getCallerIdentityOptionalAdmin(who); final int frpManagementAgentUid = getFrpManagementAgentUidOrThrow(); final ActiveAdmin admin; synchronized (getLockObject()) { if (who == null) { - Preconditions.checkCallAuthorization(frpManagementAgentUid == caller.getUid() + Preconditions.checkCallAuthorization( + frpManagementAgentUid == mInjector.binderGetCallingUid() || hasCallingPermission(permission.MASTER_CLEAR), "Must be called by the FRP management agent on device"); admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked( UserHandle.getUserId(frpManagementAgentUid)); } else { + final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization( isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)); admin = getProfileOwnerOrDeviceOwnerLocked(caller); @@ -6046,7 +6049,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity())); + + final CallerIdentity caller = getCallerIdentity(); + Preconditions.checkCallAuthorization(isSystemUid(caller)); // Managed Profile password can only be changed when it has a separate challenge. if (!isSeparateProfileChallengeEnabled(userId)) { Preconditions.checkCallAuthorization(!isManagedProfile(userId), String.format("You can " @@ -6566,8 +6571,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); - Preconditions.checkCallAuthorization(!parent - || isProfileOwnerOfOrganizationOwnedDevice(caller)); + if (parent) { + Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)); + } synchronized (getLockObject()) { ActiveAdmin ap = getActiveAdminForCallerLocked(who, @@ -6941,8 +6947,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); - Preconditions.checkCallAuthorization(!parent - || isProfileOwnerOfOrganizationOwnedDevice(caller)); + if (parent) { + Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)); + } final int userHandle = caller.getUserId(); synchronized (getLockObject()) { @@ -7180,14 +7187,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { + " as device owner for user " + userId); return false; } - Objects.requireNonNull(admin, "ComponentName is null"); - Preconditions.checkArgument(isPackageInstalledForUser(admin.getPackageName(), userId), - String.format("Invalid component %s for device owner", admin)); - - final CallerIdentity caller = getCallerIdentity(); + if (admin == null + || !isPackageInstalledForUser(admin.getPackageName(), userId)) { + throw new IllegalArgumentException("Invalid component " + admin + + " for device owner"); + } + final boolean hasIncompatibleAccountsOrNonAdb = + hasIncompatibleAccountsOrNonAdbNoLock(userId, admin); synchronized (getLockObject()) { - enforceCanSetDeviceOwnerLocked(caller, userId); - + enforceCanSetDeviceOwnerLocked(admin, userId, hasIncompatibleAccountsOrNonAdb); final ActiveAdmin activeAdmin = getActiveAdminUncheckedLocked(admin, userId); if (activeAdmin == null || getUserData(userId).mRemovingAdmins.contains(admin)) { @@ -7196,7 +7204,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // Shutting down backup manager service permanently. toggleBackupServiceActive(UserHandle.USER_SYSTEM, /* makeActive= */ false); - if (isAdb(caller)) { + if (isAdb()) { // Log device owner provisioning was started using adb. MetricsLogger.action(mContext, PROVISIONING_ENTRY_POINT_ADB, LOG_TAG_DEVICE_OWNER); DevicePolicyEventLogger @@ -7234,13 +7242,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean hasDeviceOwner() { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isCallerDeviceOwner(caller.getUid()) || canManageUsers(caller)); - + enforceDeviceOwnerOrManageUsers(); return mOwners.hasDeviceOwner(); } + boolean isDeviceOwner(ActiveAdmin admin) { + return isDeviceOwner(admin.info.getComponent(), admin.getUserHandle().getIdentifier()); + } + public boolean isDeviceOwner(ComponentName who, int userId) { synchronized (getLockObject()) { return mOwners.hasDeviceOwner() @@ -7406,20 +7415,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void clearDeviceOwner(String packageName) { Objects.requireNonNull(packageName, "packageName is null"); - - final CallerIdentity caller = getCallerIdentity(packageName); - Preconditions.checkCallAuthorization(isCallingFromPackage(packageName, caller.getUid()), - "Invalid packageName"); - + final int callingUid = mInjector.binderGetCallingUid(); + if (!isCallingFromPackage(packageName, callingUid)) { + throw new SecurityException("Invalid packageName"); + } synchronized (getLockObject()) { final ComponentName deviceOwnerComponent = mOwners.getDeviceOwnerComponent(); - final int deviceOwnerUserId = caller.getUserId(); - Preconditions.checkCallAuthorization(isCallerDeviceOwner(caller.getUid()) - && deviceOwnerComponent.getPackageName().equals(packageName), - "clearDeviceOwner can only be called by the device owner"); - Preconditions.checkState(mUserManager.isUserUnlocked(deviceOwnerUserId), - "User must be running and unlocked"); - + final int deviceOwnerUserId = mOwners.getDeviceOwnerUserId(); + if (!mOwners.hasDeviceOwner() + || !deviceOwnerComponent.getPackageName().equals(packageName) + || (deviceOwnerUserId != UserHandle.getUserId(callingUid))) { + throw new SecurityException( + "clearDeviceOwner can only be called by the device owner"); + } + enforceUserUnlocked(deviceOwnerUserId); DevicePolicyData policy = getUserData(deviceOwnerUserId); if (policy.mPasswordTokenHandle != 0) { mLockPatternUtils.removeEscrowToken(policy.mPasswordTokenHandle, deviceOwnerUserId); @@ -7504,13 +7513,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { + " as profile owner for user " + userHandle); return false; } - Objects.requireNonNull(who, "ComponentName is null"); - Preconditions.checkArgument(isPackageInstalledForUser(who.getPackageName(), userHandle), - String.format("Component %s not installed for userId: %d", who, userHandle)); + if (who == null + || !isPackageInstalledForUser(who.getPackageName(), userHandle)) { + throw new IllegalArgumentException("Component " + who + + " not installed for userId:" + userHandle); + } - final CallerIdentity caller = getCallerIdentity(); + final boolean hasIncompatibleAccountsOrNonAdb = + hasIncompatibleAccountsOrNonAdbNoLock(userHandle, who); synchronized (getLockObject()) { - enforceCanSetProfileOwnerLocked(caller, userHandle); + enforceCanSetProfileOwnerLocked(who, userHandle, hasIncompatibleAccountsOrNonAdb); final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); if (admin == null || getUserData(userHandle).mRemovingAdmins.contains(who)) { @@ -7528,7 +7540,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } - if (isAdb(caller)) { + if (isAdb()) { // Log profile owner provisioning was started using adb. MetricsLogger.action(mContext, PROVISIONING_ENTRY_POINT_ADB, LOG_TAG_PROFILE_OWNER); DevicePolicyEventLogger @@ -7561,47 +7573,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - /** - * The profile owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS - * permission. - * The profile owner can only be set before the user setup phase has completed, - * except for: - * - SYSTEM_UID - * - adb unless hasIncompatibleAccountsOrNonAdb is true. - */ - private void enforceCanSetProfileOwnerLocked(CallerIdentity caller, int userHandle) { - UserInfo info = getUserInfo(userHandle); - Preconditions.checkArgument(info != null, - String.format("Attempted to set profile owner for invalid userId: %d", userHandle)); - Preconditions.checkState(!info.isGuest(), "Cannot set a profile owner on a guest"); - Preconditions.checkState(!mOwners.hasProfileOwner(userHandle), - "Trying to set the profile owner, but profile owner is already set."); - Preconditions.checkState( - !mOwners.hasDeviceOwner() || mOwners.getDeviceOwnerUserId() != userHandle, - "Trying to set the profile owner, but the user already has a device owner."); - - - boolean hasUserSetupCompleted = mIsWatch || hasUserSetupCompleted(userHandle); - if (isAdb(caller)) { - Preconditions.checkState(!hasUserSetupCompleted - || !hasIncompatibleAccountsOrNonAdbNoLock(userHandle, caller), - "Not allowed to set the profile owner because there are already some accounts" - + " on the profile"); - return; - } - Preconditions.checkCallAuthorization( - hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); - if (hasUserSetupCompleted) { - Preconditions.checkState(isSystemUid(caller), - "Cannot set the profile owner on a user which is already set-up"); - if (!mIsWatch) { - Preconditions.checkState(isDefaultSupervisor(caller), - String.format("Unable to set non-default profile owner post-setup %s", - caller.getUserHandle())); - } - } - } - private void toggleBackupServiceActive(int userId, boolean makeActive) { long ident = mInjector.binderClearCallingIdentity(); try { @@ -7628,9 +7599,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(who); final int userId = caller.getUserId(); Preconditions.checkCallingUser(!isManagedProfile(userId)); - Preconditions.checkState(mUserManager.isUserUnlocked(userId), - "User must be running and unlocked"); + enforceUserUnlocked(userId); synchronized (getLockObject()) { // Check if this is the profile owner who is calling final ActiveAdmin admin = @@ -7763,24 +7733,28 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { + userHandle); return; } - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkState(userHandle == mOwners.getDeviceOwnerUserId() - || hasProfileOwner(userHandle) || isManagedProfile(caller.getUserId()), - "Not allowed to change provisioning state unless " - + "a device or profile owner is set."); + + if (userHandle != mOwners.getDeviceOwnerUserId() && !mOwners.hasProfileOwner(userHandle) + && getManagedUserId(userHandle) == -1) { + // No managed device, user or profile, so setting provisioning state makes no sense. + throw new IllegalStateException("Not allowed to change provisioning state unless a " + + "device or profile owner is set."); + } synchronized (getLockObject()) { boolean transitionCheckNeeded = true; // Calling identity/permission checks. - if (isAdb(caller)) { + if (isAdb()) { // ADB shell can only move directly from un-managed to finalized as part of directly // setting profile-owner or device-owner. - Preconditions.checkState(getUserProvisioningState(userHandle) - == DevicePolicyManager.STATE_USER_UNMANAGED - && newState == DevicePolicyManager.STATE_USER_SETUP_FINALIZED, - "Not allowed to change provisioning state unless current provisioning " - + "state is unmanaged, and new state is finalized."); + if (getUserProvisioningState(userHandle) != + DevicePolicyManager.STATE_USER_UNMANAGED + || newState != DevicePolicyManager.STATE_USER_SETUP_FINALIZED) { + throw new IllegalStateException("Not allowed to change provisioning state " + + "unless current provisioning state is unmanaged, and new state is " + + "finalized."); + } transitionCheckNeeded = false; } else { Preconditions.checkCallAuthorization( @@ -8016,7 +7990,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean checkDeviceIdentifierAccess(String packageName, int pid, int uid) { - enforceCallerIdentityMatchesIfNotSystem(packageName, pid, uid); + ensureCallerIdentityMatchesIfNotSystem(packageName, pid, uid); // Verify that the specified packages matches the provided uid. if (!doesPackageMatchUid(packageName, uid)) { @@ -8080,16 +8054,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return true; } - private void enforceCallerIdentityMatchesIfNotSystem(String packageName, int pid, int uid) { + private void ensureCallerIdentityMatchesIfNotSystem(String packageName, int pid, int uid) { // If the caller is not a system app then it should only be able to check its own device // identifier access. + int callingUid = mInjector.binderGetCallingUid(); int callingPid = mInjector.binderGetCallingPid(); - final CallerIdentity caller = getCallerIdentity(); - if (UserHandle.getAppId(caller.getUid()) >= Process.FIRST_APPLICATION_UID - && (caller.getUid() != uid || callingPid != pid)) { - String message = String.format("Calling uid %d, pid %d cannot check device identifier " - + "access for package %s (uid=%d, pid=%d)", - caller.getUid(), callingPid, packageName, uid, pid); + if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID + && (callingUid != uid || callingPid != pid)) { + String message = String.format( + "Calling uid %d, pid %d cannot check device identifier access for package %s " + + "(uid=%d, pid=%d)", callingUid, callingPid, packageName, uid, pid); Log.w(LOG_TAG, message); throw new SecurityException(message); } @@ -8126,19 +8100,84 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } + /** + * The profile owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS + * permission. + * The profile owner can only be set before the user setup phase has completed, + * except for: + * - SYSTEM_UID + * - adb unless hasIncompatibleAccountsOrNonAdb is true. + */ + private void enforceCanSetProfileOwnerLocked(@Nullable ComponentName owner, int userHandle, + boolean hasIncompatibleAccountsOrNonAdb) { + UserInfo info = getUserInfo(userHandle); + if (info == null) { + // User doesn't exist. + throw new IllegalArgumentException( + "Attempted to set profile owner for invalid userId: " + userHandle); + } + if (info.isGuest()) { + throw new IllegalStateException("Cannot set a profile owner on a guest"); + } + if (mOwners.hasProfileOwner(userHandle)) { + throw new IllegalStateException("Trying to set the profile owner, but profile owner " + + "is already set."); + } + if (mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerUserId() == userHandle) { + throw new IllegalStateException("Trying to set the profile owner, but the user " + + "already has a device owner."); + } + if (isAdb()) { + if ((mIsWatch || hasUserSetupCompleted(userHandle)) + && hasIncompatibleAccountsOrNonAdb) { + throw new IllegalStateException("Not allowed to set the profile owner because " + + "there are already some accounts on the profile"); + } + return; + } + Preconditions.checkCallAuthorization( + hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); + + if ((mIsWatch || hasUserSetupCompleted(userHandle))) { + if (!isCallerWithSystemUid()) { + throw new IllegalStateException("Cannot set the profile owner on a user which is " + + "already set-up"); + } + + if (!mIsWatch) { + // Only the default supervision profile owner can be set as profile owner after SUW + final String supervisor = mContext.getResources().getString( + com.android.internal.R.string + .config_defaultSupervisionProfileOwnerComponent); + if (supervisor == null) { + throw new IllegalStateException("Unable to set profile owner post-setup, no" + + "default supervisor profile owner defined"); + } + + final ComponentName supervisorComponent = ComponentName.unflattenFromString( + supervisor); + if (!owner.equals(supervisorComponent)) { + throw new IllegalStateException("Unable to set non-default profile owner" + + " post-setup " + owner); + } + } + } + } + /** * The Device owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS * permission. */ - private void enforceCanSetDeviceOwnerLocked(CallerIdentity caller, int userId) { - if (!isAdb(caller)) { + private void enforceCanSetDeviceOwnerLocked(@Nullable ComponentName owner, + @UserIdInt int userId, + boolean hasIncompatibleAccountsOrNonAdb) { + if (!isAdb()) { Preconditions.checkCallAuthorization( hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); } final int code = checkDeviceOwnerProvisioningPreConditionLocked( - caller.getComponentName(), userId, isAdb(caller), - hasIncompatibleAccountsOrNonAdbNoLock(userId, caller)); + owner, userId, isAdb(), hasIncompatibleAccountsOrNonAdb); if (code != CODE_OK) { throw new IllegalStateException(computeProvisioningErrorString(code, userId)); } @@ -8173,6 +8212,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } + private void enforceUserUnlocked(int userId) { + // Since we're doing this operation on behalf of an app, we only + // want to use the actual "unlocked" state. + Preconditions.checkState(mUserManager.isUserUnlocked(userId), + "User must be running and unlocked"); + } + + private void enforceUserUnlocked(@UserIdInt int userId, boolean parent) { + if (parent) { + enforceUserUnlocked(getProfileParentId(userId)); + } else { + enforceUserUnlocked(userId); + } + } + private boolean canManageUsers(CallerIdentity caller) { return isSystemUid(caller) || isRootUid(caller) || hasCallingOrSelfPermission(permission.MANAGE_USERS); @@ -8205,6 +8259,42 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS); } + private void enforceDeviceOwnerOrManageUsers() { + synchronized (getLockObject()) { + if (getActiveAdminWithPolicyForUidLocked(null, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER, + mInjector.binderGetCallingUid()) != null) { + return; + } + } + Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())); + } + + private void enforceProfileOwnerOrSystemUser() { + synchronized (getLockObject()) { + if (getActiveAdminWithPolicyForUidLocked(null, + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid()) + != null) { + return; + } + } + Preconditions.checkState(isCallerWithSystemUid(), + "Only profile owner, device owner and system may call this method."); + } + + private void enforceProfileOwnerOrFullCrossUsersPermission(CallerIdentity caller, + int userId) { + if (userId == caller.getUserId()) { + synchronized (getLockObject()) { + if (getActiveAdminWithPolicyForUidLocked(null, + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, caller.getUid()) != null) { + // Device Owner/Profile Owner may access the user it runs on. + return; + } + } + } + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId)); + } + private boolean canUserUseLockTaskLocked(int userId) { if (isUserAffiliatedWithDeviceLocked(userId)) { return true; @@ -8228,22 +8318,34 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return true; } + private void enforceCanCallLockTaskLocked(ComponentName who) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + final int userId = mInjector.userHandleGetCallingUserId(); + if (!canUserUseLockTaskLocked(userId)) { + throw new SecurityException("User " + userId + " is not allowed to use lock task"); + } + } + private void ensureCallerPackage(@Nullable String packageName) { - final CallerIdentity caller = getCallerIdentity(); if (packageName == null) { - Preconditions.checkCallAuthorization(isSystemUid(caller), - "Only the system can omit package name"); + enforceSystemCaller("omit package name"); } else { + final int callingUid = mInjector.binderGetCallingUid(); + final int userId = mInjector.userHandleGetCallingUserId(); try { final ApplicationInfo ai = mIPackageManager.getApplicationInfo( - packageName, 0, caller.getUserId()); - Preconditions.checkState(ai.uid == caller.getUid(), "Unmatching package name"); + packageName, 0, userId); + Preconditions.checkState(ai.uid == callingUid, "Unmatching package name"); } catch (RemoteException e) { // Shouldn't happen } } } + private boolean isCallerWithSystemUid() { + return UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID); + } + private boolean isSystemUid(CallerIdentity caller) { return UserHandle.isSameApp(caller.getUid(), Process.SYSTEM_UID); } @@ -8431,9 +8533,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(admin); Preconditions.checkCallAuthorization(isDeviceOwner(caller) || (parent && isProfileOwnerOfOrganizationOwnedDevice(caller))); - mInjector.binderWithCleanCallingIdentity(() -> Preconditions.checkArgument(!parent - || isSystemPackage(packageName, getProfileParentId(caller.getUserId())), - "The provided package is not a system package")); + if (parent) { + mInjector.binderWithCleanCallingIdentity(() -> enforcePackageIsSystemPackage( + packageName, getProfileParentId(mInjector.userHandleGetCallingUserId()))); + } mInjector.binderWithCleanCallingIdentity(() -> SmsApplication.setDefaultApplication(packageName, mContext)); @@ -8459,7 +8562,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean isCallerApplicationRestrictionsManagingPackage(String callerPackage) { - return isCallerDelegate(callerPackage, getCallerIdentity().getUid(), + return isCallerDelegate(callerPackage, mInjector.binderGetCallingUid(), DELEGATION_APP_RESTRICTIONS); } @@ -8574,9 +8677,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public ComponentName getRestrictionsProvider(int userHandle) { - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can query the permission provider"); - + enforceSystemCaller("query the permission provider"); synchronized (getLockObject()) { DevicePolicyData userData = getUserData(userHandle); return userData != null ? userData.mRestrictionsProvider : null; @@ -8844,9 +8945,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } Objects.requireNonNull(who, "ComponentName is null"); Preconditions.checkStringNotEmpty(packageName, "packageName is null"); - - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can query if an accessibility service is disabled by admin"); + enforceSystemCaller("query if an accessibility service is disabled by admin"); synchronized (getLockObject()) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); @@ -8966,9 +9065,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } Objects.requireNonNull(who, "ComponentName is null"); Preconditions.checkStringNotEmpty(packageName, "packageName is null"); - - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can query if an input method is disabled by admin"); + enforceSystemCaller("query if an input method is disabled by admin"); synchronized (getLockObject()) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); @@ -9025,10 +9122,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return true; } - Preconditions.checkStringNotEmpty(packageName, "packageName is null or empty"); - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can query if a notification listener service is permitted"); + Preconditions.checkStringNotEmpty(packageName, "packageName is null or empty"); + enforceSystemCaller("query if a notification listener service is permitted"); synchronized (getLockObject()) { ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId); @@ -9041,6 +9137,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } + private void enforceSystemCaller(String action) { + if (!isCallerWithSystemUid()) { + throw new SecurityException("Only the system can " + action); + } + } + private void maybeSendAdminEnabledBroadcastLocked(int userHandle) { DevicePolicyData policyData = getUserData(userHandle); if (policyData.mAdminBroadcastPending) { @@ -9070,14 +9172,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { ComponentName profileOwner, PersistableBundle adminExtras, int flags) { Objects.requireNonNull(admin, "admin is null"); Objects.requireNonNull(profileOwner, "profileOwner is null"); - Preconditions.checkArgument(admin.getPackageName().equals(profileOwner.getPackageName()), - String.format("profileOwner %s and admin %s are not in the same package", - profileOwner, admin)); - - final CallerIdentity caller = getCallerIdentity(admin); - Preconditions.checkCallAuthorization(caller.getUserHandle().isSystem(), - "createAndManageUser was called from non-system user"); - + if (!admin.getPackageName().equals(profileOwner.getPackageName())) { + throw new IllegalArgumentException("profileOwner " + profileOwner + " and admin " + + admin + " are not in the same package"); + } + // Only allow the system user to use this method + if (!mInjector.binderGetCallingUserHandle().isSystem()) { + throw new SecurityException("createAndManageUser was called from non-system user"); + } final boolean ephemeral = (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0; final boolean demo = (flags & DevicePolicyManager.MAKE_USER_DEMO) != 0 && UserManager.isDeviceInDemoMode(mContext); @@ -9087,12 +9189,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // Create user. UserHandle user = null; synchronized (getLockObject()) { - Preconditions.checkCallAuthorization(isDeviceOwner(caller)); + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + final int callingUid = mInjector.binderGetCallingUid(); final long id = mInjector.binderClearCallingIdentity(); try { - targetSdkVersion = mInjector.getPackageManagerInternal() - .getUidTargetSdkVersion(caller.getUid()); + targetSdkVersion = mInjector.getPackageManagerInternal().getUidTargetSdkVersion( + callingUid); // Return detail error code for checks inside // UserManagerService.createUserInternalUnchecked. @@ -9620,8 +9723,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // API cannot be used to leak if certain non-system package exists in the person // profile. mInjector.binderWithCleanCallingIdentity(() -> - Preconditions.checkArgument(isSystemPackage(packageName, userId), - "The provided package is not a system package")); + enforcePackageIsSystemPackage(packageName, userId)); } result = mInjector.binderWithCleanCallingIdentity(() -> mIPackageManager .setApplicationHiddenSettingAsUser(packageName, hidden, userId)); @@ -9652,8 +9754,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { && isManagedProfile(caller.getUserId())); // Ensure the package provided is a system package. mInjector.binderWithCleanCallingIdentity(() -> - Preconditions.checkArgument(isSystemPackage(packageName, userId), - "The provided package is not a system package")); + enforcePackageIsSystemPackage(packageName, userId)); } return mInjector.binderWithCleanCallingIdentity( @@ -9661,12 +9762,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private boolean isSystemPackage(String packageName, int userId) + private void enforcePackageIsSystemPackage(String packageName, int userId) throws RemoteException { + boolean isSystem; try { - return isSystemApp(mIPackageManager, packageName, userId); + isSystem = isSystemApp(mIPackageManager, packageName, userId); } catch (IllegalArgumentException e) { - return false; + isSystem = false; + } + if (!isSystem) { + throw new IllegalArgumentException("The provided package is not a system package"); } } @@ -10215,12 +10320,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(who, "ComponentName is null"); Objects.requireNonNull(packages, "packages is null"); - final CallerIdentity caller = getCallerIdentity(who); synchronized (getLockObject()) { - Preconditions.checkCallAuthorization((isDeviceOwner(caller) || isProfileOwner(caller)) - && canUserUseLockTaskLocked(caller.getUserId()), - String.format("User %d is not allowed to use lock task", caller.getUserId())); - setLockTaskPackagesLocked(caller.getUserId(), new ArrayList<>(Arrays.asList(packages))); + enforceCanCallLockTaskLocked(who); + final int userHandle = mInjector.userHandleGetCallingUserId(); + setLockTaskPackagesLocked(userHandle, new ArrayList<>(Arrays.asList(packages))); } } @@ -10237,12 +10340,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { public String[] getLockTaskPackages(ComponentName who) { Objects.requireNonNull(who, "ComponentName is null"); - final CallerIdentity caller = getCallerIdentity(who); + final int userHandle = mInjector.binderGetCallingUserHandle().getIdentifier(); synchronized (getLockObject()) { - Preconditions.checkCallAuthorization((isDeviceOwner(caller) || isProfileOwner(caller)) - && canUserUseLockTaskLocked(caller.getUserId()), - String.format("User %d is not allowed to use lock task", caller.getUserId())); - final List packages = getUserData(caller.getUserId()).mLockTaskPackages; + enforceCanCallLockTaskLocked(who); + final List packages = getUserData(userHandle).mLockTaskPackages; return packages.toArray(new String[packages.size()]); } } @@ -10258,6 +10359,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setLockTaskFeatures(ComponentName who, int flags) { Objects.requireNonNull(who, "ComponentName is null"); + // Throw if Overview is used without Home. boolean hasHome = (flags & LOCK_TASK_FEATURE_HOME) != 0; boolean hasOverview = (flags & LOCK_TASK_FEATURE_OVERVIEW) != 0; @@ -10267,12 +10369,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Preconditions.checkArgument(hasHome || !hasNotification, "Cannot use LOCK_TASK_FEATURE_NOTIFICATIONS without LOCK_TASK_FEATURE_HOME"); - final CallerIdentity caller = getCallerIdentity(who); + final int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (getLockObject()) { - Preconditions.checkCallAuthorization((isDeviceOwner(caller) || isProfileOwner(caller)) - && canUserUseLockTaskLocked(caller.getUserId()), - String.format("User %d is not allowed to use lock task", caller.getUserId())); - setLockTaskFeaturesLocked(caller.getUserId(), flags); + enforceCanCallLockTaskLocked(who); + setLockTaskFeaturesLocked(userHandle, flags); } } @@ -10286,13 +10386,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getLockTaskFeatures(ComponentName who) { Objects.requireNonNull(who, "ComponentName is null"); - - final CallerIdentity caller = getCallerIdentity(who); + final int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (getLockObject()) { - Preconditions.checkCallAuthorization((isDeviceOwner(caller) || isProfileOwner(caller)) - && canUserUseLockTaskLocked(caller.getUserId()), - String.format("User %d is not allowed to use lock task", caller.getUserId())); - return getUserData(caller.getUserId()).mLockTaskFeatures; + enforceCanCallLockTaskLocked(who); + return getUserData(userHandle).mLockTaskFeatures; } } @@ -10323,9 +10420,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) { - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can notify lock task mode changed"); - + enforceSystemCaller("call notifyLockTaskModeChanged"); synchronized (getLockObject()) { final DevicePolicyData policy = getUserData(userHandle); @@ -11299,13 +11394,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public Intent createAdminSupportIntent(String restriction) { Objects.requireNonNull(restriction); - - final CallerIdentity caller = getCallerIdentity(); + final int uid = mInjector.binderGetCallingUid(); + final int userId = UserHandle.getUserId(uid); Intent intent = null; if (DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction) || DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) { synchronized (getLockObject()) { - final DevicePolicyData policy = getUserData(caller.getUserId()); + final DevicePolicyData policy = getUserData(userId); final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { final ActiveAdmin admin = policy.mAdminList.get(i); @@ -11313,8 +11408,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) || (admin.disableScreenCapture && DevicePolicyManager .POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction))) { - intent = createShowAdminSupportIntent(admin.info.getComponent(), - caller.getUserId()); + intent = createShowAdminSupportIntent(admin.info.getComponent(), userId); break; } } @@ -11331,8 +11425,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } else { // if valid, |restriction| can only be a user restriction - intent = mLocalService.createUserRestrictionSupportIntent( - caller.getUserId(), restriction); + intent = mLocalService.createUserRestrictionSupportIntent(userId, restriction); } if (intent != null) { intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, restriction); @@ -11465,9 +11558,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void clearSystemUpdatePolicyFreezePeriodRecord() { - Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()), - "Non-shell user attempted to call clearSystemUpdatePolicyFreezePeriodRecord"); - + enforceShell("clearSystemUpdatePolicyFreezePeriodRecord"); synchronized (getLockObject()) { // Print out current record to help diagnosed CTS failures Slog.i(LOG_TAG, "Clear freeze period record: " @@ -11479,8 +11570,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } /** - * Checks if the caller of the method is the device owner app. This method should only be called - * if not componentName is available. + * Checks if the caller of the method is the device owner app. * * @param callerUid UID of the caller. * @return true if the caller is the device owner app @@ -11496,47 +11586,26 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } final String deviceOwnerPackageName = mOwners.getDeviceOwnerComponent() .getPackageName(); - try { - String[] pkgs = mInjector.getIPackageManager().getPackagesForUid(callerUid); - if (pkgs != null) { + try { + String[] pkgs = mInjector.getIPackageManager().getPackagesForUid(callerUid); for (String pkg : pkgs) { if (deviceOwnerPackageName.equals(pkg)) { return true; } } + } catch (RemoteException e) { + return false; } - } catch (RemoteException e) { - return false; - } - } - return false; - } - - /** - * Checks if the caller of the method is the profile owner. This method should only be called - * if not componentName is available. - * - * @param callerUid UID of the caller. - * @return true if the caller is the profile owner - */ - private boolean isCallerProfileOwner(int callerUid) { - final int userId = UserHandle.getUserId(callerUid); - for (ActiveAdmin admin : getUserData(userId).mAdminList) { - if (admin.getUid() == callerUid && isProfileOwner(admin.info.getComponent(), userId)) { - return true; - } } return false; } @Override public void notifyPendingSystemUpdate(@Nullable SystemUpdateInfo info) { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - hasCallingOrSelfPermission(permission.NOTIFY_PENDING_SYSTEM_UPDATE), + mContext.enforceCallingOrSelfPermission(permission.NOTIFY_PENDING_SYSTEM_UPDATE, "Only the system update service can broadcast update information"); - if (!caller.getUserHandle().isSystem()) { + if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) { Slog.w(LOG_TAG, "Only the system update service in the system user " + "can broadcast update information."); return; @@ -11764,12 +11833,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { public boolean isProvisioningAllowed(String action, String packageName) { Objects.requireNonNull(packageName); - final CallerIdentity caller = getCallerIdentity(); + final int callingUid = mInjector.binderGetCallingUid(); final long ident = mInjector.binderClearCallingIdentity(); try { final int uidForPackage = mInjector.getPackageManager().getPackageUidAsUser( - packageName, caller.getUserId()); - Preconditions.checkArgument(caller.getUid() == uidForPackage, + packageName, UserHandle.getUserId(callingUid)); + Preconditions.checkArgument(callingUid == uidForPackage, "Caller uid doesn't match the one for the provided package."); } catch (NameNotFoundException e) { throw new IllegalArgumentException("Invalid package provided " + packageName, e); @@ -12080,18 +12149,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(who, "ComponentName is null"); - - final CallerIdentity caller = getCallerIdentity(); + final int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForUidLocked(who, caller.getUid()); + ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid()); if (!TextUtils.equals(admin.shortSupportMessage, message)) { admin.shortSupportMessage = message; - saveSettingsLocked(caller.getUserId()); + saveSettingsLocked(userHandle); } } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_SHORT_SUPPORT_MESSAGE) - .setAdmin(caller.getComponentName()) + .setAdmin(who) .write(); } @@ -12101,9 +12169,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } Objects.requireNonNull(who, "ComponentName is null"); - synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForUidLocked(who, getCallerIdentity().getUid()); + ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid()); return admin.shortSupportMessage; } } @@ -12114,18 +12181,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(who, "ComponentName is null"); - - final CallerIdentity caller = getCallerIdentity(); + final int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForUidLocked(who, caller.getUid()); + ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid()); if (!TextUtils.equals(admin.longSupportMessage, message)) { admin.longSupportMessage = message; - saveSettingsLocked(caller.getUserId()); + saveSettingsLocked(userHandle); } } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_LONG_SUPPORT_MESSAGE) - .setAdmin(caller.getComponentName()) + .setAdmin(who) .write(); } @@ -12135,9 +12201,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } Objects.requireNonNull(who, "ComponentName is null"); - synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForUidLocked(who, getCallerIdentity().getUid()); + ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid()); return admin.longSupportMessage; } } @@ -12148,9 +12213,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } Objects.requireNonNull(who, "ComponentName is null"); - - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can query support message for user"); + enforceSystemCaller("query support message for user"); synchronized (getLockObject()) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); @@ -12167,9 +12230,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } Objects.requireNonNull(who, "ComponentName is null"); - - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can query support message for user"); + enforceSystemCaller("query support message for user"); synchronized (getLockObject()) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); @@ -12296,10 +12357,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return null; } - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isCallerDeviceOwner(caller.getUid()) || canManageUsers(caller)); - + enforceDeviceOwnerOrManageUsers(); synchronized (getLockObject()) { final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked(); return deviceOwnerAdmin == null ? null : deviceOwnerAdmin.organizationName; @@ -12396,13 +12454,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean isMeteredDataDisabledPackageForUser(ComponentName who, String packageName, int userId) { + Objects.requireNonNull(who); + if (!mHasFeature) { return false; } - Objects.requireNonNull(who, "ComponentName is null"); - - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can query restricted pkgs for a specific user"); + enforceSystemCaller("query restricted pkgs for a specific user"); synchronized (getLockObject()) { final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId); @@ -12415,27 +12472,32 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void markProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId) { - if (!mHasFeature) { - return; - } // As the caller is the system, it must specify the component name of the profile owner // as a sanity / safety check. Objects.requireNonNull(who); - final CallerIdentity caller = getCallerIdentity(); + if (!mHasFeature) { + return; + } + // Only adb or system apps with the right permission can mark a profile owner on // organization-owned device. - Preconditions.checkCallAuthorization(isAdb(caller) - || hasCallingPermission(permission.MARK_DEVICE_ORGANIZATION_OWNED), - "Only the system can mark a profile owner of organization-owned device."); - if (isAdb(caller)) { - Preconditions.checkCallAuthorization( - !hasIncompatibleAccountsOrNonAdbNoLock(userId, caller), - "Can only be called from ADB if the device has no accounts."); + if (!(isAdb() || hasCallingPermission(permission.MARK_DEVICE_ORGANIZATION_OWNED))) { + throw new SecurityException( + "Only the system can mark a profile owner of organization-owned device."); + } + + if (isAdb()) { + if (hasIncompatibleAccountsOrNonAdbNoLock(userId, who)) { + throw new SecurityException( + "Can only be called from ADB if the device has no accounts."); + } } else { - Preconditions.checkState(!hasUserSetupCompleted(UserHandle.USER_SYSTEM), - "Cannot mark profile owner as managing an organization-owned device after " - + "set-up"); + if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) { + throw new IllegalStateException( + "Cannot mark profile owner as managing an organization-owned device after" + + " set-up"); + } } // Grant access under lock. @@ -12654,13 +12716,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return false; } - final CallerIdentity caller = getCallerIdentityOptionalAdmin(admin); synchronized (getLockObject()) { - if (!isSystemUid(caller)) { - Objects.requireNonNull(admin, "ComponentName is null"); - Preconditions.checkCallAuthorization(isDeviceOwner(caller) - || isProfileOwnerOfOrganizationOwnedDevice(caller)); + if (!isCallerWithSystemUid()) { + Objects.requireNonNull(admin); + final CallerIdentity caller = getCallerIdentity(admin); + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller) || isDeviceOwner(caller)); } return mInjector.securityLogGetLoggingEnabledProperty(); } @@ -12744,15 +12806,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public long forceSecurityLogs() { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization(isAdb(caller), - "Non-shell user attempted to call forceSecurityLogs"); - Preconditions.checkState(mInjector.securityLogGetLoggingEnabledProperty(), - "logging is not available"); - + enforceShell("forceSecurityLogs"); + if (!mInjector.securityLogGetLoggingEnabledProperty()) { + throw new IllegalStateException("logging is not available"); + } return mSecurityLogMonitor.forceLogs(); } + private void enforceCallerSystemUserHandle() { + final int callingUid = mInjector.binderGetCallingUid(); + final int userId = UserHandle.getUserId(callingUid); + if (userId != UserHandle.USER_SYSTEM) { + throw new SecurityException("Caller has to be in user 0"); + } + } + @Override public boolean isUninstallInQueue(final String packageName) { final CallerIdentity caller = getCallerIdentity(); @@ -12770,21 +12838,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Preconditions.checkArgument(!TextUtils.isEmpty(packageName)); final CallerIdentity caller = getCallerIdentity(); - final int userId = caller.getUserId(); Preconditions.checkCallAuthorization( hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS)); - Preconditions.checkState(mUserManager.isUserUnlocked(userId), - "User must be running and unlocked"); + + final int userId = caller.getUserId(); + enforceUserUnlocked(userId); final ComponentName profileOwner = getProfileOwner(userId); - Preconditions.checkArgument( - profileOwner == null || !packageName.equals(profileOwner.getPackageName()), - "Cannot uninstall a package with a profile owner"); + if (profileOwner != null && packageName.equals(profileOwner.getPackageName())) { + throw new IllegalArgumentException("Cannot uninstall a package with a profile owner"); + } final ComponentName deviceOwner = getDeviceOwnerComponent(/* callingUserOnly= */ false); - Preconditions.checkArgument(deviceOwner == null || getDeviceOwnerUserId() != userId - || !packageName.equals(deviceOwner.getPackageName()), - "Cannot uninstall a package with a device owner"); + if (getDeviceOwnerUserId() == userId && deviceOwner != null + && packageName.equals(deviceOwner.getPackageName())) { + throw new IllegalArgumentException("Cannot uninstall a package with a device owner"); + } final Pair packageUserPair = new Pair<>(packageName, userId); synchronized (getLockObject()) { @@ -12935,24 +13004,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { */ @Override public void forceUpdateUserSetupComplete() { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); - Preconditions.checkCallAuthorization(caller.getUserHandle().isSystem(), - "Caller has to be in user 0"); + enforceCallerSystemUserHandle(); // no effect if it's called from user build if (!mInjector.isBuildDebuggable()) { return; } + final int userId = UserHandle.USER_SYSTEM; boolean isUserCompleted = mInjector.settingsSecureGetIntForUser( - Settings.Secure.USER_SETUP_COMPLETE, 0, caller.getUserId()) != 0; - DevicePolicyData policy = getUserData(caller.getUserId()); + Settings.Secure.USER_SETUP_COMPLETE, 0, userId) != 0; + DevicePolicyData policy = getUserData(userId); policy.mUserSetupComplete = isUserCompleted; mStateCache.setDeviceProvisioned(isUserCompleted); synchronized (getLockObject()) { - saveSettingsLocked(caller.getUserId()); + saveSettingsLocked(userId); } } @@ -13107,8 +13174,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * * DO NOT CALL IT WITH THE DPMS LOCK HELD. */ - private boolean hasIncompatibleAccountsOrNonAdbNoLock(int userId, CallerIdentity caller) { - if (!isAdb(caller)) { + private boolean hasIncompatibleAccountsOrNonAdbNoLock( + int userId, @Nullable ComponentName owner) { + if (!isAdb()) { return true; } wtfIfInLock(); @@ -13120,8 +13188,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } synchronized (getLockObject()) { - if (caller.getComponentName() == null - || !isAdminTestOnlyLocked(caller.getComponentName(), userId)) { + if (owner == null || !isAdminTestOnlyLocked(owner, userId)) { Log.w(LOG_TAG, "Non test-only owner can't be installed with existing accounts."); return true; @@ -13164,8 +13231,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private boolean isAdb(CallerIdentity caller) { - return isShellUid(caller) || isRootUid(caller); + private boolean isAdb() { + final int callingUid = mInjector.binderGetCallingUid(); + return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID; } @Override @@ -13227,13 +13295,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public long forceNetworkLogs() { - Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()), - "Non-shell user attempted to call forceNetworkLogs"); - + enforceShell("forceNetworkLogs"); synchronized (getLockObject()) { - Preconditions.checkState(isNetworkLoggingEnabledInternalLocked(), - "logging is not available"); - + if (!isNetworkLoggingEnabledInternalLocked()) { + throw new IllegalStateException("logging is not available"); + } if (mNetworkLogger != null) { return mInjector.binderWithCleanCallingIdentity( () -> mNetworkLogger.forceBatchFinalization()); @@ -13433,28 +13499,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public long getLastSecurityLogRetrievalTime() { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isCallerDeviceOwner(caller.getUid()) || canManageUsers(caller)); - + enforceDeviceOwnerOrManageUsers(); return getUserData(UserHandle.USER_SYSTEM).mLastSecurityLogRetrievalTime; } @Override public long getLastBugReportRequestTime() { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isCallerDeviceOwner(caller.getUid()) || canManageUsers(caller)); - + enforceDeviceOwnerOrManageUsers(); return getUserData(UserHandle.USER_SYSTEM).mLastBugReportRequestTime; } @Override public long getLastNetworkLogRetrievalTime() { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isCallerDeviceOwner(caller.getUid()) || canManageUsers(caller)); - + enforceDeviceOwnerOrManageUsers(); return getUserData(UserHandle.USER_SYSTEM).mLastNetworkLogsRetrievalTime; } @@ -13534,18 +13591,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return false; } - Objects.requireNonNull(admin); Objects.requireNonNull(token); - - final CallerIdentity caller = getCallerIdentity(admin); - Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)); - synchronized (getLockObject()) { - DevicePolicyData policy = getUserData(caller.getUserId()); + final int userHandle = mInjector.userHandleGetCallingUserId(); + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + + DevicePolicyData policy = getUserData(userHandle); if (policy.mPasswordTokenHandle != 0) { final String password = passwordOrNull != null ? passwordOrNull : ""; return resetPasswordInternal(password, policy.mPasswordTokenHandle, token, - flags, caller.getUid()); + flags, mInjector.binderGetCallingUid()); } else { Slog.w(LOG_TAG, "No saved token handle"); } @@ -13555,21 +13610,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean isCurrentInputMethodSetByOwner() { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization(isCallerDeviceOwner(caller.getUid()) - || isCallerProfileOwner(caller.getUid()) || isSystemUid(caller)); - - return getUserData(caller.getUserId()).mCurrentInputMethodSet; + enforceProfileOwnerOrSystemUser(); + return getUserData(mInjector.userHandleGetCallingUserId()).mCurrentInputMethodSet; } @Override public StringParceledListSlice getOwnerInstalledCaCerts(@NonNull UserHandle user) { final int userId = user.getIdentifier(); final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization(isCallerDeviceOwner(caller.getUid()) - || isCallerProfileOwner(caller.getUid()) - || hasFullCrossUsersPermission(caller, userId)); - + enforceProfileOwnerOrFullCrossUsersPermission(caller, userId); synchronized (getLockObject()) { return new StringParceledListSlice( new ArrayList<>(getUserData(userId).mOwnerInstalledCaCerts)); @@ -14456,12 +14505,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } Preconditions.checkStringNotEmpty(packageName, "Package name is empty"); - final CallerIdentity caller = getCallerIdentity(packageName); - Preconditions.checkCallAuthorization(isCallingFromPackage(packageName, caller.getUid()), - "Input package name doesn't align with actual calling package."); - + final int callingUid = mInjector.binderGetCallingUid(); + final int callingUserId = mInjector.userHandleGetCallingUserId(); + if (!isCallingFromPackage(packageName, callingUid)) { + throw new SecurityException("Input package name doesn't align with actual " + + "calling package."); + } return mInjector.binderWithCleanCallingIdentity(() -> { - final int workProfileUserId = getManagedUserId(caller.getUserId()); + final int workProfileUserId = getManagedUserId(callingUserId); if (workProfileUserId < 0) { return false; } @@ -14945,9 +14996,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean canProfileOwnerResetPasswordWhenLocked(int userId) { - Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()), - "Only the system can query profile owner can reset password when locked"); - + enforceSystemCaller("call canProfileOwnerResetPasswordWhenLocked"); synchronized (getLockObject()) { final ActiveAdmin poAdmin = getProfileOwnerAdminLocked(userId); if (poAdmin == null