From 91723d7f7ecc07e9bfa84c445213acf1dec0664f Mon Sep 17 00:00:00 2001 From: Paul Jensen Date: Thu, 14 Apr 2016 14:51:02 -0400 Subject: [PATCH] Avoid APF JNEBS instruction with R1 as it doesn't work APF version 2 and prior versions fail to execute JNEBS with R1 argument. The APF interpreter tries to use R1's value as the number of bytes to compare, as well as the offset within the packet to compare at. This change makes ApfFilter avoid using this and makes the APF generator throw if this is used. This was limiting the IPv4 filter, causing it to only drop multicast (when multicast filtering was enabled), rather than a wider range of broadcast packets. Bug: 28206777 Change-Id: I8d116e024e8bd641b21053c6b1defc734d744467 --- services/net/java/android/net/apf/ApfFilter.java | 7 +++---- services/net/java/android/net/apf/ApfGenerator.java | 6 +++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java index 6722332b4d96d..5a1027547fc67 100644 --- a/services/net/java/android/net/apf/ApfFilter.java +++ b/services/net/java/android/net/apf/ApfFilter.java @@ -107,6 +107,7 @@ public class ApfFilter { private static final boolean VDBG = false; private static final int ETH_HEADER_LEN = 14; + private static final int ETH_DEST_ADDR_OFFSET = 0; private static final int ETH_ETHERTYPE_OFFSET = 12; private static final byte[] ETH_BROADCAST_MAC_ADDRESS = new byte[]{ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }; @@ -582,7 +583,6 @@ public class ApfFilter { * DROP_LABEL or PASS_LABEL and does not fall off the end. * Preconditions: * - Packet being filtered is IPv4 - * - R1 is initialized to 0 */ @GuardedBy("this") private void generateIPv4FilterLocked(ApfGenerator gen) throws IllegalInstructionException { @@ -605,9 +605,8 @@ public class ApfFilter { // Drop all broadcasts besides DHCP addressed to us // If not a broadcast packet, pass - // NOTE: Relies on R1 being initialized to 0 which is the offset of the ethernet - // destination MAC address - gen.addJumpIfBytesNotEqual(Register.R1, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL); + gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET); + gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL); // If not UDP, drop gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET); gen.addJumpIfR0NotEquals(IPPROTO_UDP, gen.DROP_LABEL); diff --git a/services/net/java/android/net/apf/ApfGenerator.java b/services/net/java/android/net/apf/ApfGenerator.java index 96c2ba535dd10..d41fbce1f2066 100644 --- a/services/net/java/android/net/apf/ApfGenerator.java +++ b/services/net/java/android/net/apf/ApfGenerator.java @@ -734,7 +734,11 @@ public class ApfGenerator { * Add an instruction to the end of the program to jump to {@code target} if the bytes of the * packet at, an offset specified by {@code register}, match {@code bytes}. */ - public ApfGenerator addJumpIfBytesNotEqual(Register register, byte[] bytes, String target) { + public ApfGenerator addJumpIfBytesNotEqual(Register register, byte[] bytes, String target) + throws IllegalInstructionException { + if (register == Register.R1) { + throw new IllegalInstructionException("JNEBS fails with R1"); + } Instruction instruction = new Instruction(Opcodes.JNEBS, register); instruction.setUnsignedImm(bytes.length); instruction.setTargetLabel(target);