Loading services/net/java/android/net/apf/ApfGenerator.java +6 −6 Original line number Original line Diff line number Diff line Loading @@ -841,30 +841,30 @@ public class ApfGenerator { /** /** * Add an instruction to the end of the program to load 32 bits from the data memory into * 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 * {@code register}. The source address is computed by adding the signed immediate * register. * @{code offset} to the other register. * Requires APF v3 or greater. * Requires APF v3 or greater. */ */ public ApfGenerator addLoadData(Register destinationRegister, int offset) public ApfGenerator addLoadData(Register destinationRegister, int offset) throws IllegalInstructionException { throws IllegalInstructionException { requireApfVersion(3); requireApfVersion(3); Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister); Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister); instruction.setUnsignedImm(offset); instruction.setSignedImm(offset); addInstruction(instruction); addInstruction(instruction); return this; return this; } } /** /** * Add an instruction to the end of the program to store 32 bits from {@code register} into the * 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 * data memory. The destination address is computed by adding the signed immediate * register. * @{code offset} to the other register. * Requires APF v3 or greater. * Requires APF v3 or greater. */ */ public ApfGenerator addStoreData(Register sourceRegister, int offset) public ApfGenerator addStoreData(Register sourceRegister, int offset) throws IllegalInstructionException { throws IllegalInstructionException { requireApfVersion(3); requireApfVersion(3); Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister); Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister); instruction.setUnsignedImm(offset); instruction.setSignedImm(offset); addInstruction(instruction); addInstruction(instruction); return this; return this; } } Loading tests/net/java/android/net/apf/ApfTest.java +21 −13 Original line number Original line Diff line number Diff line Loading @@ -625,18 +625,19 @@ public class ApfTest { @Test @Test public void testApfDataWrite() throws IllegalInstructionException, Exception { public void testApfDataWrite() throws IllegalInstructionException, Exception { byte[] packet = new byte[MIN_PKT_SIZE]; byte[] packet = new byte[MIN_PKT_SIZE]; byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; byte[] expected_data = data.clone(); byte[] expected_data = data.clone(); // No memory access instructions: should leave the data segment untouched. // No memory access instructions: should leave the data segment untouched. ApfGenerator gen = new ApfGenerator(3); ApfGenerator gen = new ApfGenerator(3); assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); // Expect value 0x87654321 to be stored starting from address 3 + 2, in big-endian order. // Expect value 0x87654321 to be stored starting from address -11 from the end of the // data buffer, in big-endian order. gen = new ApfGenerator(3); gen = new ApfGenerator(3); gen.addLoadImmediate(Register.R0, 0x87654321); gen.addLoadImmediate(Register.R0, 0x87654321); gen.addLoadImmediate(Register.R1, 2); gen.addLoadImmediate(Register.R1, -5); gen.addStoreData(Register.R0, 3); gen.addStoreData(Register.R0, -6); // -5 + -6 = -11 (offset +5 with data_len=16) expected_data[5] = (byte)0x87; expected_data[5] = (byte)0x87; expected_data[6] = (byte)0x65; expected_data[6] = (byte)0x65; expected_data[7] = (byte)0x43; expected_data[7] = (byte)0x43; Loading @@ -646,16 +647,16 @@ public class ApfTest { @Test @Test public void testApfDataRead() throws IllegalInstructionException, Exception { public void testApfDataRead() throws IllegalInstructionException, Exception { // Program that DROPs if address 11 (7 + 3) contains 0x87654321. // Program that DROPs if address 10 (-6) contains 0x87654321. ApfGenerator gen = new ApfGenerator(3); ApfGenerator gen = new ApfGenerator(3); gen.addLoadImmediate(Register.R1, 3); gen.addLoadImmediate(Register.R1, 10); gen.addLoadData(Register.R0, 7); gen.addLoadData(Register.R0, -16); // 10 + -16 = -6 (offset +10 with data_len=16) gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL); gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL); byte[] program = gen.generate(); byte[] program = gen.generate(); byte[] packet = new byte[MIN_PKT_SIZE]; byte[] packet = new byte[MIN_PKT_SIZE]; // Content is incorrect (last byte does not match) -> PASS // Content is incorrect (last byte does not match) -> PASS byte[] data = new byte[32]; byte[] data = new byte[16]; data[10] = (byte)0x87; data[10] = (byte)0x87; data[11] = (byte)0x65; data[11] = (byte)0x65; data[12] = (byte)0x43; data[12] = (byte)0x43; Loading @@ -672,10 +673,10 @@ public class ApfTest { @Test @Test public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception { public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception { ApfGenerator gen = new ApfGenerator(3); ApfGenerator gen = new ApfGenerator(3); gen.addLoadImmediate(Register.R1, 3); gen.addLoadImmediate(Register.R1, -22); gen.addLoadData(Register.R0, 7); // Load from address 7 + 3 = 10 gen.addLoadData(Register.R0, 0); // Load from address 32 -22 + 0 = 10 gen.addAdd(0x78453412); // 87654321 + 78453412 = FFAA7733 gen.addAdd(0x78453412); // 87654321 + 78453412 = FFAA7733 gen.addStoreData(Register.R0, 11); // Write back to address 11 + 3 = 14 gen.addStoreData(Register.R0, 4); // Write back to address 32 -22 + 4 = 14 byte[] packet = new byte[MIN_PKT_SIZE]; byte[] packet = new byte[MIN_PKT_SIZE]; byte[] data = new byte[32]; byte[] data = new byte[32]; Loading Loading @@ -718,10 +719,17 @@ public class ApfTest { gen.addJump(gen.DROP_LABEL); gen.addJump(gen.DROP_LABEL); assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); // ...but underflowing isn't allowed. // ...and underflowing simply wraps around to the end of the buffer... gen = new ApfGenerator(3); gen = new ApfGenerator(3); gen.addLoadImmediate(Register.R0, 20); gen.addLoadImmediate(Register.R0, 20); gen.addLoadData(Register.R1, -30); gen.addLoadData(Register.R1, -30); gen.addJump(gen.DROP_LABEL); assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); // ...but doesn't allow accesses before the start of the buffer gen = new ApfGenerator(3); gen.addLoadImmediate(Register.R0, 20); gen.addLoadData(Register.R1, -1000); gen.addJump(gen.DROP_LABEL); // Not reached. gen.addJump(gen.DROP_LABEL); // Not reached. assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); } } Loading tests/net/jni/apf_jni.cpp +15 −6 Original line number Original line Diff line number Diff line Loading @@ -36,11 +36,20 @@ static jint com_android_server_ApfTest_apfSimulate( uint32_t program_len = env->GetArrayLength(program); uint32_t program_len = env->GetArrayLength(program); uint32_t packet_len = env->GetArrayLength(packet); uint32_t packet_len = env->GetArrayLength(packet); uint32_t data_len = data ? env->GetArrayLength(data) : 0; 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); // Merge program and data into a single buffer. uint8_t* program_and_data = (uint8_t*)malloc(program_len + data_len); memcpy(program_and_data, program_raw, program_len); memcpy(program_and_data + program_len, data_raw, data_len); jint result = accept_packet(program_and_data, program_len, program_len + data_len, packet_raw, packet_len, filter_age); if (data) { if (data) { memcpy(data_raw, program_and_data + program_len, data_len); env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */); env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */); } } free(program_and_data); env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT); env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT); env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT); env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT); return result; return result; Loading Loading @@ -109,8 +118,8 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js jstring jpcap_filename, jbyteArray japf_program) { jstring jpcap_filename, jbyteArray japf_program) { ScopedUtfChars filter(env, jfilter); ScopedUtfChars filter(env, jfilter); ScopedUtfChars pcap_filename(env, jpcap_filename); ScopedUtfChars pcap_filename(env, jpcap_filename); const uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL); uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL); const uint32_t apf_program_len = env->GetArrayLength(japf_program); uint32_t apf_program_len = env->GetArrayLength(japf_program); // Open pcap file for BPF filtering // Open pcap file for BPF filtering ScopedFILE bpf_fp(fopen(pcap_filename.c_str(), "rb")); ScopedFILE bpf_fp(fopen(pcap_filename.c_str(), "rb")); Loading Loading @@ -152,8 +161,8 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js do { do { apf_packet = pcap_next(apf_pcap.get(), &apf_header); apf_packet = pcap_next(apf_pcap.get(), &apf_header); } while (apf_packet != NULL && !accept_packet( } while (apf_packet != NULL && !accept_packet( apf_program, apf_program_len, apf_packet, apf_header.len, apf_program, apf_program_len, 0 /* data_len */, nullptr, 0, 0)); apf_packet, apf_header.len, 0 /* filter_age */)); // Make sure both filters matched the same packet. // Make sure both filters matched the same packet. if (apf_packet == NULL && bpf_packet == NULL) if (apf_packet == NULL && bpf_packet == NULL) Loading Loading
services/net/java/android/net/apf/ApfGenerator.java +6 −6 Original line number Original line Diff line number Diff line Loading @@ -841,30 +841,30 @@ public class ApfGenerator { /** /** * Add an instruction to the end of the program to load 32 bits from the data memory into * 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 * {@code register}. The source address is computed by adding the signed immediate * register. * @{code offset} to the other register. * Requires APF v3 or greater. * Requires APF v3 or greater. */ */ public ApfGenerator addLoadData(Register destinationRegister, int offset) public ApfGenerator addLoadData(Register destinationRegister, int offset) throws IllegalInstructionException { throws IllegalInstructionException { requireApfVersion(3); requireApfVersion(3); Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister); Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister); instruction.setUnsignedImm(offset); instruction.setSignedImm(offset); addInstruction(instruction); addInstruction(instruction); return this; return this; } } /** /** * Add an instruction to the end of the program to store 32 bits from {@code register} into the * 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 * data memory. The destination address is computed by adding the signed immediate * register. * @{code offset} to the other register. * Requires APF v3 or greater. * Requires APF v3 or greater. */ */ public ApfGenerator addStoreData(Register sourceRegister, int offset) public ApfGenerator addStoreData(Register sourceRegister, int offset) throws IllegalInstructionException { throws IllegalInstructionException { requireApfVersion(3); requireApfVersion(3); Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister); Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister); instruction.setUnsignedImm(offset); instruction.setSignedImm(offset); addInstruction(instruction); addInstruction(instruction); return this; return this; } } Loading
tests/net/java/android/net/apf/ApfTest.java +21 −13 Original line number Original line Diff line number Diff line Loading @@ -625,18 +625,19 @@ public class ApfTest { @Test @Test public void testApfDataWrite() throws IllegalInstructionException, Exception { public void testApfDataWrite() throws IllegalInstructionException, Exception { byte[] packet = new byte[MIN_PKT_SIZE]; byte[] packet = new byte[MIN_PKT_SIZE]; byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; byte[] expected_data = data.clone(); byte[] expected_data = data.clone(); // No memory access instructions: should leave the data segment untouched. // No memory access instructions: should leave the data segment untouched. ApfGenerator gen = new ApfGenerator(3); ApfGenerator gen = new ApfGenerator(3); assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); // Expect value 0x87654321 to be stored starting from address 3 + 2, in big-endian order. // Expect value 0x87654321 to be stored starting from address -11 from the end of the // data buffer, in big-endian order. gen = new ApfGenerator(3); gen = new ApfGenerator(3); gen.addLoadImmediate(Register.R0, 0x87654321); gen.addLoadImmediate(Register.R0, 0x87654321); gen.addLoadImmediate(Register.R1, 2); gen.addLoadImmediate(Register.R1, -5); gen.addStoreData(Register.R0, 3); gen.addStoreData(Register.R0, -6); // -5 + -6 = -11 (offset +5 with data_len=16) expected_data[5] = (byte)0x87; expected_data[5] = (byte)0x87; expected_data[6] = (byte)0x65; expected_data[6] = (byte)0x65; expected_data[7] = (byte)0x43; expected_data[7] = (byte)0x43; Loading @@ -646,16 +647,16 @@ public class ApfTest { @Test @Test public void testApfDataRead() throws IllegalInstructionException, Exception { public void testApfDataRead() throws IllegalInstructionException, Exception { // Program that DROPs if address 11 (7 + 3) contains 0x87654321. // Program that DROPs if address 10 (-6) contains 0x87654321. ApfGenerator gen = new ApfGenerator(3); ApfGenerator gen = new ApfGenerator(3); gen.addLoadImmediate(Register.R1, 3); gen.addLoadImmediate(Register.R1, 10); gen.addLoadData(Register.R0, 7); gen.addLoadData(Register.R0, -16); // 10 + -16 = -6 (offset +10 with data_len=16) gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL); gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL); byte[] program = gen.generate(); byte[] program = gen.generate(); byte[] packet = new byte[MIN_PKT_SIZE]; byte[] packet = new byte[MIN_PKT_SIZE]; // Content is incorrect (last byte does not match) -> PASS // Content is incorrect (last byte does not match) -> PASS byte[] data = new byte[32]; byte[] data = new byte[16]; data[10] = (byte)0x87; data[10] = (byte)0x87; data[11] = (byte)0x65; data[11] = (byte)0x65; data[12] = (byte)0x43; data[12] = (byte)0x43; Loading @@ -672,10 +673,10 @@ public class ApfTest { @Test @Test public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception { public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception { ApfGenerator gen = new ApfGenerator(3); ApfGenerator gen = new ApfGenerator(3); gen.addLoadImmediate(Register.R1, 3); gen.addLoadImmediate(Register.R1, -22); gen.addLoadData(Register.R0, 7); // Load from address 7 + 3 = 10 gen.addLoadData(Register.R0, 0); // Load from address 32 -22 + 0 = 10 gen.addAdd(0x78453412); // 87654321 + 78453412 = FFAA7733 gen.addAdd(0x78453412); // 87654321 + 78453412 = FFAA7733 gen.addStoreData(Register.R0, 11); // Write back to address 11 + 3 = 14 gen.addStoreData(Register.R0, 4); // Write back to address 32 -22 + 4 = 14 byte[] packet = new byte[MIN_PKT_SIZE]; byte[] packet = new byte[MIN_PKT_SIZE]; byte[] data = new byte[32]; byte[] data = new byte[32]; Loading Loading @@ -718,10 +719,17 @@ public class ApfTest { gen.addJump(gen.DROP_LABEL); gen.addJump(gen.DROP_LABEL); assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); // ...but underflowing isn't allowed. // ...and underflowing simply wraps around to the end of the buffer... gen = new ApfGenerator(3); gen = new ApfGenerator(3); gen.addLoadImmediate(Register.R0, 20); gen.addLoadImmediate(Register.R0, 20); gen.addLoadData(Register.R1, -30); gen.addLoadData(Register.R1, -30); gen.addJump(gen.DROP_LABEL); assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); // ...but doesn't allow accesses before the start of the buffer gen = new ApfGenerator(3); gen.addLoadImmediate(Register.R0, 20); gen.addLoadData(Register.R1, -1000); gen.addJump(gen.DROP_LABEL); // Not reached. gen.addJump(gen.DROP_LABEL); // Not reached. assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); } } Loading
tests/net/jni/apf_jni.cpp +15 −6 Original line number Original line Diff line number Diff line Loading @@ -36,11 +36,20 @@ static jint com_android_server_ApfTest_apfSimulate( uint32_t program_len = env->GetArrayLength(program); uint32_t program_len = env->GetArrayLength(program); uint32_t packet_len = env->GetArrayLength(packet); uint32_t packet_len = env->GetArrayLength(packet); uint32_t data_len = data ? env->GetArrayLength(data) : 0; 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); // Merge program and data into a single buffer. uint8_t* program_and_data = (uint8_t*)malloc(program_len + data_len); memcpy(program_and_data, program_raw, program_len); memcpy(program_and_data + program_len, data_raw, data_len); jint result = accept_packet(program_and_data, program_len, program_len + data_len, packet_raw, packet_len, filter_age); if (data) { if (data) { memcpy(data_raw, program_and_data + program_len, data_len); env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */); env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */); } } free(program_and_data); env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT); env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT); env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT); env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT); return result; return result; Loading Loading @@ -109,8 +118,8 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js jstring jpcap_filename, jbyteArray japf_program) { jstring jpcap_filename, jbyteArray japf_program) { ScopedUtfChars filter(env, jfilter); ScopedUtfChars filter(env, jfilter); ScopedUtfChars pcap_filename(env, jpcap_filename); ScopedUtfChars pcap_filename(env, jpcap_filename); const uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL); uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL); const uint32_t apf_program_len = env->GetArrayLength(japf_program); uint32_t apf_program_len = env->GetArrayLength(japf_program); // Open pcap file for BPF filtering // Open pcap file for BPF filtering ScopedFILE bpf_fp(fopen(pcap_filename.c_str(), "rb")); ScopedFILE bpf_fp(fopen(pcap_filename.c_str(), "rb")); Loading Loading @@ -152,8 +161,8 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js do { do { apf_packet = pcap_next(apf_pcap.get(), &apf_header); apf_packet = pcap_next(apf_pcap.get(), &apf_header); } while (apf_packet != NULL && !accept_packet( } while (apf_packet != NULL && !accept_packet( apf_program, apf_program_len, apf_packet, apf_header.len, apf_program, apf_program_len, 0 /* data_len */, nullptr, 0, 0)); apf_packet, apf_header.len, 0 /* filter_age */)); // Make sure both filters matched the same packet. // Make sure both filters matched the same packet. if (apf_packet == NULL && bpf_packet == NULL) if (apf_packet == NULL && bpf_packet == NULL) Loading