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

Commit 97bdfc81 authored by Bernie Innocenti's avatar Bernie Innocenti Committed by android-build-merger
Browse files

Merge "Teach ApfGenerator about the new opcodes for accessing data memory" am: 5a533ae4

am: faf23c92

Change-Id: Ia6fafc71380a2d05cd3d3ea019e69b8109269da1
parents b1e51a08 faf23c92
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -522,7 +522,7 @@ public class ApfFilter {
                    ICMP6_4_BYTE_LIFETIME_OFFSET, ICMP6_4_BYTE_LIFETIME_LEN);
        }

        // Note that this parses RA and may throw IllegalArgumentException (from
        // Note that this parses RA and may throw InvalidRaException (from
        // Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException
        // (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with
        // specifications.
@@ -986,9 +986,8 @@ public class ApfFilter {
     */
    @GuardedBy("this")
    private ApfGenerator beginProgramLocked() throws IllegalInstructionException {
        ApfGenerator gen = new ApfGenerator();
        // This is guaranteed to return true because of the check in maybeCreate.
        gen.setApfVersion(mApfCapabilities.apfVersionSupported);
        // This is guaranteed to succeed because of the check in maybeCreate.
        ApfGenerator gen = new ApfGenerator(mApfCapabilities.apfVersionSupported);

        // Here's a basic summary of what the initial program does:
        //
@@ -1216,7 +1215,7 @@ public class ApfFilter {
        //   1. the program generator will need its offsets adjusted.
        //   2. the packet filter attached to our packet socket will need its offset adjusted.
        if (apfCapabilities.apfPacketFormat != ARPHRD_ETHER) return null;
        if (!new ApfGenerator().setApfVersion(apfCapabilities.apfVersionSupported)) {
        if (!ApfGenerator.supportsVersion(apfCapabilities.apfVersionSupported)) {
            Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
            return null;
        }
+57 −6
Original line number Diff line number Diff line
@@ -58,7 +58,9 @@ public class ApfGenerator {
        JLT(18),   // Compare less than and branch, e.g. "jlt R0,5,label"
        JSET(19),  // Compare any bits set and branch, e.g. "jset R0,5,label"
        JNEBS(20), // Compare not equal byte sequence, e.g. "jnebs R0,5,label,0x1122334455"
        EXT(21);   // Followed by immediate indicating ExtendedOpcodes.
        EXT(21),   // Followed by immediate indicating ExtendedOpcodes.
        LDDW(22),  // Load 4 bytes from data memory address (register + immediate): "lddw R0, [5]R1"
        STDW(23);  // Store 4 bytes to data memory address (register + immediate): "stdw R0, [5]R1"

        final int value;

@@ -355,19 +357,38 @@ public class ApfGenerator {
     */
    public static final int LAST_PREFILLED_MEMORY_SLOT = FILTER_AGE_MEMORY_SLOT;

    // This version number syncs up with APF_VERSION in hardware/google/apf/apf_interpreter.h
    private static final int MIN_APF_VERSION = 2;

    private final ArrayList<Instruction> mInstructions = new ArrayList<Instruction>();
    private final HashMap<String, Instruction> mLabels = new HashMap<String, Instruction>();
    private final Instruction mDropLabel = new Instruction(Opcodes.LABEL);
    private final Instruction mPassLabel = new Instruction(Opcodes.LABEL);
    private final int mVersion;
    private boolean mGenerated;

    /**
     * Set version of APF instruction set to generate instructions for. Returns {@code true}
     * if generating for this version is supported, {@code false} otherwise.
     * Creates an ApfGenerator instance which is able to emit instructions for the specified
     * {@code version} of the APF interpreter. Throws {@code IllegalInstructionException} if
     * the requested version is unsupported.
     */
    public boolean setApfVersion(int version) {
        // This version number syncs up with APF_VERSION in hardware/google/apf/apf_interpreter.h
        return version >= 2;
    ApfGenerator(int version) throws IllegalInstructionException {
        mVersion = version;
        requireApfVersion(MIN_APF_VERSION);
    }

    /**
     * Returns true if the specified {@code version} is supported by the ApfGenerator, otherwise
     * false.
     */
    public static boolean supportsVersion(int version) {
        return version >= MIN_APF_VERSION;
    }

    private void requireApfVersion(int minimumVersion) throws IllegalInstructionException {
        if (mVersion < minimumVersion) {
            throw new IllegalInstructionException("Requires APF >= " + minimumVersion);
        }
    }

    private void addInstruction(Instruction instruction) {
@@ -818,6 +839,36 @@ public class ApfGenerator {
        return this;
    }

    /**
     * Add an instruction to the end of the program to load 32 bits from the data memory into
     * {@code register}. The source address is computed by adding @{code offset} to the other
     * register.
     * Requires APF v3 or greater.
     */
    public ApfGenerator addLoadData(Register destinationRegister, int offset)
            throws IllegalInstructionException {
        requireApfVersion(3);
        Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister);
        instruction.setUnsignedImm(offset);
        addInstruction(instruction);
        return this;
    }

    /**
     * Add an instruction to the end of the program to store 32 bits from {@code register} into the
     * data memory. The destination address is computed by adding @{code offset} to the other
     * register.
     * Requires APF v3 or greater.
     */
    public ApfGenerator addStoreData(Register sourceRegister, int offset)
            throws IllegalInstructionException {
        requireApfVersion(3);
        Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister);
        instruction.setUnsignedImm(offset);
        addInstruction(instruction);
        return this;
    }

    /**
     * Updates instruction offset fields using latest instruction sizes.
     * @return current program length in bytes.
+223 −84

File changed.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Diff line number Diff line
@@ -307,7 +307,7 @@ public class Bpf2Apf {
     * program and return it.
     */
    public static byte[] convert(String bpf) throws IllegalInstructionException {
        ApfGenerator gen = new ApfGenerator();
        ApfGenerator gen = new ApfGenerator(3);
        for (String line : bpf.split("\\n")) convertLine(line, gen);
        return gen.generate();
    }
@@ -320,7 +320,7 @@ public class Bpf2Apf {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        StringBuilder responseData = new StringBuilder();
        ApfGenerator gen = new ApfGenerator();
        ApfGenerator gen = new ApfGenerator(3);
        while ((line = in.readLine()) != null) convertLine(line, gen);
        System.out.write(gen.generate());
    }
+18 −11
Original line number Diff line number Diff line
/*
 * Copyright 2016, The Android Open Source Project
 * Copyright 2018, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -28,15 +28,22 @@

// JNI function acting as simply call-through to native APF interpreter.
static jint com_android_server_ApfTest_apfSimulate(
        JNIEnv* env, jclass, jbyteArray program, jbyteArray packet, jint filter_age) {
    return accept_packet(
            (uint8_t*)env->GetByteArrayElements(program, NULL),
            env->GetArrayLength(program),
            (uint8_t*)env->GetByteArrayElements(packet, NULL),
            env->GetArrayLength(packet),
            nullptr,
            0,
            filter_age);
        JNIEnv* env, jclass, jbyteArray program, jbyteArray packet,
        jbyteArray data, jint filter_age) {
    uint8_t* program_raw = (uint8_t*)env->GetByteArrayElements(program, nullptr);
    uint8_t* packet_raw = (uint8_t*)env->GetByteArrayElements(packet, nullptr);
    uint8_t* data_raw = (uint8_t*)(data ? env->GetByteArrayElements(data, nullptr) : nullptr);
    uint32_t program_len = env->GetArrayLength(program);
    uint32_t packet_len = env->GetArrayLength(packet);
    uint32_t data_len = data ? env->GetArrayLength(data) : 0;
    jint result = accept_packet(program_raw, program_len, packet_raw,
                                packet_len, data_raw, data_len, filter_age);
    if (data) {
        env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */);
    }
    env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT);
    env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT);
    return result;
}

class ScopedPcap {
@@ -170,7 +177,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
    }

    static JNINativeMethod gMethods[] = {
            { "apfSimulate", "([B[BI)I",
            { "apfSimulate", "([B[B[BI)I",
                    (void*)com_android_server_ApfTest_apfSimulate },
            { "compileToBpf", "(Ljava/lang/String;)Ljava/lang/String;",
                    (void*)com_android_server_ApfTest_compileToBpf },