1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.net; 18 19 import static android.Manifest.permission.CONNECTIVITY_INTERNAL; 20 import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND; 21 import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE; 22 import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY; 23 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW; 24 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_ADMIN; 25 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER; 26 import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE; 27 import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED; 28 import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY; 29 import static android.net.INetd.FIREWALL_ALLOWLIST; 30 import static android.net.INetd.FIREWALL_CHAIN_NONE; 31 import static android.net.INetd.FIREWALL_DENYLIST; 32 import static android.net.INetd.FIREWALL_RULE_ALLOW; 33 import static android.net.INetd.FIREWALL_RULE_DENY; 34 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_BACKGROUND; 35 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE; 36 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY; 37 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_METERED_ALLOW; 38 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_METERED_DENY_ADMIN; 39 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_METERED_DENY_USER; 40 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE; 41 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED; 42 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY; 43 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; 44 45 import android.annotation.NonNull; 46 import android.app.ActivityManager; 47 import android.content.Context; 48 import android.net.ConnectivityManager; 49 import android.net.INetd; 50 import android.net.INetdUnsolicitedEventListener; 51 import android.net.INetworkManagementEventObserver; 52 import android.net.InetAddresses; 53 import android.net.InterfaceConfiguration; 54 import android.net.InterfaceConfigurationParcel; 55 import android.net.IpPrefix; 56 import android.net.LinkAddress; 57 import android.net.NetworkPolicyManager; 58 import android.net.RouteInfo; 59 import android.net.util.NetdService; 60 import android.os.BatteryStats; 61 import android.os.Binder; 62 import android.os.Handler; 63 import android.os.IBinder; 64 import android.os.INetworkManagementService; 65 import android.os.PermissionEnforcer; 66 import android.os.Process; 67 import android.os.RemoteCallbackList; 68 import android.os.RemoteException; 69 import android.os.ServiceManager; 70 import android.os.ServiceSpecificException; 71 import android.os.StrictMode; 72 import android.os.SystemClock; 73 import android.os.Trace; 74 import android.text.TextUtils; 75 import android.util.Log; 76 import android.util.Slog; 77 import android.util.SparseBooleanArray; 78 import android.util.SparseIntArray; 79 80 import com.android.internal.annotations.GuardedBy; 81 import com.android.internal.app.IBatteryStats; 82 import com.android.internal.util.DumpUtils; 83 import com.android.internal.util.HexDump; 84 import com.android.modules.utils.build.SdkLevel; 85 import com.android.net.module.util.NetdUtils; 86 import com.android.net.module.util.PermissionUtils; 87 import com.android.server.FgThread; 88 import com.android.server.LocalServices; 89 90 import com.google.android.collect.Maps; 91 92 import java.io.FileDescriptor; 93 import java.io.PrintWriter; 94 import java.net.InetAddress; 95 import java.util.ArrayList; 96 import java.util.HashMap; 97 import java.util.Map; 98 99 /** 100 * @hide 101 */ 102 public class NetworkManagementService extends INetworkManagementService.Stub { 103 104 /** 105 * Helper class that encapsulates NetworkManagementService dependencies and makes them 106 * easier to mock in unit tests. 107 */ 108 static class Dependencies { getService(String name)109 public IBinder getService(String name) { 110 return ServiceManager.getService(name); 111 } registerLocalService(NetworkManagementInternal nmi)112 public void registerLocalService(NetworkManagementInternal nmi) { 113 LocalServices.addService(NetworkManagementInternal.class, nmi); 114 } getNetd()115 public INetd getNetd() { 116 return NetdService.get(); 117 } 118 getCallingUid()119 public int getCallingUid() { 120 return Binder.getCallingUid(); 121 } 122 } 123 124 private static final String TAG = "NetworkManagement"; 125 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); 126 127 /** 128 * Binder context for this service 129 */ 130 private final Context mContext; 131 132 private final Handler mDaemonHandler; 133 134 private final Dependencies mDeps; 135 136 private INetd mNetdService; 137 138 private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener; 139 140 private IBatteryStats mBatteryStats; 141 142 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers = 143 new RemoteCallbackList<>(); 144 145 /** 146 * If both locks need to be held, then they should be obtained in the order: 147 * first {@link #mQuotaLock} and then {@link #mRulesLock}. 148 */ 149 private final Object mQuotaLock = new Object(); 150 private final Object mRulesLock = new Object(); 151 152 private final boolean mUseMeteredFirewallChains; 153 154 /** Set of interfaces with active quotas. */ 155 @GuardedBy("mQuotaLock") 156 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap(); 157 /** Set of interfaces with active alerts. */ 158 @GuardedBy("mQuotaLock") 159 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap(); 160 /** Set of UIDs denied on metered networks. */ 161 // TODO: b/336693007 - Remove once NPMS has completely migrated to metered firewall chains. 162 @GuardedBy("mRulesLock") 163 private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray(); 164 /** Set of UIDs allowed on metered networks. */ 165 // TODO: b/336693007 - Remove once NPMS has completely migrated to metered firewall chains. 166 @GuardedBy("mRulesLock") 167 private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray(); 168 /** Set of UIDs with cleartext penalties. */ 169 @GuardedBy("mQuotaLock") 170 private SparseIntArray mUidCleartextPolicy = new SparseIntArray(); 171 /** Set of UIDs that are to be blocked/allowed by firewall controller. */ 172 @GuardedBy("mRulesLock") 173 private final SparseIntArray mUidFirewallRules = new SparseIntArray(); 174 /** 175 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches 176 * to application idles. 177 */ 178 @GuardedBy("mRulesLock") 179 private final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray(); 180 /** 181 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches 182 * to device idles. 183 */ 184 @GuardedBy("mRulesLock") 185 private final SparseIntArray mUidFirewallDozableRules = new SparseIntArray(); 186 /** 187 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches 188 * to device on power-save mode. 189 */ 190 @GuardedBy("mRulesLock") 191 private final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray(); 192 /** 193 * Contains the per-UID firewall rules that are used when Restricted Networking Mode is enabled. 194 */ 195 @GuardedBy("mRulesLock") 196 private final SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray(); 197 /** 198 * Contains the per-UID firewall rules that are used when Low Power Standby is enabled. 199 */ 200 @GuardedBy("mRulesLock") 201 private final SparseIntArray mUidFirewallLowPowerStandbyRules = new SparseIntArray(); 202 203 /** 204 * Contains the per-UID firewall rules that are used when Background chain is enabled. 205 */ 206 @GuardedBy("mRulesLock") 207 private final SparseIntArray mUidFirewallBackgroundRules = new SparseIntArray(); 208 209 /** 210 * Contains the per-UID firewall rules that are used to allowlist the app from metered-network 211 * restrictions when data saver is enabled. 212 */ 213 @GuardedBy("mRulesLock") 214 private final SparseIntArray mUidMeteredFirewallAllowRules = new SparseIntArray(); 215 216 /** 217 * Contains the per-UID firewall rules that are used to deny app access to metered networks 218 * due to user action. 219 */ 220 @GuardedBy("mRulesLock") 221 private final SparseIntArray mUidMeteredFirewallDenyUserRules = new SparseIntArray(); 222 223 /** 224 * Contains the per-UID firewall rules that are used to deny app access to metered networks 225 * due to admin action. 226 */ 227 @GuardedBy("mRulesLock") 228 private final SparseIntArray mUidMeteredFirewallDenyAdminRules = new SparseIntArray(); 229 230 /** Set of states for the child firewall chains. True if the chain is active. */ 231 @GuardedBy("mRulesLock") 232 final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray(); 233 234 // TODO: b/336693007 - Remove once NPMS has completely migrated to metered firewall chains. 235 @GuardedBy("mQuotaLock") 236 private volatile boolean mDataSaverMode; 237 238 private volatile boolean mFirewallEnabled; 239 private volatile boolean mStrictEnabled; 240 241 /** 242 * Constructs a new NetworkManagementService instance 243 * 244 * @param context Binder context for this service 245 */ NetworkManagementService( Context context, Dependencies deps)246 private NetworkManagementService( 247 Context context, Dependencies deps) { 248 super(PermissionEnforcer.fromContext(context)); 249 mContext = context; 250 mDeps = deps; 251 252 mUseMeteredFirewallChains = Flags.useMeteredFirewallChains(); 253 254 if (mUseMeteredFirewallChains) { 255 // These firewalls are always on and currently ConnectivityService does not allow 256 // changing their enabled state. 257 mFirewallChainStates.put(FIREWALL_CHAIN_METERED_DENY_USER, true); 258 mFirewallChainStates.put(FIREWALL_CHAIN_METERED_DENY_ADMIN, true); 259 } 260 261 mDaemonHandler = new Handler(FgThread.get().getLooper()); 262 263 mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener(); 264 265 mDeps.registerLocalService(new LocalService()); 266 } 267 create(Context context, Dependencies deps)268 static NetworkManagementService create(Context context, Dependencies deps) 269 throws InterruptedException { 270 final NetworkManagementService service = 271 new NetworkManagementService(context, deps); 272 if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); 273 if (DBG) Slog.d(TAG, "Connecting native netd service"); 274 service.connectNativeNetdService(); 275 if (DBG) Slog.d(TAG, "Connected"); 276 return service; 277 } 278 create(Context context)279 public static NetworkManagementService create(Context context) throws InterruptedException { 280 return create(context, new Dependencies()); 281 } 282 systemReady()283 public void systemReady() { 284 if (DBG) { 285 final long start = System.currentTimeMillis(); 286 prepareNativeDaemon(); 287 final long delta = System.currentTimeMillis() - start; 288 Slog.d(TAG, "Prepared in " + delta + "ms"); 289 return; 290 } else { 291 prepareNativeDaemon(); 292 } 293 } 294 getBatteryStats()295 private IBatteryStats getBatteryStats() { 296 synchronized (this) { 297 if (mBatteryStats != null) { 298 return mBatteryStats; 299 } 300 mBatteryStats = 301 IBatteryStats.Stub.asInterface(mDeps.getService(BatteryStats.SERVICE_NAME)); 302 return mBatteryStats; 303 } 304 } 305 306 @Override registerObserver(INetworkManagementEventObserver observer)307 public void registerObserver(INetworkManagementEventObserver observer) { 308 PermissionUtils.enforceNetworkStackPermission(mContext); 309 mObservers.register(observer); 310 } 311 312 @Override unregisterObserver(INetworkManagementEventObserver observer)313 public void unregisterObserver(INetworkManagementEventObserver observer) { 314 PermissionUtils.enforceNetworkStackPermission(mContext); 315 mObservers.unregister(observer); 316 } 317 318 @FunctionalInterface 319 private interface NetworkManagementEventCallback { sendCallback(INetworkManagementEventObserver o)320 void sendCallback(INetworkManagementEventObserver o) throws RemoteException; 321 } 322 invokeForAllObservers(NetworkManagementEventCallback eventCallback)323 private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) { 324 final int length = mObservers.beginBroadcast(); 325 try { 326 for (int i = 0; i < length; i++) { 327 try { 328 eventCallback.sendCallback(mObservers.getBroadcastItem(i)); 329 } catch (RemoteException | RuntimeException e) { 330 } 331 } 332 } finally { 333 mObservers.finishBroadcast(); 334 } 335 } 336 337 /** 338 * Notify our observers of an interface status change 339 */ notifyInterfaceStatusChanged(String iface, boolean up)340 private void notifyInterfaceStatusChanged(String iface, boolean up) { 341 invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up)); 342 } 343 344 /** 345 * Notify our observers of an interface link state change 346 * (typically, an Ethernet cable has been plugged-in or unplugged). 347 */ notifyInterfaceLinkStateChanged(String iface, boolean up)348 private void notifyInterfaceLinkStateChanged(String iface, boolean up) { 349 invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up)); 350 } 351 352 /** 353 * Notify our observers of an interface addition. 354 */ notifyInterfaceAdded(String iface)355 private void notifyInterfaceAdded(String iface) { 356 invokeForAllObservers(o -> o.interfaceAdded(iface)); 357 } 358 359 /** 360 * Notify our observers of an interface removal. 361 */ notifyInterfaceRemoved(String iface)362 private void notifyInterfaceRemoved(String iface) { 363 // netd already clears out quota and alerts for removed ifaces; update 364 // our validity-checking state. 365 mActiveAlerts.remove(iface); 366 mActiveQuotas.remove(iface); 367 invokeForAllObservers(o -> o.interfaceRemoved(iface)); 368 } 369 370 /** 371 * Notify our observers of a limit reached. 372 */ notifyLimitReached(String limitName, String iface)373 private void notifyLimitReached(String limitName, String iface) { 374 invokeForAllObservers(o -> o.limitReached(limitName, iface)); 375 } 376 377 /** 378 * Notify our observers of a change in the data activity state of the interface 379 */ notifyInterfaceClassActivity(int label, boolean isActive, long tsNanos, int uid)380 private void notifyInterfaceClassActivity(int label, boolean isActive, long tsNanos, 381 int uid) { 382 invokeForAllObservers(o -> o.interfaceClassDataActivityChanged( 383 label, isActive, tsNanos, uid)); 384 } 385 386 // Sync the state of the given chain with the native daemon. syncFirewallChainLocked(int chain, String name)387 private void syncFirewallChainLocked(int chain, String name) { 388 SparseIntArray rules; 389 synchronized (mRulesLock) { 390 final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain); 391 // Make a copy of the current rules, and then clear them. This is because 392 // setFirewallUidRuleInternal only pushes down rules to the native daemon if they 393 // are different from the current rules stored in the mUidFirewall*Rules array for 394 // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal 395 // will do nothing. 396 rules = uidFirewallRules.clone(); 397 uidFirewallRules.clear(); 398 } 399 if (rules.size() > 0) { 400 // Now push the rules. setFirewallUidRuleInternal will push each of these down to the 401 // native daemon, and also add them to the mUidFirewall*Rules array for the specified 402 // chain. 403 if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall " 404 + name + "UID rules"); 405 for (int i = 0; i < rules.size(); i++) { 406 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i)); 407 } 408 } 409 } 410 connectNativeNetdService()411 private void connectNativeNetdService() { 412 mNetdService = mDeps.getNetd(); 413 try { 414 mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener); 415 if (DBG) Slog.d(TAG, "Register unsolicited event listener"); 416 } catch (RemoteException | ServiceSpecificException e) { 417 Slog.e(TAG, "Failed to set Netd unsolicited event listener " + e); 418 } 419 } 420 421 /** 422 * Prepare native daemon once connected, enabling modules and pushing any 423 * existing in-memory rules. 424 */ prepareNativeDaemon()425 private void prepareNativeDaemon() { 426 427 // push any existing quota or UID rules 428 synchronized (mQuotaLock) { 429 430 mStrictEnabled = true; 431 432 setDataSaverModeEnabled(mDataSaverMode); 433 434 int size = mActiveQuotas.size(); 435 if (size > 0) { 436 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules"); 437 final HashMap<String, Long> activeQuotas = mActiveQuotas; 438 mActiveQuotas = Maps.newHashMap(); 439 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) { 440 setInterfaceQuota(entry.getKey(), entry.getValue()); 441 } 442 } 443 444 size = mActiveAlerts.size(); 445 if (size > 0) { 446 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules"); 447 final HashMap<String, Long> activeAlerts = mActiveAlerts; 448 mActiveAlerts = Maps.newHashMap(); 449 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) { 450 setInterfaceAlert(entry.getKey(), entry.getValue()); 451 } 452 } 453 454 if (!mUseMeteredFirewallChains) { 455 SparseBooleanArray uidRejectOnQuota = null; 456 SparseBooleanArray uidAcceptOnQuota = null; 457 synchronized (mRulesLock) { 458 size = mUidRejectOnMetered.size(); 459 if (size > 0) { 460 if (DBG) { 461 Slog.d(TAG, "Pushing " + size + " UIDs to metered denylist rules"); 462 } 463 uidRejectOnQuota = mUidRejectOnMetered; 464 mUidRejectOnMetered = new SparseBooleanArray(); 465 } 466 467 size = mUidAllowOnMetered.size(); 468 if (size > 0) { 469 if (DBG) { 470 Slog.d(TAG, "Pushing " + size + " UIDs to metered allowlist rules"); 471 } 472 uidAcceptOnQuota = mUidAllowOnMetered; 473 mUidAllowOnMetered = new SparseBooleanArray(); 474 } 475 } 476 if (uidRejectOnQuota != null) { 477 for (int i = 0; i < uidRejectOnQuota.size(); i++) { 478 setUidOnMeteredNetworkDenylist(uidRejectOnQuota.keyAt(i), 479 uidRejectOnQuota.valueAt(i)); 480 } 481 } 482 if (uidAcceptOnQuota != null) { 483 for (int i = 0; i < uidAcceptOnQuota.size(); i++) { 484 setUidOnMeteredNetworkAllowlist(uidAcceptOnQuota.keyAt(i), 485 uidAcceptOnQuota.valueAt(i)); 486 } 487 } 488 } 489 490 size = mUidCleartextPolicy.size(); 491 if (size > 0) { 492 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies"); 493 final SparseIntArray local = mUidCleartextPolicy; 494 mUidCleartextPolicy = new SparseIntArray(); 495 for (int i = 0; i < local.size(); i++) { 496 setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i)); 497 } 498 } 499 500 setFirewallEnabled(mFirewallEnabled); 501 502 syncFirewallChainLocked(FIREWALL_CHAIN_NONE, ""); 503 syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby "); 504 syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable "); 505 syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave "); 506 syncFirewallChainLocked(FIREWALL_CHAIN_RESTRICTED, "restricted "); 507 syncFirewallChainLocked(FIREWALL_CHAIN_LOW_POWER_STANDBY, "low power standby "); 508 syncFirewallChainLocked(FIREWALL_CHAIN_BACKGROUND, FIREWALL_CHAIN_NAME_BACKGROUND); 509 if (mUseMeteredFirewallChains) { 510 syncFirewallChainLocked(FIREWALL_CHAIN_METERED_ALLOW, 511 FIREWALL_CHAIN_NAME_METERED_ALLOW); 512 syncFirewallChainLocked(FIREWALL_CHAIN_METERED_DENY_USER, 513 FIREWALL_CHAIN_NAME_METERED_DENY_USER); 514 syncFirewallChainLocked(FIREWALL_CHAIN_METERED_DENY_ADMIN, 515 FIREWALL_CHAIN_NAME_METERED_DENY_ADMIN); 516 } 517 518 final int[] chainsToEnable = { 519 FIREWALL_CHAIN_STANDBY, 520 FIREWALL_CHAIN_DOZABLE, 521 FIREWALL_CHAIN_POWERSAVE, 522 FIREWALL_CHAIN_RESTRICTED, 523 FIREWALL_CHAIN_LOW_POWER_STANDBY, 524 FIREWALL_CHAIN_BACKGROUND, 525 }; 526 527 for (int chain : chainsToEnable) { 528 if (getFirewallChainState(chain)) { 529 setFirewallChainEnabled(chain, true); 530 } 531 } 532 } 533 534 try { 535 getBatteryStats().noteNetworkStatsEnabled(); 536 } catch (RemoteException e) { 537 } 538 539 } 540 541 /** 542 * Notify our observers of a new or updated interface address. 543 */ notifyAddressUpdated(String iface, LinkAddress address)544 private void notifyAddressUpdated(String iface, LinkAddress address) { 545 invokeForAllObservers(o -> o.addressUpdated(iface, address)); 546 } 547 548 /** 549 * Notify our observers of a deleted interface address. 550 */ notifyAddressRemoved(String iface, LinkAddress address)551 private void notifyAddressRemoved(String iface, LinkAddress address) { 552 invokeForAllObservers(o -> o.addressRemoved(iface, address)); 553 } 554 555 /** 556 * Notify our observers of DNS server information received. 557 */ notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses)558 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) { 559 invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses)); 560 } 561 562 /** 563 * Notify our observers of a route change. 564 */ notifyRouteChange(boolean updated, RouteInfo route)565 private void notifyRouteChange(boolean updated, RouteInfo route) { 566 if (updated) { 567 invokeForAllObservers(o -> o.routeUpdated(route)); 568 } else { 569 invokeForAllObservers(o -> o.routeRemoved(route)); 570 } 571 } 572 573 private class NetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub { 574 @Override onInterfaceClassActivityChanged(boolean isActive, int label, long timestamp, int uid)575 public void onInterfaceClassActivityChanged(boolean isActive, 576 int label, long timestamp, int uid) throws RemoteException { 577 final long timestampNanos; 578 if (timestamp <= 0) { 579 timestampNanos = SystemClock.elapsedRealtimeNanos(); 580 } else { 581 timestampNanos = timestamp; 582 } 583 mDaemonHandler.post(() -> 584 notifyInterfaceClassActivity(label, isActive, timestampNanos, uid)); 585 } 586 587 @Override onQuotaLimitReached(String alertName, String ifName)588 public void onQuotaLimitReached(String alertName, String ifName) 589 throws RemoteException { 590 mDaemonHandler.post(() -> notifyLimitReached(alertName, ifName)); 591 } 592 593 @Override onInterfaceDnsServerInfo(String ifName, long lifetime, String[] servers)594 public void onInterfaceDnsServerInfo(String ifName, 595 long lifetime, String[] servers) throws RemoteException { 596 mDaemonHandler.post(() -> notifyInterfaceDnsServerInfo(ifName, lifetime, servers)); 597 } 598 599 @Override onInterfaceAddressUpdated(String addr, String ifName, int flags, int scope)600 public void onInterfaceAddressUpdated(String addr, 601 String ifName, int flags, int scope) throws RemoteException { 602 final LinkAddress address = new LinkAddress(addr, flags, scope); 603 mDaemonHandler.post(() -> notifyAddressUpdated(ifName, address)); 604 } 605 606 @Override onInterfaceAddressRemoved(String addr, String ifName, int flags, int scope)607 public void onInterfaceAddressRemoved(String addr, 608 String ifName, int flags, int scope) throws RemoteException { 609 final LinkAddress address = new LinkAddress(addr, flags, scope); 610 mDaemonHandler.post(() -> notifyAddressRemoved(ifName, address)); 611 } 612 613 @Override onInterfaceAdded(String ifName)614 public void onInterfaceAdded(String ifName) throws RemoteException { 615 mDaemonHandler.post(() -> notifyInterfaceAdded(ifName)); 616 } 617 618 @Override onInterfaceRemoved(String ifName)619 public void onInterfaceRemoved(String ifName) throws RemoteException { 620 mDaemonHandler.post(() -> notifyInterfaceRemoved(ifName)); 621 } 622 623 @Override onInterfaceChanged(String ifName, boolean up)624 public void onInterfaceChanged(String ifName, boolean up) 625 throws RemoteException { 626 mDaemonHandler.post(() -> notifyInterfaceStatusChanged(ifName, up)); 627 } 628 629 @Override onInterfaceLinkStateChanged(String ifName, boolean up)630 public void onInterfaceLinkStateChanged(String ifName, boolean up) 631 throws RemoteException { 632 mDaemonHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up)); 633 } 634 635 @Override onRouteChanged(boolean updated, String route, String gateway, String ifName)636 public void onRouteChanged(boolean updated, 637 String route, String gateway, String ifName) throws RemoteException { 638 final RouteInfo processRoute = new RouteInfo(new IpPrefix(route), 639 ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway), 640 ifName, RouteInfo.RTN_UNICAST); 641 mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute)); 642 } 643 644 @Override onStrictCleartextDetected(int uid, String hex)645 public void onStrictCleartextDetected(int uid, String hex) throws RemoteException { 646 // Don't need to post to mDaemonHandler because the only thing 647 // that notifyCleartextNetwork does is post to a handler 648 ActivityManager.getService().notifyCleartextNetwork(uid, 649 HexDump.hexStringToByteArray(hex)); 650 } 651 652 @Override getInterfaceVersion()653 public int getInterfaceVersion() { 654 return INetdUnsolicitedEventListener.VERSION; 655 } 656 657 @Override getInterfaceHash()658 public String getInterfaceHash() { 659 return INetdUnsolicitedEventListener.HASH; 660 } 661 } 662 663 // 664 // INetworkManagementService members 665 // 666 @Override listInterfaces()667 public String[] listInterfaces() { 668 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these 669 // APIs. 670 PermissionUtils.enforceNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL); 671 try { 672 return mNetdService.interfaceGetList(); 673 } catch (RemoteException | ServiceSpecificException e) { 674 throw new IllegalStateException(e); 675 } 676 } 677 678 /** 679 * Convert InterfaceConfiguration to InterfaceConfigurationParcel with given ifname. 680 */ toStableParcel(InterfaceConfiguration cfg, String iface)681 private static InterfaceConfigurationParcel toStableParcel(InterfaceConfiguration cfg, 682 String iface) { 683 InterfaceConfigurationParcel cfgParcel = new InterfaceConfigurationParcel(); 684 cfgParcel.ifName = iface; 685 String hwAddr = cfg.getHardwareAddress(); 686 if (!TextUtils.isEmpty(hwAddr)) { 687 cfgParcel.hwAddr = hwAddr; 688 } else { 689 cfgParcel.hwAddr = ""; 690 } 691 cfgParcel.ipv4Addr = cfg.getLinkAddress().getAddress().getHostAddress(); 692 cfgParcel.prefixLength = cfg.getLinkAddress().getPrefixLength(); 693 ArrayList<String> flags = new ArrayList<>(); 694 for (String flag : cfg.getFlags()) { 695 flags.add(flag); 696 } 697 cfgParcel.flags = flags.toArray(new String[0]); 698 699 return cfgParcel; 700 } 701 702 /** 703 * Construct InterfaceConfiguration from InterfaceConfigurationParcel. 704 */ fromStableParcel(InterfaceConfigurationParcel p)705 public static InterfaceConfiguration fromStableParcel(InterfaceConfigurationParcel p) { 706 InterfaceConfiguration cfg = new InterfaceConfiguration(); 707 cfg.setHardwareAddress(p.hwAddr); 708 709 final InetAddress addr = InetAddresses.parseNumericAddress(p.ipv4Addr); 710 cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength)); 711 for (String flag : p.flags) { 712 cfg.setFlag(flag); 713 } 714 715 return cfg; 716 } 717 718 @Override getInterfaceConfig(String iface)719 public InterfaceConfiguration getInterfaceConfig(String iface) { 720 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these 721 // APIs. 722 PermissionUtils.enforceNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL); 723 final InterfaceConfigurationParcel result; 724 try { 725 result = mNetdService.interfaceGetCfg(iface); 726 } catch (RemoteException | ServiceSpecificException e) { 727 throw new IllegalStateException(e); 728 } 729 730 try { 731 final InterfaceConfiguration cfg = fromStableParcel(result); 732 return cfg; 733 } catch (IllegalArgumentException iae) { 734 throw new IllegalStateException("Invalid InterfaceConfigurationParcel", iae); 735 } 736 } 737 738 @Override setInterfaceConfig(String iface, InterfaceConfiguration cfg)739 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { 740 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these 741 // APIs. 742 PermissionUtils.enforceNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL); 743 LinkAddress linkAddr = cfg.getLinkAddress(); 744 if (linkAddr == null || linkAddr.getAddress() == null) { 745 throw new IllegalStateException("Null LinkAddress given"); 746 } 747 748 final InterfaceConfigurationParcel cfgParcel = toStableParcel(cfg, iface); 749 750 try { 751 mNetdService.interfaceSetCfg(cfgParcel); 752 } catch (RemoteException | ServiceSpecificException e) { 753 throw new IllegalStateException(e); 754 } 755 } 756 757 @Override setInterfaceDown(String iface)758 public void setInterfaceDown(String iface) { 759 PermissionUtils.enforceNetworkStackPermission(mContext); 760 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 761 ifcg.setInterfaceDown(); 762 setInterfaceConfig(iface, ifcg); 763 } 764 765 @Override setInterfaceUp(String iface)766 public void setInterfaceUp(String iface) { 767 PermissionUtils.enforceNetworkStackPermission(mContext); 768 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 769 ifcg.setInterfaceUp(); 770 setInterfaceConfig(iface, ifcg); 771 } 772 773 @Override setInterfaceIpv6PrivacyExtensions(String iface, boolean enable)774 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { 775 PermissionUtils.enforceNetworkStackPermission(mContext); 776 try { 777 mNetdService.interfaceSetIPv6PrivacyExtensions(iface, enable); 778 } catch (RemoteException | ServiceSpecificException e) { 779 throw new IllegalStateException(e); 780 } 781 } 782 783 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 784 IPv6 addresses on interface down, but we need to do full clean up here */ 785 @Override clearInterfaceAddresses(String iface)786 public void clearInterfaceAddresses(String iface) { 787 PermissionUtils.enforceNetworkStackPermission(mContext); 788 try { 789 mNetdService.interfaceClearAddrs(iface); 790 } catch (RemoteException | ServiceSpecificException e) { 791 throw new IllegalStateException(e); 792 } 793 } 794 795 @Override enableIpv6(String iface)796 public void enableIpv6(String iface) { 797 PermissionUtils.enforceNetworkStackPermission(mContext); 798 try { 799 mNetdService.interfaceSetEnableIPv6(iface, true); 800 } catch (RemoteException | ServiceSpecificException e) { 801 throw new IllegalStateException(e); 802 } 803 } 804 805 @Override setIPv6AddrGenMode(String iface, int mode)806 public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException { 807 PermissionUtils.enforceNetworkStackPermission(mContext); 808 try { 809 mNetdService.setIPv6AddrGenMode(iface, mode); 810 } catch (RemoteException e) { 811 throw e.rethrowAsRuntimeException(); 812 } 813 } 814 815 @Override disableIpv6(String iface)816 public void disableIpv6(String iface) { 817 PermissionUtils.enforceNetworkStackPermission(mContext); 818 try { 819 mNetdService.interfaceSetEnableIPv6(iface, false); 820 } catch (RemoteException | ServiceSpecificException e) { 821 throw new IllegalStateException(e); 822 } 823 } 824 825 @android.annotation.EnforcePermission(android.Manifest.permission.SHUTDOWN) 826 @Override shutdown()827 public void shutdown() { 828 // TODO: remove from aidl if nobody calls externally 829 830 super.shutdown_enforcePermission(); 831 832 Slog.i(TAG, "Shutting down"); 833 } 834 835 @Override getIpForwardingEnabled()836 public boolean getIpForwardingEnabled() throws IllegalStateException{ 837 PermissionUtils.enforceNetworkStackPermission(mContext); 838 if (SdkLevel.isAtLeastV()) { 839 throw new UnsupportedOperationException( 840 "NMS#getIpForwardingEnabled not supported in V+"); 841 } 842 try { 843 return mNetdService.ipfwdEnabled(); 844 } catch (RemoteException | ServiceSpecificException e) { 845 throw new IllegalStateException(e); 846 } 847 } 848 849 @Override setIpForwardingEnabled(boolean enable)850 public void setIpForwardingEnabled(boolean enable) { 851 PermissionUtils.enforceNetworkStackPermission(mContext); 852 if (SdkLevel.isAtLeastV()) { 853 throw new UnsupportedOperationException( 854 "NMS#setIpForwardingEnabled not supported in V+"); 855 } try { 856 if (enable) { 857 mNetdService.ipfwdEnableForwarding("tethering"); 858 } else { 859 mNetdService.ipfwdDisableForwarding("tethering"); 860 } 861 } catch (RemoteException | ServiceSpecificException e) { 862 throw new IllegalStateException(e); 863 } 864 } 865 866 @Override startTethering(String[] dhcpRange)867 public void startTethering(String[] dhcpRange) { 868 PermissionUtils.enforceNetworkStackPermission(mContext); 869 if (SdkLevel.isAtLeastV()) { 870 throw new UnsupportedOperationException("NMS#startTethering not supported in V+"); 871 } 872 try { 873 NetdUtils.tetherStart(mNetdService, true /* usingLegacyDnsProxy */, dhcpRange); 874 } catch (RemoteException | ServiceSpecificException e) { 875 throw new IllegalStateException(e); 876 } 877 } 878 879 @Override stopTethering()880 public void stopTethering() { 881 PermissionUtils.enforceNetworkStackPermission(mContext); 882 if (SdkLevel.isAtLeastV()) { 883 throw new UnsupportedOperationException("NMS#stopTethering not supported in V+"); 884 } 885 try { 886 mNetdService.tetherStop(); 887 } catch (RemoteException | ServiceSpecificException e) { 888 throw new IllegalStateException(e); 889 } 890 } 891 892 @Override isTetheringStarted()893 public boolean isTetheringStarted() { 894 PermissionUtils.enforceNetworkStackPermission(mContext); 895 if (SdkLevel.isAtLeastV()) { 896 throw new UnsupportedOperationException("NMS#isTetheringStarted not supported in V+"); 897 } 898 try { 899 return mNetdService.tetherIsEnabled(); 900 } catch (RemoteException | ServiceSpecificException e) { 901 throw new IllegalStateException(e); 902 } 903 } 904 905 @Override tetherInterface(String iface)906 public void tetherInterface(String iface) { 907 PermissionUtils.enforceNetworkStackPermission(mContext); 908 if (SdkLevel.isAtLeastV()) { 909 throw new UnsupportedOperationException("NMS#tetherInterface not supported in V+"); 910 } 911 try { 912 final LinkAddress addr = getInterfaceConfig(iface).getLinkAddress(); 913 final IpPrefix dest = new IpPrefix(addr.getAddress(), addr.getPrefixLength()); 914 NetdUtils.tetherInterface(mNetdService, iface, dest); 915 } catch (RemoteException | ServiceSpecificException e) { 916 throw new IllegalStateException(e); 917 } 918 } 919 920 @Override untetherInterface(String iface)921 public void untetherInterface(String iface) { 922 PermissionUtils.enforceNetworkStackPermission(mContext); 923 if (SdkLevel.isAtLeastV()) { 924 throw new UnsupportedOperationException("NMS#untetherInterface not supported in V+"); 925 } 926 try { 927 NetdUtils.untetherInterface(mNetdService, iface); 928 } catch (RemoteException | ServiceSpecificException e) { 929 throw new IllegalStateException(e); 930 } 931 } 932 933 @Override listTetheredInterfaces()934 public String[] listTetheredInterfaces() { 935 PermissionUtils.enforceNetworkStackPermission(mContext); 936 if (SdkLevel.isAtLeastV()) { 937 throw new UnsupportedOperationException( 938 "NMS#listTetheredInterfaces not supported in V+"); 939 } 940 try { 941 return mNetdService.tetherInterfaceList(); 942 } catch (RemoteException | ServiceSpecificException e) { 943 throw new IllegalStateException(e); 944 } 945 } 946 947 @Override enableNat(String internalInterface, String externalInterface)948 public void enableNat(String internalInterface, String externalInterface) { 949 PermissionUtils.enforceNetworkStackPermission(mContext); 950 if (SdkLevel.isAtLeastV()) { 951 throw new UnsupportedOperationException("NMS#enableNat not supported in V+"); 952 } 953 try { 954 mNetdService.tetherAddForward(internalInterface, externalInterface); 955 } catch (RemoteException | ServiceSpecificException e) { 956 throw new IllegalStateException(e); 957 } 958 } 959 960 @Override disableNat(String internalInterface, String externalInterface)961 public void disableNat(String internalInterface, String externalInterface) { 962 PermissionUtils.enforceNetworkStackPermission(mContext); 963 if (SdkLevel.isAtLeastV()) { 964 throw new UnsupportedOperationException("NMS#disableNat not supported in V+"); 965 } 966 try { 967 mNetdService.tetherRemoveForward(internalInterface, externalInterface); 968 } catch (RemoteException | ServiceSpecificException e) { 969 throw new IllegalStateException(e); 970 } 971 } 972 973 @Override setInterfaceQuota(String iface, long quotaBytes)974 public void setInterfaceQuota(String iface, long quotaBytes) { 975 PermissionUtils.enforceNetworkStackPermission(mContext); 976 977 synchronized (mQuotaLock) { 978 if (mActiveQuotas.containsKey(iface)) { 979 throw new IllegalStateException("iface " + iface + " already has quota"); 980 } 981 982 try { 983 // TODO: support quota shared across interfaces 984 mNetdService.bandwidthSetInterfaceQuota(iface, quotaBytes); 985 986 mActiveQuotas.put(iface, quotaBytes); 987 } catch (RemoteException | ServiceSpecificException e) { 988 throw new IllegalStateException(e); 989 } 990 } 991 } 992 993 @Override removeInterfaceQuota(String iface)994 public void removeInterfaceQuota(String iface) { 995 PermissionUtils.enforceNetworkStackPermission(mContext); 996 997 synchronized (mQuotaLock) { 998 if (!mActiveQuotas.containsKey(iface)) { 999 // TODO: eventually consider throwing 1000 return; 1001 } 1002 1003 mActiveQuotas.remove(iface); 1004 mActiveAlerts.remove(iface); 1005 1006 try { 1007 // TODO: support quota shared across interfaces 1008 mNetdService.bandwidthRemoveInterfaceQuota(iface); 1009 } catch (RemoteException | ServiceSpecificException e) { 1010 throw new IllegalStateException(e); 1011 } 1012 } 1013 } 1014 1015 @Override setInterfaceAlert(String iface, long alertBytes)1016 public void setInterfaceAlert(String iface, long alertBytes) { 1017 PermissionUtils.enforceNetworkStackPermission(mContext); 1018 1019 // quick validity check 1020 if (!mActiveQuotas.containsKey(iface)) { 1021 throw new IllegalStateException("setting alert requires existing quota on iface"); 1022 } 1023 1024 synchronized (mQuotaLock) { 1025 if (mActiveAlerts.containsKey(iface)) { 1026 throw new IllegalStateException("iface " + iface + " already has alert"); 1027 } 1028 1029 try { 1030 // TODO: support alert shared across interfaces 1031 mNetdService.bandwidthSetInterfaceAlert(iface, alertBytes); 1032 mActiveAlerts.put(iface, alertBytes); 1033 } catch (RemoteException | ServiceSpecificException e) { 1034 throw new IllegalStateException(e); 1035 } 1036 } 1037 } 1038 1039 @Override removeInterfaceAlert(String iface)1040 public void removeInterfaceAlert(String iface) { 1041 PermissionUtils.enforceNetworkStackPermission(mContext); 1042 1043 synchronized (mQuotaLock) { 1044 if (!mActiveAlerts.containsKey(iface)) { 1045 // TODO: eventually consider throwing 1046 return; 1047 } 1048 1049 try { 1050 // TODO: support alert shared across interfaces 1051 mNetdService.bandwidthRemoveInterfaceAlert(iface); 1052 mActiveAlerts.remove(iface); 1053 } catch (RemoteException | ServiceSpecificException e) { 1054 throw new IllegalStateException(e); 1055 } 1056 } 1057 } 1058 setUidOnMeteredNetworkList(int uid, boolean allowlist, boolean enable)1059 private void setUidOnMeteredNetworkList(int uid, boolean allowlist, boolean enable) { 1060 PermissionUtils.enforceNetworkStackPermission(mContext); 1061 1062 synchronized (mQuotaLock) { 1063 boolean oldEnable; 1064 SparseBooleanArray quotaList; 1065 synchronized (mRulesLock) { 1066 quotaList = allowlist ? mUidAllowOnMetered : mUidRejectOnMetered; 1067 oldEnable = quotaList.get(uid, false); 1068 } 1069 if (oldEnable == enable) { 1070 // TODO: eventually consider throwing 1071 return; 1072 } 1073 1074 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth"); 1075 final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1076 try { 1077 if (allowlist) { 1078 if (enable) { 1079 cm.addUidToMeteredNetworkAllowList(uid); 1080 } else { 1081 cm.removeUidFromMeteredNetworkAllowList(uid); 1082 } 1083 } else { 1084 if (enable) { 1085 cm.addUidToMeteredNetworkDenyList(uid); 1086 } else { 1087 cm.removeUidFromMeteredNetworkDenyList(uid); 1088 } 1089 } 1090 synchronized (mRulesLock) { 1091 if (enable) { 1092 quotaList.put(uid, true); 1093 } else { 1094 quotaList.delete(uid); 1095 } 1096 } 1097 } catch (RuntimeException e) { 1098 throw new IllegalStateException(e); 1099 } finally { 1100 Trace.traceEnd(Trace.TRACE_TAG_NETWORK); 1101 } 1102 } 1103 } 1104 1105 @Override setUidOnMeteredNetworkDenylist(int uid, boolean enable)1106 public void setUidOnMeteredNetworkDenylist(int uid, boolean enable) { 1107 setUidOnMeteredNetworkList(uid, false, enable); 1108 } 1109 1110 @Override setUidOnMeteredNetworkAllowlist(int uid, boolean enable)1111 public void setUidOnMeteredNetworkAllowlist(int uid, boolean enable) { 1112 setUidOnMeteredNetworkList(uid, true, enable); 1113 } 1114 1115 @android.annotation.EnforcePermission(android.Manifest.permission.NETWORK_SETTINGS) 1116 @Override setDataSaverModeEnabled(boolean enable)1117 public boolean setDataSaverModeEnabled(boolean enable) { 1118 1119 super.setDataSaverModeEnabled_enforcePermission(); 1120 1121 if (DBG) Log.d(TAG, "setDataSaverMode: " + enable); 1122 synchronized (mQuotaLock) { 1123 if (mDataSaverMode == enable) { 1124 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode); 1125 return true; 1126 } 1127 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setDataSaverModeEnabled"); 1128 try { 1129 if (SdkLevel.isAtLeastV()) { 1130 // setDataSaverEnabled throws if it fails to set data saver. 1131 mContext.getSystemService(ConnectivityManager.class) 1132 .setDataSaverEnabled(enable); 1133 mDataSaverMode = enable; 1134 if (mUseMeteredFirewallChains) { 1135 // Copy mDataSaverMode state to FIREWALL_CHAIN_METERED_ALLOW 1136 // until ConnectivityService allows manipulation of the data saver mode via 1137 // FIREWALL_CHAIN_METERED_ALLOW. 1138 synchronized (mRulesLock) { 1139 mFirewallChainStates.put(FIREWALL_CHAIN_METERED_ALLOW, enable); 1140 } 1141 } 1142 return true; 1143 } else { 1144 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable); 1145 if (changed) { 1146 mDataSaverMode = enable; 1147 } else { 1148 Log.e(TAG, "setDataSaverMode(" + enable + "): failed to set iptables"); 1149 } 1150 return changed; 1151 } 1152 } catch (RemoteException | IllegalStateException e) { 1153 Log.e(TAG, "setDataSaverMode(" + enable + "): failed with exception", e); 1154 return false; 1155 } finally { 1156 Trace.traceEnd(Trace.TRACE_TAG_NETWORK); 1157 } 1158 } 1159 } 1160 applyUidCleartextNetworkPolicy(int uid, int policy)1161 private void applyUidCleartextNetworkPolicy(int uid, int policy) { 1162 final int policyValue; 1163 switch (policy) { 1164 case StrictMode.NETWORK_POLICY_ACCEPT: 1165 policyValue = INetd.PENALTY_POLICY_ACCEPT; 1166 break; 1167 case StrictMode.NETWORK_POLICY_LOG: 1168 policyValue = INetd.PENALTY_POLICY_LOG; 1169 break; 1170 case StrictMode.NETWORK_POLICY_REJECT: 1171 policyValue = INetd.PENALTY_POLICY_REJECT; 1172 break; 1173 default: 1174 throw new IllegalArgumentException("Unknown policy " + policy); 1175 } 1176 1177 try { 1178 mNetdService.strictUidCleartextPenalty(uid, policyValue); 1179 mUidCleartextPolicy.put(uid, policy); 1180 } catch (RemoteException | ServiceSpecificException e) { 1181 throw new IllegalStateException(e); 1182 } 1183 } 1184 1185 @Override setUidCleartextNetworkPolicy(int uid, int policy)1186 public void setUidCleartextNetworkPolicy(int uid, int policy) { 1187 if (mDeps.getCallingUid() != uid) { 1188 PermissionUtils.enforceNetworkStackPermission(mContext); 1189 } 1190 1191 synchronized (mQuotaLock) { 1192 final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT); 1193 if (oldPolicy == policy) { 1194 // This also ensures we won't needlessly apply an ACCEPT policy if we've just 1195 // enabled strict and the underlying iptables rules are empty. 1196 return; 1197 } 1198 1199 // TODO: remove this code after removing prepareNativeDaemon() 1200 if (!mStrictEnabled) { 1201 // Module isn't enabled yet; stash the requested policy away to 1202 // apply later once the daemon is connected. 1203 mUidCleartextPolicy.put(uid, policy); 1204 return; 1205 } 1206 1207 // netd does not keep state on strict mode policies, and cannot replace a non-accept 1208 // policy without deleting it first. Rather than add state to netd, just always send 1209 // it an accept policy when switching between two non-accept policies. 1210 // TODO: consider keeping state in netd so we can simplify this code. 1211 if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT && 1212 policy != StrictMode.NETWORK_POLICY_ACCEPT) { 1213 applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT); 1214 } 1215 1216 applyUidCleartextNetworkPolicy(uid, policy); 1217 } 1218 } 1219 1220 @Override isBandwidthControlEnabled()1221 public boolean isBandwidthControlEnabled() { 1222 return true; 1223 } 1224 1225 @Override setFirewallEnabled(boolean enabled)1226 public void setFirewallEnabled(boolean enabled) { 1227 enforceSystemUid(); 1228 try { 1229 mNetdService.firewallSetFirewallType( 1230 enabled ? INetd.FIREWALL_ALLOWLIST : INetd.FIREWALL_DENYLIST); 1231 mFirewallEnabled = enabled; 1232 } catch (RemoteException | ServiceSpecificException e) { 1233 throw new IllegalStateException(e); 1234 } 1235 } 1236 1237 @Override isFirewallEnabled()1238 public boolean isFirewallEnabled() { 1239 enforceSystemUid(); 1240 return mFirewallEnabled; 1241 } 1242 1243 @Override setFirewallChainEnabled(int chain, boolean enable)1244 public void setFirewallChainEnabled(int chain, boolean enable) { 1245 enforceSystemUid(); 1246 synchronized (mQuotaLock) { 1247 synchronized (mRulesLock) { 1248 if (getFirewallChainState(chain) == enable) { 1249 // All is the same, nothing to do. This relies on the fact that netd has child 1250 // chains default detached. 1251 return; 1252 } 1253 setFirewallChainState(chain, enable); 1254 } 1255 1256 if (!isValidFirewallChainForSetEnabled(chain)) { 1257 throw new IllegalArgumentException("Invalid chain for setFirewallChainEnabled: " 1258 + NetworkPolicyLogger.getFirewallChainName(chain)); 1259 } 1260 1261 final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1262 try { 1263 cm.setFirewallChainEnabled(chain, enable); 1264 } catch (RuntimeException e) { 1265 throw new IllegalStateException(e); 1266 } 1267 } 1268 } 1269 isValidFirewallChainForSetEnabled(int chain)1270 private boolean isValidFirewallChainForSetEnabled(int chain) { 1271 return switch (chain) { 1272 case FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE, 1273 FIREWALL_CHAIN_RESTRICTED, FIREWALL_CHAIN_LOW_POWER_STANDBY, 1274 FIREWALL_CHAIN_BACKGROUND -> true; 1275 // METERED_* firewall chains are not yet supported by 1276 // ConnectivityService#setFirewallChainEnabled. 1277 default -> false; 1278 }; 1279 } 1280 getFirewallType(int chain)1281 private int getFirewallType(int chain) { 1282 switch (chain) { 1283 case FIREWALL_CHAIN_STANDBY: 1284 case FIREWALL_CHAIN_METERED_DENY_ADMIN: 1285 case FIREWALL_CHAIN_METERED_DENY_USER: 1286 return FIREWALL_DENYLIST; 1287 case FIREWALL_CHAIN_DOZABLE: 1288 case FIREWALL_CHAIN_POWERSAVE: 1289 case FIREWALL_CHAIN_RESTRICTED: 1290 case FIREWALL_CHAIN_LOW_POWER_STANDBY: 1291 case FIREWALL_CHAIN_BACKGROUND: 1292 case FIREWALL_CHAIN_METERED_ALLOW: 1293 return FIREWALL_ALLOWLIST; 1294 default: 1295 return isFirewallEnabled() ? FIREWALL_ALLOWLIST : FIREWALL_DENYLIST; 1296 } 1297 } 1298 1299 @Override setFirewallUidRules(int chain, int[] uids, int[] rules)1300 public void setFirewallUidRules(int chain, int[] uids, int[] rules) { 1301 enforceSystemUid(); 1302 synchronized (mQuotaLock) { 1303 synchronized (mRulesLock) { 1304 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain); 1305 SparseIntArray newRules = new SparseIntArray(); 1306 // apply new set of rules 1307 for (int index = uids.length - 1; index >= 0; --index) { 1308 int uid = uids[index]; 1309 int rule = rules[index]; 1310 updateFirewallUidRuleLocked(chain, uid, rule); 1311 newRules.put(uid, rule); 1312 } 1313 // collect the rules to remove. 1314 SparseIntArray rulesToRemove = new SparseIntArray(); 1315 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) { 1316 int uid = uidFirewallRules.keyAt(index); 1317 if (newRules.indexOfKey(uid) < 0) { 1318 rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT); 1319 } 1320 } 1321 // remove dead rules 1322 for (int index = rulesToRemove.size() - 1; index >= 0; --index) { 1323 int uid = rulesToRemove.keyAt(index); 1324 updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT); 1325 } 1326 } 1327 final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1328 try { 1329 cm.replaceFirewallChain(chain, uids); 1330 } catch (RuntimeException e) { 1331 Slog.w(TAG, "Error flushing firewall chain " + chain, e); 1332 } 1333 } 1334 } 1335 1336 @Override setFirewallUidRule(int chain, int uid, int rule)1337 public void setFirewallUidRule(int chain, int uid, int rule) { 1338 enforceSystemUid(); 1339 synchronized (mQuotaLock) { 1340 setFirewallUidRuleLocked(chain, uid, rule); 1341 } 1342 } 1343 setFirewallUidRuleLocked(int chain, int uid, int rule)1344 private void setFirewallUidRuleLocked(int chain, int uid, int rule) { 1345 if (updateFirewallUidRuleLocked(chain, uid, rule)) { 1346 final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1347 try { 1348 cm.setUidFirewallRule(chain, uid, rule); 1349 } catch (RuntimeException e) { 1350 throw new IllegalStateException(e); 1351 } 1352 } 1353 } 1354 1355 // TODO: now that netd supports batching, NMS should not keep these data structures anymore... updateFirewallUidRuleLocked(int chain, int uid, int rule)1356 private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) { 1357 synchronized (mRulesLock) { 1358 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain); 1359 1360 final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT); 1361 if (DBG) { 1362 Slog.d(TAG, "oldRule = " + oldUidFirewallRule 1363 + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain); 1364 } 1365 if (oldUidFirewallRule == rule) { 1366 if (DBG) Slog.d(TAG, "!!!!! Skipping change"); 1367 // TODO: eventually consider throwing 1368 return false; 1369 } 1370 1371 String ruleName = getFirewallRuleName(chain, rule); 1372 String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule); 1373 1374 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { 1375 uidFirewallRules.delete(uid); 1376 } else { 1377 uidFirewallRules.put(uid, rule); 1378 } 1379 return !ruleName.equals(oldRuleName); 1380 } 1381 } 1382 getFirewallRuleName(int chain, int rule)1383 private @NonNull String getFirewallRuleName(int chain, int rule) { 1384 String ruleName; 1385 if (getFirewallType(chain) == FIREWALL_ALLOWLIST) { 1386 if (rule == FIREWALL_RULE_ALLOW) { 1387 ruleName = "allow"; 1388 } else { 1389 ruleName = "deny"; 1390 } 1391 } else { // Deny mode 1392 if (rule == FIREWALL_RULE_DENY) { 1393 ruleName = "deny"; 1394 } else { 1395 ruleName = "allow"; 1396 } 1397 } 1398 return ruleName; 1399 } 1400 1401 @GuardedBy("mRulesLock") getUidFirewallRulesLR(int chain)1402 private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) { 1403 switch (chain) { 1404 case FIREWALL_CHAIN_STANDBY: 1405 return mUidFirewallStandbyRules; 1406 case FIREWALL_CHAIN_DOZABLE: 1407 return mUidFirewallDozableRules; 1408 case FIREWALL_CHAIN_POWERSAVE: 1409 return mUidFirewallPowerSaveRules; 1410 case FIREWALL_CHAIN_RESTRICTED: 1411 return mUidFirewallRestrictedRules; 1412 case FIREWALL_CHAIN_LOW_POWER_STANDBY: 1413 return mUidFirewallLowPowerStandbyRules; 1414 case FIREWALL_CHAIN_BACKGROUND: 1415 return mUidFirewallBackgroundRules; 1416 case FIREWALL_CHAIN_METERED_ALLOW: 1417 return mUidMeteredFirewallAllowRules; 1418 case FIREWALL_CHAIN_METERED_DENY_USER: 1419 return mUidMeteredFirewallDenyUserRules; 1420 case FIREWALL_CHAIN_METERED_DENY_ADMIN: 1421 return mUidMeteredFirewallDenyAdminRules; 1422 case FIREWALL_CHAIN_NONE: 1423 return mUidFirewallRules; 1424 default: 1425 throw new IllegalArgumentException("Unknown chain:" + chain); 1426 } 1427 } 1428 enforceSystemUid()1429 private void enforceSystemUid() { 1430 final int uid = mDeps.getCallingUid(); 1431 if (uid != Process.SYSTEM_UID) { 1432 throw new SecurityException("Only available to AID_SYSTEM"); 1433 } 1434 } 1435 1436 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1437 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1438 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1439 1440 pw.println("Flags:"); 1441 pw.println(Flags.FLAG_USE_METERED_FIREWALL_CHAINS + ": " + mUseMeteredFirewallChains); 1442 pw.println(); 1443 1444 synchronized (mQuotaLock) { 1445 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 1446 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 1447 pw.print("Data saver mode: "); pw.println(mDataSaverMode); 1448 synchronized (mRulesLock) { 1449 dumpUidRuleOnQuotaLocked(pw, "denied UIDs", mUidRejectOnMetered); 1450 dumpUidRuleOnQuotaLocked(pw, "allowed UIDs", mUidAllowOnMetered); 1451 } 1452 } 1453 1454 synchronized (mRulesLock) { 1455 dumpUidFirewallRule(pw, "", mUidFirewallRules); 1456 1457 pw.print("UID firewall standby chain enabled: "); 1458 pw.println(getFirewallChainState(FIREWALL_CHAIN_STANDBY)); 1459 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules); 1460 1461 pw.print("UID firewall dozable chain enabled: "); 1462 pw.println(getFirewallChainState(FIREWALL_CHAIN_DOZABLE)); 1463 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules); 1464 1465 pw.print("UID firewall powersave chain enabled: "); 1466 pw.println(getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)); 1467 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules); 1468 1469 pw.print("UID firewall restricted mode chain enabled: "); 1470 pw.println(getFirewallChainState(FIREWALL_CHAIN_RESTRICTED)); 1471 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_RESTRICTED, 1472 mUidFirewallRestrictedRules); 1473 1474 pw.print("UID firewall low power standby chain enabled: "); 1475 pw.println(getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY)); 1476 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY, 1477 mUidFirewallLowPowerStandbyRules); 1478 1479 pw.print("UID firewall background chain enabled: "); 1480 pw.println(getFirewallChainState(FIREWALL_CHAIN_BACKGROUND)); 1481 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_BACKGROUND, mUidFirewallBackgroundRules); 1482 1483 pw.print("UID firewall metered allow chain enabled (Data saver mode): "); 1484 // getFirewallChainState should maintain a duplicated state from mDataSaverMode when 1485 // mUseMeteredFirewallChains is enabled. 1486 pw.println(getFirewallChainState(FIREWALL_CHAIN_METERED_ALLOW)); 1487 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_METERED_ALLOW, 1488 mUidMeteredFirewallAllowRules); 1489 1490 pw.print("UID firewall metered deny_user chain enabled (always-on): "); 1491 // This always-on state should be reflected by getFirewallChainState when 1492 // mUseMeteredFirewallChains is enabled. 1493 pw.println(getFirewallChainState(FIREWALL_CHAIN_METERED_DENY_USER)); 1494 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_METERED_DENY_USER, 1495 mUidMeteredFirewallDenyUserRules); 1496 1497 pw.print("UID firewall metered deny_admin chain enabled (always-on): "); 1498 // This always-on state should be reflected by getFirewallChainState when 1499 // mUseMeteredFirewallChains is enabled. 1500 pw.println(getFirewallChainState(FIREWALL_CHAIN_METERED_DENY_ADMIN)); 1501 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_METERED_DENY_ADMIN, 1502 mUidMeteredFirewallDenyAdminRules); 1503 } 1504 1505 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 1506 pw.print("Netd service status: " ); 1507 if (mNetdService == null) { 1508 pw.println("disconnected"); 1509 } else { 1510 try { 1511 final boolean alive = mNetdService.isAlive(); 1512 pw.println(alive ? "alive": "dead"); 1513 } catch (RemoteException e) { 1514 pw.println("unreachable"); 1515 } 1516 } 1517 } 1518 dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list)1519 private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) { 1520 pw.print("UID bandwith control "); 1521 pw.print(name); 1522 pw.print(": ["); 1523 final int size = list.size(); 1524 for (int i = 0; i < size; i++) { 1525 pw.print(list.keyAt(i)); 1526 if (i < size - 1) pw.print(","); 1527 } 1528 pw.println("]"); 1529 } 1530 dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules)1531 private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) { 1532 pw.print("UID firewall "); 1533 pw.print(name); 1534 pw.print(" rule: ["); 1535 final int size = rules.size(); 1536 for (int i = 0; i < size; i++) { 1537 pw.print(rules.keyAt(i)); 1538 pw.print(":"); 1539 pw.print(rules.valueAt(i)); 1540 if (i < size - 1) pw.print(","); 1541 } 1542 pw.println("]"); 1543 } 1544 1545 @Override allowProtect(int uid)1546 public void allowProtect(int uid) { 1547 PermissionUtils.enforceNetworkStackPermission(mContext); 1548 1549 try { 1550 mNetdService.networkSetProtectAllow(uid); 1551 } catch (RemoteException | ServiceSpecificException e) { 1552 throw new IllegalStateException(e); 1553 } 1554 } 1555 1556 @Override denyProtect(int uid)1557 public void denyProtect(int uid) { 1558 PermissionUtils.enforceNetworkStackPermission(mContext); 1559 1560 try { 1561 mNetdService.networkSetProtectDeny(uid); 1562 } catch (RemoteException | ServiceSpecificException e) { 1563 throw new IllegalStateException(e); 1564 } 1565 } 1566 1567 @android.annotation.EnforcePermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) 1568 @Override isNetworkRestricted(int uid)1569 public boolean isNetworkRestricted(int uid) { 1570 super.isNetworkRestricted_enforcePermission(); 1571 1572 return isNetworkRestrictedInternal(uid); 1573 } 1574 isNetworkRestrictedInternal(int uid)1575 private boolean isNetworkRestrictedInternal(int uid) { 1576 synchronized (mRulesLock) { 1577 if (getFirewallChainState(FIREWALL_CHAIN_STANDBY) 1578 && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) { 1579 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode"); 1580 return true; 1581 } 1582 if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE) 1583 && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) { 1584 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode"); 1585 return true; 1586 } 1587 if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE) 1588 && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) { 1589 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode"); 1590 return true; 1591 } 1592 if (getFirewallChainState(FIREWALL_CHAIN_RESTRICTED) 1593 && mUidFirewallRestrictedRules.get(uid) != FIREWALL_RULE_ALLOW) { 1594 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of restricted mode"); 1595 return true; 1596 } 1597 if (getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY) 1598 && mUidFirewallLowPowerStandbyRules.get(uid) != FIREWALL_RULE_ALLOW) { 1599 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of low power standby"); 1600 return true; 1601 } 1602 if (getFirewallChainState(FIREWALL_CHAIN_BACKGROUND) 1603 && mUidFirewallBackgroundRules.get(uid) != FIREWALL_RULE_ALLOW) { 1604 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because it is in background"); 1605 return true; 1606 } 1607 if (mUseMeteredFirewallChains) { 1608 if (getFirewallChainState(FIREWALL_CHAIN_METERED_DENY_USER) 1609 && mUidMeteredFirewallDenyUserRules.get(uid) == FIREWALL_RULE_DENY) { 1610 if (DBG) { 1611 Slog.d(TAG, "Uid " + uid + " restricted because of user-restricted metered" 1612 + " data in the background"); 1613 } 1614 return true; 1615 } 1616 if (getFirewallChainState(FIREWALL_CHAIN_METERED_DENY_ADMIN) 1617 && mUidMeteredFirewallDenyAdminRules.get(uid) == FIREWALL_RULE_DENY) { 1618 if (DBG) { 1619 Slog.d(TAG, "Uid " + uid + " restricted because of admin-restricted metered" 1620 + " data in the background"); 1621 } 1622 return true; 1623 } 1624 if (getFirewallChainState(FIREWALL_CHAIN_METERED_ALLOW) 1625 && mUidMeteredFirewallAllowRules.get(uid) != FIREWALL_RULE_ALLOW) { 1626 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode"); 1627 return true; 1628 } 1629 } else { 1630 if (mUidRejectOnMetered.get(uid)) { 1631 if (DBG) { 1632 Slog.d(TAG, "Uid " + uid 1633 + " restricted because of no metered data in the background"); 1634 } 1635 return true; 1636 } 1637 if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) { 1638 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode"); 1639 return true; 1640 } 1641 } 1642 return false; 1643 } 1644 } 1645 setFirewallChainState(int chain, boolean state)1646 private void setFirewallChainState(int chain, boolean state) { 1647 synchronized (mRulesLock) { 1648 mFirewallChainStates.put(chain, state); 1649 } 1650 } 1651 getFirewallChainState(int chain)1652 private boolean getFirewallChainState(int chain) { 1653 synchronized (mRulesLock) { 1654 return mFirewallChainStates.get(chain); 1655 } 1656 } 1657 1658 private class LocalService extends NetworkManagementInternal { 1659 @Override isNetworkRestrictedForUid(int uid)1660 public boolean isNetworkRestrictedForUid(int uid) { 1661 return isNetworkRestrictedInternal(uid); 1662 } 1663 } 1664 } 1665