diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-04-22 07:22:00 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-04-22 07:22:00 +0000 |
commit | d76579eb148c3b1aebd4dd35b97dd80ea7b4a831 (patch) | |
tree | 5520a802631d8e7295dd370433b3261081d4bd18 | |
parent | 0e55264fa5e72647cb434a48f6f241cdb19925f2 (diff) | |
parent | d2cc2b74f161d88bc0622b03d48ef176fefee03a (diff) | |
download | apf-d76579eb148c3b1aebd4dd35b97dd80ea7b4a831.tar.gz |
Snap for 4736748 from d2cc2b74f161d88bc0622b03d48ef176fefee03a to pi-releaseandroid-wear-9.0.0_r9android-wear-9.0.0_r8android-wear-9.0.0_r7android-wear-9.0.0_r6android-wear-9.0.0_r5android-wear-9.0.0_r4android-wear-9.0.0_r34android-wear-9.0.0_r33android-wear-9.0.0_r32android-wear-9.0.0_r31android-wear-9.0.0_r30android-wear-9.0.0_r3android-wear-9.0.0_r29android-wear-9.0.0_r28android-wear-9.0.0_r27android-wear-9.0.0_r26android-wear-9.0.0_r25android-wear-9.0.0_r24android-wear-9.0.0_r23android-wear-9.0.0_r22android-wear-9.0.0_r21android-wear-9.0.0_r20android-wear-9.0.0_r2android-wear-9.0.0_r19android-wear-9.0.0_r18android-wear-9.0.0_r17android-wear-9.0.0_r16android-wear-9.0.0_r15android-wear-9.0.0_r14android-wear-9.0.0_r13android-wear-9.0.0_r12android-wear-9.0.0_r11android-wear-9.0.0_r10android-wear-9.0.0_r1android-vts-9.0_r9android-vts-9.0_r8android-vts-9.0_r7android-vts-9.0_r6android-vts-9.0_r5android-vts-9.0_r4android-vts-9.0_r19android-vts-9.0_r18android-vts-9.0_r17android-vts-9.0_r16android-vts-9.0_r15android-vts-9.0_r14android-vts-9.0_r13android-vts-9.0_r12android-vts-9.0_r11android-vts-9.0_r10android-security-9.0.0_r76android-security-9.0.0_r75android-security-9.0.0_r74android-security-9.0.0_r73android-security-9.0.0_r72android-security-9.0.0_r71android-security-9.0.0_r70android-security-9.0.0_r69android-security-9.0.0_r68android-security-9.0.0_r67android-security-9.0.0_r66android-security-9.0.0_r65android-security-9.0.0_r64android-security-9.0.0_r63android-security-9.0.0_r62android-cts-9.0_r9android-cts-9.0_r8android-cts-9.0_r7android-cts-9.0_r6android-cts-9.0_r5android-cts-9.0_r4android-cts-9.0_r3android-cts-9.0_r20android-cts-9.0_r2android-cts-9.0_r19android-cts-9.0_r18android-cts-9.0_r17android-cts-9.0_r16android-cts-9.0_r15android-cts-9.0_r14android-cts-9.0_r13android-cts-9.0_r12android-cts-9.0_r11android-cts-9.0_r10android-cts-9.0_r1android-9.0.0_r9android-9.0.0_r8android-9.0.0_r7android-9.0.0_r61android-9.0.0_r60android-9.0.0_r6android-9.0.0_r59android-9.0.0_r58android-9.0.0_r57android-9.0.0_r56android-9.0.0_r55android-9.0.0_r54android-9.0.0_r53android-9.0.0_r52android-9.0.0_r51android-9.0.0_r50android-9.0.0_r5android-9.0.0_r49android-9.0.0_r48android-9.0.0_r3android-9.0.0_r2android-9.0.0_r18android-9.0.0_r17android-9.0.0_r10android-9.0.0_r1security-pi-releasepie-vts-releasepie-security-releasepie-s2-releasepie-release-2pie-releasepie-r2-s2-releasepie-r2-s1-releasepie-r2-releasepie-platform-releasepie-gsipie-cuttlefish-testingpie-cts-release
Change-Id: I41f644223454c399aa11065fb959f58440db94f2
-rw-r--r-- | apf.h | 19 | ||||
-rw-r--r-- | apf_disassembler.c | 2 | ||||
-rw-r--r-- | apf_interpreter.c | 30 | ||||
-rw-r--r-- | apf_interpreter.h | 24 | ||||
-rw-r--r-- | apf_run.c | 18 |
5 files changed, 67 insertions, 26 deletions
@@ -1,5 +1,5 @@ /* - * 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. @@ -14,6 +14,9 @@ * limitations under the License. */ +#ifndef ANDROID_APF_APF_H +#define ANDROID_APF_APF_H + // A brief overview of APF: // // APF machine is composed of: @@ -83,6 +86,8 @@ // When the APF program begins execution, three of the sixteen memory slots // are pre-filled by the interpreter with values that may be useful for // programs: +// Slot #11 contains the size (in bytes) of the APF program. +// Slot #12 contains the total size of the APF buffer (program + data). // Slot #13 is filled with the IPv4 header length. This value is calculated // by loading the first byte of the IPv4 header and taking the // bottom 4 bits and multiplying their value by 4. This value is @@ -91,7 +96,7 @@ // Slot #14 is filled with size of the packet in bytes, including the // link-layer header if any. // Slot #15 is filled with the filter age in seconds. This is the number of -// seconds since the AP send the program to the chipset. This may +// seconds since the AP sent the program to the chipset. This may // be used by filters that should have a particular lifetime. For // example, it can be used to rate-limit particular packets to one // every N seconds. @@ -119,6 +124,8 @@ // Number of temporary memory slots, see ldm/stm instructions. #define MEMORY_ITEMS 16 // Upon program execution, some temporary memory slots are prefilled: +#define MEMORY_OFFSET_PROGRAM_SIZE 11 // Size of program (in bytes) +#define MEMORY_OFFSET_DATA_SIZE 12 // Total size of program + data #define MEMORY_OFFSET_IPV4_HEADER_SIZE 13 // 4*([APF_FRAME_HEADER_SIZE]&15) #define MEMORY_OFFSET_PACKET_SIZE 14 // Size of packet in bytes. #define MEMORY_OFFSET_FILTER_AGE 15 // Age since filter installed in seconds. @@ -136,7 +143,7 @@ #define AND_OPCODE 10 // And, e.g. "and R0,5" #define OR_OPCODE 11 // Or, e.g. "or R0,5" #define SH_OPCODE 12 // Left shift, e.g, "sh R0, 5" or "sh R0, -5" (shifts right) -#define LI_OPCODE 13 // Load immediate, e.g. "li R0,5" (immediate encoded as signed value) +#define LI_OPCODE 13 // Load signed immediate, e.g. "li R0,5" #define JMP_OPCODE 14 // Unconditional jump, e.g. "jmp label" #define JEQ_OPCODE 15 // Compare equal and branch, e.g. "jeq R0,5,label" #define JNE_OPCODE 16 // Compare not equal and branch, e.g. "jne R0,5,label" @@ -145,8 +152,8 @@ #define JSET_OPCODE 19 // Compare any bits set and branch, e.g. "jset R0,5,label" #define JNEBS_OPCODE 20 // Compare not equal byte sequence, e.g. "jnebs R0,5,label,0x1122334455" #define EXT_OPCODE 21 // Immediate value is one of *_EXT_OPCODE -#define LDDW_OPCODE 22 // Load 4 bytes from data address (register + imm): "lddw R0, [5+R1]" -#define STDW_OPCODE 23 // Store 4 bytes to data address (register + imm): "stdw R0, [5+R1]" +#define LDDW_OPCODE 22 // Load 4 bytes from data address (register + simm): "lddw R0, [5+R1]" +#define STDW_OPCODE 23 // Store 4 bytes to data address (register + simm): "stdw R0, [5+R1]" // Extended opcodes. These all have an opcode of EXT_OPCODE // and specify the actual opcode in the immediate field. @@ -162,3 +169,5 @@ #define EXTRACT_OPCODE(i) (((i) >> 3) & 31) #define EXTRACT_REGISTER(i) ((i) & 1) #define EXTRACT_IMM_LENGTH(i) (((i) >> 1) & 3) + +#endif // ANDROID_APF_APF_H diff --git a/apf_disassembler.c b/apf_disassembler.c index b61202c..818de7b 100644 --- a/apf_disassembler.c +++ b/apf_disassembler.c @@ -211,7 +211,7 @@ int main(void) { case LDDW_OPCODE: case STDW_OPCODE: PRINT_OPCODE(); - printf("r%u, [%u+r%u]", reg_num, imm, reg_num ^ 1); + printf("r%u, [%d+r%u]", reg_num, signed_imm, reg_num ^ 1); break; // Unknown opcode diff --git a/apf_interpreter.c b/apf_interpreter.c index e2f46cb..1585a34 100644 --- a/apf_interpreter.c +++ b/apf_interpreter.c @@ -1,5 +1,5 @@ /* - * 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. @@ -31,9 +31,8 @@ // superfluous ">= 0" with unsigned expressions generates compile warnings. #define ENFORCE_UNSIGNED(c) ((c)==(uint32_t)(c)) -int accept_packet(const uint8_t* program, uint32_t program_len, +int accept_packet(uint8_t* program, uint32_t program_len, uint32_t ram_len, const uint8_t* packet, uint32_t packet_len, - uint8_t* data, uint32_t data_len, uint32_t filter_age) { // Is offset within program bounds? #define IN_PROGRAM_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < program_len) @@ -42,7 +41,8 @@ int accept_packet(const uint8_t* program, uint32_t program_len, // Is access to offset |p| length |size| within data bounds? #define IN_DATA_BOUNDS(p, size) (ENFORCE_UNSIGNED(p) && \ ENFORCE_UNSIGNED(size) && \ - (p) + (size) <= data_len && \ + (p) + (size) <= ram_len && \ + (p) >= program_len && \ (p) + (size) >= (p)) // catch wraparounds // Accept packet if not within program bounds #define ASSERT_IN_PROGRAM_BOUNDS(p) ASSERT_RETURN(IN_PROGRAM_BOUNDS(p)) @@ -58,6 +58,8 @@ int accept_packet(const uint8_t* program, uint32_t program_len, // Memory slot values. uint32_t memory[MEMORY_ITEMS] = {}; // Fill in pre-filled memory slot values. + memory[MEMORY_OFFSET_PROGRAM_SIZE] = program_len; + memory[MEMORY_OFFSET_DATA_SIZE] = ram_len; memory[MEMORY_OFFSET_PACKET_SIZE] = packet_len; memory[MEMORY_OFFSET_FILTER_AGE] = filter_age; ASSERT_IN_PACKET_BOUNDS(APF_FRAME_HEADER_SIZE); @@ -265,22 +267,34 @@ int accept_packet(const uint8_t* program, uint32_t program_len, } break; case LDDW_OPCODE: { - uint32_t offs = imm + OTHER_REG; + uint32_t offs = OTHER_REG + signed_imm; uint32_t size = 4; uint32_t val = 0; + // Negative offsets wrap around the end of the address space. + // This allows us to efficiently access the end of the + // address space with one-byte immediates without using %=. + if (offs & 0x80000000) { + offs = ram_len + offs; // unsigned overflow intended + } ASSERT_IN_DATA_BOUNDS(offs, size); while (size--) - val = (val << 8) | data[offs++]; + val = (val << 8) | program[offs++]; REG = val; break; } case STDW_OPCODE: { - uint32_t offs = imm + OTHER_REG; + uint32_t offs = OTHER_REG + signed_imm; uint32_t size = 4; uint32_t val = REG; + // Negative offsets wrap around the end of the address space. + // This allows us to efficiently access the end of the + // address space with one-byte immediates without using %=. + if (offs & 0x80000000) { + offs = ram_len + offs; // unsigned overflow intended + } ASSERT_IN_DATA_BOUNDS(offs, size); while (size--) { - data[offs++] = (val >> 24); + program[offs++] = (val >> 24); val <<= 8; } break; diff --git a/apf_interpreter.h b/apf_interpreter.h index 78a0dd3..368ae04 100644 --- a/apf_interpreter.h +++ b/apf_interpreter.h @@ -27,26 +27,36 @@ extern "C" { * Version of APF instruction set processed by accept_packet(). * Should be returned by wifi_get_packet_filter_info. */ -#define APF_VERSION 3 +#define APF_VERSION 4 /** * Runs a packet filtering program over a packet. * - * @param program the program bytecode. - * @param program_len the length of {@code apf_program} in bytes. + * The text section containing the program instructions starts at address + * program and stops at + program_len - 1, and the writable data section + * begins at program + program_len and ends at program + ram_len - 1, + * as described in the following diagram: + * + * program program + program_len program + ram_len + * | text section | data section | + * +--------------------+------------------------+ + * + * @param program the program bytecode, followed by the writable data region. + * @param program_len the length in bytes of the read-only portion of the APF + * buffer pointed to by {@code program}. + * @param ram_len total length of the APF buffer pointed to by {@code program}, + * including the read-only bytecode portion and the read-write + * data portion. * @param packet the packet bytes, starting from the 802.3 header and not * including any CRC bytes at the end. * @param packet_len the length of {@code packet} in bytes. - * @param data writable data memory region (preserved between packets). - * @param data_len the length of {@code data} in bytes. * @param filter_age the number of seconds since the filter was programmed. * * @return non-zero if packet should be passed to AP, zero if * packet should be dropped. */ -int accept_packet(const uint8_t* program, uint32_t program_len, +int accept_packet(uint8_t* program, uint32_t program_len, uint32_t ram_len, const uint8_t* packet, uint32_t packet_len, - uint8_t* data, uint32_t data_len, uint32_t filter_age); #ifdef __cplusplus @@ -74,14 +74,22 @@ int main(int argc, char* argv[]) { uint8_t* data = NULL; uint32_t data_len = argc > 3 ? parse_hex(argv[3], &data) : 0; uint32_t filter_age = argc > 4 ? atoi(argv[4]) : 0; - int ret = accept_packet(program, program_len, packet, packet_len, - data, data_len, filter_age); - printf("Packet %sed\n", ret ? "pass" : "dropp"); + + // Combine the program and data into the unified APF buffer. if (data) { + program = realloc(program, program_len + data_len); + memcpy(program + program_len, data, data_len); + free(data); + } + + uint32_t ram_len = program_len + data_len; + int ret = accept_packet(program, program_len, ram_len, packet, packet_len, + filter_age); + printf("Packet %sed\n", ret ? "pass" : "dropp"); + if (data_len) { printf("Data: "); - print_hex(data, data_len); + print_hex(program + program_len, data_len); printf("\n"); - free(data); } free(program); free(packet); |