Setup permissions for SDK sandbox UIDs.

Applications may have an additional SDK sandbox process that should run
with the same network policy as the app itself. There is a 1:1 mapping
between appId and the SDK sandbox process that belongs to it; use that
mapping to set the same policy for SDK sandbox processes as for the app
that they belong to.

Bug: 215012578
Test: atest com.android.server.PermissionMonitorTest
Change-Id: Ibd2ada09c94d46e048f5731b90a721d8e85d3289
This commit is contained in:
Martijn Coenen
2022-02-04 14:25:22 +01:00
parent 422c7dd460
commit 3f01be0407
2 changed files with 116 additions and 4 deletions

View File

@@ -52,6 +52,7 @@ import android.net.UidRange;
import android.net.Uri;
import android.net.util.SharedLog;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.SystemConfigManager;
@@ -66,7 +67,10 @@ import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.CollectionUtils;
import com.android.networkstack.apishim.ProcessShimImpl;
import com.android.networkstack.apishim.common.ProcessShim;
import com.android.server.BpfNetMaps;
import java.util.ArrayList;
@@ -95,6 +99,8 @@ public class PermissionMonitor {
private final Context mContext;
private final BpfNetMaps mBpfNetMaps;
private static final ProcessShim sProcessShim = ProcessShimImpl.newInstance();
@GuardedBy("this")
private final Set<UserHandle> mUsers = new HashSet<>();
@@ -235,6 +241,10 @@ public class PermissionMonitor {
}
}
private static boolean hasSdkSandbox(final int uid) {
return SdkLevel.isAtLeastT() && Process.isApplicationUid(uid);
}
// Return the network permission for the passed list of apps. Note that this depends on the
// current settings of the device (See isUidAllowedOnRestrictedNetworks).
private SparseIntArray makeUidsNetworkPerm(final List<PackageInfo> apps) {
@@ -247,6 +257,10 @@ public class PermissionMonitor {
final int permission = getPackageNetdNetworkPermission(app);
if (isHigherNetworkPermission(permission, uidsPerm.get(uid, PERMISSION_NONE))) {
uidsPerm.put(uid, permission);
if (hasSdkSandbox(uid)) {
int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
uidsPerm.put(sdkSandboxUid, permission);
}
}
}
return uidsPerm;
@@ -262,7 +276,11 @@ public class PermissionMonitor {
}
final int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions,
app.requestedPermissionsFlags);
appIdsPerm.put(appId, appIdsPerm.get(appId) | otherNetdPerms);
final int permission = appIdsPerm.get(appId) | otherNetdPerms;
appIdsPerm.put(appId, permission);
if (hasSdkSandbox(appId)) {
appIdsPerm.put(sProcessShim.toSdkSandboxUid(appId), permission);
}
}
return appIdsPerm;
}
@@ -288,11 +306,19 @@ public class PermissionMonitor {
final SparseIntArray appIdsPerm = new SparseIntArray();
for (final int uid : mSystemConfigManager.getSystemPermissionUids(INTERNET)) {
final int appId = UserHandle.getAppId(uid);
appIdsPerm.put(appId, appIdsPerm.get(appId) | PERMISSION_INTERNET);
final int permission = appIdsPerm.get(appId) | PERMISSION_INTERNET;
appIdsPerm.put(appId, permission);
if (hasSdkSandbox(appId)) {
appIdsPerm.put(sProcessShim.toSdkSandboxUid(appId), permission);
}
}
for (final int uid : mSystemConfigManager.getSystemPermissionUids(UPDATE_DEVICE_STATS)) {
final int appId = UserHandle.getAppId(uid);
appIdsPerm.put(appId, appIdsPerm.get(appId) | PERMISSION_UPDATE_DEVICE_STATS);
final int permission = appIdsPerm.get(appId) | PERMISSION_UPDATE_DEVICE_STATS;
appIdsPerm.put(appId, permission);
if (hasSdkSandbox(appId)) {
appIdsPerm.put(sProcessShim.toSdkSandboxUid(appId), permission);
}
}
return appIdsPerm;
}
@@ -592,6 +618,12 @@ public class PermissionMonitor {
SparseIntArray apps = new SparseIntArray();
apps.put(uid, permission);
if (hasSdkSandbox(uid)) {
int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
mUidToNetworkPerm.put(sdkSandboxUid, permission);
apps.put(sdkSandboxUid, permission);
}
sendUidsNetworkPermission(apps, true /* add */);
}
@@ -654,13 +686,25 @@ public class PermissionMonitor {
+ ", tPerm=" + permissionToString(trafficPerm));
if (permission != currentPermission) {
final SparseIntArray apps = new SparseIntArray();
int sdkSandboxUid = -1;
if (hasSdkSandbox(uid)) {
sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
}
if (permission == PERMISSION_NONE) {
mUidToNetworkPerm.delete(uid);
apps.put(uid, PERMISSION_NETWORK); // doesn't matter which permission we pick here
if (sdkSandboxUid != -1) {
mUidToNetworkPerm.delete(sdkSandboxUid);
apps.put(sdkSandboxUid, PERMISSION_NETWORK);
}
sendUidsNetworkPermission(apps, false);
} else {
mUidToNetworkPerm.put(uid, permission);
apps.put(uid, permission);
if (sdkSandboxUid != -1) {
mUidToNetworkPerm.put(sdkSandboxUid, permission);
apps.put(sdkSandboxUid, permission);
}
sendUidsNetworkPermission(apps, true);
}
}
@@ -828,6 +872,10 @@ public class PermissionMonitor {
void sendPackagePermissionsForAppId(int appId, int permissions) {
SparseIntArray netdPermissionsAppIds = new SparseIntArray();
netdPermissionsAppIds.put(appId, permissions);
if (hasSdkSandbox(appId)) {
int sdkSandboxAppId = sProcessShim.toSdkSandboxUid(appId);
netdPermissionsAppIds.put(sdkSandboxAppId, permissions);
}
sendAppIdsTrafficPermission(netdPermissionsAppIds);
}
@@ -925,9 +973,19 @@ public class PermissionMonitor {
// Doesn't matter which permission is set here.
removedUids.put(uid, PERMISSION_NETWORK);
mUidToNetworkPerm.delete(uid);
if (hasSdkSandbox(uid)) {
int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
removedUids.put(sdkSandboxUid, PERMISSION_NETWORK);
mUidToNetworkPerm.delete(sdkSandboxUid);
}
} else {
updatedUids.put(uid, permission);
mUidToNetworkPerm.put(uid, permission);
if (hasSdkSandbox(uid)) {
int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
updatedUids.put(sdkSandboxUid, permission);
mUidToNetworkPerm.put(sdkSandboxUid, permission);
}
}
}

View File

@@ -77,6 +77,7 @@ import android.net.INetd;
import android.net.UidRange;
import android.net.Uri;
import android.os.Build;
import android.os.Process;
import android.os.SystemConfigManager;
import android.os.UserHandle;
import android.os.UserManager;
@@ -88,7 +89,10 @@ import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.CollectionUtils;
import com.android.networkstack.apishim.ProcessShimImpl;
import com.android.networkstack.apishim.common.ProcessShim;
import com.android.server.BpfNetMaps;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -153,6 +157,8 @@ public class PermissionMonitorTest {
private NetdMonitor mNetdMonitor;
private BpfMapMonitor mBpfMapMonitor;
private ProcessShim mProcessShim = ProcessShimImpl.newInstance();
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -197,6 +203,10 @@ public class PermissionMonitorTest {
return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo);
}
private boolean hasSdkSandbox(final int uid) {
return SdkLevel.isAtLeastT() && Process.isApplicationUid(uid);
}
private static PackageInfo systemPackageInfoWithPermissions(String... permissions) {
return packageInfoWithPermissions(
REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM);
@@ -493,6 +503,11 @@ public class PermissionMonitorTest {
String... permissions) throws Exception {
addPackage(name, uid, permissions);
assertEquals(hasPermission, mPermissionMonitor.hasUseBackgroundNetworksPermission(uid));
if (hasSdkSandbox(uid)) {
final int sdkSandboxUid = mProcessShim.toSdkSandboxUid(uid);
assertEquals(hasPermission,
mPermissionMonitor.hasUseBackgroundNetworksPermission(sdkSandboxUid));
}
}
@Test
@@ -531,7 +546,7 @@ public class PermissionMonitorTest {
}).when(mockBpfmap).setNetPermForUids(anyInt(), any(int[].class));
}
public void expectTrafficPerm(int permission, int... appIds) {
public void expectTrafficPerm(int permission, Integer... appIds) {
for (final int appId : appIds) {
if (mAppIdsTrafficPermission.get(appId, DOES_NOT_EXIST) == DOES_NOT_EXIST) {
fail("appId " + appId + " does not exist.");
@@ -540,6 +555,17 @@ public class PermissionMonitorTest {
fail("appId " + appId + " has wrong permission: "
+ mAppIdsTrafficPermission.get(appId));
}
if (hasSdkSandbox(appId)) {
int sdkSandboxAppId = mProcessShim.toSdkSandboxUid(appId);
if (mAppIdsTrafficPermission.get(sdkSandboxAppId, DOES_NOT_EXIST)
== DOES_NOT_EXIST) {
fail("SDK sandbox appId " + sdkSandboxAppId + " does not exist.");
}
if (mAppIdsTrafficPermission.get(sdkSandboxAppId) != permission) {
fail("SDK sandbox appId " + sdkSandboxAppId + " has wrong permission: "
+ mAppIdsTrafficPermission.get(sdkSandboxAppId));
}
}
}
}
}
@@ -589,6 +615,17 @@ public class PermissionMonitorTest {
if (mUidsNetworkPermission.get(uid) != permission) {
fail("uid " + uid + " has wrong permission: " + permission);
}
if (hasSdkSandbox(uid)) {
int sdkSandboxUid = mProcessShim.toSdkSandboxUid(uid);
if (mUidsNetworkPermission.get(sdkSandboxUid, DOES_NOT_EXIST)
== DOES_NOT_EXIST) {
fail("SDK sandbox uid " + uid + " does not exist.");
}
if (mUidsNetworkPermission.get(sdkSandboxUid) != permission) {
fail("SDK sandbox uid " + uid + " has wrong permission: "
+ permission);
}
}
}
}
}
@@ -600,6 +637,14 @@ public class PermissionMonitorTest {
if (mUidsNetworkPermission.get(uid, DOES_NOT_EXIST) != DOES_NOT_EXIST) {
fail("uid " + uid + " has listed permissions, expected none.");
}
if (hasSdkSandbox(uid)) {
int sdkSandboxUid = mProcessShim.toSdkSandboxUid(uid);
if (mUidsNetworkPermission.get(sdkSandboxUid, DOES_NOT_EXIST)
!= DOES_NOT_EXIST) {
fail("SDK sandbox uid " + sdkSandboxUid
+ " has listed permissions, expected none.");
}
}
}
}
}
@@ -785,9 +830,18 @@ public class PermissionMonitorTest {
// MOCK_APPID2: MOCK_PACKAGE2 does not have any permission.
// SYSTEM_APPID1: SYSTEM_PACKAGE1 has internet permission and update device stats permission
// SYSTEM_APPID2: SYSTEM_PACKAGE2 has only update device stats permission.
// The SDK sandbox APPIDs must have permissions mirroring the app
SparseIntArray netdPermissionsAppIds = new SparseIntArray();
netdPermissionsAppIds.put(MOCK_APPID1, PERMISSION_INTERNET);
if (hasSdkSandbox(MOCK_APPID1)) {
netdPermissionsAppIds.put(mProcessShim.toSdkSandboxUid(MOCK_APPID1),
PERMISSION_INTERNET);
}
netdPermissionsAppIds.put(MOCK_APPID2, PERMISSION_NONE);
if (hasSdkSandbox(MOCK_APPID2)) {
netdPermissionsAppIds.put(mProcessShim.toSdkSandboxUid(MOCK_APPID2),
PERMISSION_NONE);
}
netdPermissionsAppIds.put(SYSTEM_APPID1, PERMISSION_TRAFFIC_ALL);
netdPermissionsAppIds.put(SYSTEM_APPID2, PERMISSION_UPDATE_DEVICE_STATS);