summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkholoud mohamed <kholoudm@google.com>2020-01-15 15:30:07 +0000
committerkholoud mohamed <kholoudm@google.com>2020-01-21 14:28:46 +0000
commit79a89f022d4e2f372b048b36e056fbaf496e3874 (patch)
tree881a9192474cef85a7ac2505682c874b4b034465
parent30bf54729bfd2daf21eda0550f1d774f976e2fb0 (diff)
Add a checks for _ACROSS_PROFILES apppop or permission.
Use hasPermissionOrAppOpForPreflight to check for INTERACT_ACROSS_PROFILES permission or appop rather than only checking for the permission. BUG: 140728653 BUG: 136249261 Test: atest CrossProfileAppsPermissionHostSideTest Test: atest CrossProfileAppsHostSideTest Test: atest com.android.server.devicepolicy.DevicePolicyManagerTest Test: atest ContextCrossProfileHostTest Change-Id: I81d428d47afd54f294ef9bb44133004762840d09
-rw-r--r--services/core/java/com/android/server/am/UserController.java16
-rw-r--r--services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java30
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java13
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java11
-rw-r--r--services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java17
9 files changed, 99 insertions, 19 deletions
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index f3a2e70f9b89..afc3d918073e 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -54,6 +54,7 @@ import android.appwidget.AppWidgetManagerInternal;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
+import android.content.PermissionChecker;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
@@ -1756,7 +1757,7 @@ class UserController implements Handler.Callback {
// We require full access, sucks to be you.
allow = false;
} else if (canInteractWithAcrossProfilesPermission(
- allowMode, isSameProfileGroup, callingPid, callingUid)) {
+ allowMode, isSameProfileGroup, callingPid, callingUid, callerPackage)) {
allow = true;
} else if (mInjector.checkComponentPermission(INTERACT_ACROSS_USERS, callingPid,
callingUid, -1, true) != PackageManager.PERMISSION_GRANTED) {
@@ -1821,16 +1822,21 @@ class UserController implements Handler.Callback {
}
private boolean canInteractWithAcrossProfilesPermission(
- int allowMode, boolean isSameProfileGroup, int callingPid, int callingUid) {
+ int allowMode, boolean isSameProfileGroup, int callingPid, int callingUid,
+ String callingPackage) {
if (allowMode != ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE) {
return false;
}
if (!isSameProfileGroup) {
return false;
}
- return mInjector.checkComponentPermission(
- INTERACT_ACROSS_PROFILES, callingPid, callingUid, /*owningUid= */-1,
- /*exported= */true) == PackageManager.PERMISSION_GRANTED;
+ return PermissionChecker.PERMISSION_GRANTED
+ == PermissionChecker.checkPermissionForPreflight(
+ mInjector.getContext(),
+ INTERACT_ACROSS_PROFILES,
+ callingPid,
+ callingUid,
+ callingPackage);
}
int unsafeConvertIncomingUser(@UserIdInt int userId) {
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index bdc1b074920a..3635004987e8 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -35,6 +35,7 @@ import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.PermissionChecker;
import android.content.pm.ActivityInfo;
import android.content.pm.ICrossProfileApps;
import android.content.pm.IPackageManager;
@@ -114,6 +115,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
final int callerUserId = mInjector.getCallingUserId();
final int callingUid = mInjector.getCallingUid();
+ final int callingPid = mInjector.getCallingPid();
List<UserHandle> allowedTargetUsers = getTargetUserProfilesUnchecked(
callingPackage, callerUserId);
@@ -143,10 +145,13 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
// must have the required permission and the users must be in the same profile group
// in order to launch any of its own activities.
if (callerUserId != userId) {
- final int permissionFlag = mInjector.checkComponentPermission(
- android.Manifest.permission.INTERACT_ACROSS_PROFILES, callingUid,
- -1, true);
- if (permissionFlag != PackageManager.PERMISSION_GRANTED
+ final int permissionFlag = PermissionChecker.checkPermissionForPreflight(
+ mContext,
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES,
+ callingPid,
+ callingUid,
+ callingPackage);
+ if (permissionFlag != PermissionChecker.PERMISSION_GRANTED
|| !isSameProfileGroup(callerUserId, userId)) {
throw new SecurityException("Attempt to launch activity without required "
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission"
@@ -210,12 +215,15 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
return false;
}
final int callingUid = mInjector.getCallingUid();
+ final int callingPid = mInjector.getCallingPid();
return isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid)
|| isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, callingUid)
- || isPermissionGranted(Manifest.permission.INTERACT_ACROSS_PROFILES, callingUid)
- || AppOpsManager.MODE_ALLOWED == getAppOpsService().noteOperation(
- OP_INTERACT_ACROSS_PROFILES, callingUid, callingPackage, /* featureId= */ null,
- /*shouldCollectAsyncNotedOp= */false, /*message= */null);
+ || PermissionChecker.checkPermissionForPreflight(
+ mContext,
+ Manifest.permission.INTERACT_ACROSS_PROFILES,
+ callingPid,
+ callingUid,
+ callingPackage) == PermissionChecker.PERMISSION_GRANTED;
}
private boolean isCrossProfilePackageWhitelisted(String packageName) {
@@ -436,6 +444,10 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
return Binder.getCallingUid();
}
+ public int getCallingPid() {
+ return Binder.getCallingPid();
+ }
+
public int getCallingUserId() {
return UserHandle.getCallingUserId();
}
@@ -504,6 +516,8 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
public interface Injector {
int getCallingUid();
+ int getCallingPid();
+
int getCallingUserId();
UserHandle getCallingUserHandle();
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 0411e29f68a1..6167a509b85f 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -58,6 +58,7 @@ import android.app.IActivityManager;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.content.Context;
+import android.content.PermissionChecker;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.PermissionGroupInfoFlags;
@@ -4070,8 +4071,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return;
}
final boolean isSameProfileGroup = isSameProfileGroup(callingUserId, userId);
- if (isSameProfileGroup
- && hasPermission(android.Manifest.permission.INTERACT_ACROSS_PROFILES)) {
+ if (isSameProfileGroup && PermissionChecker.checkPermissionForPreflight(
+ mContext,
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES,
+ PermissionChecker.PID_UNKNOWN,
+ callingUid,
+ mPackageManagerInt.getPackage(callingUid).getPackageName())
+ == PermissionChecker.PERMISSION_GRANTED) {
return;
}
String errorMessage = buildInvalidCrossUserOrProfilePermissionMessage(
@@ -4349,7 +4355,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@Override
public void enforceCrossUserOrProfilePermission(int callingUid, int userId,
boolean requireFullPermission, boolean checkShell, String message) {
- PermissionManagerService.this.enforceCrossUserOrProfilePermission(callingUid,
+ PermissionManagerService.this.enforceCrossUserOrProfilePermission(
+ callingUid,
userId,
requireFullPermission,
checkShell,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index af57c29fda82..ac85932e92f0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -9102,11 +9102,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void enforceAcrossUsersPermissions() {
- if (isCallerWithSystemUid() || mInjector.binderGetCallingUid() == Process.ROOT_UID) {
+ final int callingUid = mInjector.binderGetCallingUid();
+ final int callingPid = mInjector.binderGetCallingPid();
+ final String packageName = mContext.getPackageName();
+
+ if (isCallerWithSystemUid() || callingUid == Process.ROOT_UID) {
return;
}
- if (mContext.checkCallingPermission(permission.INTERACT_ACROSS_PROFILES)
- == PackageManager.PERMISSION_GRANTED) {
+ if (PermissionChecker.checkPermissionForPreflight(
+ mContext, permission.INTERACT_ACROSS_PROFILES, callingPid, callingUid,
+ packageName) == PermissionChecker.PERMISSION_GRANTED) {
return;
}
if (mContext.checkCallingPermission(permission.INTERACT_ACROSS_USERS)
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index ce0886435906..96ff9c1ba726 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -79,6 +79,7 @@ import java.util.Set;
@Config(shadows = {ShadowUserManager.class, ShadowApplicationPackageManager.class})
public class CrossProfileAppsServiceImplRoboTest {
private static final int CALLING_UID = 1111;
+ private static final int CALLING_PID = 1000;
private static final String CROSS_PROFILE_APP_PACKAGE_NAME =
"com.android.server.pm.crossprofileappsserviceimplrobotest.crossprofileapp";
private static final int PERSONAL_PROFILE_USER_ID = 0;
@@ -383,6 +384,11 @@ public class CrossProfileAppsServiceImplRoboTest {
}
@Override
+ public int getCallingPid() {
+ return CALLING_PID;
+ }
+
+ @Override
public @UserIdInt int getCallingUserId() {
return PERSONAL_PROFILE_USER_ID;
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 632a2c1edfae..e70cd60c9e19 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -5678,6 +5678,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
public void testGetAllCrossProfilePackages_notSet_returnsEmpty() throws Exception {
addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
+ mContext.packageName = admin1.getPackageName();
setCrossProfileAppsList();
@@ -5687,6 +5688,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
public void testGetAllCrossProfilePackages_notSet_dpmsReinitialized_returnsEmpty()
throws Exception {
addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
+ mContext.packageName = admin1.getPackageName();
setCrossProfileAppsList();
initializeDpms();
@@ -5697,6 +5699,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
public void testGetAllCrossProfilePackages_whenSet_returnsCombinedSet() throws Exception {
addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
final Set<String> packages = Sets.newSet("TEST_PACKAGE", "TEST_COMMON_PACKAGE");
+ mContext.packageName = admin1.getPackageName();
dpm.setCrossProfilePackages(admin1, packages);
setCrossProfileAppsList("TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE");
@@ -5711,6 +5714,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
throws Exception {
addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
final Set<String> packages = Sets.newSet("TEST_PACKAGE", "TEST_COMMON_PACKAGE");
+ mContext.packageName = admin1.getPackageName();
dpm.setCrossProfilePackages(admin1, packages);
setCrossProfileAppsList("TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE");
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 960f670904d6..6cf6b67430ae 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -219,6 +219,8 @@ public class DpmMockContext extends MockContext {
return mMockSystemServices.accountManager;
case Context.TELEPHONY_SERVICE:
return mMockSystemServices.telephonyManager;
+ case Context.APP_OPS_SERVICE:
+ return mMockSystemServices.appOpsManager;
}
throw new UnsupportedOperationException();
}
@@ -256,6 +258,22 @@ public class DpmMockContext extends MockContext {
}
@Override
+ public int checkPermission(String permission, int pid, int uid) {
+ if (UserHandle.isSameApp(binder.getCallingUid(), SYSTEM_UID)) {
+ return PackageManager.PERMISSION_GRANTED; // Assume system has all permissions.
+ }
+ List<String> permissions = binder.callingPermissions.get(binder.getCallingUid());
+ if (permissions == null) {
+ permissions = callerPermissions;
+ }
+ if (permissions.contains(permission)) {
+ return PackageManager.PERMISSION_GRANTED;
+ } else {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ }
+
+ @Override
public void sendBroadcast(Intent intent) {
spiedContext.sendBroadcast(intent);
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 068daf5ee310..b9fb1aab65ba 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -28,6 +28,7 @@ import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
+import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.IActivityTaskManager;
import android.app.NotificationManager;
@@ -120,6 +121,7 @@ public class MockSystemServices {
public final TimeZoneDetector timeZoneDetector;
public final KeyChain.KeyChainConnection keyChainConnection;
public final PersistentDataBlockManagerInternal persistentDataBlockManagerInternal;
+ public final AppOpsManager appOpsManager;
/** Note this is a partial mock, not a real mock. */
public final PackageManager packageManager;
public final BuildMock buildMock = new BuildMock();
@@ -164,6 +166,7 @@ public class MockSystemServices {
timeZoneDetector = mock(TimeZoneDetector.class);
keyChainConnection = mock(KeyChain.KeyChainConnection.class, RETURNS_DEEP_STUBS);
persistentDataBlockManagerInternal = mock(PersistentDataBlockManagerInternal.class);
+ appOpsManager = mock(AppOpsManager.class);
// Package manager is huge, so we use a partial mock instead.
packageManager = spy(realContext.getPackageManager());
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 68f60b4ff67a..91cc9f35da1e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -27,6 +27,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.Bundle;
import android.os.UserHandle;
@@ -95,6 +96,7 @@ public class CrossProfileAppsServiceImplTest {
public void initCrossProfileAppsServiceImpl() {
mTestInjector = new TestInjector();
mCrossProfileAppsServiceImpl = new CrossProfileAppsServiceImpl(mContext, mTestInjector);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
}
@Before
@@ -365,6 +367,11 @@ public class CrossProfileAppsServiceImplTest {
@Test
public void startAnyActivityAsUser_profile_notExported() {
+ try {
+ when(mPackageManager.getPermissionInfo(anyString(), anyInt()))
+ .thenReturn(new PermissionInfo());
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
mActivityInfo.exported = false;
assertThrows(
@@ -523,11 +530,16 @@ public class CrossProfileAppsServiceImplTest {
private class TestInjector implements CrossProfileAppsServiceImpl.Injector {
private int mCallingUid;
private int mCallingUserId;
+ private int mCallingPid;
public void setCallingUid(int uid) {
mCallingUid = uid;
}
+ public void setCallingPid(int pid) {
+ mCallingPid = pid;
+ }
+
public void setCallingUserId(int userId) {
mCallingUserId = userId;
}
@@ -538,6 +550,11 @@ public class CrossProfileAppsServiceImplTest {
}
@Override
+ public int getCallingPid() {
+ return mCallingPid;
+ }
+
+ @Override
public int getCallingUserId() {
return mCallingUserId;
}