209 lines
9.9 KiB
Diff
209 lines
9.9 KiB
Diff
![]() |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
|
||
|
Date: Wed, 6 Oct 2021 03:05:49 +0300
|
||
|
Subject: [PATCH] enforce INTERNET permission per-uid instead of per-appId
|
||
|
|
||
|
---
|
||
|
bpf_progs/netd.c | 10 +--
|
||
|
.../connectivity/PermissionMonitor.java | 63 ++++++++++++++-----
|
||
|
2 files changed, 48 insertions(+), 25 deletions(-)
|
||
|
|
||
|
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
|
||
|
index 24b3fed58..065f41fd8 100644
|
||
|
--- a/bpf_progs/netd.c
|
||
|
+++ b/bpf_progs/netd.c
|
||
|
@@ -429,14 +429,8 @@ DEFINE_BPF_PROG_EXT("cgroupsock/inet/create", AID_ROOT, AID_ROOT, inet_socket_cr
|
||
|
KVER(4, 14, 0), KVER_INF, false, "fs_bpf_netd_readonly", "")
|
||
|
(struct bpf_sock* sk) {
|
||
|
uint64_t gid_uid = bpf_get_current_uid_gid();
|
||
|
- /*
|
||
|
- * A given app is guaranteed to have the same app ID in all the profiles in
|
||
|
- * which it is installed, and install permission is granted to app for all
|
||
|
- * user at install time so we only check the appId part of a request uid at
|
||
|
- * run time. See UserHandle#isSameApp for detail.
|
||
|
- */
|
||
|
- uint32_t appId = (gid_uid & 0xffffffff) % AID_USER_OFFSET; // == PER_USER_RANGE == 100000
|
||
|
- uint8_t* permissions = bpf_uid_permission_map_lookup_elem(&appId);
|
||
|
+ uint32_t uid = (gid_uid & 0xffffffff);
|
||
|
+ uint8_t* permissions = bpf_uid_permission_map_lookup_elem(&uid);
|
||
|
if (!permissions) {
|
||
|
// UID not in map. Default to just INTERNET permission.
|
||
|
return 1;
|
||
|
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
|
||
|
index 0e265f9ef..4509d9f3f 100755
|
||
|
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
|
||
|
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
|
||
|
@@ -392,6 +392,11 @@ public class PermissionMonitor {
|
||
|
public synchronized void startMonitoring() {
|
||
|
log("Monitoring");
|
||
|
|
||
|
+ mPackageManager.addOnPermissionsChangeListener(uid -> {
|
||
|
+ // traffic permissions are INTERNET and UPDATE_DEVICE_STATS
|
||
|
+ sendPackagePermissionsForUid(uid, getTrafficPermissionForUid(uid));
|
||
|
+ });
|
||
|
+
|
||
|
final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
|
||
|
final IntentFilter intentFilter = new IntentFilter();
|
||
|
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||
|
@@ -566,7 +571,7 @@ public class PermissionMonitor {
|
||
|
mUsersTrafficPermissions.put(user, addedUserAppIds);
|
||
|
// Generate appIds from all users and send result to netd.
|
||
|
final SparseIntArray appIds = makeAppIdsTrafficPermForAllUsers();
|
||
|
- sendAppIdsTrafficPermission(appIds);
|
||
|
+ sendUidsTrafficPermission(user.getIdentifier(), appIds);
|
||
|
|
||
|
// Log user added
|
||
|
mPermissionUpdateLogs.log("New user(" + user.getIdentifier() + ") added: nPerm uids="
|
||
|
@@ -614,7 +619,7 @@ public class PermissionMonitor {
|
||
|
appIds.put(appId, PERMISSION_UNINSTALLED);
|
||
|
}
|
||
|
}
|
||
|
- sendAppIdsTrafficPermission(appIds);
|
||
|
+ sendUidsTrafficPermission(user.getIdentifier(), appIds);
|
||
|
|
||
|
// Log user removed
|
||
|
mPermissionUpdateLogs.log("User(" + user.getIdentifier() + ") removed: nPerm uids="
|
||
|
@@ -734,16 +739,25 @@ public class PermissionMonitor {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- private synchronized int getAppIdTrafficPermission(int appId) {
|
||
|
+ private synchronized int getUidTrafficPermission(final int uid) {
|
||
|
+ final int userId = UserHandle.getUserId(uid);
|
||
|
+
|
||
|
int permission = PERMISSION_NONE;
|
||
|
boolean installed = false;
|
||
|
+
|
||
|
for (UserHandle user : mUsersTrafficPermissions.keySet()) {
|
||
|
+ if (user.getIdentifier() != userId) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
final SparseIntArray userApps = mUsersTrafficPermissions.get(user);
|
||
|
+ final int appId = UserHandle.getAppId(uid);
|
||
|
final int appIdx = userApps.indexOfKey(appId);
|
||
|
if (appIdx >= 0) {
|
||
|
permission |= userApps.valueAt(appIdx);
|
||
|
installed = true;
|
||
|
}
|
||
|
+ break;
|
||
|
}
|
||
|
return installed ? permission : PERMISSION_UNINSTALLED;
|
||
|
}
|
||
|
@@ -761,8 +775,8 @@ public class PermissionMonitor {
|
||
|
updateAppIdTrafficPermission(uid);
|
||
|
// Get the appId permission from all users then send the latest permission to netd.
|
||
|
final int appId = UserHandle.getAppId(uid);
|
||
|
- final int appIdTrafficPerm = getAppIdTrafficPermission(appId);
|
||
|
- sendPackagePermissionsForAppId(appId, appIdTrafficPerm);
|
||
|
+ final int uidTrafficPerm = getUidTrafficPermission(uid);
|
||
|
+ sendPackagePermissionsForUid(uid, uidTrafficPerm);
|
||
|
|
||
|
final int currentPermission = mUidToNetworkPerm.get(uid, PERMISSION_NONE);
|
||
|
final int permission = highestPermissionForUid(uid, currentPermission, packageName);
|
||
|
@@ -792,7 +806,7 @@ public class PermissionMonitor {
|
||
|
mPermissionUpdateLogs.log("Package add: name=" + packageName + ", uid=" + uid
|
||
|
+ ", nPerm=(" + permissionToString(permission) + "/"
|
||
|
+ permissionToString(currentPermission) + ")"
|
||
|
- + ", tPerm=" + permissionToString(appIdTrafficPerm));
|
||
|
+ + ", tPerm=" + permissionToString(uidTrafficPerm));
|
||
|
}
|
||
|
|
||
|
private int highestUidNetworkPermission(int uid) {
|
||
|
@@ -824,8 +838,8 @@ public class PermissionMonitor {
|
||
|
updateAppIdTrafficPermission(uid);
|
||
|
// Get the appId permission from all users then send the latest permission to netd.
|
||
|
final int appId = UserHandle.getAppId(uid);
|
||
|
- final int appIdTrafficPerm = getAppIdTrafficPermission(appId);
|
||
|
- sendPackagePermissionsForAppId(appId, appIdTrafficPerm);
|
||
|
+ final int uidTrafficPerm = getUidTrafficPermission(uid);
|
||
|
+ sendPackagePermissionsForUid(uid, uidTrafficPerm);
|
||
|
|
||
|
// 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
|
||
|
@@ -845,7 +859,7 @@ public class PermissionMonitor {
|
||
|
mPermissionUpdateLogs.log("Package remove: name=" + packageName + ", uid=" + uid
|
||
|
+ ", nPerm=(" + permissionToString(permission) + "/"
|
||
|
+ permissionToString(currentPermission) + ")"
|
||
|
- + ", tPerm=" + permissionToString(appIdTrafficPerm));
|
||
|
+ + ", tPerm=" + permissionToString(uidTrafficPerm));
|
||
|
|
||
|
if (permission != currentPermission) {
|
||
|
final SparseIntArray apps = new SparseIntArray();
|
||
|
@@ -1097,14 +1111,17 @@ public class PermissionMonitor {
|
||
|
* @hide
|
||
|
*/
|
||
|
@VisibleForTesting
|
||
|
- void sendPackagePermissionsForAppId(int appId, int permissions) {
|
||
|
+ void sendPackagePermissionsForUid(int uid, int permissions) {
|
||
|
+ int userId = UserHandle.getUserId(uid);
|
||
|
+ int appId = UserHandle.getAppId(uid);
|
||
|
+
|
||
|
SparseIntArray netdPermissionsAppIds = new SparseIntArray();
|
||
|
netdPermissionsAppIds.put(appId, permissions);
|
||
|
if (hasSdkSandbox(appId)) {
|
||
|
int sdkSandboxAppId = sProcessShim.toSdkSandboxUid(appId);
|
||
|
netdPermissionsAppIds.put(sdkSandboxAppId, permissions);
|
||
|
}
|
||
|
- sendAppIdsTrafficPermission(netdPermissionsAppIds);
|
||
|
+ sendUidsTrafficPermission(userId, netdPermissionsAppIds);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
@@ -1116,7 +1133,7 @@ public class PermissionMonitor {
|
||
|
* @hide
|
||
|
*/
|
||
|
@VisibleForTesting
|
||
|
- void sendAppIdsTrafficPermission(SparseIntArray netdPermissionsAppIds) {
|
||
|
+ void sendUidsTrafficPermission(final int userId, SparseIntArray netdPermissionsAppIds) {
|
||
|
final ArrayList<Integer> allPermissionAppIds = new ArrayList<>();
|
||
|
final ArrayList<Integer> internetPermissionAppIds = new ArrayList<>();
|
||
|
final ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>();
|
||
|
@@ -1150,29 +1167,41 @@ public class PermissionMonitor {
|
||
|
if (allPermissionAppIds.size() != 0) {
|
||
|
mBpfNetMaps.setNetPermForUids(
|
||
|
PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS,
|
||
|
- toIntArray(allPermissionAppIds));
|
||
|
+ appIdListToUidArray(userId, allPermissionAppIds));
|
||
|
}
|
||
|
if (internetPermissionAppIds.size() != 0) {
|
||
|
mBpfNetMaps.setNetPermForUids(PERMISSION_INTERNET,
|
||
|
- toIntArray(internetPermissionAppIds));
|
||
|
+ appIdListToUidArray(userId, internetPermissionAppIds));
|
||
|
}
|
||
|
if (updateStatsPermissionAppIds.size() != 0) {
|
||
|
mBpfNetMaps.setNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS,
|
||
|
- toIntArray(updateStatsPermissionAppIds));
|
||
|
+ appIdListToUidArray(userId, updateStatsPermissionAppIds));
|
||
|
}
|
||
|
if (noPermissionAppIds.size() != 0) {
|
||
|
mBpfNetMaps.setNetPermForUids(PERMISSION_NONE,
|
||
|
- toIntArray(noPermissionAppIds));
|
||
|
+ appIdListToUidArray(userId, noPermissionAppIds));
|
||
|
}
|
||
|
if (uninstalledAppIds.size() != 0) {
|
||
|
mBpfNetMaps.setNetPermForUids(PERMISSION_UNINSTALLED,
|
||
|
- toIntArray(uninstalledAppIds));
|
||
|
+ appIdListToUidArray(userId, uninstalledAppIds));
|
||
|
}
|
||
|
} catch (RemoteException | ServiceSpecificException e) {
|
||
|
Log.e(TAG, "Pass appId list of special permission failed." + e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ private static int[] appIdListToUidArray(int userId, ArrayList<Integer> appIds) {
|
||
|
+ final int cnt = appIds.size();
|
||
|
+ int[] array = new int[cnt];
|
||
|
+
|
||
|
+ for (int i = 0; i < cnt; ++i) {
|
||
|
+ int appId = appIds.get(i).intValue();
|
||
|
+ array[i] = UserHandle.getUid(userId, appId);
|
||
|
+ }
|
||
|
+
|
||
|
+ return array;
|
||
|
+ }
|
||
|
+
|
||
|
/** Should only be used by unit tests */
|
||
|
@VisibleForTesting
|
||
|
public Set<UidRange> getVpnInterfaceUidRanges(String iface) {
|