Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ba3b2ec authored by Oliver Scott's avatar Oliver Scott Committed by Michael Bestas
Browse files

fixup! fw/b: Add support for allowing/disallowing apps on cellular, vpn and wifi networks

* Listen to changes in all networks
* Limit backend calls during network capability changes to transport changes
* Allow traffic over VPN networks if policy does not restrict it even if other transports are present

Change-Id: I0d719bb7c7f04a493a4ddefa8e6154ef4159abd0
parent 263c70d6
Loading
Loading
Loading
Loading
+79 −16
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
@@ -626,6 +627,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    /** Map from network ID to last observed roaming state */
    @GuardedBy("mNetworkPoliciesSecondLock")
    private final SparseBooleanArray mNetworkRoaming = new SparseBooleanArray();
    /** Map from network ID to last observed transports state */
    @GuardedBy("mNetworkPoliciesSecondLock")
    private final SparseArray<int[]> mNetworkTransports = new SparseArray<>();

    /** Map from netId to subId as of last update */
    @GuardedBy("mNetworkPoliciesSecondLock")
@@ -1027,6 +1031,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                    ACTION_CARRIER_CONFIG_CHANGED);
            mContext.registerReceiver(mCarrierConfigReceiver, carrierConfigFilter, null, mHandler);

            for (UserInfo userInfo : mUserManager.getAliveUsers()) {
                mConnManager.registerDefaultNetworkCallbackForUid(
                        UserHandle.getUid(userInfo.id, Process.myUid()),
                        mDefaultNetworkCallback,
                        mUidEventHandler
                );
            }

            // listen for meteredness changes
            mConnManager.registerNetworkCallback(
                    new NetworkRequest.Builder().build(), mNetworkCallback);
@@ -1207,6 +1219,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                                ConnectivitySettingsManager.getUidsAllowedOnRestrictedNetworks(
                                        mContext);
                        if (action == ACTION_USER_ADDED) {
                            mConnManager.registerDefaultNetworkCallbackForUid(
                                    UserHandle.getUid(userId, Process.myUid()),
                                    mDefaultNetworkCallback,
                                    mUidEventHandler
                            );
                            // Add apps that are allowed by default.
                            addDefaultRestrictBackgroundAllowlistUidsUL(userId);
                            try {
@@ -1311,6 +1328,35 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        return changed;
    }

    private static boolean updateTransportChange(SparseArray<int[]> lastValues, int[] newValue,
            Network network) {
        final int[] lastValue = lastValues.get(network.getNetId(), new int[]{});
        final boolean changed = (!Arrays.equals(lastValue, newValue))
                || lastValues.indexOfKey(network.getNetId()) < 0;
        if (changed) {
            lastValues.put(network.getNetId(), newValue);
        }
        return changed;
    }

    private final NetworkCallback mDefaultNetworkCallback = new NetworkCallback() {
        @Override
        public void onAvailable(@NonNull Network network) {
            updateRestrictedModeAllowlistUL();
        }

        @Override
        public void onCapabilitiesChanged(@NonNull Network network,
                @NonNull NetworkCapabilities networkCapabilities) {
            final int[] newTransports = networkCapabilities.getTransportTypes();
            final boolean transportsChanged = updateTransportChange(
                    mNetworkTransports, newTransports, network);
            if (transportsChanged) {
                updateRestrictedModeAllowlistUL();
            }
        }
    };

    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
        @Override
        public void onCapabilitiesChanged(Network network,
@@ -1332,7 +1378,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                    mLogger.meterednessChanged(network.getNetId(), newMetered);
                    updateNetworkRulesNL();
                }
                updateRestrictedModeAllowlistUL();
            }
        }
    };
@@ -4252,33 +4297,51 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    }

    private boolean hasRestrictedModeAccess(int uid) {
        final long token = Binder.clearCallingIdentity();
        try {
            NetworkCapabilities nc = mConnManager.getNetworkCapabilities(
                    mConnManager.getActiveNetwork());
            Binder.restoreCallingIdentity(token);
            int policy = getUidPolicy(uid);
            if (nc != null
                    && ((nc.hasTransport(TRANSPORT_VPN) && ((policy & POLICY_REJECT_VPN) != 0))
                    || (nc.hasTransport(TRANSPORT_CELLULAR) && ((policy & POLICY_REJECT_CELLULAR)
                    != 0))
                    || (nc.hasTransport(TRANSPORT_WIFI) && ((policy & POLICY_REJECT_WIFI) != 0)))) {
                return false;
            }
            // TODO: this needs to be kept in sync with
            // PermissionMonitor#hasRestrictedNetworkPermission
            return ConnectivitySettingsManager.getUidsAllowedOnRestrictedNetworks(mContext)
            // Check for restricted-networking-mode status
            final boolean isUidAllowedOnRestrictedNetworks =
                    ConnectivitySettingsManager.getUidsAllowedOnRestrictedNetworks(mContext)
                    .contains(uid)
                    || mIPm.checkUidPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, uid)
                    == PERMISSION_GRANTED
                    || mIPm.checkUidPermission(NETWORK_STACK, uid) == PERMISSION_GRANTED
                    || mIPm.checkUidPermission(PERMISSION_MAINLINE_NETWORK_STACK, uid)
                    == PERMISSION_GRANTED;
        } catch (RemoteException e) {
            return false;

            // Check for other policies (data-restrictions)
            final long token = Binder.clearCallingIdentity();
            NetworkCapabilities nc;
            try {
                nc = mConnManager.getNetworkCapabilities(mConnManager.getActiveNetwork());
            } finally {
                Binder.restoreCallingIdentity(token);
            }
            boolean isUidRestrictedByPolicy = false;
            if (isUidAllowedOnRestrictedNetworks && nc != null) {
                int policy = getUidPolicy(uid);
                final boolean isUidAllowedOnVpn = nc.hasTransport(TRANSPORT_VPN)
                        && ((policy & POLICY_REJECT_VPN) == 0);
                if (!isUidAllowedOnVpn) {
                    final boolean isUidRestrictedOnCell = nc.hasTransport(TRANSPORT_CELLULAR)
                            && ((policy & POLICY_REJECT_CELLULAR) != 0);
                    final boolean isUidRestrictedOnVpn = nc.hasTransport(TRANSPORT_VPN)
                            && ((policy & POLICY_REJECT_VPN) != 0);
                    final boolean isUidRestrictedOnWifi = nc.hasTransport(TRANSPORT_WIFI)
                            && ((policy & POLICY_REJECT_WIFI) != 0);
                    if (isUidRestrictedOnVpn || isUidRestrictedOnCell || isUidRestrictedOnWifi) {
                            isUidRestrictedByPolicy = true;
                    }
                }
            }
            // If app is restricted (aka not on the allowlist), it's not allowed to use the internet
            // If it is on the allowlist, then we also check its networking is not blocked
            // (aka active network is not null) and then other policies
            return isUidAllowedOnRestrictedNetworks && nc != null && !isUidRestrictedByPolicy;
        } catch (RemoteException e) {
            return false;
        }
    }

    @GuardedBy("mUidRulesFirstLock")