Skip to content
Snippets Groups Projects
Commit 34afa7b7 authored by Chiachang Wang's avatar Chiachang Wang Committed by Gerrit Code Review
Browse files

Merge "Check target sockets by UID range" into main

parents 9d962db1 d8474bb1
No related branches found
No related tags found
No related merge requests found
...@@ -25,9 +25,6 @@ import static android.system.OsConstants.AF_INET6; ...@@ -25,9 +25,6 @@ import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.SOL_SOCKET; import static android.system.OsConstants.SOL_SOCKET;
import static android.system.OsConstants.SO_SNDTIMEO; import static android.system.OsConstants.SO_SNDTIMEO;
import static com.android.net.module.util.netlink.NetlinkConstants.NLMSG_DONE;
import static com.android.net.module.util.netlink.NetlinkConstants.SOCKDIAG_MSG_HEADER_SIZE;
import static com.android.net.module.util.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
import static com.android.net.module.util.netlink.NetlinkUtils.IO_TIMEOUT_MS; import static com.android.net.module.util.netlink.NetlinkUtils.IO_TIMEOUT_MS;
import android.annotation.IntDef; import android.annotation.IntDef;
...@@ -90,6 +87,7 @@ import java.util.Set; ...@@ -90,6 +87,7 @@ import java.util.Set;
*/ */
public class AutomaticOnOffKeepaliveTracker { public class AutomaticOnOffKeepaliveTracker {
private static final String TAG = "AutomaticOnOffKeepaliveTracker"; private static final String TAG = "AutomaticOnOffKeepaliveTracker";
private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET6, AF_INET}; private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET6, AF_INET};
private static final long LOW_TCP_POLLING_INTERVAL_MS = 1_000L; private static final long LOW_TCP_POLLING_INTERVAL_MS = 1_000L;
private static final int ADJUST_TCP_POLLING_DELAY_MS = 2000; private static final int ADJUST_TCP_POLLING_DELAY_MS = 2000;
...@@ -794,22 +792,18 @@ public class AutomaticOnOffKeepaliveTracker { ...@@ -794,22 +792,18 @@ public class AutomaticOnOffKeepaliveTracker {
try { try {
while (NetlinkUtils.enoughBytesRemainForValidNlMsg(bytes)) { while (NetlinkUtils.enoughBytesRemainForValidNlMsg(bytes)) {
final int startPos = bytes.position(); // NetlinkMessage.parse() will move the byte buffer position.
// TODO: Parse dst address information to filter socket.
final int nlmsgLen = bytes.getInt(); final NetlinkMessage nlMsg = NetlinkMessage.parse(
final int nlmsgType = bytes.getShort(); bytes, OsConstants.NETLINK_INET_DIAG);
if (isEndOfMessageOrError(nlmsgType)) return false; if (!(nlMsg instanceof InetDiagMessage)) {
// TODO: Parse InetDiagMessage to get uid and dst address information to filter if (DBG) Log.e(TAG, "Not a SOCK_DIAG_BY_FAMILY msg");
// socket via NetlinkMessage.parse. return false;
}
// Skip the header to move to data part.
bytes.position(startPos + SOCKDIAG_MSG_HEADER_SIZE); final InetDiagMessage diagMsg = (InetDiagMessage) nlMsg;
if (isTargetTcpSocket(diagMsg, networkMark, networkMask, vpnUidRanges)) {
if (isTargetTcpSocket(bytes, nlmsgLen, networkMark, networkMask)) { if (DBG) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
bytes.position(startPos);
final InetDiagMessage diagMsg = (InetDiagMessage) NetlinkMessage.parse(
bytes, OsConstants.NETLINK_INET_DIAG);
Log.d(TAG, String.format("Found open TCP connection by uid %d to %s" Log.d(TAG, String.format("Found open TCP connection by uid %d to %s"
+ " cookie %d", + " cookie %d",
diagMsg.inetDiagMsg.idiag_uid, diagMsg.inetDiagMsg.idiag_uid,
...@@ -834,26 +828,31 @@ public class AutomaticOnOffKeepaliveTracker { ...@@ -834,26 +828,31 @@ public class AutomaticOnOffKeepaliveTracker {
return false; return false;
} }
private boolean isEndOfMessageOrError(int nlmsgType) { private static boolean containsUid(Set<Range<Integer>> ranges, int uid) {
return nlmsgType == NLMSG_DONE || nlmsgType != SOCK_DIAG_BY_FAMILY; for (final Range<Integer> range: ranges) {
if (range.contains(uid)) {
return true;
}
}
return false;
} }
private boolean isTargetTcpSocket(@NonNull ByteBuffer bytes, int nlmsgLen, int networkMark, private boolean isTargetTcpSocket(@NonNull InetDiagMessage diagMsg,
int networkMask) { int networkMark, int networkMask, @NonNull Set<Range<Integer>> vpnUidRanges) {
final int mark = readSocketDataAndReturnMark(bytes, nlmsgLen); if (!containsUid(vpnUidRanges, diagMsg.inetDiagMsg.idiag_uid)) return false;
final int mark = readSocketDataAndReturnMark(diagMsg);
return (mark & networkMask) == networkMark; return (mark & networkMask) == networkMark;
} }
private int readSocketDataAndReturnMark(@NonNull ByteBuffer bytes, int nlmsgLen) { private int readSocketDataAndReturnMark(@NonNull InetDiagMessage diagMsg) {
final int nextMsgOffset = bytes.position() + nlmsgLen - SOCKDIAG_MSG_HEADER_SIZE;
int mark = NetlinkUtils.INIT_MARK_VALUE; int mark = NetlinkUtils.INIT_MARK_VALUE;
// Get socket mark // Get socket mark
// TODO: Add a parsing method in NetlinkMessage.parse to support this to skip the remaining for (StructNlAttr attr : diagMsg.nlAttrs) {
// data. if (attr.nla_type == NetlinkUtils.INET_DIAG_MARK) {
while (bytes.position() < nextMsgOffset) { // The netlink attributes should contain only one INET_DIAG_MARK for each socket.
final StructNlAttr nlattr = StructNlAttr.parse(bytes); mark = attr.getValueAsInteger();
if (nlattr != null && nlattr.nla_type == NetlinkUtils.INET_DIAG_MARK) { break;
mark = nlattr.getValueAsInteger();
} }
} }
return mark; return mark;
......
...@@ -162,7 +162,7 @@ public class AutomaticOnOffKeepaliveTrackerTest { ...@@ -162,7 +162,7 @@ public class AutomaticOnOffKeepaliveTrackerTest {
+ "00000000" // idiag_expires + "00000000" // idiag_expires
+ "00000000" // idiag_rqueue + "00000000" // idiag_rqueue
+ "00000000" // idiag_wqueue + "00000000" // idiag_wqueue
+ "00000000" // idiag_uid + "39300000" // idiag_uid = 12345
+ "00000000" // idiag_inode + "00000000" // idiag_inode
// rtattr // rtattr
+ "0500" // len = 5 + "0500" // len = 5
...@@ -426,6 +426,16 @@ public class AutomaticOnOffKeepaliveTrackerTest { ...@@ -426,6 +426,16 @@ public class AutomaticOnOffKeepaliveTrackerTest {
() -> mAOOKeepaliveTracker.isAnyTcpSocketConnected(TEST_NETID, TEST_UID_RANGES))); () -> mAOOKeepaliveTracker.isAnyTcpSocketConnected(TEST_NETID, TEST_UID_RANGES)));
} }
@Test
public void testIsAnyTcpSocketConnected_noTargetUidSocket() throws Exception {
setupResponseWithSocketExisting();
// Configured uid(12345) is not in the VPN range.
assertFalse(visibleOnHandlerThread(mTestHandler,
() -> mAOOKeepaliveTracker.isAnyTcpSocketConnected(
TEST_NETID,
new ArraySet<>(Arrays.asList(new Range<>(99999, 99999))))));
}
@Test @Test
public void testIsAnyTcpSocketConnected_withIncorrectNetId() throws Exception { public void testIsAnyTcpSocketConnected_withIncorrectNetId() throws Exception {
setupResponseWithSocketExisting(); setupResponseWithSocketExisting();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment