Loading services/net/java/android/net/apf/ApfFilter.java +41 −31 Original line number Diff line number Diff line Loading @@ -139,7 +139,8 @@ public class ApfFilter { DROPPED_IPV6_MULTICAST_PING, DROPPED_IPV6_NON_ICMP_MULTICAST, DROPPED_802_3_FRAME, DROPPED_ETHERTYPE_BLACKLISTED; DROPPED_ETHERTYPE_BLACKLISTED, DROPPED_ARP_REPLY_SPA_NO_HOST; // Returns the negative byte offset from the end of the APF data segment for // a given counter. Loading @@ -156,7 +157,7 @@ public class ApfFilter { /** * When APFv4 is supported, loads R1 with the offset of the specified counter. */ private void maybeSetCounter(ApfGenerator gen, Counter c) { private void maybeSetupCounter(ApfGenerator gen, Counter c) { if (mApfCapabilities.hasDataAccess()) { gen.addLoadImmediate(Register.R1, c.offset()); } Loading Loading @@ -288,16 +289,18 @@ public class ApfFilter { private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28; private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN; private static final int ARP_OPCODE_OFFSET = ARP_HEADER_OFFSET + 6; private static final short ARP_OPCODE_REQUEST = 1; private static final short ARP_OPCODE_REPLY = 2; private static final byte[] ARP_IPV4_HEADER = { 0, 1, // Hardware type: Ethernet (1) 8, 0, // Protocol type: IP (0x0800) 6, // Hardware size: 6 4, // Protocol size: 4 }; private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24; private static final int ARP_OPCODE_OFFSET = ARP_HEADER_OFFSET + 6; // Opcode: ARP request (0x0001), ARP reply (0x0002) private static final short ARP_OPCODE_REQUEST = 1; private static final short ARP_OPCODE_REPLY = 2; private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14; private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24; // Do not log ApfProgramEvents whose actual lifetimes was less than this. private static final int APF_PROGRAM_EVENT_LIFETIME_THRESHOLD = 2; // Limit on the Black List size to cap on program usage for this Loading Loading @@ -816,7 +819,7 @@ public class ApfFilter { gen.addJumpIfR0LessThan(filterLifetime, nextFilterLabel); } } maybeSetCounter(gen, Counter.DROPPED_RA); maybeSetupCounter(gen, Counter.DROPPED_RA); gen.addJump(mCountAndDropLabel); gen.defineLabel(nextFilterLabel); return filterLifetime; Loading Loading @@ -883,6 +886,8 @@ public class ApfFilter { // pass // if not ARP IPv4 reply or request // pass // if ARP reply source ip is 0.0.0.0 // drop // if unicast ARP reply // pass // if interface has no IPv4 address Loading @@ -897,18 +902,23 @@ public class ApfFilter { // Pass if not ARP IPv4. gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET); maybeSetCounter(gen, Counter.PASSED_ARP_NON_IPV4); maybeSetupCounter(gen, Counter.PASSED_ARP_NON_IPV4); gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_HEADER, mCountAndPassLabel); // Pass if unknown ARP opcode. gen.addLoad16(Register.R0, ARP_OPCODE_OFFSET); gen.addJumpIfR0Equals(ARP_OPCODE_REQUEST, checkTargetIPv4); // Skip to unicast check maybeSetCounter(gen, Counter.PASSED_ARP_UNKNOWN); maybeSetupCounter(gen, Counter.PASSED_ARP_UNKNOWN); gen.addJumpIfR0NotEquals(ARP_OPCODE_REPLY, mCountAndPassLabel); // Drop if ARP reply source IP is 0.0.0.0 gen.addLoad32(Register.R0, ARP_SOURCE_IP_ADDRESS_OFFSET); maybeSetupCounter(gen, Counter.DROPPED_ARP_REPLY_SPA_NO_HOST); gen.addJumpIfR0Equals(IPV4_ANY_HOST_ADDRESS, mCountAndDropLabel); // Pass if unicast reply. gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET); maybeSetCounter(gen, Counter.PASSED_ARP_UNICAST_REPLY); maybeSetupCounter(gen, Counter.PASSED_ARP_UNICAST_REPLY); gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel); // Either a unicast request, a unicast reply, or a broadcast reply. Loading @@ -916,17 +926,17 @@ public class ApfFilter { if (mIPv4Address == null) { // When there is no IPv4 address, drop GARP replies (b/29404209). gen.addLoad32(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET); maybeSetCounter(gen, Counter.DROPPED_GARP_REPLY); maybeSetupCounter(gen, Counter.DROPPED_GARP_REPLY); gen.addJumpIfR0Equals(IPV4_ANY_HOST_ADDRESS, mCountAndDropLabel); } else { // When there is an IPv4 address, drop unicast/broadcast requests // and broadcast replies with a different target IPv4 address. gen.addLoadImmediate(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET); maybeSetCounter(gen, Counter.DROPPED_ARP_OTHER_HOST); maybeSetupCounter(gen, Counter.DROPPED_ARP_OTHER_HOST); gen.addJumpIfBytesNotEqual(Register.R0, mIPv4Address, mCountAndDropLabel); } maybeSetCounter(gen, Counter.PASSED_ARP); maybeSetupCounter(gen, Counter.PASSED_ARP); gen.addJump(mCountAndPassLabel); } Loading Loading @@ -970,7 +980,7 @@ public class ApfFilter { // NOTE: Relies on R1 containing IPv4 header offset. gen.addAddR1(); gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, skipDhcpv4Filter); maybeSetCounter(gen, Counter.PASSED_DHCP); maybeSetupCounter(gen, Counter.PASSED_DHCP); gen.addJump(mCountAndPassLabel); // Drop all multicasts/broadcasts. Loading @@ -979,30 +989,30 @@ public class ApfFilter { // If IPv4 destination address is in multicast range, drop. gen.addLoad8(Register.R0, IPV4_DEST_ADDR_OFFSET); gen.addAnd(0xf0); maybeSetCounter(gen, Counter.DROPPED_IPV4_MULTICAST); maybeSetupCounter(gen, Counter.DROPPED_IPV4_MULTICAST); gen.addJumpIfR0Equals(0xe0, mCountAndDropLabel); // If IPv4 broadcast packet, drop regardless of L2 (b/30231088). maybeSetCounter(gen, Counter.DROPPED_IPV4_BROADCAST_ADDR); maybeSetupCounter(gen, Counter.DROPPED_IPV4_BROADCAST_ADDR); gen.addLoad32(Register.R0, IPV4_DEST_ADDR_OFFSET); gen.addJumpIfR0Equals(IPV4_BROADCAST_ADDRESS, mCountAndDropLabel); if (mIPv4Address != null && mIPv4PrefixLength < 31) { maybeSetCounter(gen, Counter.DROPPED_IPV4_BROADCAST_NET); maybeSetupCounter(gen, Counter.DROPPED_IPV4_BROADCAST_NET); int broadcastAddr = ipv4BroadcastAddress(mIPv4Address, mIPv4PrefixLength); gen.addJumpIfR0Equals(broadcastAddr, mCountAndDropLabel); } // If L2 broadcast packet, drop. // TODO: can we invert this condition to fall through to the common pass case below? maybeSetCounter(gen, Counter.PASSED_IPV4_UNICAST); maybeSetupCounter(gen, Counter.PASSED_IPV4_UNICAST); gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET); gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel); maybeSetCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST); maybeSetupCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST); gen.addJump(mCountAndDropLabel); } // Otherwise, pass maybeSetCounter(gen, Counter.PASSED_IPV4); maybeSetupCounter(gen, Counter.PASSED_IPV4); gen.addJump(mCountAndPassLabel); } Loading Loading @@ -1050,16 +1060,16 @@ public class ApfFilter { // Drop all other packets sent to ff00::/8 (multicast prefix). gen.defineLabel(dropAllIPv6MulticastsLabel); maybeSetCounter(gen, Counter.DROPPED_IPV6_NON_ICMP_MULTICAST); maybeSetupCounter(gen, Counter.DROPPED_IPV6_NON_ICMP_MULTICAST); gen.addLoad8(Register.R0, IPV6_DEST_ADDR_OFFSET); gen.addJumpIfR0Equals(0xff, mCountAndDropLabel); // Not multicast. Pass. maybeSetCounter(gen, Counter.PASSED_IPV6_UNICAST_NON_ICMP); maybeSetupCounter(gen, Counter.PASSED_IPV6_UNICAST_NON_ICMP); gen.addJump(mCountAndPassLabel); gen.defineLabel(skipIPv6MulticastFilterLabel); } else { // If not ICMPv6, pass. maybeSetCounter(gen, Counter.PASSED_IPV6_NON_ICMP); maybeSetupCounter(gen, Counter.PASSED_IPV6_NON_ICMP); gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, mCountAndPassLabel); } Loading @@ -1069,7 +1079,7 @@ public class ApfFilter { String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA"; gen.addLoad8(Register.R0, ICMP6_TYPE_OFFSET); // Drop all router solicitations (b/32833400) maybeSetCounter(gen, Counter.DROPPED_IPV6_ROUTER_SOLICITATION); maybeSetupCounter(gen, Counter.DROPPED_IPV6_ROUTER_SOLICITATION); gen.addJumpIfR0Equals(ICMPV6_ROUTER_SOLICITATION, mCountAndDropLabel); // If not neighbor announcements, skip filter. gen.addJumpIfR0NotEquals(ICMPV6_NEIGHBOR_ADVERTISEMENT, skipUnsolicitedMulticastNALabel); Loading @@ -1078,7 +1088,7 @@ public class ApfFilter { gen.addLoadImmediate(Register.R0, IPV6_DEST_ADDR_OFFSET); gen.addJumpIfBytesNotEqual(Register.R0, IPV6_ALL_NODES_ADDRESS, skipUnsolicitedMulticastNALabel); maybeSetCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA); maybeSetupCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA); gen.addJump(mCountAndDropLabel); gen.defineLabel(skipUnsolicitedMulticastNALabel); } Loading Loading @@ -1108,7 +1118,7 @@ public class ApfFilter { if (mApfCapabilities.hasDataAccess()) { // Increment TOTAL_PACKETS maybeSetCounter(gen, Counter.TOTAL_PACKETS); maybeSetupCounter(gen, Counter.TOTAL_PACKETS); gen.addLoadData(Register.R0, 0); // load counter gen.addAdd(1); gen.addStoreData(Register.R0, 0); // write-back counter Loading @@ -1134,12 +1144,12 @@ public class ApfFilter { if (mDrop802_3Frames) { // drop 802.3 frames (ethtype < 0x0600) maybeSetCounter(gen, Counter.DROPPED_802_3_FRAME); maybeSetupCounter(gen, Counter.DROPPED_802_3_FRAME); gen.addJumpIfR0LessThan(ETH_TYPE_MIN, mCountAndDropLabel); } // Handle ether-type black list maybeSetCounter(gen, Counter.DROPPED_ETHERTYPE_BLACKLISTED); maybeSetupCounter(gen, Counter.DROPPED_ETHERTYPE_BLACKLISTED); for (int p : mEthTypeBlackList) { gen.addJumpIfR0Equals(p, mCountAndDropLabel); } Loading Loading @@ -1168,9 +1178,9 @@ public class ApfFilter { // Drop non-IP non-ARP broadcasts, pass the rest gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET); maybeSetCounter(gen, Counter.PASSED_NON_IP_UNICAST); maybeSetupCounter(gen, Counter.PASSED_NON_IP_UNICAST); gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel); maybeSetCounter(gen, Counter.DROPPED_ETH_BROADCAST); maybeSetupCounter(gen, Counter.DROPPED_ETH_BROADCAST); gen.addJump(mCountAndDropLabel); // Add IPv6 filters: Loading @@ -1193,7 +1203,7 @@ public class ApfFilter { // Execution will reach the bottom of the program if none of the filters match, // which will pass the packet to the application processor. maybeSetCounter(gen, Counter.PASSED_IPV6_ICMP); maybeSetupCounter(gen, Counter.PASSED_IPV6_ICMP); // Append the count & pass trampoline, which increments the counter at the data address // pointed to by R1, then jumps to the pass label. This saves a few bytes over inserting Loading tests/net/java/android/net/apf/ApfTest.java +20 −8 Original line number Diff line number Diff line Loading @@ -1048,12 +1048,17 @@ public class ApfTest { 4, // Protocol size: 4 0, 2 // Opcode: reply (2) }; private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24; private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14; private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24; private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1}; private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19 private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1}; private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2}; private static final byte[] IPV4_SOURCE_ADDR = {10, 0, 0, 3}; private static final byte[] ANOTHER_IPV4_SOURCE_ADDR = {(byte) 192, 0, 2, 1}; private static final byte[] BUG_PROBE_SOURCE_ADDR1 = {0, 0, 1, 2}; private static final byte[] BUG_PROBE_SOURCE_ADDR2 = {3, 4, 0, 0}; private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0}; // Helper to initialize a default apfFilter. Loading Loading @@ -1399,10 +1404,16 @@ public class ApfTest { assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR)); assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR)); // Verify ARP reply packets from different source ip assertDrop(program, arpReply(IPV4_ANY_HOST_ADDR, IPV4_ANY_HOST_ADDR)); assertPass(program, arpReply(ANOTHER_IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR)); assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR1, IPV4_ANY_HOST_ADDR)); assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR2, IPV4_ANY_HOST_ADDR)); // Verify unicast ARP reply packet is always accepted. assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR)); assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR)); assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR)); assertPass(program, arpReply(IPV4_SOURCE_ADDR, MOCK_IPV4_ADDR)); assertPass(program, arpReply(IPV4_SOURCE_ADDR, ANOTHER_IPV4_ADDR)); assertPass(program, arpReply(IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR)); // Verify GARP reply packets are always filtered assertDrop(program, garpReply()); Loading Loading @@ -1431,19 +1442,20 @@ public class ApfTest { apfFilter.shutdown(); } private static byte[] arpRequestBroadcast(byte[] tip) { private static byte[] arpReply(byte[] sip, byte[] tip) { ByteBuffer packet = ByteBuffer.wrap(new byte[100]); packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); put(packet, ARP_SOURCE_IP_ADDRESS_OFFSET, sip); put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); return packet.array(); } private static byte[] arpReplyUnicast(byte[] tip) { private static byte[] arpRequestBroadcast(byte[] tip) { ByteBuffer packet = ByteBuffer.wrap(new byte[100]); packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REQUEST_HEADER); put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); return packet.array(); } Loading Loading
services/net/java/android/net/apf/ApfFilter.java +41 −31 Original line number Diff line number Diff line Loading @@ -139,7 +139,8 @@ public class ApfFilter { DROPPED_IPV6_MULTICAST_PING, DROPPED_IPV6_NON_ICMP_MULTICAST, DROPPED_802_3_FRAME, DROPPED_ETHERTYPE_BLACKLISTED; DROPPED_ETHERTYPE_BLACKLISTED, DROPPED_ARP_REPLY_SPA_NO_HOST; // Returns the negative byte offset from the end of the APF data segment for // a given counter. Loading @@ -156,7 +157,7 @@ public class ApfFilter { /** * When APFv4 is supported, loads R1 with the offset of the specified counter. */ private void maybeSetCounter(ApfGenerator gen, Counter c) { private void maybeSetupCounter(ApfGenerator gen, Counter c) { if (mApfCapabilities.hasDataAccess()) { gen.addLoadImmediate(Register.R1, c.offset()); } Loading Loading @@ -288,16 +289,18 @@ public class ApfFilter { private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28; private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN; private static final int ARP_OPCODE_OFFSET = ARP_HEADER_OFFSET + 6; private static final short ARP_OPCODE_REQUEST = 1; private static final short ARP_OPCODE_REPLY = 2; private static final byte[] ARP_IPV4_HEADER = { 0, 1, // Hardware type: Ethernet (1) 8, 0, // Protocol type: IP (0x0800) 6, // Hardware size: 6 4, // Protocol size: 4 }; private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24; private static final int ARP_OPCODE_OFFSET = ARP_HEADER_OFFSET + 6; // Opcode: ARP request (0x0001), ARP reply (0x0002) private static final short ARP_OPCODE_REQUEST = 1; private static final short ARP_OPCODE_REPLY = 2; private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14; private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24; // Do not log ApfProgramEvents whose actual lifetimes was less than this. private static final int APF_PROGRAM_EVENT_LIFETIME_THRESHOLD = 2; // Limit on the Black List size to cap on program usage for this Loading Loading @@ -816,7 +819,7 @@ public class ApfFilter { gen.addJumpIfR0LessThan(filterLifetime, nextFilterLabel); } } maybeSetCounter(gen, Counter.DROPPED_RA); maybeSetupCounter(gen, Counter.DROPPED_RA); gen.addJump(mCountAndDropLabel); gen.defineLabel(nextFilterLabel); return filterLifetime; Loading Loading @@ -883,6 +886,8 @@ public class ApfFilter { // pass // if not ARP IPv4 reply or request // pass // if ARP reply source ip is 0.0.0.0 // drop // if unicast ARP reply // pass // if interface has no IPv4 address Loading @@ -897,18 +902,23 @@ public class ApfFilter { // Pass if not ARP IPv4. gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET); maybeSetCounter(gen, Counter.PASSED_ARP_NON_IPV4); maybeSetupCounter(gen, Counter.PASSED_ARP_NON_IPV4); gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_HEADER, mCountAndPassLabel); // Pass if unknown ARP opcode. gen.addLoad16(Register.R0, ARP_OPCODE_OFFSET); gen.addJumpIfR0Equals(ARP_OPCODE_REQUEST, checkTargetIPv4); // Skip to unicast check maybeSetCounter(gen, Counter.PASSED_ARP_UNKNOWN); maybeSetupCounter(gen, Counter.PASSED_ARP_UNKNOWN); gen.addJumpIfR0NotEquals(ARP_OPCODE_REPLY, mCountAndPassLabel); // Drop if ARP reply source IP is 0.0.0.0 gen.addLoad32(Register.R0, ARP_SOURCE_IP_ADDRESS_OFFSET); maybeSetupCounter(gen, Counter.DROPPED_ARP_REPLY_SPA_NO_HOST); gen.addJumpIfR0Equals(IPV4_ANY_HOST_ADDRESS, mCountAndDropLabel); // Pass if unicast reply. gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET); maybeSetCounter(gen, Counter.PASSED_ARP_UNICAST_REPLY); maybeSetupCounter(gen, Counter.PASSED_ARP_UNICAST_REPLY); gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel); // Either a unicast request, a unicast reply, or a broadcast reply. Loading @@ -916,17 +926,17 @@ public class ApfFilter { if (mIPv4Address == null) { // When there is no IPv4 address, drop GARP replies (b/29404209). gen.addLoad32(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET); maybeSetCounter(gen, Counter.DROPPED_GARP_REPLY); maybeSetupCounter(gen, Counter.DROPPED_GARP_REPLY); gen.addJumpIfR0Equals(IPV4_ANY_HOST_ADDRESS, mCountAndDropLabel); } else { // When there is an IPv4 address, drop unicast/broadcast requests // and broadcast replies with a different target IPv4 address. gen.addLoadImmediate(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET); maybeSetCounter(gen, Counter.DROPPED_ARP_OTHER_HOST); maybeSetupCounter(gen, Counter.DROPPED_ARP_OTHER_HOST); gen.addJumpIfBytesNotEqual(Register.R0, mIPv4Address, mCountAndDropLabel); } maybeSetCounter(gen, Counter.PASSED_ARP); maybeSetupCounter(gen, Counter.PASSED_ARP); gen.addJump(mCountAndPassLabel); } Loading Loading @@ -970,7 +980,7 @@ public class ApfFilter { // NOTE: Relies on R1 containing IPv4 header offset. gen.addAddR1(); gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, skipDhcpv4Filter); maybeSetCounter(gen, Counter.PASSED_DHCP); maybeSetupCounter(gen, Counter.PASSED_DHCP); gen.addJump(mCountAndPassLabel); // Drop all multicasts/broadcasts. Loading @@ -979,30 +989,30 @@ public class ApfFilter { // If IPv4 destination address is in multicast range, drop. gen.addLoad8(Register.R0, IPV4_DEST_ADDR_OFFSET); gen.addAnd(0xf0); maybeSetCounter(gen, Counter.DROPPED_IPV4_MULTICAST); maybeSetupCounter(gen, Counter.DROPPED_IPV4_MULTICAST); gen.addJumpIfR0Equals(0xe0, mCountAndDropLabel); // If IPv4 broadcast packet, drop regardless of L2 (b/30231088). maybeSetCounter(gen, Counter.DROPPED_IPV4_BROADCAST_ADDR); maybeSetupCounter(gen, Counter.DROPPED_IPV4_BROADCAST_ADDR); gen.addLoad32(Register.R0, IPV4_DEST_ADDR_OFFSET); gen.addJumpIfR0Equals(IPV4_BROADCAST_ADDRESS, mCountAndDropLabel); if (mIPv4Address != null && mIPv4PrefixLength < 31) { maybeSetCounter(gen, Counter.DROPPED_IPV4_BROADCAST_NET); maybeSetupCounter(gen, Counter.DROPPED_IPV4_BROADCAST_NET); int broadcastAddr = ipv4BroadcastAddress(mIPv4Address, mIPv4PrefixLength); gen.addJumpIfR0Equals(broadcastAddr, mCountAndDropLabel); } // If L2 broadcast packet, drop. // TODO: can we invert this condition to fall through to the common pass case below? maybeSetCounter(gen, Counter.PASSED_IPV4_UNICAST); maybeSetupCounter(gen, Counter.PASSED_IPV4_UNICAST); gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET); gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel); maybeSetCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST); maybeSetupCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST); gen.addJump(mCountAndDropLabel); } // Otherwise, pass maybeSetCounter(gen, Counter.PASSED_IPV4); maybeSetupCounter(gen, Counter.PASSED_IPV4); gen.addJump(mCountAndPassLabel); } Loading Loading @@ -1050,16 +1060,16 @@ public class ApfFilter { // Drop all other packets sent to ff00::/8 (multicast prefix). gen.defineLabel(dropAllIPv6MulticastsLabel); maybeSetCounter(gen, Counter.DROPPED_IPV6_NON_ICMP_MULTICAST); maybeSetupCounter(gen, Counter.DROPPED_IPV6_NON_ICMP_MULTICAST); gen.addLoad8(Register.R0, IPV6_DEST_ADDR_OFFSET); gen.addJumpIfR0Equals(0xff, mCountAndDropLabel); // Not multicast. Pass. maybeSetCounter(gen, Counter.PASSED_IPV6_UNICAST_NON_ICMP); maybeSetupCounter(gen, Counter.PASSED_IPV6_UNICAST_NON_ICMP); gen.addJump(mCountAndPassLabel); gen.defineLabel(skipIPv6MulticastFilterLabel); } else { // If not ICMPv6, pass. maybeSetCounter(gen, Counter.PASSED_IPV6_NON_ICMP); maybeSetupCounter(gen, Counter.PASSED_IPV6_NON_ICMP); gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, mCountAndPassLabel); } Loading @@ -1069,7 +1079,7 @@ public class ApfFilter { String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA"; gen.addLoad8(Register.R0, ICMP6_TYPE_OFFSET); // Drop all router solicitations (b/32833400) maybeSetCounter(gen, Counter.DROPPED_IPV6_ROUTER_SOLICITATION); maybeSetupCounter(gen, Counter.DROPPED_IPV6_ROUTER_SOLICITATION); gen.addJumpIfR0Equals(ICMPV6_ROUTER_SOLICITATION, mCountAndDropLabel); // If not neighbor announcements, skip filter. gen.addJumpIfR0NotEquals(ICMPV6_NEIGHBOR_ADVERTISEMENT, skipUnsolicitedMulticastNALabel); Loading @@ -1078,7 +1088,7 @@ public class ApfFilter { gen.addLoadImmediate(Register.R0, IPV6_DEST_ADDR_OFFSET); gen.addJumpIfBytesNotEqual(Register.R0, IPV6_ALL_NODES_ADDRESS, skipUnsolicitedMulticastNALabel); maybeSetCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA); maybeSetupCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA); gen.addJump(mCountAndDropLabel); gen.defineLabel(skipUnsolicitedMulticastNALabel); } Loading Loading @@ -1108,7 +1118,7 @@ public class ApfFilter { if (mApfCapabilities.hasDataAccess()) { // Increment TOTAL_PACKETS maybeSetCounter(gen, Counter.TOTAL_PACKETS); maybeSetupCounter(gen, Counter.TOTAL_PACKETS); gen.addLoadData(Register.R0, 0); // load counter gen.addAdd(1); gen.addStoreData(Register.R0, 0); // write-back counter Loading @@ -1134,12 +1144,12 @@ public class ApfFilter { if (mDrop802_3Frames) { // drop 802.3 frames (ethtype < 0x0600) maybeSetCounter(gen, Counter.DROPPED_802_3_FRAME); maybeSetupCounter(gen, Counter.DROPPED_802_3_FRAME); gen.addJumpIfR0LessThan(ETH_TYPE_MIN, mCountAndDropLabel); } // Handle ether-type black list maybeSetCounter(gen, Counter.DROPPED_ETHERTYPE_BLACKLISTED); maybeSetupCounter(gen, Counter.DROPPED_ETHERTYPE_BLACKLISTED); for (int p : mEthTypeBlackList) { gen.addJumpIfR0Equals(p, mCountAndDropLabel); } Loading Loading @@ -1168,9 +1178,9 @@ public class ApfFilter { // Drop non-IP non-ARP broadcasts, pass the rest gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET); maybeSetCounter(gen, Counter.PASSED_NON_IP_UNICAST); maybeSetupCounter(gen, Counter.PASSED_NON_IP_UNICAST); gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel); maybeSetCounter(gen, Counter.DROPPED_ETH_BROADCAST); maybeSetupCounter(gen, Counter.DROPPED_ETH_BROADCAST); gen.addJump(mCountAndDropLabel); // Add IPv6 filters: Loading @@ -1193,7 +1203,7 @@ public class ApfFilter { // Execution will reach the bottom of the program if none of the filters match, // which will pass the packet to the application processor. maybeSetCounter(gen, Counter.PASSED_IPV6_ICMP); maybeSetupCounter(gen, Counter.PASSED_IPV6_ICMP); // Append the count & pass trampoline, which increments the counter at the data address // pointed to by R1, then jumps to the pass label. This saves a few bytes over inserting Loading
tests/net/java/android/net/apf/ApfTest.java +20 −8 Original line number Diff line number Diff line Loading @@ -1048,12 +1048,17 @@ public class ApfTest { 4, // Protocol size: 4 0, 2 // Opcode: reply (2) }; private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24; private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14; private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24; private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1}; private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19 private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1}; private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2}; private static final byte[] IPV4_SOURCE_ADDR = {10, 0, 0, 3}; private static final byte[] ANOTHER_IPV4_SOURCE_ADDR = {(byte) 192, 0, 2, 1}; private static final byte[] BUG_PROBE_SOURCE_ADDR1 = {0, 0, 1, 2}; private static final byte[] BUG_PROBE_SOURCE_ADDR2 = {3, 4, 0, 0}; private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0}; // Helper to initialize a default apfFilter. Loading Loading @@ -1399,10 +1404,16 @@ public class ApfTest { assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR)); assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR)); // Verify ARP reply packets from different source ip assertDrop(program, arpReply(IPV4_ANY_HOST_ADDR, IPV4_ANY_HOST_ADDR)); assertPass(program, arpReply(ANOTHER_IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR)); assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR1, IPV4_ANY_HOST_ADDR)); assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR2, IPV4_ANY_HOST_ADDR)); // Verify unicast ARP reply packet is always accepted. assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR)); assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR)); assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR)); assertPass(program, arpReply(IPV4_SOURCE_ADDR, MOCK_IPV4_ADDR)); assertPass(program, arpReply(IPV4_SOURCE_ADDR, ANOTHER_IPV4_ADDR)); assertPass(program, arpReply(IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR)); // Verify GARP reply packets are always filtered assertDrop(program, garpReply()); Loading Loading @@ -1431,19 +1442,20 @@ public class ApfTest { apfFilter.shutdown(); } private static byte[] arpRequestBroadcast(byte[] tip) { private static byte[] arpReply(byte[] sip, byte[] tip) { ByteBuffer packet = ByteBuffer.wrap(new byte[100]); packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); put(packet, ARP_SOURCE_IP_ADDRESS_OFFSET, sip); put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); return packet.array(); } private static byte[] arpReplyUnicast(byte[] tip) { private static byte[] arpRequestBroadcast(byte[] tip) { ByteBuffer packet = ByteBuffer.wrap(new byte[100]); packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REQUEST_HEADER); put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); return packet.array(); } Loading