浏览代码

feat: Add support for ebpf to ebpf call in assembler and disassembler

Move my tests into misc.
add comment and fix the tests error

Signed-off-by: Godones <chenlinfeng25@outlook.com>
Godones 2 月之前
父节点
当前提交
2c302ee5d9
共有 12 个文件被更改,包括 281 次插入138 次删除
  1. 4 1
      src/assembler.rs
  2. 7 1
      src/disassembler.rs
  3. 4 4
      src/ebpf.rs
  4. 12 8
      src/interpreter.rs
  5. 7 1
      src/jit.rs
  6. 110 2
      src/lib.rs
  7. 9 5
      src/stack.rs
  8. 2 4
      src/verifier.rs
  9. 125 0
      tests/misc.rs
  10. 1 52
      tests/ubpf_jit_x86_64.rs
  11. 0 11
      tests/ubpf_verifier.rs
  12. 0 49
      tests/ubpf_vm.rs

+ 4 - 1
src/assembler.rs

@@ -8,7 +8,7 @@ use crate::asm_parser::Operand::{Integer, Memory, Register, Nil};
 use crate::ebpf;
 use crate::ebpf::Insn;
 use self::InstructionType::{AluBinary, AluUnary, LoadAbs, LoadInd, LoadImm, LoadReg, StoreImm,
-                            StoreReg, JumpUnconditional, JumpConditional, Call, Endian, NoOperand};
+                            StoreReg, JumpUnconditional, JumpConditional, Call, Callx, Endian, NoOperand};
 use crate::lib::*;
 
 #[derive(Clone, Copy, Debug, PartialEq)]
@@ -24,6 +24,7 @@ enum InstructionType {
     JumpUnconditional,
     JumpConditional,
     Call,
+    Callx,
     Endian(i64),
     NoOperand,
 }
@@ -68,6 +69,7 @@ fn make_instruction_map() -> HashMap<String, (InstructionType, u8)> {
         entry("exit", NoOperand, ebpf::EXIT);
         entry("ja", JumpUnconditional, ebpf::JA);
         entry("call", Call, ebpf::CALL);
+        entry("callx", Callx, ebpf::CALL);
         entry("lddw", LoadImm, ebpf::LD_DW_IMM);
 
         // AluUnary.
@@ -170,6 +172,7 @@ fn encode(inst_type: InstructionType, opc: u8, operands: &[Operand]) -> Result<I
             insn(opc | ebpf::BPF_K, dst, 0, off, imm)
         }
         (Call, Integer(imm), Nil, Nil) => insn(opc, 0, 0, 0, imm),
+        (Callx, Integer(imm), Nil, Nil) => insn(opc, 0, 1, 0, imm),
         (Endian(size), Register(dst), Nil, Nil) => insn(opc, dst, 0, 0, size),
         (LoadImm, Register(dst), Integer(imm), Nil) => insn(opc, dst, 0, 0, (imm << 32) >> 32),
         _ => Err(format!("Unexpected operands: {operands:?}")),

+ 7 - 1
src/disassembler.rs

