Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b12247c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add fuzzing tests to ApfFilter RA processing"

parents 7e98d9e2 8acea76a
Loading
Loading
Loading
Loading
+22 −10
Original line number Diff line number Diff line
@@ -289,8 +289,15 @@ public class ApfFilter {
        return System.currentTimeMillis() / DateUtils.SECOND_IN_MILLIS;
    }

    public static class InvalidRaException extends Exception {
        public InvalidRaException(String m) {
            super(m);
        }
    }

    // A class to hold information about an RA.
    private class Ra {
    @VisibleForTesting
    class Ra {
        // From RFC4861:
        private static final int ICMP6_RA_HEADER_LEN = 16;
        private static final int ICMP6_RA_CHECKSUM_OFFSET =
@@ -436,7 +443,11 @@ public class ApfFilter {
        // Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException
        // (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with
        // specifications.
        Ra(byte[] packet, int length) {
        Ra(byte[] packet, int length) throws InvalidRaException {
            if (length < ICMP6_RA_OPTION_OFFSET) {
                throw new InvalidRaException("Not an ICMP6 router advertisement");
            }

            mPacket = ByteBuffer.wrap(Arrays.copyOf(packet, length));
            mLastSeen = curTime();

@@ -445,7 +456,7 @@ public class ApfFilter {
            if (getUint16(mPacket, ETH_ETHERTYPE_OFFSET) != ETH_P_IPV6 ||
                    uint8(mPacket.get(IPV6_NEXT_HEADER_OFFSET)) != IPPROTO_ICMPV6 ||
                    uint8(mPacket.get(ICMP6_TYPE_OFFSET)) != ICMP6_ROUTER_ADVERTISEMENT) {
                throw new IllegalArgumentException("Not an ICMP6 router advertisement");
                throw new InvalidRaException("Not an ICMP6 router advertisement");
            }


@@ -511,7 +522,7 @@ public class ApfFilter {
                        break;
                }
                if (optionLength <= 0) {
                    throw new IllegalArgumentException(String.format(
                    throw new InvalidRaException(String.format(
                        "Invalid option length opt=%d len=%d", optionType, optionLength));
                }
                mPacket.position(position + optionLength);
@@ -925,8 +936,8 @@ public class ApfFilter {
            // Execution will reach the end of the program if no filters match, which will pass the
            // packet to the AP.
            program = gen.generate();
        } catch (IllegalInstructionException e) {
            Log.e(TAG, "Program failed to generate: ", e);
        } catch (IllegalInstructionException|IllegalStateException e) {
            Log.e(TAG, "Failed to generate APF program.", e);
            return;
        }
        mLastTimeInstalledProgram = curTime();
@@ -972,7 +983,8 @@ public class ApfFilter {
     * if the current APF program should be updated.
     * @return a ProcessRaResult enum describing what action was performed.
     */
    private synchronized ProcessRaResult processRa(byte[] packet, int length) {
    @VisibleForTesting
    synchronized ProcessRaResult processRa(byte[] packet, int length) {
        if (VDBG) hexDump("Read packet = ", packet, length);

        // Have we seen this RA before?
@@ -1011,7 +1023,7 @@ public class ApfFilter {
        try {
            ra = new Ra(packet, length);
        } catch (Exception e) {
            Log.e(TAG, "Error parsing RA: " + e);
            Log.e(TAG, "Error parsing RA", e);
            return ProcessRaResult.PARSE_ERROR;
        }
        // Ignore 0 lifetime RAs.
+38 −4
Original line number Diff line number Diff line
@@ -16,10 +16,6 @@

package android.net.apf;

import static android.system.OsConstants.*;

import com.android.frameworks.servicestests.R;

import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkUtils;
@@ -37,6 +33,10 @@ import android.system.ErrnoException;
import android.system.Os;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import static android.system.OsConstants.*;

import com.android.frameworks.servicestests.R;
import com.android.internal.util.HexDump;

import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@@ -54,6 +54,7 @@ import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Random;

import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -1146,6 +1147,39 @@ public class ApfTest extends AndroidTestCase {
        buffer.position(original);
    }

    public void testRaParsing() throws Exception {
        final int maxRandomPacketSize = 512;
        final Random r = new Random();
        MockIpManagerCallback cb = new MockIpManagerCallback();
        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog);
        for (int i = 0; i < 1000; i++) {
            byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
            r.nextBytes(packet);
            try {
                apfFilter.new Ra(packet, packet.length);
            } catch (ApfFilter.InvalidRaException e) {
            } catch (Exception e) {
                throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
            }
        }
    }

    public void testRaProcessing() throws Exception {
        final int maxRandomPacketSize = 512;
        final Random r = new Random();
        MockIpManagerCallback cb = new MockIpManagerCallback();
        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog);
        for (int i = 0; i < 1000; i++) {
            byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
            r.nextBytes(packet);
            try {
                apfFilter.processRa(packet, packet.length);
            } catch (Exception e) {
                throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
            }
        }
    }

    /**
     * Call the APF interpreter the run {@code program} on {@code packet} pretending the
     * filter was installed {@code filter_age} seconds ago.