diff options
3 files changed, 83 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java index 28c8642d3e60..e82ee22c8064 100644 --- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java +++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java @@ -50,6 +50,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; +import android.permission.PermissionManager; import android.stats.devicepolicy.DevicePolicyEnums; import android.text.TextUtils; import android.util.Slog; @@ -458,6 +459,10 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { + packageName + " on user ID " + userId); return; } + + final boolean hadPermission = hasInteractAcrossProfilesPermission( + packageName, uid, PermissionChecker.PID_UNKNOWN); + final int callingUid = mInjector.getCallingUid(); if (isPermissionGranted( Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) { @@ -472,6 +477,22 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { } sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(userId)); maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, userId, logMetrics, uid); + maybeKillUid(packageName, uid, hadPermission); + } + + /** + * Kills the process represented by the given UID if it has lost the permission to + * interact across profiles. + */ + private void maybeKillUid( + String packageName, int uid, boolean hadPermission) { + if (!hadPermission) { + return; + } + if (hasInteractAcrossProfilesPermission(packageName, uid, PermissionChecker.PID_UNKNOWN)) { + return; + } + mInjector.killUid(packageName, uid); } private void maybeLogSetInteractAcrossProfilesAppOp( @@ -774,6 +795,18 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { String permission, int uid, int owningUid, boolean exported) { return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported); } + + @Override + public void killUid(String packageName, int uid) { + try { + ActivityManager.getService().killApplication( + packageName, + UserHandle.getAppId(uid), + UserHandle.getUserId(uid), + PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED); + } catch (RemoteException ignored) { + } + } } @VisibleForTesting @@ -813,6 +846,8 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { void sendBroadcastAsUser(Intent intent, UserHandle user); int checkComponentPermission(String permission, int uid, int owningUid, boolean exported); + + void killUid(String packageName, int uid); } class LocalService extends CrossProfileAppsInternal { diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java index f8d197acf883..d78dad55e181 100644 --- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java +++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java @@ -46,6 +46,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; +import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.os.Process; import android.os.UserHandle; @@ -106,6 +107,7 @@ public class CrossProfileAppsServiceImplRoboTest { new CrossProfileAppsServiceImpl(mContext, mInjector); private final Map<UserHandle, Set<Intent>> mSentUserBroadcasts = new HashMap<>(); private final Map<Integer, List<ApplicationInfo>> installedApplications = new HashMap<>(); + private final Set<Integer> mKilledUids = new HashSet<>(); @Mock private PackageManagerInternal mPackageManagerInternal; @Mock private IPackageManager mIPackageManager; @@ -389,6 +391,33 @@ public class CrossProfileAppsServiceImplRoboTest { } @Test + public void setInteractAcrossProfilesAppOp_toAllowed_doesNotKillApp() { + mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp( + CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED); + assertThat(mKilledUids).isEmpty(); + } + + @Test + public void setInteractAcrossProfilesAppOp_toDisallowed_killsAppsInBothProfiles() { + shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo()); + mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp( + CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED); + + mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp( + CROSS_PROFILE_APP_PACKAGE_NAME, MODE_DEFAULT); + + assertThat(mKilledUids).contains(WORK_PROFILE_UID); + assertThat(mKilledUids).contains(PERSONAL_PROFILE_UID); + } + + private PermissionInfo createCrossProfilesPermissionInfo() { + PermissionInfo permissionInfo = new PermissionInfo(); + permissionInfo.name = Manifest.permission.INTERACT_ACROSS_PROFILES; + permissionInfo.protectionLevel = PermissionInfo.PROTECTION_FLAG_APPOP; + return permissionInfo; + } + + @Test public void canConfigureInteractAcrossProfiles_packageNotInstalledInProfile_returnsFalse() { mockUninstallCrossProfileAppFromWorkProfile(); assertThat(mCrossProfileAppsServiceImpl @@ -678,5 +707,10 @@ public class CrossProfileAppsServiceImplRoboTest { // ShadowActivityThread with Robolectric. This method is currently not supported there. return mContext.checkPermission(permission, Process.myPid(), uid); } + + @Override + public void killUid(String packageName, int uid) { + mKilledUids.add(uid); + } } } diff --git a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java index e79b5af32b19..a2393a80d11e 100644 --- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java @@ -32,8 +32,10 @@ import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.IBinder; +import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; +import android.permission.PermissionManager; import android.platform.test.annotations.Presubmit; import android.util.SparseArray; @@ -692,5 +694,17 @@ public class CrossProfileAppsServiceImplTest { String permission, int uid, int owningUid, boolean exported) { return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported); } + + @Override + public void killUid(String packageName, int uid) { + try { + ActivityManager.getService().killApplication( + packageName, + UserHandle.getAppId(uid), + UserHandle.getUserId(uid), + PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED); + } catch (RemoteException ignored) { + } + } } } |