diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java index ac46054381..2885ba78dd 100755 --- a/service/src/com/android/server/connectivity/PermissionMonitor.java +++ b/service/src/com/android/server/connectivity/PermissionMonitor.java @@ -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 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 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); + } } } diff --git a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java index 65905430f5..6b379e83f1 100644 --- a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -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);