summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-04-22 07:22:00 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-04-22 07:22:00 +0000
commitd76579eb148c3b1aebd4dd35b97dd80ea7b4a831 (patch)
tree5520a802631d8e7295dd370433b3261081d4bd18
parent0e55264fa5e72647cb434a48f6f241cdb19925f2 (diff)
parentd2cc2b74f161d88bc0622b03d48ef176fefee03a (diff)
downloadapf-security-pi-release.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.h19
-rw-r--r--apf_disassembler.c2
-rw-r--r--apf_interpreter.c30
-rw-r--r--apf_interpreter.h24
-rw-r--r--apf_run.c18
5 files changed, 67 insertions, 26 deletions
diff --git a/apf.h b/apf.h
index 2d64930..4722888 100644
--- a/apf.h
+++ b/apf.h
@@ -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
diff --git a/apf_run.c b/apf_run.c
index 3d654cf..d485b71 100644
--- a/apf_run.c
+++ b/apf_run.c
@@ -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);