@@ -307,7 +307,13 @@ pub fn to_insn_vec(prog: &[u8]) -> Vec<HLInsn> {
             ebpf::JSLT_REG   => { name = "jslt"; desc = jmp_reg_str(name, &insn); },
             ebpf::JSLE_IMM   => { name = "jsle"; desc = jmp_imm_str(name, &insn); },
             ebpf::JSLE_REG   => { name = "jsle"; desc = jmp_reg_str(name, &insn); },
-            ebpf::CALL       => { name = "call"; desc = format!("{name} {:#x}", insn.imm); },
+            ebpf::CALL       => {
+                match insn.src {
+                    0 => { name = "call"; desc = format!("{name} {:#x}", insn.imm); },
+                    1 => { name = "callx"; desc = format!("{name} {:#x}", insn.imm); },
+                    _ => { panic!("[Disassembler] Error: unsupported call insn (insn #{:?})", insn_ptr); }
+                }
+             },
             ebpf::TAIL_CALL  => { name = "tail_call"; desc = name.to_string(); },
             ebpf::EXIT       => { name = "exit";      desc = name.to_string(); },
 

+ 4 - 4
src/ebpf.rs

@@ -17,10 +17,6 @@
 use byteorder::{ByteOrder, LittleEndian};
 use crate::lib::*;
 
-/// The default stack size for the eBPF program if there is some bpf to bpf calls.
-pub const RBPF_EBPF_LOCAL_FUNCTION_STACK_SIZE: u16 = 256;
-/// Maximum number of bpf to bpf call depth.
-pub const RBPF_MAX_CALL_DEPTH: usize = 8;
 /// Maximum number of instructions in an eBPF program.
 pub const PROG_MAX_INSNS: usize = 1000000;
 /// Size of an eBPF instructions, in bytes.
@@ -29,6 +25,10 @@ pub const INSN_SIZE: usize = 8;
 pub const PROG_MAX_SIZE: usize = PROG_MAX_INSNS * INSN_SIZE;
 /// Stack for the eBPF stack, in bytes.
 pub const STACK_SIZE: usize = 512;
+/// The default stack size for the eBPF program if there is some eBPF to eBPF calls.
+pub const LOCAL_FUNCTION_STACK_SIZE: u16 = 256;
+/// Maximum number of eBPF to eBPF call depth.
+pub const MAX_CALL_DEPTH: usize = 8;
 
 // eBPF op codes.
 // See also https://www.kernel.org/doc/Documentation/networking/filter.txt

+ 12 - 8
src/interpreter.rs

@@ -6,7 +6,7 @@
 //      (Translation to Rust, MetaBuff/multiple classes addition, hashmaps for helpers)
 
 use crate::ebpf;
-use crate::ebpf::RBPF_MAX_CALL_DEPTH;
+use crate::ebpf::MAX_CALL_DEPTH;
 use crate::lib::*;
 use crate::stack::{StackFrame, StackUsage};
 
@@ -56,14 +56,15 @@ pub fn execute_program(
     const U32MAX: u64 = u32::MAX as u64;
     const SHIFT_MASK_64: u64 = 0x3f;
 
-    let (prog,stack_usage) = match prog_ {
+    let (prog, stack_usage) = match prog_ {
         Some(prog) => (prog, stack_usage.unwrap()),
         None => Err(Error::new(ErrorKind::Other,
                     "Error: No program set, call prog_set() to load one"))?,
     };
     let stack = vec![0u8;ebpf::STACK_SIZE];
-    let mut stacks = [StackFrame::new();RBPF_MAX_CALL_DEPTH];
+    let mut stacks = [StackFrame::new();MAX_CALL_DEPTH];
     let mut stack_frame_idx = 0;
+
     // R1 points to beginning of memory area, R10 to stack
     let mut reg: [u64;11] = [
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, stack.as_ptr() as u64 + stack.len() as u64
@@ -86,7 +87,7 @@ pub fn execute_program(
     let mut insn_ptr:usize = 0;
     while insn_ptr * ebpf::INSN_SIZE < prog.len() {
         let insn = ebpf::get_insn(prog, insn_ptr);
-        if stack_frame_idx < RBPF_MAX_CALL_DEPTH{
+        if stack_frame_idx < MAX_CALL_DEPTH{
             if let Some(usage) = stack_usage.stack_usage_for_local_func(insn_ptr) {
                 stacks[stack_frame_idx].set_stack_usage(usage);
             }
@@ -375,19 +376,22 @@ pub fn execute_program(
                             Err(Error::new(ErrorKind::Other, format!("Error: unknown helper function (id: {:#x})", insn.imm as u32)))?;
                         }
                     }
-                    // BPF To BPF call
+                    // eBPF to eBPF call
                     1 => {
-                        if stack_frame_idx >= RBPF_MAX_CALL_DEPTH {
-                            Err(Error::new(ErrorKind::Other, format!("Error: too many nested calls (max: {RBPF_MAX_CALL_DEPTH})")))?;
+                        if stack_frame_idx >= MAX_CALL_DEPTH {
+                            Err(Error::new(ErrorKind::Other, format!("Error: too many nested calls (max: {MAX_CALL_DEPTH})")))?;
                         }
                         stacks[stack_frame_idx].save_registers(&reg[6..=9]);
                         stacks[stack_frame_idx].save_return_address(insn_ptr);
+                        // Why we don't need to check the stack usage here?
+                        // When the stack is exhausted, if there are instructions in the new function
+                        // that read or write to the stack, check_mem_load or check_mem_store will return an error.
                         reg[10] -= stacks[stack_frame_idx].get_stack_usage().stack_usage() as u64;
                         stack_frame_idx += 1;
                         insn_ptr += insn.imm as usize;
                     }
                     _ => {
-                        Err(Error::new(ErrorKind::Other, format!("Error: unexpected call type #{} (insn #{})", _src, insn_ptr-1)))?;
+                        Err(Error::new(ErrorKind::Other, format!("Error: unsupported call type #{} (insn #{})", _src, insn_ptr-1)))?;
                     }
                 }
             }

+ 7 - 1
src/jit.rs

@@ -466,7 +466,7 @@ impl JitCompiler {
         self.emit_push(mem, map_register(7));
         self.emit_push(mem, map_register(8));
         self.emit_push(mem, map_register(9));
-        // e8 is the opcode for a CALL
+        // 0xe8 is the opcode for a CALL
         self.emit1(mem, 0xe8); 
         self.emit_jump_offset(mem, target_pc);
         self.emit_pop(mem, map_register(9));
@@ -530,8 +530,14 @@ impl JitCompiler {
         // Allocate stack space
         self.emit_alu64_imm32(mem, 0x81, 5, RSP, ebpf::STACK_SIZE as i32);
 
+        // Use a call to set up a place where we can land after eBPF program's
+        // final EXIT call. This will make JIT of BPF EXIT call easier in the
+        // presence of calls to local functions.
         self.emit1(mem, 0xe8);
         self.emit4(mem, 5);
+
+        // We jump over this instruction in the first place; return here
+        // after the eBPF program is finished executing.
         self.emit_jmp(mem, TARGET_PC_EXIT);
 
         self.pc_locs = vec![0; prog.len() / ebpf::INSN_SIZE + 1];

+ 110 - 2
src/lib.rs

@@ -68,7 +68,7 @@ pub mod lib {
     pub use self::core::mem;
     pub use self::core::mem::ManuallyDrop;
     pub use self::core::ptr;
-    pub use core::any::Any;
+    pub use self::core::any::Any;
     pub use self::core::f64;
 
     #[cfg(feature = "std")]
@@ -445,7 +445,7 @@ impl<'a> EbpfVmMbuff<'a> {
     /// ```
     pub fn execute_program(&self, mem: &[u8], mbuff: &[u8]) -> Result<u64, Error> {
         let stack_usage = self.stack_usage.as_ref();
-        interpreter::execute_program(self.prog,stack_usage, mem, mbuff, &self.helpers, &self.allowed_memory)
+        interpreter::execute_program(self.prog, stack_usage, mem, mbuff, &self.helpers, &self.allowed_memory)
     }
 
     /// JIT-compile the loaded program. No argument required for this.
@@ -862,6 +862,42 @@ impl<'a> EbpfVmFixedMbuff<'a> {
         self.parent.set_verifier(verifier)
     }
 
+    /// Set a new stack usage calculator function. The function should return the stack usage
+    /// of the program in bytes. If a program has been loaded to the VM already, the calculator
+    /// is immediately run.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use rbpf::lib::{Error, ErrorKind};
+    /// use rbpf::ebpf;
+    /// use core::any::Any;
+    /// // Define a simple stack usage calculator function.
+    /// fn calculator(prog: &[u8], pc: usize, data: &mut dyn Any) -> u16 {
+    ///    // This is a dummy implementation, just for the example.
+    ///    // In a real implementation, you would calculate the stack usage based on the program.
+    ///    // Here we just return a fixed value.
+    ///    16
+    /// }
+    ///
+    /// let prog1 = &[
+    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
+    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
+    /// ];
+    ///
+    /// // Instantiate a VM.
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
+    /// // Change the stack usage calculator.
+    /// vm.set_stack_usage_calculator(calculator, Box::new(())).unwrap();
+    /// ```
+    pub fn set_stack_usage_calculator(
+        &mut self,
+        calculator: StackUsageCalculator,
+        data: Box<dyn Any>,
+    ) -> Result<(), Error> {
+        self.parent.set_stack_usage_calculator(calculator, data)
+    }
+
     /// Register a built-in or user-defined helper function in order to use it later from within
     /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
     ///
@@ -1341,6 +1377,42 @@ impl<'a> EbpfVmRaw<'a> {
         self.parent.set_verifier(verifier)
     }
 
+    /// Set a new stack usage calculator function. The function should return the stack usage
+    /// of the program in bytes. If a program has been loaded to the VM already, the calculator
+    /// is immediately run.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use rbpf::lib::{Error, ErrorKind};
+    /// use rbpf::ebpf;
+    /// use core::any::Any;
+    /// // Define a simple stack usage calculator function.
+    /// fn calculator(prog: &[u8], pc: usize, data: &mut dyn Any) -> u16 {
+    ///    // This is a dummy implementation, just for the example.
+    ///    // In a real implementation, you would calculate the stack usage based on the program.
+    ///    // Here we just return a fixed value.
+    ///    16
+    /// }
+    ///
+    /// let prog1 = &[
+    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
+    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
+    /// ];
+    ///
+    /// // Instantiate a VM.
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
+    /// // Change the stack usage calculator.
+    /// vm.set_stack_usage_calculator(calculator, Box::new(())).unwrap();
+    /// ```
+    pub fn set_stack_usage_calculator(
+        &mut self,
+        calculator: StackUsageCalculator,
+        data: Box<dyn Any>,
+    ) -> Result<(), Error> {
+        self.parent.set_stack_usage_calculator(calculator, data)
+    }
+
     /// Register a built-in or user-defined helper function in order to use it later from within
     /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
     ///
@@ -1726,6 +1798,42 @@ impl<'a> EbpfVmNoData<'a> {
         self.parent.set_verifier(verifier)
     }
 
+    /// Set a new stack usage calculator function. The function should return the stack usage
+    /// of the program in bytes. If a program has been loaded to the VM already, the calculator
+    /// is immediately run.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use rbpf::lib::{Error, ErrorKind};
+    /// use rbpf::ebpf;
+    /// use core::any::Any;
+    /// // Define a simple stack usage calculator function.
+    /// fn calculator(prog: &[u8], pc: usize, data: &mut dyn Any) -> u16 {
+    ///    // This is a dummy implementation, just for the example.
+    ///    // In a real implementation, you would calculate the stack usage based on the program.
+    ///    // Here we just return a fixed value.
+    ///    16
+    /// }
+    ///
+    /// let prog1 = &[
+    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
+    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
+    /// ];
+    ///
+    /// // Instantiate a VM.
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
+    /// // Change the stack usage calculator.
+    /// vm.set_stack_usage_calculator(calculator, Box::new(())).unwrap();
+    /// ```
+    pub fn set_stack_usage_calculator(
+        &mut self,
+        calculator: StackUsageCalculator,
+        data: Box<dyn Any>,
+    ) -> Result<(), Error> {
+        self.parent.set_stack_usage_calculator(calculator, data)
+    }
+
     /// Register a built-in or user-defined helper function in order to use it later from within
     /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
     ///

+ 9 - 5
src/stack.rs

@@ -1,7 +1,9 @@
+// SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
 use core::any::Any;
 
 use crate::{
-    ebpf::{self, RBPF_EBPF_LOCAL_FUNCTION_STACK_SIZE},
+    ebpf::{self, LOCAL_FUNCTION_STACK_SIZE},
     lib::*,
     StackUsageCalculator,
 };
@@ -61,7 +63,7 @@ pub enum StackUsageType {
 impl StackUsageType {
     pub fn stack_usage(&self) -> u16 {
         match self {
-            StackUsageType::Default => RBPF_EBPF_LOCAL_FUNCTION_STACK_SIZE,
+            StackUsageType::Default => LOCAL_FUNCTION_STACK_SIZE,
             StackUsageType::Custom(size) => *size,
         }
     }
@@ -112,9 +114,11 @@ impl StackVerifier {
         pc: usize,
     ) -> Result<StackUsageType, Error> {
         let mut ty = StackUsageType::Default;
-        if let Some(calculator) = self.calculator {
-            let size = calculator(prog, pc, self.data.as_mut().unwrap());
-            ty = StackUsageType::Custom(size);
+        match self.calculator {
+            Some(calculator) => {
+                ty = StackUsageType::Custom(calculator(prog, pc, self.data.as_mut().unwrap()));
+            }
+            None => return Ok(ty),
         }
         if ty.stack_usage() % 16 > 0 {
             Err(Error::new(

+ 2 - 4
src/verifier.rs

@@ -251,16 +251,14 @@ pub fn check(prog: &[u8]) -> Result<(), Error> {
             ebpf::CALL       => {
                 let src = insn.src;
                 match src {
-                    0 => {
-                        if insn.imm < 0 { reject(format!("invalid call to function #{:?} (insn #{insn_ptr:?})", insn.imm))?; }
-                    }
+                    0 => {}
                     1 => {
                         let dst_insn_ptr = insn_ptr as isize + 1 + insn.imm as isize;
                         if dst_insn_ptr < 0 || dst_insn_ptr as usize >= (prog.len() / ebpf::INSN_SIZE) {
                             reject(format!("call out of code to #{dst_insn_ptr:?} (insn #{insn_ptr:?})"))?;
                         }
                     }
-                    _ => { reject(format!("unexpected call type #{:?} (insn #{insn_ptr:?})", src))?; }
+                    _ => { reject(format!("unsupported call type #{:?} (insn #{insn_ptr:?})", src))?; }
                 }
             },
             ebpf::TAIL_CALL  => { unimplemented!() },

+ 125 - 0
tests/misc.rs

@@ -602,3 +602,128 @@ fn test_verifier_fail() {
     vm.set_program(&prog).unwrap();
     assert_eq!(vm.execute_program().unwrap(), 0xBEE);
 }
+
+#[test]
+fn test_vm_bpf_to_bpf_call(){
+    let test_code = assemble(
+        "
+        mov64 r1, 0x10
+        mov64 r2, 0x1
+        callx 0x4
+        mov64 r1, 0x1
+        mov64 r2, r0
+        callx 0x4
+        exit
+        mov64 r0, r1
+        sub64 r0, r2
+        exit
+        mov64 r0, r2
+        add64 r0, r1
+        exit
+        ").unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&test_code)).unwrap();
+    let vm_res= vm.execute_program().unwrap();
+    assert_eq!(vm_res, 0x10);
+}
+
+#[cfg(all(not(windows), feature = "std"))]
+#[test]
+fn test_vm_jit_bpf_to_bpf_call(){
+    let test_code = assemble(
+        "
+        mov64 r1, 0x10
+        mov64 r2, 0x1
+        callx 0x4
+        mov64 r1, 0x1
+        mov64 r2, r0
+        callx 0x4
+        exit
+        mov64 r0, r1
+        sub64 r0, r2
+        exit
+        mov64 r0, r2
+        add64 r0, r1
+        exit").unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&test_code)).unwrap();
+    vm.jit_compile().unwrap();
+    let vm_res= unsafe { vm.execute_program_jit().unwrap() };
+    assert_eq!(vm_res, 0x10);
+}
+
+#[test]
+#[should_panic(expected = "[Verifier] Error: unsupported call type #2 (insn #0)")]
+fn test_verifier_err_other_type_call(){
+    let prog = &[
+        0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    ];
+    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
+    vm.execute_program().unwrap();
+}
+
+#[test]
+#[should_panic(expected = "Error: unsupported call type #2 (insn #0)")]
+fn test_vm_other_type_call(){
+    let prog = &[
+        0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    ];
+    let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
+    vm.set_verifier(|_|{
+        Ok(())
+    }).unwrap();
+    vm.set_program(prog).unwrap();
+    vm.execute_program().unwrap();
+}
+
+#[cfg(all(not(windows), feature = "std"))]
+#[test]
+#[should_panic(expected = "[JIT] Error: unexpected call type #2 (insn #0)")]
+fn test_vm_jit_other_type_call(){
+    let prog = &[
+        0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    ];
+    let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
+    vm.set_verifier(|_|{
+        Ok(())
+    }).unwrap();
+    vm.set_program(prog).unwrap();
+    vm.jit_compile().unwrap();
+    unsafe { vm.execute_program_jit().unwrap() };
+}
+
+#[test]
+#[should_panic(expected = "local function (at PC 0) has improperly sized stack use (15)")]
+fn test_invalid_stack_alignment(){
+    let prog = assemble("
+        mov r0, 0x1
+        exit").unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
+    vm.set_stack_usage_calculator(|_,_,_| 15, Box::new(())).unwrap();
+}
+
+#[test]
+#[should_panic(expected = "Error: out of bounds memory store (insn #8)")]
+fn test_stack_overflow(){
+    // The stdw instruction is used to test the stack overflow.
+    let test_code = assemble(
+        "
+        mov64 r1, 0x10
+        mov64 r2, 0x1
+        callx 0x4
+        mov64 r1, 0x1
+        mov64 r2, r0
+        callx 0x5
+        exit
+        stdw [r10-8], 0xcd
+        mov64 r0, r1
+        sub64 r0, r2
+        exit
+        mov64 r0, r2
+        add64 r0, r1
+        exit").unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&test_code)).unwrap();
+    vm.set_stack_usage_calculator(|_,_,_| 512, Box::new(())).unwrap();
+    vm.execute_program().unwrap();
+}

+ 1 - 52
tests/ubpf_jit_x86_64.rs

@@ -21,8 +21,7 @@
 extern crate rbpf;
 mod common;
 
-use rbpf::ebpf::CALL;
-use rbpf::{ebpf::to_insn_vec, helpers};
+use rbpf::helpers;
 use rbpf::assembler::assemble;
 use common::{TCP_SACK_ASM, TCP_SACK_MATCH, TCP_SACK_NOMATCH};
 
@@ -2357,53 +2356,3 @@ fn test_jit_tcp_sack_nomatch() {
     vm.jit_compile().unwrap();
     unsafe { assert_eq!(vm.execute_program_jit(mem.as_mut_slice()).unwrap(), 0x0); }
 }
-
-#[test]
-fn test_bpf_to_bpf_call(){
-    let test_code = assemble(
-        "
-    mov64 r1, 0x10
-    mov64 r2, 0x1
-    call 0x4
-    mov64 r1, 0x1
-    mov64 r2, r0
-    call 0x4
-    exit
-    mov64 r0, r1
-    sub64 r0, r2
-    exit
-    mov64 r0, r2
-    add64 r0, r1
-    exit
-    ",
-    )
-    .unwrap();
-    let mut code = to_insn_vec(&test_code);
-    let mut real_code = Vec::new();
-    code.iter_mut().for_each(|insn| {
-        if insn.opc == CALL {
-            insn.src = 0x1;
-        }
-        real_code.extend_from_slice(&insn.to_array());
-    });
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&real_code)).unwrap();
-    vm.jit_compile().unwrap();
-    let vm_res= unsafe { vm.execute_program_jit().unwrap() };    
-    assert_eq!(vm_res, 0x10);
-}
-
-#[test]
-#[should_panic(expected = "[JIT] Error: unexpected call type #2 (insn #0)")]
-fn test_other_type_call(){
-    let prog = &[
-        0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
-    vm.set_verifier(|_|{
-        Ok(())
-    }).unwrap();
-    vm.set_program(prog).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe { vm.execute_program_jit().unwrap() };
-}

+ 0 - 11
tests/ubpf_verifier.rs

@@ -161,14 +161,3 @@ fn test_verifier_err_funcall_over_the_end() {
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     vm.execute_program().unwrap();
 }
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: unexpected call type #2 (insn #0)")]
-fn test_verifier_err_other_type_call(){
-    let prog = &[
-        0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.execute_program().unwrap();
-}

+ 0 - 49
tests/ubpf_vm.rs

@@ -19,7 +19,6 @@
 extern crate rbpf;
 mod common;
 
-use rbpf::ebpf::{to_insn_vec, CALL};
 use rbpf::helpers;
 use rbpf::assembler::assemble;
 use common::{TCP_SACK_ASM, TCP_SACK_MATCH, TCP_SACK_NOMATCH};
@@ -2228,39 +2227,6 @@ fn test_vm_stxw() {
     assert_eq!(vm.execute_program(mem).unwrap(), 0x44332211);
 }
 
-#[test]
-fn test_bpf_to_bpf_call(){
-    let test_code = assemble(
-        "
-    mov64 r1, 0x10
-    mov64 r2, 0x1
-    call 0x4
-    mov64 r1, 0x1
-    mov64 r2, r0
-    call 0x4
-    exit
-    mov64 r0, r1
-    sub64 r0, r2
-    exit
-    mov64 r0, r2
-    add64 r0, r1
-    exit
-    ",
-    )
-    .unwrap();
-    let mut code = to_insn_vec(&test_code);
-    let mut real_code = Vec::new();
-    code.iter_mut().for_each(|insn| {
-        if insn.opc == CALL {
-            insn.src = 0x1;
-        }
-        real_code.extend_from_slice(&insn.to_array());
-    });
-    let vm = rbpf::EbpfVmNoData::new(Some(&real_code)).unwrap();
-    let vm_res= vm.execute_program().unwrap();    
-    assert_eq!(vm_res, 0x10);
-}
-
 #[test]
 fn test_vm_subnet() {
     let prog = assemble("
@@ -2420,18 +2386,3 @@ fn test_vm_tcp_sack_nomatch() {
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.execute_program(mem.as_mut_slice()).unwrap(), 0x0);
 }
-
-#[test]
-#[should_panic(expected = "Error: unexpected call type #2 (insn #0)")]
-fn test_other_type_call(){
-    let prog = &[
-        0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
-    vm.set_verifier(|_|{
-        Ok(())
-    }).unwrap();
-    vm.set_program(prog).unwrap();
-    vm.execute_program().unwrap();
-}