Merge "Prevent DPCs from requesting INTERACT_ACROSS_PROFILES" into rvc-dev am: 5d6cf38cd1 am: 3fb3ffeda8 am: 39bca2cdec

Change-Id: I6670634d6f78a68a02613cd42c8e0f310fdd8723
This commit is contained in:
TreeHugger Robot
2020-05-21 16:57:06 +00:00
committed by Automerger Merge Worker
4 changed files with 74 additions and 0 deletions

View File

@@ -217,4 +217,9 @@ public abstract class DevicePolicyManagerInternal {
*/
public abstract void broadcastIntentToCrossProfileManifestReceiversAsUser(Intent intent,
UserHandle parentHandle, boolean requiresPermission);
/**
* Returns the profile owner component for the given user, or {@code null} if there is not one.
*/
public abstract ComponentName getProfileOwnerAsUser(int userHandle);
}

View File

@@ -31,6 +31,7 @@ import android.app.AppOpsManager;
import android.app.AppOpsManager.Mode;
import android.app.IApplicationThread;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
import android.content.Context;
@@ -256,6 +257,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
if (enabledProfileIds.length < 2) {
return false;
}
if (isProfileOwner(packageName, enabledProfileIds)) {
return false;
}
return hasRequestedAppOpPermission(
AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName);
}
@@ -575,6 +579,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
if (profileIds.length < 2) {
return false;
}
if (isProfileOwner(packageName, profileIds)) {
return false;
}
return hasRequestedAppOpPermission(
AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)
&& !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
@@ -698,6 +705,25 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
packageName);
}
private boolean isProfileOwner(String packageName, int[] userIds) {
for (int userId : userIds) {
if (isProfileOwner(packageName, userId)) {
return true;
}
}
return false;
}
private boolean isProfileOwner(String packageName, final @UserIdInt int userId) {
final ComponentName profileOwner =
mInjector.withCleanCallingIdentity(() ->
mInjector.getDevicePolicyManagerInternal().getProfileOwnerAsUser(userId));
if (profileOwner == null) {
return false;
}
return profileOwner.getPackageName().equals(packageName);
}
private static class InjectorImpl implements Injector {
private Context mContext;

View File

@@ -12730,6 +12730,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Binder.restoreCallingIdentity(ident);
}
}
@Override
public ComponentName getProfileOwnerAsUser(int userHandle) {
return DevicePolicyManagerService.this.getProfileOwnerAsUser(userHandle);
}
}
private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {

View File

@@ -37,7 +37,9 @@ import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.AppOpsManager.Mode;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -97,6 +99,7 @@ public class CrossProfileAppsServiceImplRoboTest {
private static final int WORK_PROFILE_USER_ID = 10;
private static final int WORK_PROFILE_UID = 3333;
private static final int OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID = 20;
private static final int OUTSIDE_PROFILE_GROUP_USER_ID = 30;
private final ContextWrapper mContext = ApplicationProvider.getApplicationContext();
private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
@@ -226,6 +229,7 @@ public class CrossProfileAppsServiceImplRoboTest {
PERSONAL_PROFILE_USER_ID,
WORK_PROFILE_USER_ID,
OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID);
shadowUserManager.addProfileIds(OUTSIDE_PROFILE_GROUP_USER_ID);
}
@Before
@@ -503,6 +507,36 @@ public class CrossProfileAppsServiceImplRoboTest {
.isFalse();
}
@Test
public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerWorkProfile_returnsFalse() {
when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(WORK_PROFILE_USER_ID))
.thenReturn(buildCrossProfileComponentName());
assertThat(mCrossProfileAppsServiceImpl
.canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
.isFalse();
}
@Test
public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOtherProfile_returnsFalse() {
// Normally, the DPC would not be a profile owner of the personal profile, but for the
// purposes of this test, it is just a profile owner of any profile within the profile
// group.
when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(PERSONAL_PROFILE_USER_ID))
.thenReturn(buildCrossProfileComponentName());
assertThat(mCrossProfileAppsServiceImpl
.canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
.isFalse();
}
@Test
public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOutsideProfileGroup_returnsTrue() {
when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OUTSIDE_PROFILE_GROUP_USER_ID))
.thenReturn(buildCrossProfileComponentName());
assertThat(mCrossProfileAppsServiceImpl
.canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
.isTrue();
}
@Test
public void canUserAttemptToConfigureInteractAcrossProfiles_returnsTrue() {
assertThat(mCrossProfileAppsServiceImpl
@@ -607,6 +641,10 @@ public class CrossProfileAppsServiceImplRoboTest {
.hideAsParsed()).hideAsFinal());
}
private ComponentName buildCrossProfileComponentName() {
return new ComponentName(CROSS_PROFILE_APP_PACKAGE_NAME, "testClassName");
}
private class TestInjector implements CrossProfileAppsServiceImpl.Injector {
@Override