Save appIds permissions for each user
PermissionMonitor does not store any information regarding
traffic permission. It just checks permission from each package
and sends the result to netd. In addition, bpf can store traffic
permissions for appIds only because of memory limitations.
However, there is a mistaken permission overwriting when
different packages are installed on multi-user. Because
PermissionMonitor updates appIds traffic permissions to netd
from each user, so the permission result will depend on the
latest user state.
To fix the problem, save the traffic permissions by each user and
appId on PermissionMonitor. An appId has a permission if and
only if at least one uid in that appId has that permission.
bug: 224775316
Test: atest FrameworksNetTests CtsNetTestCases \
CtsNetTestCasesUpdateStatsPermission \
CtsNetTestCasesInternetPermission
Change-Id: Ieb01fb21f6201a58723eb7e6446b127627be2c0e
This commit is contained in:
@@ -127,9 +127,17 @@ public class PermissionMonitor {
|
||||
@GuardedBy("this")
|
||||
private final Set<Integer> mUidsAllowedOnRestrictedNetworks = new ArraySet<>();
|
||||
|
||||
// Store PackageManager for each user.
|
||||
// Keys are users, Values are PackageManagers which get from each user.
|
||||
@GuardedBy("this")
|
||||
private final Map<UserHandle, PackageManager> mUsersPackageManager = new ArrayMap<>();
|
||||
|
||||
// Store appIds traffic permissions for each user.
|
||||
// Keys are users, Values are SparseArrays where each entry maps an appId to the permissions
|
||||
// that appId has within that user.
|
||||
@GuardedBy("this")
|
||||
private final Map<UserHandle, SparseIntArray> mUsersTrafficPermissions = new ArrayMap<>();
|
||||
|
||||
private static final int SYSTEM_APPID = SYSTEM_UID;
|
||||
|
||||
private static final int MAX_PERMISSION_UPDATE_LOGS = 40;
|
||||
@@ -292,14 +300,24 @@ public class PermissionMonitor {
|
||||
sendUidsNetworkPermission(uids, true /* add */);
|
||||
}
|
||||
|
||||
private void updateAppIdsTrafficPermission(final SparseIntArray appIds,
|
||||
final SparseIntArray extraAppIds) {
|
||||
for (int i = 0; i < extraAppIds.size(); i++) {
|
||||
final int appId = extraAppIds.keyAt(i);
|
||||
final int permission = extraAppIds.valueAt(i);
|
||||
appIds.put(appId, appIds.get(appId) | permission);
|
||||
/**
|
||||
* Calculates permissions for appIds.
|
||||
* Maps each appId to the union of all traffic permissions that the appId has in all users.
|
||||
*
|
||||
* @return The appIds traffic permissions.
|
||||
*/
|
||||
private synchronized SparseIntArray makeAppIdsTrafficPermForAllUsers() {
|
||||
final SparseIntArray appIds = new SparseIntArray();
|
||||
// Check appIds permissions from each user.
|
||||
for (UserHandle user : mUsersTrafficPermissions.keySet()) {
|
||||
final SparseIntArray userAppIds = mUsersTrafficPermissions.get(user);
|
||||
for (int i = 0; i < userAppIds.size(); i++) {
|
||||
final int appId = userAppIds.keyAt(i);
|
||||
final int permission = userAppIds.valueAt(i);
|
||||
appIds.put(appId, appIds.get(appId) | permission);
|
||||
}
|
||||
}
|
||||
sendAppIdsTrafficPermission(appIds);
|
||||
return appIds;
|
||||
}
|
||||
|
||||
private SparseIntArray getSystemTrafficPerm() {
|
||||
@@ -363,6 +381,10 @@ public class PermissionMonitor {
|
||||
// mUidsAllowedOnRestrictedNetworks.
|
||||
updateUidsAllowedOnRestrictedNetworks(mDeps.getUidsAllowedOnRestrictedNetworks(mContext));
|
||||
|
||||
// Read system traffic permissions when a user removed and put them to USER_ALL because they
|
||||
// are not specific to any particular user.
|
||||
mUsersTrafficPermissions.put(UserHandle.ALL, getSystemTrafficPerm());
|
||||
|
||||
final List<UserHandle> usrs = mUserManager.getUserHandles(true /* excludeDying */);
|
||||
// Update netd permissions for all users.
|
||||
for (UserHandle user : usrs) {
|
||||
@@ -487,9 +509,16 @@ public class PermissionMonitor {
|
||||
final SparseIntArray uids = makeUidsNetworkPerm(apps);
|
||||
updateUidsNetworkPermission(uids);
|
||||
|
||||
// App ids traffic permission
|
||||
final SparseIntArray appIds = makeAppIdsTrafficPerm(apps);
|
||||
updateAppIdsTrafficPermission(appIds, getSystemTrafficPerm());
|
||||
// Add new user appIds permissions.
|
||||
final SparseIntArray addedUserAppIds = makeAppIdsTrafficPerm(apps);
|
||||
mUsersTrafficPermissions.put(user, addedUserAppIds);
|
||||
// Generate appIds from all users and send result to netd.
|
||||
final SparseIntArray appIds = makeAppIdsTrafficPermForAllUsers();
|
||||
sendAppIdsTrafficPermission(appIds);
|
||||
|
||||
// Log user added
|
||||
mPermissionUpdateLogs.log("New user(" + user.getIdentifier() + ") added: nPerm uids="
|
||||
+ uids + ", tPerm appIds=" + addedUserAppIds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -502,6 +531,7 @@ public class PermissionMonitor {
|
||||
public synchronized void onUserRemoved(@NonNull UserHandle user) {
|
||||
mUsers.remove(user);
|
||||
|
||||
// Remove uids network permissions that belongs to the user.
|
||||
final SparseIntArray removedUids = new SparseIntArray();
|
||||
final SparseIntArray allUids = mUidToNetworkPerm.clone();
|
||||
for (int i = 0; i < allUids.size(); i++) {
|
||||
@@ -512,6 +542,27 @@ public class PermissionMonitor {
|
||||
}
|
||||
}
|
||||
sendUidsNetworkPermission(removedUids, false /* add */);
|
||||
|
||||
// Remove appIds traffic permission that belongs to the user
|
||||
final SparseIntArray removedUserAppIds = mUsersTrafficPermissions.remove(user);
|
||||
// Generate appIds from left users.
|
||||
final SparseIntArray appIds = makeAppIdsTrafficPermForAllUsers();
|
||||
// Clear permission on those appIds belong to this user only, set the permission to
|
||||
// PERMISSION_UNINSTALLED.
|
||||
if (removedUserAppIds != null) {
|
||||
for (int i = 0; i < removedUserAppIds.size(); i++) {
|
||||
final int appId = removedUserAppIds.keyAt(i);
|
||||
// Need to clear permission if the removed appId is not found in the array.
|
||||
if (appIds.indexOfKey(appId) < 0) {
|
||||
appIds.put(appId, PERMISSION_UNINSTALLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
sendAppIdsTrafficPermission(appIds);
|
||||
|
||||
// Log user removed
|
||||
mPermissionUpdateLogs.log("User(" + user.getIdentifier() + ") removed: nPerm uids="
|
||||
+ removedUids + ", tPerm appIds=" + removedUserAppIds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -598,6 +649,39 @@ public class PermissionMonitor {
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void updateAppIdTrafficPermission(int uid) {
|
||||
final int appId = UserHandle.getAppId(uid);
|
||||
final int uidTrafficPerm = getTrafficPermissionForUid(uid);
|
||||
final SparseIntArray userTrafficPerms =
|
||||
mUsersTrafficPermissions.get(UserHandle.getUserHandleForUid(uid));
|
||||
if (userTrafficPerms == null) {
|
||||
Log.wtf(TAG, "Can't get user traffic permission from uid=" + uid);
|
||||
return;
|
||||
}
|
||||
// Do not put PERMISSION_UNINSTALLED into the array. If no package left on the uid
|
||||
// (PERMISSION_UNINSTALLED), remove the appId from the array. Otherwise, update the latest
|
||||
// permission to the appId.
|
||||
if (uidTrafficPerm == PERMISSION_UNINSTALLED) {
|
||||
userTrafficPerms.delete(appId);
|
||||
} else {
|
||||
userTrafficPerms.put(appId, uidTrafficPerm);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized int getAppIdTrafficPermission(int appId) {
|
||||
int permission = PERMISSION_NONE;
|
||||
boolean installed = false;
|
||||
for (UserHandle user : mUsersTrafficPermissions.keySet()) {
|
||||
final SparseIntArray userApps = mUsersTrafficPermissions.get(user);
|
||||
final int appIdx = userApps.indexOfKey(appId);
|
||||
if (appIdx >= 0) {
|
||||
permission |= userApps.valueAt(appIdx);
|
||||
installed = true;
|
||||
}
|
||||
}
|
||||
return installed ? permission : PERMISSION_UNINSTALLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a package is added.
|
||||
*
|
||||
@@ -607,9 +691,12 @@ public class PermissionMonitor {
|
||||
* @hide
|
||||
*/
|
||||
public synchronized void onPackageAdded(@NonNull final String packageName, final int uid) {
|
||||
// Update uid permission.
|
||||
updateAppIdTrafficPermission(uid);
|
||||
// Get the appId permission from all users then send the latest permission to netd.
|
||||
final int appId = UserHandle.getAppId(uid);
|
||||
final int trafficPerm = getTrafficPermissionForUid(uid);
|
||||
sendPackagePermissionsForAppId(appId, trafficPerm);
|
||||
final int appIdTrafficPerm = getAppIdTrafficPermission(appId);
|
||||
sendPackagePermissionsForAppId(appId, appIdTrafficPerm);
|
||||
|
||||
final int currentPermission = mUidToNetworkPerm.get(uid, PERMISSION_NONE);
|
||||
final int permission = highestPermissionForUid(uid, currentPermission, packageName);
|
||||
@@ -633,10 +720,12 @@ public class PermissionMonitor {
|
||||
// package can bypass VPN.
|
||||
updateVpnUid(uid, true /* add */);
|
||||
mAllApps.add(appId);
|
||||
|
||||
// Log package added.
|
||||
mPermissionUpdateLogs.log("Package add: name=" + packageName + ", uid=" + uid
|
||||
+ ", nPerm=(" + permissionToString(permission) + "/"
|
||||
+ permissionToString(currentPermission) + ")"
|
||||
+ ", tPerm=" + permissionToString(trafficPerm));
|
||||
+ ", tPerm=" + permissionToString(appIdTrafficPerm));
|
||||
}
|
||||
|
||||
private int highestUidNetworkPermission(int uid) {
|
||||
@@ -664,9 +753,12 @@ public class PermissionMonitor {
|
||||
* @hide
|
||||
*/
|
||||
public synchronized void onPackageRemoved(@NonNull final String packageName, final int uid) {
|
||||
// Update uid permission.
|
||||
updateAppIdTrafficPermission(uid);
|
||||
// Get the appId permission from all users then send the latest permission to netd.
|
||||
final int appId = UserHandle.getAppId(uid);
|
||||
final int trafficPerm = getTrafficPermissionForUid(uid);
|
||||
sendPackagePermissionsForAppId(appId, trafficPerm);
|
||||
final int appIdTrafficPerm = getAppIdTrafficPermission(appId);
|
||||
sendPackagePermissionsForAppId(appId, appIdTrafficPerm);
|
||||
|
||||
// If the newly-removed package falls within some VPN's uid range, update Netd with it.
|
||||
// This needs to happen before the mUidToNetworkPerm update below, since
|
||||
@@ -680,10 +772,13 @@ public class PermissionMonitor {
|
||||
|
||||
final int currentPermission = mUidToNetworkPerm.get(uid, PERMISSION_NONE);
|
||||
final int permission = highestUidNetworkPermission(uid);
|
||||
|
||||
// Log package removed.
|
||||
mPermissionUpdateLogs.log("Package remove: name=" + packageName + ", uid=" + uid
|
||||
+ ", nPerm=(" + permissionToString(permission) + "/"
|
||||
+ permissionToString(currentPermission) + ")"
|
||||
+ ", tPerm=" + permissionToString(trafficPerm));
|
||||
+ ", tPerm=" + permissionToString(appIdTrafficPerm));
|
||||
|
||||
if (permission != currentPermission) {
|
||||
final SparseIntArray apps = new SparseIntArray();
|
||||
int sdkSandboxUid = -1;
|
||||
|
||||
@@ -117,23 +117,32 @@ import java.util.Set;
|
||||
public class PermissionMonitorTest {
|
||||
private static final int MOCK_USER_ID1 = 0;
|
||||
private static final int MOCK_USER_ID2 = 1;
|
||||
private static final int MOCK_USER_ID3 = 2;
|
||||
private static final UserHandle MOCK_USER1 = UserHandle.of(MOCK_USER_ID1);
|
||||
private static final UserHandle MOCK_USER2 = UserHandle.of(MOCK_USER_ID2);
|
||||
private static final UserHandle MOCK_USER3 = UserHandle.of(MOCK_USER_ID3);
|
||||
private static final int MOCK_APPID1 = 10001;
|
||||
private static final int MOCK_APPID2 = 10086;
|
||||
private static final int MOCK_APPID3 = 10110;
|
||||
private static final int SYSTEM_APPID1 = 1100;
|
||||
private static final int SYSTEM_APPID2 = 1108;
|
||||
private static final int VPN_APPID = 10002;
|
||||
private static final int MOCK_UID11 = MOCK_USER1.getUid(MOCK_APPID1);
|
||||
private static final int MOCK_UID12 = MOCK_USER1.getUid(MOCK_APPID2);
|
||||
private static final int MOCK_UID13 = MOCK_USER1.getUid(MOCK_APPID3);
|
||||
private static final int SYSTEM_APP_UID11 = MOCK_USER1.getUid(SYSTEM_APPID1);
|
||||
private static final int VPN_UID = MOCK_USER1.getUid(VPN_APPID);
|
||||
private static final int MOCK_UID21 = MOCK_USER2.getUid(MOCK_APPID1);
|
||||
private static final int MOCK_UID22 = MOCK_USER2.getUid(MOCK_APPID2);
|
||||
private static final int MOCK_UID23 = MOCK_USER2.getUid(MOCK_APPID3);
|
||||
private static final int SYSTEM_APP_UID21 = MOCK_USER2.getUid(SYSTEM_APPID1);
|
||||
private static final int MOCK_UID31 = MOCK_USER3.getUid(MOCK_APPID1);
|
||||
private static final int MOCK_UID32 = MOCK_USER3.getUid(MOCK_APPID2);
|
||||
private static final int MOCK_UID33 = MOCK_USER3.getUid(MOCK_APPID3);
|
||||
private static final String REAL_SYSTEM_PACKAGE_NAME = "android";
|
||||
private static final String MOCK_PACKAGE1 = "appName1";
|
||||
private static final String MOCK_PACKAGE2 = "appName2";
|
||||
private static final String MOCK_PACKAGE3 = "appName3";
|
||||
private static final String SYSTEM_PACKAGE1 = "sysName1";
|
||||
private static final String SYSTEM_PACKAGE2 = "sysName2";
|
||||
private static final String PARTITION_SYSTEM = "system";
|
||||
@@ -191,6 +200,7 @@ public class PermissionMonitorTest {
|
||||
mBpfMapMonitor = new BpfMapMonitor(mBpfNetMaps);
|
||||
|
||||
doReturn(List.of()).when(mPackageManager).getInstalledPackagesAsUser(anyInt(), anyInt());
|
||||
mPermissionMonitor.onUserAdded(MOCK_USER1);
|
||||
}
|
||||
|
||||
private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion,
|
||||
@@ -283,6 +293,18 @@ public class PermissionMonitorTest {
|
||||
mPermissionMonitor.onPackageAdded(packageName, uid);
|
||||
}
|
||||
|
||||
private void removePackage(String packageName, int uid) {
|
||||
final String[] oldPackages = mPackageManager.getPackagesForUid(uid);
|
||||
// If the package isn't existed, no need to remove it.
|
||||
if (!CollectionUtils.contains(oldPackages, packageName)) return;
|
||||
|
||||
// Remove the package if this uid is shared with other packages.
|
||||
final String[] newPackages = Arrays.stream(oldPackages).filter(e -> !e.equals(packageName))
|
||||
.toArray(String[]::new);
|
||||
doReturn(newPackages).when(mPackageManager).getPackagesForUid(eq(uid));
|
||||
mPermissionMonitor.onPackageRemoved(packageName, uid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasPermission() {
|
||||
PackageInfo app = systemPackageInfoWithPermissions();
|
||||
@@ -791,6 +813,7 @@ public class PermissionMonitorTest {
|
||||
buildPackageInfo(SYSTEM_PACKAGE2, VPN_UID)))
|
||||
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
|
||||
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID11);
|
||||
doReturn(List.of(MOCK_USER1, MOCK_USER2)).when(mUserManager).getUserHandles(eq(true));
|
||||
|
||||
mPermissionMonitor.startMonitoring();
|
||||
final Set<UidRange> vpnRange = Set.of(UidRange.createForUser(MOCK_USER1),
|
||||
@@ -881,7 +904,7 @@ public class PermissionMonitorTest {
|
||||
addPackage(MOCK_PACKAGE1, MOCK_UID11, INTERNET, UPDATE_DEVICE_STATS);
|
||||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
|
||||
|
||||
// Install another package with the same uid and no permissions should not cause the app id
|
||||
// Install another package with the same uid and no permissions should not cause the appId
|
||||
// to lose permissions.
|
||||
addPackage(MOCK_PACKAGE2, MOCK_UID11);
|
||||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
|
||||
@@ -1249,4 +1272,211 @@ public class PermissionMonitorTest {
|
||||
assertTrue(isHigherNetworkPermission(PERMISSION_SYSTEM, PERMISSION_NETWORK));
|
||||
assertFalse(isHigherNetworkPermission(PERMISSION_SYSTEM, PERMISSION_SYSTEM));
|
||||
}
|
||||
|
||||
private void prepareMultiUserPackages() {
|
||||
// MOCK_USER1 has installed 3 packages
|
||||
// mockApp1 has no permission and share MOCK_APPID1.
|
||||
// mockApp2 has INTERNET permission and share MOCK_APPID2.
|
||||
// mockApp3 has UPDATE_DEVICE_STATS permission and share MOCK_APPID3.
|
||||
final List<PackageInfo> pkgs1 = List.of(
|
||||
buildPackageInfo("mockApp1", MOCK_UID11),
|
||||
buildPackageInfo("mockApp2", MOCK_UID12, INTERNET),
|
||||
buildPackageInfo("mockApp3", MOCK_UID13, UPDATE_DEVICE_STATS));
|
||||
|
||||
// MOCK_USER2 has installed 2 packages
|
||||
// mockApp4 has UPDATE_DEVICE_STATS permission and share MOCK_APPID1.
|
||||
// mockApp5 has INTERNET permission and share MOCK_APPID2.
|
||||
final List<PackageInfo> pkgs2 = List.of(
|
||||
buildPackageInfo("mockApp4", MOCK_UID21, UPDATE_DEVICE_STATS),
|
||||
buildPackageInfo("mockApp5", MOCK_UID23, INTERNET));
|
||||
|
||||
// MOCK_USER3 has installed 1 packages
|
||||
// mockApp6 has UPDATE_DEVICE_STATS permission and share MOCK_APPID2.
|
||||
final List<PackageInfo> pkgs3 = List.of(
|
||||
buildPackageInfo("mockApp6", MOCK_UID32, UPDATE_DEVICE_STATS));
|
||||
|
||||
doReturn(pkgs1).when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS),
|
||||
eq(MOCK_USER_ID1));
|
||||
doReturn(pkgs2).when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS),
|
||||
eq(MOCK_USER_ID2));
|
||||
doReturn(pkgs3).when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS),
|
||||
eq(MOCK_USER_ID3));
|
||||
}
|
||||
|
||||
private void addUserAndVerifyAppIdsPermissions(UserHandle user, int appId1Perm,
|
||||
int appId2Perm, int appId3Perm) {
|
||||
mPermissionMonitor.onUserAdded(user);
|
||||
mBpfMapMonitor.expectTrafficPerm(appId1Perm, MOCK_APPID1);
|
||||
mBpfMapMonitor.expectTrafficPerm(appId2Perm, MOCK_APPID2);
|
||||
mBpfMapMonitor.expectTrafficPerm(appId3Perm, MOCK_APPID3);
|
||||
}
|
||||
|
||||
private void removeUserAndVerifyAppIdsPermissions(UserHandle user, int appId1Perm,
|
||||
int appId2Perm, int appId3Perm) {
|
||||
mPermissionMonitor.onUserRemoved(user);
|
||||
mBpfMapMonitor.expectTrafficPerm(appId1Perm, MOCK_APPID1);
|
||||
mBpfMapMonitor.expectTrafficPerm(appId2Perm, MOCK_APPID2);
|
||||
mBpfMapMonitor.expectTrafficPerm(appId3Perm, MOCK_APPID3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppIdsTrafficPermission_UserAddedRemoved() {
|
||||
prepareMultiUserPackages();
|
||||
|
||||
// Add MOCK_USER1 and verify the permissions with each appIds.
|
||||
addUserAndVerifyAppIdsPermissions(MOCK_USER1, PERMISSION_NONE, PERMISSION_INTERNET,
|
||||
PERMISSION_UPDATE_DEVICE_STATS);
|
||||
|
||||
// Add MOCK_USER2 and verify the permissions upgrade on MOCK_APPID1 & MOCK_APPID3.
|
||||
addUserAndVerifyAppIdsPermissions(MOCK_USER2, PERMISSION_UPDATE_DEVICE_STATS,
|
||||
PERMISSION_INTERNET, PERMISSION_TRAFFIC_ALL);
|
||||
|
||||
// Add MOCK_USER3 and verify the permissions upgrade on MOCK_APPID2.
|
||||
addUserAndVerifyAppIdsPermissions(MOCK_USER3, PERMISSION_UPDATE_DEVICE_STATS,
|
||||
PERMISSION_TRAFFIC_ALL, PERMISSION_TRAFFIC_ALL);
|
||||
|
||||
// Remove MOCK_USER2 and verify the permissions downgrade on MOCK_APPID1 & MOCK_APPID3.
|
||||
removeUserAndVerifyAppIdsPermissions(MOCK_USER2, PERMISSION_NONE, PERMISSION_TRAFFIC_ALL,
|
||||
PERMISSION_UPDATE_DEVICE_STATS);
|
||||
|
||||
// Remove MOCK_USER1 and verify the permissions downgrade on all appIds.
|
||||
removeUserAndVerifyAppIdsPermissions(MOCK_USER1, PERMISSION_UNINSTALLED,
|
||||
PERMISSION_UPDATE_DEVICE_STATS, PERMISSION_UNINSTALLED);
|
||||
|
||||
// Add MOCK_USER2 back and verify the permissions upgrade on MOCK_APPID1 & MOCK_APPID3.
|
||||
addUserAndVerifyAppIdsPermissions(MOCK_USER2, PERMISSION_UPDATE_DEVICE_STATS,
|
||||
PERMISSION_UPDATE_DEVICE_STATS, PERMISSION_INTERNET);
|
||||
|
||||
// Remove MOCK_USER3 and verify the permissions downgrade on MOCK_APPID2.
|
||||
removeUserAndVerifyAppIdsPermissions(MOCK_USER3, PERMISSION_UPDATE_DEVICE_STATS,
|
||||
PERMISSION_UNINSTALLED, PERMISSION_INTERNET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppIdsTrafficPermission_Multiuser_PackageAdded() throws Exception {
|
||||
// Add two users with empty package list.
|
||||
mPermissionMonitor.onUserAdded(MOCK_USER1);
|
||||
mPermissionMonitor.onUserAdded(MOCK_USER2);
|
||||
|
||||
final int[] netdPermissions = {PERMISSION_NONE, PERMISSION_INTERNET,
|
||||
PERMISSION_UPDATE_DEVICE_STATS, PERMISSION_TRAFFIC_ALL};
|
||||
final String[][] grantPermissions = {new String[]{}, new String[]{INTERNET},
|
||||
new String[]{UPDATE_DEVICE_STATS}, new String[]{INTERNET, UPDATE_DEVICE_STATS}};
|
||||
|
||||
// Verify that the permission combination is expected when same appId package is installed
|
||||
// on another user. List the expected permissions below.
|
||||
// NONE + NONE = NONE
|
||||
// NONE + INTERNET = INTERNET
|
||||
// NONE + UPDATE_DEVICE_STATS = UPDATE_DEVICE_STATS
|
||||
// NONE + ALL = ALL
|
||||
// INTERNET + NONE = INTERNET
|
||||
// INTERNET + INTERNET = INTERNET
|
||||
// INTERNET + UPDATE_DEVICE_STATS = ALL
|
||||
// INTERNET + ALL = ALL
|
||||
// UPDATE_DEVICE_STATS + NONE = UPDATE_DEVICE_STATS
|
||||
// UPDATE_DEVICE_STATS + INTERNET = ALL
|
||||
// UPDATE_DEVICE_STATS + UPDATE_DEVICE_STATS = UPDATE_DEVICE_STATS
|
||||
// UPDATE_DEVICE_STATS + ALL = ALL
|
||||
// ALL + NONE = ALL
|
||||
// ALL + INTERNET = ALL
|
||||
// ALL + UPDATE_DEVICE_STATS = ALL
|
||||
// ALL + ALL = ALL
|
||||
for (int i = 0, num = 0; i < netdPermissions.length; i++) {
|
||||
final int current = netdPermissions[i];
|
||||
final String[] user1Perm = grantPermissions[i];
|
||||
for (int j = 0; j < netdPermissions.length; j++) {
|
||||
final int appId = MOCK_APPID1 + num;
|
||||
final int added = netdPermissions[j];
|
||||
final String[] user2Perm = grantPermissions[j];
|
||||
// Add package on MOCK_USER1 and verify the permission is same as package granted.
|
||||
addPackage(MOCK_PACKAGE1, MOCK_USER1.getUid(appId), user1Perm);
|
||||
mBpfMapMonitor.expectTrafficPerm(current, appId);
|
||||
|
||||
// Add package which share the same appId on MOCK_USER2, and verify the permission
|
||||
// has combined.
|
||||
addPackage(MOCK_PACKAGE2, MOCK_USER2.getUid(appId), user2Perm);
|
||||
mBpfMapMonitor.expectTrafficPerm((current | added), appId);
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyAppIdPermissionsAfterPackageRemoved(int appId, int expectedPerm,
|
||||
String[] user1Perm, String[] user2Perm) throws Exception {
|
||||
// Add package on MOCK_USER1 and verify the permission is same as package granted.
|
||||
addPackage(MOCK_PACKAGE1, MOCK_USER1.getUid(appId), user1Perm);
|
||||
mBpfMapMonitor.expectTrafficPerm(expectedPerm, appId);
|
||||
|
||||
// Add two packages which share the same appId and don't declare permission on
|
||||
// MOCK_USER2. Verify the permission has no change.
|
||||
addPackage(MOCK_PACKAGE2, MOCK_USER2.getUid(appId));
|
||||
addPackage(MOCK_PACKAGE3, MOCK_USER2.getUid(appId), user2Perm);
|
||||
mBpfMapMonitor.expectTrafficPerm(expectedPerm, appId);
|
||||
|
||||
// Remove one packages from MOCK_USER2. Verify the permission has no change too.
|
||||
removePackage(MOCK_PACKAGE2, MOCK_USER2.getUid(appId));
|
||||
mBpfMapMonitor.expectTrafficPerm(expectedPerm, appId);
|
||||
|
||||
// Remove last packages from MOCK_USER2. Verify the permission has still no change.
|
||||
removePackage(MOCK_PACKAGE3, MOCK_USER2.getUid(appId));
|
||||
mBpfMapMonitor.expectTrafficPerm(expectedPerm, appId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppIdsTrafficPermission_Multiuser_PackageRemoved() throws Exception {
|
||||
// Add two users with empty package list.
|
||||
mPermissionMonitor.onUserAdded(MOCK_USER1);
|
||||
mPermissionMonitor.onUserAdded(MOCK_USER2);
|
||||
|
||||
int appId = MOCK_APPID1;
|
||||
// Verify that the permission combination is expected when same appId package is removed on
|
||||
// another user. List the expected permissions below.
|
||||
/***** NONE *****/
|
||||
// NONE + NONE = NONE
|
||||
verifyAppIdPermissionsAfterPackageRemoved(
|
||||
appId++, PERMISSION_NONE, new String[]{}, new String[]{});
|
||||
|
||||
/***** INTERNET *****/
|
||||
// INTERNET + NONE = INTERNET
|
||||
verifyAppIdPermissionsAfterPackageRemoved(
|
||||
appId++, PERMISSION_INTERNET, new String[]{INTERNET}, new String[]{});
|
||||
|
||||
// INTERNET + INTERNET = INTERNET
|
||||
verifyAppIdPermissionsAfterPackageRemoved(
|
||||
appId++, PERMISSION_INTERNET, new String[]{INTERNET}, new String[]{INTERNET});
|
||||
|
||||
/***** UPDATE_DEVICE_STATS *****/
|
||||
// UPDATE_DEVICE_STATS + NONE = UPDATE_DEVICE_STATS
|
||||
verifyAppIdPermissionsAfterPackageRemoved(appId++, PERMISSION_UPDATE_DEVICE_STATS,
|
||||
new String[]{UPDATE_DEVICE_STATS}, new String[]{});
|
||||
|
||||
// UPDATE_DEVICE_STATS + UPDATE_DEVICE_STATS = UPDATE_DEVICE_STATS
|
||||
verifyAppIdPermissionsAfterPackageRemoved(appId++, PERMISSION_UPDATE_DEVICE_STATS,
|
||||
new String[]{UPDATE_DEVICE_STATS}, new String[]{UPDATE_DEVICE_STATS});
|
||||
|
||||
/***** ALL *****/
|
||||
// ALL + NONE = ALL
|
||||
verifyAppIdPermissionsAfterPackageRemoved(appId++, PERMISSION_TRAFFIC_ALL,
|
||||
new String[]{INTERNET, UPDATE_DEVICE_STATS}, new String[]{});
|
||||
|
||||
// ALL + INTERNET = ALL
|
||||
verifyAppIdPermissionsAfterPackageRemoved(appId++, PERMISSION_TRAFFIC_ALL,
|
||||
new String[]{INTERNET, UPDATE_DEVICE_STATS}, new String[]{INTERNET});
|
||||
|
||||
// ALL + UPDATE_DEVICE_STATS = ALL
|
||||
verifyAppIdPermissionsAfterPackageRemoved(appId++, PERMISSION_TRAFFIC_ALL,
|
||||
new String[]{INTERNET, UPDATE_DEVICE_STATS}, new String[]{UPDATE_DEVICE_STATS});
|
||||
|
||||
// ALL + ALL = ALL
|
||||
verifyAppIdPermissionsAfterPackageRemoved(appId++, PERMISSION_TRAFFIC_ALL,
|
||||
new String[]{INTERNET, UPDATE_DEVICE_STATS},
|
||||
new String[]{INTERNET, UPDATE_DEVICE_STATS});
|
||||
|
||||
/***** UNINSTALL *****/
|
||||
// UNINSTALL + UNINSTALL = UNINSTALL
|
||||
verifyAppIdPermissionsAfterPackageRemoved(
|
||||
appId, PERMISSION_NONE, new String[]{}, new String[]{});
|
||||
removePackage(MOCK_PACKAGE1, MOCK_USER1.getUid(appId));
|
||||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, appId);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user