Destroy sockets of apps under background firewall chain restriction
Currently, CS destroys sockets of apps under firewall chain restriction only when the firewall chains get enabled by setFirewallChainEnabled. This CL updates CS to also destroy sockets of apps when the setUidFirewallRule and replaceFirewallChain update uid rule and apps lose network access due to FIREWALL_CHAIN_BACKGROUND. This socket destruction is delayed until the cell modem is up in the same way that CS destroys sockets of frozen apps. Test: CSSocketDestroyTest Bug: 300681644 Change-Id: I6a6fb5d6d7b71c0949a4195b84d30efef95bff37
This commit is contained in:
parent
ee96ba0e60
commit
ff555a709c
1 changed files with 483 additions and 5 deletions
|
|
@ -36,6 +36,7 @@ import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP
|
|||
import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE;
|
||||
import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
|
||||
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
|
||||
import static android.net.ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND;
|
||||
import static android.net.ConnectivityManager.BLOCKED_REASON_LOCKDOWN_VPN;
|
||||
import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
|
||||
import static android.net.ConnectivityManager.BLOCKED_REASON_NETWORK_RESTRICTED;
|
||||
|
|
@ -877,6 +878,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
*/
|
||||
private static final int EVENT_UID_FROZEN_STATE_CHANGED = 61;
|
||||
|
||||
/**
|
||||
* Event to update firewall socket destroy reasons for uids.
|
||||
* obj = List of Pair(uid, socketDestroyReasons)
|
||||
*/
|
||||
private static final int EVENT_UPDATE_FIREWALL_DESTROY_SOCKET_REASONS = 62;
|
||||
|
||||
/**
|
||||
* Event to clear firewall socket destroy reasons for all uids.
|
||||
* arg1 = socketDestroyReason
|
||||
*/
|
||||
private static final int EVENT_CLEAR_FIREWALL_DESTROY_SOCKET_REASONS = 63;
|
||||
|
||||
/**
|
||||
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
|
||||
* should be shown.
|
||||
|
|
@ -1033,6 +1046,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
|
||||
private static final int DESTROY_SOCKET_REASON_NONE = 0;
|
||||
private static final int DESTROY_SOCKET_REASON_FROZEN = 1 << 0;
|
||||
private static final int DESTROY_SOCKET_REASON_FIREWALL_BACKGROUND = 1 << 1;
|
||||
|
||||
// Flag to drop packets to VPN addresses ingressing via non-VPN interfaces.
|
||||
private final boolean mIngressToVpnAddressFiltering;
|
||||
|
|
@ -3404,6 +3418,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
return !mNetworkActivityTracker.isDefaultNetworkActive();
|
||||
}
|
||||
|
||||
private boolean shouldTrackFirewallDestroySocketReasons() {
|
||||
return mDeps.isAtLeastV();
|
||||
}
|
||||
|
||||
private void updateDestroySocketReasons(final int uid, final int reason,
|
||||
final boolean addReason) {
|
||||
final int destroyReasons = mDestroySocketPendingUids.get(uid, DESTROY_SOCKET_REASON_NONE);
|
||||
|
|
@ -3432,6 +3450,43 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
}
|
||||
}
|
||||
|
||||
private void handleUpdateFirewallDestroySocketReasons(
|
||||
List<Pair<Integer, Integer>> reasonsList) {
|
||||
if (!shouldTrackFirewallDestroySocketReasons()) {
|
||||
Log.wtf(TAG, "handleUpdateFirewallDestroySocketReasons is called unexpectedly");
|
||||
return;
|
||||
}
|
||||
ensureRunningOnConnectivityServiceThread();
|
||||
|
||||
for (Pair<Integer, Integer> uidSocketDestroyReasons: reasonsList) {
|
||||
final int uid = uidSocketDestroyReasons.first;
|
||||
final int reasons = uidSocketDestroyReasons.second;
|
||||
final boolean destroyByFirewallBackground =
|
||||
(reasons & DESTROY_SOCKET_REASON_FIREWALL_BACKGROUND)
|
||||
!= DESTROY_SOCKET_REASON_NONE;
|
||||
updateDestroySocketReasons(uid, DESTROY_SOCKET_REASON_FIREWALL_BACKGROUND,
|
||||
destroyByFirewallBackground);
|
||||
}
|
||||
|
||||
if (!mDelayDestroySockets || !isCellNetworkIdle()) {
|
||||
destroyPendingSockets();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleClearFirewallDestroySocketReasons(final int reason) {
|
||||
if (!shouldTrackFirewallDestroySocketReasons()) {
|
||||
Log.wtf(TAG, "handleClearFirewallDestroySocketReasons is called uexpectedly");
|
||||
return;
|
||||
}
|
||||
ensureRunningOnConnectivityServiceThread();
|
||||
|
||||
// Unset reason from all pending uids
|
||||
for (int i = mDestroySocketPendingUids.size() - 1; i >= 0; i--) {
|
||||
final int uid = mDestroySocketPendingUids.keyAt(i);
|
||||
updateDestroySocketReasons(uid, reason, false /* addReason */);
|
||||
}
|
||||
}
|
||||
|
||||
private void destroyPendingSockets() {
|
||||
ensureRunningOnConnectivityServiceThread();
|
||||
if (mDestroySocketPendingUids.size() == 0) {
|
||||
|
|
@ -6617,6 +6672,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
UidFrozenStateChangedArgs args = (UidFrozenStateChangedArgs) msg.obj;
|
||||
handleFrozenUids(args.mUids, args.mFrozenStates);
|
||||
break;
|
||||
case EVENT_UPDATE_FIREWALL_DESTROY_SOCKET_REASONS:
|
||||
handleUpdateFirewallDestroySocketReasons((List) msg.obj);
|
||||
break;
|
||||
case EVENT_CLEAR_FIREWALL_DESTROY_SOCKET_REASONS:
|
||||
handleClearFirewallDestroySocketReasons(msg.arg1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13734,6 +13795,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_BLOCKED_REASONS_CHANGED,
|
||||
List.of(new Pair<>(uid, mBpfNetMaps.getUidNetworkingBlockedReasons(uid)))));
|
||||
}
|
||||
if (shouldTrackFirewallDestroySocketReasons()) {
|
||||
maybePostFirewallDestroySocketReasons(chain, Set.of(uid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -13777,24 +13841,41 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
return rule;
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
private Set<Integer> getUidsOnFirewallChain(final int chain) throws ErrnoException {
|
||||
if (BpfNetMapsUtils.isFirewallAllowList(chain)) {
|
||||
return mBpfNetMaps.getUidsWithAllowRuleOnAllowListChain(chain);
|
||||
} else {
|
||||
return mBpfNetMaps.getUidsWithDenyRuleOnDenyListChain(chain);
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
private void closeSocketsForFirewallChainLocked(final int chain)
|
||||
throws ErrnoException, SocketException, InterruptedIOException {
|
||||
final Set<Integer> uidsOnChain = getUidsOnFirewallChain(chain);
|
||||
if (BpfNetMapsUtils.isFirewallAllowList(chain)) {
|
||||
// Allowlist means the firewall denies all by default, uids must be explicitly allowed
|
||||
// So, close all non-system socket owned by uids that are not explicitly allowed
|
||||
Set<Range<Integer>> ranges = new ArraySet<>();
|
||||
ranges.add(new Range<>(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE));
|
||||
final Set<Integer> exemptUids = mBpfNetMaps.getUidsWithAllowRuleOnAllowListChain(chain);
|
||||
mDeps.destroyLiveTcpSockets(ranges, exemptUids);
|
||||
mDeps.destroyLiveTcpSockets(ranges, uidsOnChain /* exemptUids */);
|
||||
} else {
|
||||
// Denylist means the firewall allows all by default, uids must be explicitly denied
|
||||
// So, close socket owned by uids that are explicitly denied
|
||||
final Set<Integer> ownerUids = mBpfNetMaps.getUidsWithDenyRuleOnDenyListChain(chain);
|
||||
mDeps.destroyLiveTcpSocketsByOwnerUids(ownerUids);
|
||||
mDeps.destroyLiveTcpSocketsByOwnerUids(uidsOnChain /* ownerUids */);
|
||||
}
|
||||
}
|
||||
|
||||
private void maybePostClearFirewallDestroySocketReasons(int chain) {
|
||||
if (chain != FIREWALL_CHAIN_BACKGROUND) {
|
||||
// TODO (b/300681644): Support other firewall chains
|
||||
return;
|
||||
}
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CLEAR_FIREWALL_DESTROY_SOCKET_REASONS,
|
||||
DESTROY_SOCKET_REASON_FIREWALL_BACKGROUND, 0 /* arg2 */));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFirewallChainEnabled(final int chain, final boolean enable) {
|
||||
enforceNetworkStackOrSettingsPermission();
|
||||
|
|
@ -13820,6 +13901,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
if (shouldTrackUidsForBlockedStatusCallbacks()) {
|
||||
updateTrackingUidsBlockedReasons();
|
||||
}
|
||||
if (shouldTrackFirewallDestroySocketReasons() && !enable) {
|
||||
// Clear destroy socket reasons so that CS does not destroy sockets of apps that
|
||||
// have network access.
|
||||
maybePostClearFirewallDestroySocketReasons(chain);
|
||||
}
|
||||
}
|
||||
|
||||
if (mDeps.isAtLeastU() && enable) {
|
||||
|
|
@ -13847,6 +13933,31 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
uidBlockedReasonsList));
|
||||
}
|
||||
|
||||
private int getFirewallDestroySocketReasons(final int blockedReasons) {
|
||||
int destroySocketReasons = DESTROY_SOCKET_REASON_NONE;
|
||||
if ((blockedReasons & BLOCKED_REASON_APP_BACKGROUND) != BLOCKED_REASON_NONE) {
|
||||
destroySocketReasons |= DESTROY_SOCKET_REASON_FIREWALL_BACKGROUND;
|
||||
}
|
||||
return destroySocketReasons;
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
@GuardedBy("mBlockedStatusTrackingUids")
|
||||
private void maybePostFirewallDestroySocketReasons(int chain, Set<Integer> uids) {
|
||||
if (chain != FIREWALL_CHAIN_BACKGROUND) {
|
||||
// TODO (b/300681644): Support other firewall chains
|
||||
return;
|
||||
}
|
||||
final ArrayList<Pair<Integer, Integer>> reasonsList = new ArrayList<>();
|
||||
for (int uid: uids) {
|
||||
final int blockedReasons = mBpfNetMaps.getUidNetworkingBlockedReasons(uid);
|
||||
final int destroySocketReaons = getFirewallDestroySocketReasons(blockedReasons);
|
||||
reasonsList.add(new Pair<>(uid, destroySocketReaons));
|
||||
}
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UPDATE_FIREWALL_DESTROY_SOCKET_REASONS,
|
||||
reasonsList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getFirewallChainEnabled(final int chain) {
|
||||
enforceNetworkStackOrSettingsPermission();
|
||||
|
|
@ -13872,11 +13983,29 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
}
|
||||
|
||||
synchronized (mBlockedStatusTrackingUids) {
|
||||
mBpfNetMaps.replaceUidChain(chain, uids);
|
||||
// replaceFirewallChain removes uids that are currently on the chain and put |uids| on
|
||||
// the chain.
|
||||
// So this method could change blocked reasons of uids that are currently on chain +
|
||||
// |uids|.
|
||||
final Set<Integer> affectedUids = new ArraySet<>();
|
||||
if (shouldTrackFirewallDestroySocketReasons()) {
|
||||
try {
|
||||
affectedUids.addAll(getUidsOnFirewallChain(chain));
|
||||
} catch (ErrnoException e) {
|
||||
Log.e(TAG, "Failed to get uids on chain(" + chain + "): " + e);
|
||||
}
|
||||
for (final int uid: uids) {
|
||||
affectedUids.add(uid);
|
||||
}
|
||||
}
|
||||
|
||||
mBpfNetMaps.replaceUidChain(chain, uids);
|
||||
if (shouldTrackUidsForBlockedStatusCallbacks()) {
|
||||
updateTrackingUidsBlockedReasons();
|
||||
}
|
||||
if (shouldTrackFirewallDestroySocketReasons()) {
|
||||
maybePostFirewallDestroySocketReasons(chain, affectedUids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue