Merge "StrictMode to detect untagged network traffic."

This commit is contained in:
Jeff Sharkey
2017-01-20 17:31:55 +00:00
committed by Android (Google) Code Review
13 changed files with 115 additions and 12 deletions

View File

@@ -24497,6 +24497,7 @@ package android.net {
public class TrafficStats {
ctor public TrafficStats();
method public static void clearThreadStatsTag();
method public static int getAndSetThreadStatsTag(int);
method public static long getMobileRxBytes();
method public static long getMobileRxPackets();
method public static long getMobileTxBytes();
@@ -30078,6 +30079,7 @@ package android.os {
method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects();
method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects();
method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure();

View File

@@ -26484,6 +26484,7 @@ package android.net {
ctor public TrafficStats();
method public static void clearThreadStatsTag();
method public static void clearThreadStatsUid();
method public static int getAndSetThreadStatsTag(int);
method public static long getMobileRxBytes();
method public static long getMobileRxPackets();
method public static long getMobileTxBytes();
@@ -32730,6 +32731,7 @@ package android.os {
method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects();
method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects();
method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure();

View File

@@ -24587,6 +24587,7 @@ package android.net {
public class TrafficStats {
ctor public TrafficStats();
method public static void clearThreadStatsTag();
method public static int getAndSetThreadStatsTag(int);
method public static long getMobileRxBytes();
method public static long getMobileRxPackets();
method public static long getMobileTxBytes();
@@ -30190,6 +30191,7 @@ package android.os {
method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects();
method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects();
method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure();

View File

@@ -96,6 +96,7 @@ public class SntpClient {
public boolean requestTime(InetAddress address, int port, int timeout) {
DatagramSocket socket = null;
final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NTP);
try {
socket = new DatagramSocket();
socket.setSoTimeout(timeout);
@@ -161,6 +162,7 @@ public class SntpClient {
if (socket != null) {
socket.close();
}
TrafficStats.setThreadStatsTag(oldTag);
}
return true;

View File

@@ -166,6 +166,24 @@ public class TrafficStats {
NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
}
/**
* Set active tag to use when accounting {@link Socket} traffic originating
* from the current thread. Only one active tag per thread is supported.
* <p>
* Changes only take effect during subsequent calls to
* {@link #tagSocket(Socket)}.
* <p>
* Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
* used internally by system services like {@link DownloadManager} when
* performing traffic on behalf of an application.
*
* @return the current tag for the calling thread, which can be used to
* restore any existing values after a nested operation is finished
*/
public static int getAndSetThreadStatsTag(int tag) {
return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
}
/**
* Set active tag to use when accounting {@link Socket} traffic originating
* from the current thread. The tag used internally is well-defined to

View File

@@ -24,6 +24,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.TrafficStats;
import android.net.Uri;
import android.util.ArrayMap;
import android.util.Log;
@@ -245,11 +246,17 @@ public final class StrictMode {
*/
private static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy
/**
* @hide
*/
private static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy
private static final int ALL_VM_DETECT_BITS =
DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE |
DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION;
DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION |
DETECT_VM_UNTAGGED_SOCKET;
// Byte 3: Penalty
@@ -300,6 +307,8 @@ public final class StrictMode {
*/
public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
// CAUTION: we started stealing the top bits of Byte 4 for VM above
/**
* Mask of all the penalty bits valid for thread policies.
*/
@@ -715,7 +724,8 @@ public final class StrictMode {
public Builder detectAll() {
int flags = DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS
| DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS
| DETECT_VM_FILE_URI_EXPOSURE | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION;
| DETECT_VM_FILE_URI_EXPOSURE | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION
| DETECT_VM_UNTAGGED_SOCKET;
// TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have facility
// for apps to mark sockets that should be ignored
@@ -819,6 +829,22 @@ public final class StrictMode {
return enable(DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION);
}
/**
* Detect any sockets in the calling app which have not been tagged
* using {@link TrafficStats}. Tagging sockets can help you
* investigate network usage inside your app, such as a narrowing
* down heavy usage to a specific library or component.
* <p>
* This currently does not detect sockets created in native code.
*
* @see TrafficStats#setThreadStatsTag(int)
* @see TrafficStats#tagSocket(java.net.Socket)
* @see TrafficStats#tagDatagramSocket(java.net.DatagramSocket)
*/
public Builder detectUntaggedSockets() {
return enable(DETECT_VM_UNTAGGED_SOCKET);
}
/**
* Crashes the whole process on violation. This penalty runs at the
* end of all enabled penalties so you'll still get your logging or
@@ -1152,6 +1178,11 @@ public final class StrictMode {
if (IS_ENG_BUILD) {
policyBuilder.penaltyLog();
}
// All core system components need to tag their sockets to aid
// system health investigations
if (android.os.Process.myUid() < android.os.Process.FIRST_APPLICATION_UID) {
policyBuilder.detectUntaggedSockets();
}
setVmPolicy(policyBuilder.build());
setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
}
@@ -1829,6 +1860,13 @@ public final class StrictMode {
return (sVmPolicyMask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
}
/**
* @hide
*/
public static boolean vmUntaggedSocketEnabled() {
return (sVmPolicyMask & DETECT_VM_UNTAGGED_SOCKET) != 0;
}
/**
* @hide
*/
@@ -1911,6 +1949,14 @@ public final class StrictMode {
forceDeath);
}
/**
* @hide
*/
public static void onUntaggedSocket() {
onVmPolicyViolation(null, new Throwable("Untagged socket detected; use"
+ " TrafficStats.setThreadSocketTag() to track all network usage"));
}
// Map from VM violation fingerprint to uptime millis.
private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();

View File

@@ -16,6 +16,7 @@
package com.android.server;
import android.os.StrictMode;
import android.os.SystemProperties;
import android.util.Log;
import android.util.Slog;
@@ -50,16 +51,20 @@ public final class NetworkManagementSocketTagger extends SocketTagger {
SocketTagger.set(new NetworkManagementSocketTagger());
}
public static void setThreadSocketStatsTag(int tag) {
public static int setThreadSocketStatsTag(int tag) {
final int old = threadSocketTags.get().statsTag;
threadSocketTags.get().statsTag = tag;
return old;
}
public static int getThreadSocketStatsTag() {
return threadSocketTags.get().statsTag;
}
public static void setThreadSocketStatsUid(int uid) {
public static int setThreadSocketStatsUid(int uid) {
final int old = threadSocketTags.get().statsUid;
threadSocketTags.get().statsUid = uid;
return old;
}
@Override
@@ -69,6 +74,9 @@ public final class NetworkManagementSocketTagger extends SocketTagger {
Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
+ Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid);
}
if (options.statsTag == -1 && StrictMode.vmUntaggedSocketEnabled()) {
StrictMode.onUntaggedSocket();
}
// TODO: skip tagging when options would be no-op
tagSocketFd(fd, options.statsTag, options.statsUid);
}

View File

@@ -23,6 +23,7 @@ import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.TrafficStats;
import android.os.SystemClock;
import android.system.ErrnoException;
import android.system.Os;
@@ -381,7 +382,12 @@ public class NetworkDiagnostics {
protected void setupSocket(
int sockType, int protocol, long writeTimeout, long readTimeout, int dstPort)
throws ErrnoException, IOException {
mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol);
final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
try {
mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol);
} finally {
TrafficStats.setThreadStatsTag(oldTag);
}
// Setting SNDTIMEO is purely for defensive purposes.
Os.setsockoptTimeval(mFileDescriptor,
SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(writeTimeout));

View File

@@ -779,6 +779,7 @@ public class NetworkMonitor extends StateMachine {
int httpResponseCode = 599;
String redirectUrl = null;
final Stopwatch probeTimer = new Stopwatch().start();
final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
try {
urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url);
urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC);
@@ -839,6 +840,7 @@ public class NetworkMonitor extends StateMachine {
if (urlConnection != null) {
urlConnection.disconnect();
}
TrafficStats.setThreadStatsTag(oldTag);
}
logValidationProbe(probeTimer.stop(), probeType, httpResponseCode);
return new CaptivePortalProbeResult(httpResponseCode, redirectUrl, url.toString());

View File

@@ -25,6 +25,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.net.ProxyInfo;
import android.net.TrafficStats;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
@@ -103,11 +104,15 @@ public class PacManager {
String file;
synchronized (mProxyLock) {
if (Uri.EMPTY.equals(mPacUrl)) return;
final int oldTag = TrafficStats
.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PAC);
try {
file = get(mPacUrl);
} catch (IOException ioe) {
file = null;
Log.w(TAG, "Failed to load PAC file: " + ioe);
} finally {
TrafficStats.setThreadStatsTag(oldTag);
}
}
if (file != null) {

View File

@@ -16,22 +16,19 @@
package com.android.server.location;
import android.net.TrafficStats;
import android.text.TextUtils;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import libcore.io.Streams;
/**
* A class for downloading GPS XTRA data.
*
@@ -94,7 +91,12 @@ public class GpsXtraDownloader {
// load balance our requests among the available servers
while (result == null) {
result = doDownload(mXtraServers[mNextServerIndex]);
final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_GPS);
try {
result = doDownload(mXtraServers[mNextServerIndex]);
} finally {
TrafficStats.setThreadStatsTag(oldTag);
}
// increment mNextServerIndex and wrap around if necessary
mNextServerIndex++;

View File

@@ -30,6 +30,7 @@ import android.net.DhcpResults;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.NetworkUtils;
import android.net.TrafficStats;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.DhcpClientEvent;
import android.net.metrics.DhcpErrorEvent;
@@ -303,6 +304,7 @@ public class DhcpClient extends StateMachine {
}
private boolean initUdpSocket() {
final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_DHCP);
try {
mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_REUSEADDR, 1);
@@ -314,6 +316,8 @@ public class DhcpClient extends StateMachine {
} catch(SocketException|ErrnoException e) {
Log.e(TAG, "Error creating UDP socket", e);
return false;
} finally {
TrafficStats.setThreadStatsTag(oldTag);
}
return true;
}

View File

@@ -22,6 +22,7 @@ import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.TrafficStats;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructGroupReq;
@@ -563,6 +564,7 @@ public class RouterAdvertisementDaemon {
private boolean createSocket() {
final int SEND_TIMEOUT_MS = 300;
final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NEIGHBOR);
try {
mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
// Setting SNDTIMEO is purely for defensive purposes.
@@ -574,6 +576,8 @@ public class RouterAdvertisementDaemon {
} catch (ErrnoException | IOException e) {
Log.e(TAG, "Failed to create RA daemon socket: " + e);
return false;
} finally {
TrafficStats.setThreadStatsTag(oldTag);
}
return true;