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

Commit 15e47235 authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Remove network access for idle apps

Track apps going in and out of idle in the NetworkPolicyManagerService.
Apply DROP rules in firewall controller if app is to be blacklisted
for network access.

Firewall can now be in whitelist (old) or blacklist mode. When in
blacklist, it allows all by default and we can selectively DENY
some uids.

Track app idle in UsageStats and update periodically.
Track charging/discharging states.

TODO: Check for appidle temporary parole state

Bug: 20066058
Change-Id: Ia65d7544204b3bcb78a517310ef4adcc05aac6fb
parent 9ac2718e
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import java.util.HashSet;
 */
public class NetworkPolicyManager {

    /* POLICY_* are masks and can be ORed */
    /** No specific network policy, use system default. */
    public static final int POLICY_NONE = 0x0;
    /** Reject network usage on metered networks when application in background. */
@@ -48,10 +49,17 @@ public class NetworkPolicyManager {
    /** Allow network use (metered or not) in the background in battery save mode. */
    public static final int POLICY_ALLOW_BACKGROUND_BATTERY_SAVE = 0x2;

    /* RULE_* are not masks and they must be exclusive */
    /** All network traffic should be allowed. */
    public static final int RULE_ALLOW_ALL = 0x0;
    /** Reject traffic on metered networks. */
    public static final int RULE_REJECT_METERED = 0x1;
    /** Reject traffic on all networks. */
    public static final int RULE_REJECT_ALL = 0x2;

    public static final int FIREWALL_RULE_DEFAULT = 0;
    public static final int FIREWALL_RULE_ALLOW = 1;
    public static final int FIREWALL_RULE_DENY = 2;

    private static final boolean ALLOW_PLATFORM_APP_POLICY = true;

@@ -80,7 +88,7 @@ public class NetworkPolicyManager {
     * Set policy flags for specific UID.
     *
     * @param policy {@link #POLICY_NONE} or combination of flags like
     * {@link #POLICY_REJECT_METERED_BACKGROUND}, {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}.
     * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}.
     */
    public void setUidPolicy(int uid, int policy) {
        try {
@@ -322,6 +330,8 @@ public class NetworkPolicyManager {
        fout.write("[");
        if ((rules & RULE_REJECT_METERED) != 0) {
            fout.write("REJECT_METERED");
        } else if ((rules & RULE_REJECT_ALL) != 0) {
            fout.write("REJECT_ALL");
        }
        fout.write("]");
    }
+1 −1
Original line number Diff line number Diff line
@@ -342,7 +342,7 @@ interface INetworkManagementService
    void setFirewallInterfaceRule(String iface, boolean allow);
    void setFirewallEgressSourceRule(String addr, boolean allow);
    void setFirewallEgressDestRule(String addr, int port, boolean allow);
    void setFirewallUidRule(int uid, boolean allow);
    void setFirewallUidRule(int uid, int rule);

    /**
     * Set all packets from users in ranges to go through VPN specified by netId.
+4 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;

import android.annotation.Nullable;
@@ -832,7 +833,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
            uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
        }

        if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) {
        if ((uidRules & RULE_REJECT_ALL) != 0
                || (networkCostly && (uidRules & RULE_REJECT_METERED) != 0)) {
            return true;
        }

@@ -3490,7 +3492,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
            synchronized(mRulesLock) {
                uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
            }
            if ((uidRules & RULE_REJECT_METERED) != 0) {
            if ((uidRules & (RULE_REJECT_METERED | RULE_REJECT_ALL)) != 0) {
                // we could silently fail or we can filter the available nets to only give
                // them those they have access to.  Chose the more useful
                networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+72 −13
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.Network;
import android.net.NetworkPolicyManager;
import android.net.NetworkStats;
import android.net.NetworkUtils;
import android.net.RouteInfo;
@@ -107,8 +108,8 @@ import java.util.concurrent.CountDownLatch;
 */
public class NetworkManagementService extends INetworkManagementService.Stub
        implements Watchdog.Monitor {
    private static final String TAG = "NetworkManagementService";
    private static final boolean DBG = false;
    private static final String TAG = "NetworkManagement";
    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
    private static final String NETD_TAG = "NetdConnector";
    private static final String NETD_SOCKET_NAME = "netd";

@@ -188,6 +189,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
    /** Set of UIDs with cleartext penalties. */
    @GuardedBy("mQuotaLock")
    private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
    /** Set of UIDs that are to be blocked/allowed by firewall controller. */
    @GuardedBy("mQuotaLock")
    private SparseIntArray mUidFirewallRules = new SparseIntArray();

    private Object mIdleTimerLock = new Object();
    /** Set of interfaces with active idle timers. */
@@ -563,10 +567,19 @@ public class NetworkManagementService extends INetworkManagementService.Stub
                    setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
                }
            }
        }

        // TODO: Push any existing firewall state
            setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled());

            size = mUidFirewallRules.size();
            if (size > 0) {
                Slog.d(TAG, "Pushing " + size + " active firewall UID rules");
                final SparseIntArray uidFirewallRules = mUidFirewallRules;
                mUidFirewallRules = new SparseIntArray();
                for (int i = 0; i < uidFirewallRules.size(); i++) {
                    setFirewallUidRule(uidFirewallRules.keyAt(i), uidFirewallRules.valueAt(i));
                }
            }
        }
    }

