From 98769f8bddc208e42e6619be60a5ce213bb61396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Thu, 3 Oct 2024 17:55:07 +0200 Subject: [PATCH] Enables the new opcodes conditionally in the interpreter and JIT. --- src/interpreter.rs | 50 ++++++++++++++++++++++++++- src/jit.rs | 36 +++++++++++++++++++ tests/elfs/relative_call.so | Bin 5384 -> 5384 bytes tests/elfs/reloc_64_relative_data.so | Bin 5784 -> 5784 bytes tests/elfs/rodata_section.so | Bin 5424 -> 5424 bytes tests/execution.rs | 2 +- 6 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/interpreter.rs b/src/interpreter.rs index eb11ad95d..4330d1dd6 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -213,7 +213,7 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> { // BPF_ST class ebpf::ST_B_IMM if !self.executable.get_sbpf_version().move_memory_instruction_classes() => { - let vm_addr = (self.reg[dst] as i64).wrapping_add( insn.off as i64) as u64; + let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; translate_memory_access!(self, store, insn.imm, vm_addr, u8); }, ebpf::ST_H_IMM if !self.executable.get_sbpf_version().move_memory_instruction_classes() => { @@ -258,11 +258,19 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> { ebpf::SUB32_REG => self.reg[dst] = (self.reg[dst] as i32).wrapping_sub(self.reg[src] as i32) as u64, ebpf::MUL32_IMM if !self.executable.get_sbpf_version().enable_pqr() => self.reg[dst] = (self.reg[dst] as i32).wrapping_mul(insn.imm as i32) as u64, ebpf::MUL32_REG if !self.executable.get_sbpf_version().enable_pqr() => self.reg[dst] = (self.reg[dst] as i32).wrapping_mul(self.reg[src] as i32) as u64, + ebpf::LD_1B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[src] as i64).wrapping_add(insn.off as i64) as u64; + self.reg[dst] = translate_memory_access!(self, load, vm_addr, u8); + }, ebpf::DIV32_IMM if !self.executable.get_sbpf_version().enable_pqr() => self.reg[dst] = (self.reg[dst] as u32 / insn.imm as u32) as u64, ebpf::DIV32_REG if !self.executable.get_sbpf_version().enable_pqr() => { throw_error!(DivideByZero; self, self.reg[src], u32); self.reg[dst] = (self.reg[dst] as u32 / self.reg[src] as u32) as u64; }, + ebpf::LD_2B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[src] as i64).wrapping_add(insn.off as i64) as u64; + self.reg[dst] = translate_memory_access!(self, load, vm_addr, u16); + }, ebpf::OR32_IMM => self.reg[dst] = (self.reg[dst] as u32 | insn.imm as u32) as u64, ebpf::OR32_REG => self.reg[dst] = (self.reg[dst] as u32 | self.reg[src] as u32) as u64, ebpf::AND32_IMM => self.reg[dst] = (self.reg[dst] as u32 & insn.imm as u32) as u64, @@ -272,11 +280,19 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> { ebpf::RSH32_IMM => self.reg[dst] = (self.reg[dst] as u32).wrapping_shr(insn.imm as u32) as u64, ebpf::RSH32_REG => self.reg[dst] = (self.reg[dst] as u32).wrapping_shr(self.reg[src] as u32) as u64, ebpf::NEG32 if self.executable.get_sbpf_version().enable_neg() => self.reg[dst] = (self.reg[dst] as i32).wrapping_neg() as u64 & (u32::MAX as u64), + ebpf::LD_4B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[src] as i64).wrapping_add(insn.off as i64) as u64; + self.reg[dst] = translate_memory_access!(self, load, vm_addr, u32); + }, ebpf::MOD32_IMM if !self.executable.get_sbpf_version().enable_pqr() => self.reg[dst] = (self.reg[dst] as u32 % insn.imm as u32) as u64, ebpf::MOD32_REG if !self.executable.get_sbpf_version().enable_pqr() => { throw_error!(DivideByZero; self, self.reg[src], u32); self.reg[dst] = (self.reg[dst] as u32 % self.reg[src] as u32) as u64; }, + ebpf::LD_8B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[src] as i64).wrapping_add(insn.off as i64) as u64; + self.reg[dst] = translate_memory_access!(self, load, vm_addr, u64); + }, ebpf::XOR32_IMM => self.reg[dst] = (self.reg[dst] as u32 ^ insn.imm as u32) as u64, ebpf::XOR32_REG => self.reg[dst] = (self.reg[dst] as u32 ^ self.reg[src] as u32) as u64, ebpf::MOV32_IMM => self.reg[dst] = insn.imm as u32 as u64, @@ -314,12 +330,28 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> { }, ebpf::SUB64_REG => self.reg[dst] = self.reg[dst].wrapping_sub(self.reg[src]), ebpf::MUL64_IMM if !self.executable.get_sbpf_version().enable_pqr() => self.reg[dst] = self.reg[dst].wrapping_mul(insn.imm as u64), + ebpf::ST_1B_IMM if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; + translate_memory_access!(self, store, insn.imm, vm_addr, u8); + }, ebpf::MUL64_REG if !self.executable.get_sbpf_version().enable_pqr() => self.reg[dst] = self.reg[dst].wrapping_mul(self.reg[src]), + ebpf::ST_1B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; + translate_memory_access!(self, store, self.reg[src], vm_addr, u8); + }, ebpf::DIV64_IMM if !self.executable.get_sbpf_version().enable_pqr() => self.reg[dst] /= insn.imm as u64, + ebpf::ST_2B_IMM if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; + translate_memory_access!(self, store, insn.imm, vm_addr, u16); + }, ebpf::DIV64_REG if !self.executable.get_sbpf_version().enable_pqr() => { throw_error!(DivideByZero; self, self.reg[src], u64); self.reg[dst] /= self.reg[src]; }, + ebpf::ST_2B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; + translate_memory_access!(self, store, self.reg[src], vm_addr, u16); + }, ebpf::OR64_IMM => self.reg[dst] |= insn.imm as u64, ebpf::OR64_REG => self.reg[dst] |= self.reg[src], ebpf::AND64_IMM => self.reg[dst] &= insn.imm as u64, @@ -328,12 +360,28 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> { ebpf::LSH64_REG => self.reg[dst] = self.reg[dst].wrapping_shl(self.reg[src] as u32), ebpf::RSH64_IMM => self.reg[dst] = self.reg[dst].wrapping_shr(insn.imm as u32), ebpf::RSH64_REG => self.reg[dst] = self.reg[dst].wrapping_shr(self.reg[src] as u32), + ebpf::ST_4B_IMM if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; + translate_memory_access!(self, store, insn.imm, vm_addr, u32); + }, ebpf::NEG64 if self.executable.get_sbpf_version().enable_neg() => self.reg[dst] = (self.reg[dst] as i64).wrapping_neg() as u64, + ebpf::ST_4B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; + translate_memory_access!(self, store, self.reg[src], vm_addr, u32); + }, ebpf::MOD64_IMM if !self.executable.get_sbpf_version().enable_pqr() => self.reg[dst] %= insn.imm as u64, + ebpf::ST_8B_IMM if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; + translate_memory_access!(self, store, insn.imm, vm_addr, u64); + }, ebpf::MOD64_REG if !self.executable.get_sbpf_version().enable_pqr() => { throw_error!(DivideByZero; self, self.reg[src], u64); self.reg[dst] %= self.reg[src]; }, + ebpf::ST_8B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; + translate_memory_access!(self, store, self.reg[src], vm_addr, u64); + }, ebpf::XOR64_IMM => self.reg[dst] ^= insn.imm as u64, ebpf::XOR64_REG => self.reg[dst] ^= self.reg[src], ebpf::MOV64_IMM => self.reg[dst] = insn.imm as u64, diff --git a/src/jit.rs b/src/jit.rs index 73328d623..1eeddeb28 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -506,8 +506,14 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { }, ebpf::MUL32_IMM | ebpf::DIV32_IMM | ebpf::MOD32_IMM if !self.executable.get_sbpf_version().enable_pqr() => self.emit_product_quotient_remainder(OperandSize::S32, (insn.opc & ebpf::BPF_ALU_OP_MASK) == ebpf::BPF_MOD, (insn.opc & ebpf::BPF_ALU_OP_MASK) != ebpf::BPF_MUL, (insn.opc & ebpf::BPF_ALU_OP_MASK) == ebpf::BPF_MUL, dst, dst, Some(insn.imm)), + ebpf::LD_1B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(Some(dst), Value::RegisterPlusConstant64(src, insn.off as i64, true), 1, None); + }, ebpf::MUL32_REG | ebpf::DIV32_REG | ebpf::MOD32_REG if !self.executable.get_sbpf_version().enable_pqr() => self.emit_product_quotient_remainder(OperandSize::S32, (insn.opc & ebpf::BPF_ALU_OP_MASK) == ebpf::BPF_MOD, (insn.opc & ebpf::BPF_ALU_OP_MASK) != ebpf::BPF_MUL, (insn.opc & ebpf::BPF_ALU_OP_MASK) == ebpf::BPF_MUL, src, dst, None), + ebpf::LD_2B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(Some(dst), Value::RegisterPlusConstant64(src, insn.off as i64, true), 2, None); + }, ebpf::OR32_IMM => self.emit_sanitized_alu(OperandSize::S32, 0x09, 1, dst, insn.imm), ebpf::OR32_REG => self.emit_ins(X86Instruction::alu(OperandSize::S32, 0x09, src, dst, 0, None)), ebpf::AND32_IMM => self.emit_sanitized_alu(OperandSize::S32, 0x21, 4, dst, insn.imm), @@ -517,6 +523,12 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { ebpf::RSH32_IMM => self.emit_shift(OperandSize::S32, 5, REGISTER_SCRATCH, dst, Some(insn.imm)), ebpf::RSH32_REG => self.emit_shift(OperandSize::S32, 5, src, dst, None), ebpf::NEG32 if self.executable.get_sbpf_version().enable_neg() => self.emit_ins(X86Instruction::alu(OperandSize::S32, 0xf7, 3, dst, 0, None)), + ebpf::LD_4B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(Some(dst), Value::RegisterPlusConstant64(src, insn.off as i64, true), 4, None); + }, + ebpf::LD_8B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(Some(dst), Value::RegisterPlusConstant64(src, insn.off as i64, true), 8, None); + }, ebpf::XOR32_IMM => self.emit_sanitized_alu(OperandSize::S32, 0x31, 6, dst, insn.imm), ebpf::XOR32_REG => self.emit_ins(X86Instruction::alu(OperandSize::S32, 0x31, src, dst, 0, None)), ebpf::MOV32_IMM => { @@ -573,8 +585,20 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { ebpf::SUB64_REG => self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x29, src, dst, 0, None)), ebpf::MUL64_IMM | ebpf::DIV64_IMM | ebpf::MOD64_IMM if !self.executable.get_sbpf_version().enable_pqr() => self.emit_product_quotient_remainder(OperandSize::S64, (insn.opc & ebpf::BPF_ALU_OP_MASK) == ebpf::BPF_MOD, (insn.opc & ebpf::BPF_ALU_OP_MASK) != ebpf::BPF_MUL, (insn.opc & ebpf::BPF_ALU_OP_MASK) == ebpf::BPF_MUL, dst, dst, Some(insn.imm)), + ebpf::ST_1B_IMM if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(None, Value::RegisterPlusConstant64(dst, insn.off as i64, true), 1, Some(Value::Constant64(insn.imm, true))); + }, + ebpf::ST_2B_IMM if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(None, Value::RegisterPlusConstant64(dst, insn.off as i64, true), 2, Some(Value::Constant64(insn.imm, true))); + }, ebpf::MUL64_REG | ebpf::DIV64_REG | ebpf::MOD64_REG if !self.executable.get_sbpf_version().enable_pqr() => self.emit_product_quotient_remainder(OperandSize::S64, (insn.opc & ebpf::BPF_ALU_OP_MASK) == ebpf::BPF_MOD, (insn.opc & ebpf::BPF_ALU_OP_MASK) != ebpf::BPF_MUL, (insn.opc & ebpf::BPF_ALU_OP_MASK) == ebpf::BPF_MUL, src, dst, None), + ebpf::ST_1B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(None, Value::RegisterPlusConstant64(dst, insn.off as i64, true), 1, Some(Value::Register(src))); + }, + ebpf::ST_2B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(None, Value::RegisterPlusConstant64(dst, insn.off as i64, true), 2, Some(Value::Register(src))); + }, ebpf::OR64_IMM => self.emit_sanitized_alu(OperandSize::S64, 0x09, 1, dst, insn.imm), ebpf::OR64_REG => self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x09, src, dst, 0, None)), ebpf::AND64_IMM => self.emit_sanitized_alu(OperandSize::S64, 0x21, 4, dst, insn.imm), @@ -583,7 +607,19 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { ebpf::LSH64_REG => self.emit_shift(OperandSize::S64, 4, src, dst, None), ebpf::RSH64_IMM => self.emit_shift(OperandSize::S64, 5, REGISTER_SCRATCH, dst, Some(insn.imm)), ebpf::RSH64_REG => self.emit_shift(OperandSize::S64, 5, src, dst, None), + ebpf::ST_4B_IMM if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(None, Value::RegisterPlusConstant64(dst, insn.off as i64, true), 4, Some(Value::Constant64(insn.imm, true))); + }, ebpf::NEG64 if self.executable.get_sbpf_version().enable_neg() => self.emit_ins(X86Instruction::alu(OperandSize::S64, 0xf7, 3, dst, 0, None)), + ebpf::ST_4B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(None, Value::RegisterPlusConstant64(dst, insn.off as i64, true), 4, Some(Value::Register(src))); + }, + ebpf::ST_8B_IMM if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(None, Value::RegisterPlusConstant64(dst, insn.off as i64, true), 8, Some(Value::Constant64(insn.imm, true))); + }, + ebpf::ST_8B_REG if self.executable.get_sbpf_version().move_memory_instruction_classes() => { + self.emit_address_translation(None, Value::RegisterPlusConstant64(dst, insn.off as i64, true), 8, Some(Value::Register(src))); + }, ebpf::XOR64_IMM => self.emit_sanitized_alu(OperandSize::S64, 0x31, 6, dst, insn.imm), ebpf::XOR64_REG => self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x31, src, dst, 0, None)), ebpf::MOV64_IMM => { diff --git a/tests/elfs/relative_call.so b/tests/elfs/relative_call.so index 9f24730e209597b7bb901191dc47dca8bd3a6887..3599680548a3627a5b7414f1d21251d0e3f5322e 100755 GIT binary patch delta 43 ocmeCs>d;ysAUH>W0SwrIBqI>dpDZXK&Z#2?5uLx;P~bWX0GVS3{Qv*} delta 43 ocmeCs>d;ysAXq8D00!(pk`aijCkqOQa~6t0M5{L&3S4Ia0F;#m*8l(j diff --git a/tests/elfs/reloc_64_relative_data.so b/tests/elfs/reloc_64_relative_data.so index fe2e0db33786bd587bb9e869050f45b78320a29d..cb327629b34b851e89e2e464b6e9d8a2b639266b 100755 GIT binary patch delta 14 VcmbQCJ41JafB@s1&4L2$Yyc!&1X%z8 delta 14 VcmbQCJ41JafB<9VWwLxoxfB@s1&4L2*tNwLxoxfB<9VW