    /**
@@ -1899,7 +1912,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
    public void setFirewallEnabled(boolean enabled) {
        enforceSystemUid();
        try {
            mConnector.execute("firewall", enabled ? "enable" : "disable");
            mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist");
            mFirewallEnabled = enabled;
        } catch (NativeDaemonConnectorException e) {
            throw e.rethrowAsParcelableException();
@@ -1949,16 +1962,50 @@ public class NetworkManagementService extends INetworkManagementService.Stub
    }

    @Override
    public void setFirewallUidRule(int uid, boolean allow) {
    public void setFirewallUidRule(int uid, int rule) {
        enforceSystemUid();
        if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
            Preconditions.checkState(mFirewallEnabled);
        final String rule = allow ? "allow" : "deny";
        }
        synchronized (mQuotaLock) {
            final int oldUidFirewallRule = mUidFirewallRules.get(uid);
            if (DBG) {
                Slog.d(TAG, "oldRule = " + oldUidFirewallRule
                        + ", newRule=" + rule + " for uid=" + uid);
            }
            if (oldUidFirewallRule == rule) {
                if (DBG) Slog.d(TAG, "!!!!! Skipping change");
                // TODO: eventually consider throwing
                return;
            }

            try {
            mConnector.execute("firewall", "set_uid_rule", uid, rule);
                String ruleName;
                if (isFirewallEnabled()) { // Whitelist mode
                    if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
                        ruleName = "allow";
                    } else {
                        ruleName = "deny";
                    }
                } else { // Blacklist mode
                    if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
                        ruleName = "deny";
                    } else {
                        ruleName = "allow";
                    }
                }

                if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
                    mUidFirewallRules.delete(uid);
                } else {
                    mUidFirewallRules.put(uid, rule);
                }
                mConnector.execute("firewall", "set_uid_rule", uid, ruleName);
            } catch (NativeDaemonConnectorException e) {
                throw e.rethrowAsParcelableException();
            }
        }
    }

    private static void enforceSystemUid() {
        final int uid = Binder.getCallingUid();
@@ -2072,6 +2119,18 @@ public class NetworkManagementService extends INetworkManagementService.Stub
            pw.println("]");
        }

        synchronized (mUidFirewallRules) {
            pw.print("UID firewall rule: [");
            final int size = mUidFirewallRules.size();
            for (int i = 0; i < size; i++) {
                pw.print(mUidFirewallRules.keyAt(i));
                pw.print(":");
                pw.print(mUidFirewallRules.valueAt(i));
                if (i < size - 1) pw.print(",");
            }
            pw.println("]");
        }

        synchronized (mIdleTimerLock) {
            pw.println("Idle timers:");
            for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
+7 −4
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.server.net;

import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;

import android.app.Notification;
import android.app.NotificationManager;
@@ -31,6 +33,7 @@ import android.net.LinkAddress;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo.State;
import android.net.NetworkPolicyManager;
import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.security.Credentials;
@@ -198,8 +201,8 @@ public class LockdownVpnTracker {
                    setFirewallEgressSourceRule(addr, true);
                }

                mNetService.setFirewallUidRule(ROOT_UID, true);
                mNetService.setFirewallUidRule(Os.getuid(), true);
                mNetService.setFirewallUidRule(ROOT_UID, FIREWALL_RULE_ALLOW);
                mNetService.setFirewallUidRule(Os.getuid(), FIREWALL_RULE_ALLOW);

                mErrorCount = 0;
                mAcceptedIface = iface;
@@ -288,8 +291,8 @@ public class LockdownVpnTracker {
                    setFirewallEgressSourceRule(addr, false);
                }

                mNetService.setFirewallUidRule(ROOT_UID, false);
                mNetService.setFirewallUidRule(Os.getuid(), false);
                mNetService.setFirewallUidRule(ROOT_UID, FIREWALL_RULE_DEFAULT);
                mNetService.setFirewallUidRule(Os.getuid(), FIREWALL_RULE_DEFAULT);

                mAcceptedSourceAddr = null;
            }
Loading