Browse Source

API: make JITted program and `prog_exec_jit()` function unsafe

The JITted program could make the system crash if it contains errors,
and as a consequence should be marked as `unsafe`.

Reported-by: @CensoredUsername
Reported-at: https://www.reddit.com/r/rust/comments/5n4n1p/rust_virtual_machine_and_jit_compiler_for_ebpf/dc8os42/
Quentin Monnet 8 years ago
parent
commit
6124d65ae2
5 changed files with 161 additions and 125 deletions
  1. 18 10
      README.md
  2. 1 1
      src/jit.rs
  3. 37 13
      src/lib.rs
  4. 10 6
      tests/misc.rs
  5. 95 95
      tests/ubpf_jit_x86_64.rs

+ 18 - 10
README.md

@@ -129,7 +129,9 @@ All these structs implement the same public functions:
 pub fn new(prog: &'a std::vec::Vec<u8>) -> EbpfVmMbuff<'a>
 pub fn new(prog: &'a std::vec::Vec<u8>) -> EbpfVmMbuff<'a>
 
 
 // called with EbpfVmFixedMbuff:: prefix
 // called with EbpfVmFixedMbuff:: prefix
-pub fn new(prog: &'a std::vec::Vec<u8>, data_offset: usize, data_end_offset: usize) -> EbpfVmFixedMbuff<'a>
+pub fn new(prog: &'a std::vec::Vec<u8>,
+           data_offset: usize,
+           data_end_offset: usize) -> EbpfVmFixedMbuff<'a>
 
 
 // called with EbpfVmRaw:: prefix
 // called with EbpfVmRaw:: prefix
 pub fn new(prog: &'a std::vec::Vec<u8>) -> EbpfVmRaw<'a>
 pub fn new(prog: &'a std::vec::Vec<u8>) -> EbpfVmRaw<'a>
@@ -166,7 +168,9 @@ program after the VM instance creation. This program is checked with the
 verifier.
 verifier.
 
 
 ```rust
 ```rust
-pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64)
+pub fn register_helper(&mut self,
+                       key: u32,
+                       function: fn (u64, u64, u64, u64, u64) -> u64)
 ```
 ```
 
 
 This function is used to register a helper function. The VM stores its
 This function is used to register a helper function. The VM stores its
@@ -176,10 +180,13 @@ therefore must use specific helper numbers.
 
 
 ```rust
 ```rust
 // for struct EbpfVmMbuff
 // for struct EbpfVmMbuff
-pub fn prog_exec(&self, mem: &'a mut std::vec::Vec<u8>, mbuff: &'a mut std::vec::Vec<u8>) -> u64
+pub fn prog_exec(&self,
+                 mem: &'a mut std::vec::Vec<u8>,
+                 mbuff: &'a mut std::vec::Vec<u8>) -> u64
 
 
 // for struct EbpfVmFixedMbuff and struct EbpfVmRaw
 // for struct EbpfVmFixedMbuff and struct EbpfVmRaw
-pub fn prog_exec(&self, mem: &'a mut std::vec::Vec<u8>) -> u64
+pub fn prog_exec(&self,
+                 mem: &'a mut std::vec::Vec<u8>) -> u64
 
 
 // for struct EbpfVmNoData
 // for struct EbpfVmNoData
 pub fn prog_exec(&self) -> u64
 pub fn prog_exec(&self) -> u64
@@ -200,13 +207,14 @@ is called. The generated assembly function is internally stored in the VM.
 
 
 ```rust
 ```rust
 // for struct EbpfVmMbuff
 // for struct EbpfVmMbuff
-pub fn prog_exec_jit(&self, mem: &'a mut std::vec::Vec<u8>, mbuff: &'a mut std::vec::Vec<u8>) -> u64
+pub unsafe fn prog_exec_jit(&self, mem: &'a mut std::vec::Vec<u8>,
+                            mbuff: &'a mut std::vec::Vec<u8>) -> u64
 
 
 // for struct EbpfVmFixedMbuff and struct EbpfVmRaw
 // for struct EbpfVmFixedMbuff and struct EbpfVmRaw
-pub fn prog_exec_jit(&self, mem: &'a mut std::vec::Vec<u8>) -> u64
+pub unsafe fn prog_exec_jit(&self, mem: &'a mut std::vec::Vec<u8>) -> u64
 
 
 // for struct EbpfVmNoData
 // for struct EbpfVmNoData
-pub fn prog_exec_jit(&self) -> u64
+pub unsafe fn prog_exec_jit(&self) -> u64
 ```
 ```
 
 
 Calls the JIT-compiled program. The arguments to provide are the same as for
 Calls the JIT-compiled program. The arguments to provide are the same as for
@@ -214,7 +222,7 @@ Calls the JIT-compiled program. The arguments to provide are the same as for
 the JIT-compiled program should be the same as with the interpreter, but it
 the JIT-compiled program should be the same as with the interpreter, but it
 should run faster. Note that if errors occur during the program execution, the
 should run faster. Note that if errors occur during the program execution, the
 JIT-compiled version does not handle it as well as the interpreter, and the
 JIT-compiled version does not handle it as well as the interpreter, and the
-program may crash.
+program may crash. For this reason the functions are marked as `unsafe`.
 
 
 ## Example uses
 ## Example uses
 
 
@@ -273,7 +281,7 @@ fn main() {
 
 
     // Then we execute it. For this kind of VM, a reference to the packet data
     // Then we execute it. For this kind of VM, a reference to the packet data
     // must be passed to the function that executes the program.
     // must be passed to the function that executes the program.
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x11);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x11); }
 }
 }
 ```
 ```
 ### Using a metadata buffer
 ### Using a metadata buffer
@@ -314,7 +322,7 @@ fn main() {
 
 
     // Here we must provide both a reference to the packet data, and to the
     // Here we must provide both a reference to the packet data, and to the
     // metadata buffer we use.
     // metadata buffer we use.
-    assert_eq!(vm.prog_exec_jit(&mut mem, &mut mbuff), 0x2211);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem, &mut mbuff), 0x2211); }
 }
 }
 ```
 ```
 
 

+ 1 - 1
src/jit.rs

@@ -835,7 +835,7 @@ impl<'a> std::fmt::Debug for JitMemory<'a> {
 pub fn compile(prog: &std::vec::Vec<u8>,
 pub fn compile(prog: &std::vec::Vec<u8>,
                helpers: &HashMap<u32, fn (u64, u64, u64, u64, u64) -> u64>,
                helpers: &HashMap<u32, fn (u64, u64, u64, u64, u64) -> u64>,
                use_mbuff: bool, update_data_ptr: bool)
                use_mbuff: bool, update_data_ptr: bool)
-    -> (fn(*mut u8, usize, *mut u8, usize, usize, usize) -> u64) {
+    -> (unsafe fn(*mut u8, usize, *mut u8, usize, usize, usize) -> u64) {
 
 
     // TODO: check how long the page must be to be sure to support an eBPF program of maximum
     // TODO: check how long the page must be to be sure to support an eBPF program of maximum
     // possible length
     // possible length

+ 37 - 13
src/lib.rs

@@ -69,7 +69,7 @@ struct MetaBuff {
 /// ```
 /// ```
 pub struct EbpfVmMbuff<'a> {
 pub struct EbpfVmMbuff<'a> {
     prog:    &'a std::vec::Vec<u8>,
     prog:    &'a std::vec::Vec<u8>,
-    jit:     (fn (*mut u8, usize, *mut u8, usize, usize, usize) -> u64),
+    jit:     (unsafe fn (*mut u8, usize, *mut u8, usize, usize, usize) -> u64),
     helpers: HashMap<u32, fn (u64, u64, u64, u64, u64) -> u64>,
     helpers: HashMap<u32, fn (u64, u64, u64, u64, u64) -> u64>,
 }
 }
 
 
@@ -524,11 +524,15 @@ impl<'a> EbpfVmMbuff<'a> {
     ///
     ///
     /// This function panics if an error occurs during the execution of the program.
     /// This function panics if an error occurs during the execution of the program.
     ///
     ///
+    /// # Safety
+    ///
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
     /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
     /// very bad (program may segfault). It may be wise to check that the program works with the
     /// very bad (program may segfault). It may be wise to check that the program works with the
     /// interpreter before running the JIT-compiled version of it.
     /// interpreter before running the JIT-compiled version of it.
     ///
     ///
+    /// For this reason the function should be called from within an `unsafe` bloc.
+    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -557,10 +561,12 @@ impl<'a> EbpfVmMbuff<'a> {
     /// vm.jit_compile();
     /// vm.jit_compile();
     ///
     ///
     /// // Provide both a reference to the packet data, and to the metadata buffer.
     /// // Provide both a reference to the packet data, and to the metadata buffer.
-    /// let res = vm.prog_exec_jit(&mut mem, &mut mbuff);
-    /// assert_eq!(res, 0x2211);
+    /// unsafe {
+    ///     let res = vm.prog_exec_jit(&mut mem, &mut mbuff);
+    ///     assert_eq!(res, 0x2211);
+    /// }
     /// ```
     /// ```
-    pub fn prog_exec_jit(&self, mem: &mut std::vec::Vec<u8>, mbuff: &'a mut std::vec::Vec<u8>) -> u64 {
+    pub unsafe fn prog_exec_jit(&self, mem: &mut std::vec::Vec<u8>, mbuff: &'a mut std::vec::Vec<u8>) -> u64 {
         // If packet data is empty, do not send the address of an empty vector; send a null
         // If packet data is empty, do not send the address of an empty vector; send a null
         // pointer (zero value) as first argument instead, as this is uBPF's behavior (empty
         // pointer (zero value) as first argument instead, as this is uBPF's behavior (empty
         // packet should not happen in the kernel; anyway the verifier would prevent the use of
         // packet should not happen in the kernel; anyway the verifier would prevent the use of
@@ -875,11 +881,15 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     ///
     ///
     /// This function panics if an error occurs during the execution of the program.
     /// This function panics if an error occurs during the execution of the program.
     ///
     ///
+    /// # Safety
+    ///
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
     /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
     /// very bad (program may segfault). It may be wise to check that the program works with the
     /// very bad (program may segfault). It may be wise to check that the program works with the
     /// interpreter before running the JIT-compiled version of it.
     /// interpreter before running the JIT-compiled version of it.
     ///
     ///
+    /// For this reason the function should be called from within an `unsafe` bloc.
+    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -902,12 +912,14 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// vm.jit_compile();
     /// vm.jit_compile();
     ///
     ///
     /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
     /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
-    /// let res = vm.prog_exec_jit(&mut mem);
-    /// assert_eq!(res, 0xdd);
+    /// unsafe {
+    ///     let res = vm.prog_exec_jit(&mut mem);
+    ///     assert_eq!(res, 0xdd);
+    /// }
     /// ```
     /// ```
     // This struct redefines the `prog_exec_jit()` function, in order to pass the offsets
     // This struct redefines the `prog_exec_jit()` function, in order to pass the offsets
     // associated with the fixed mbuff.
     // associated with the fixed mbuff.
-    pub fn prog_exec_jit(&mut self, mem: &'a mut std::vec::Vec<u8>) -> u64 {
+    pub unsafe fn prog_exec_jit(&mut self, mem: &'a mut std::vec::Vec<u8>) -> u64 {
         // If packet data is empty, do not send the address of an empty vector; send a null
         // If packet data is empty, do not send the address of an empty vector; send a null
         // pointer (zero value) as first argument instead, as this is uBPF's behavior (empty
         // pointer (zero value) as first argument instead, as this is uBPF's behavior (empty
         // packet should not happen in the kernel; anyway the verifier would prevent the use of
         // packet should not happen in the kernel; anyway the verifier would prevent the use of
@@ -1117,11 +1129,15 @@ impl<'a> EbpfVmRaw<'a> {
     ///
     ///
     /// This function panics if an error occurs during the execution of the program.
     /// This function panics if an error occurs during the execution of the program.
     ///
     ///
+    /// # Safety
+    ///
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
     /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
     /// very bad (program may segfault). It may be wise to check that the program works with the
     /// very bad (program may segfault). It may be wise to check that the program works with the
     /// interpreter before running the JIT-compiled version of it.
     /// interpreter before running the JIT-compiled version of it.
     ///
     ///
+    /// For this reason the function should be called from within an `unsafe` bloc.
+    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -1140,10 +1156,12 @@ impl<'a> EbpfVmRaw<'a> {
     ///
     ///
     /// vm.jit_compile();
     /// vm.jit_compile();
     ///
     ///
-    /// let res = vm.prog_exec_jit(&mut mem);
-    /// assert_eq!(res, 0x22cc);
+    /// unsafe {
+    ///     let res = vm.prog_exec_jit(&mut mem);
+    ///     assert_eq!(res, 0x22cc);
+    /// }
     /// ```
     /// ```
-    pub fn prog_exec_jit(&self, mem: &'a mut std::vec::Vec<u8>) -> u64 {
+    pub unsafe fn prog_exec_jit(&self, mem: &'a mut std::vec::Vec<u8>) -> u64 {
         let mut mbuff = vec![];
         let mut mbuff = vec![];
         self.parent.prog_exec_jit(mem, &mut mbuff)
         self.parent.prog_exec_jit(mem, &mut mbuff)
     }
     }
@@ -1349,11 +1367,15 @@ impl<'a> EbpfVmNoData<'a> {
     ///
     ///
     /// This function panics if an error occurs during the execution of the program.
     /// This function panics if an error occurs during the execution of the program.
     ///
     ///
+    /// # Safety
+    ///
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
     /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
     /// very bad (program may segfault). It may be wise to check that the program works with the
     /// very bad (program may segfault). It may be wise to check that the program works with the
     /// interpreter before running the JIT-compiled version of it.
     /// interpreter before running the JIT-compiled version of it.
     ///
     ///
+    /// For this reason the function should be called from within an `unsafe` bloc.
+    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -1367,10 +1389,12 @@ impl<'a> EbpfVmNoData<'a> {
     ///
     ///
     /// vm.jit_compile();
     /// vm.jit_compile();
     ///
     ///
-    /// let res = vm.prog_exec_jit();
-    /// assert_eq!(res, 0x1122);
+    /// unsafe {
+    ///     let res = vm.prog_exec_jit();
+    ///     assert_eq!(res, 0x1122);
+    /// }
     /// ```
     /// ```
-    pub fn prog_exec_jit(&self) -> u64 {
+    pub unsafe fn prog_exec_jit(&self) -> u64 {
         self.parent.prog_exec_jit(&mut vec![])
         self.parent.prog_exec_jit(&mut vec![])
     }
     }
 }
 }

+ 10 - 6
tests/misc.rs

@@ -246,9 +246,11 @@ fn test_jit_block_port() {
     vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf);
     vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf);
     vm.jit_compile();
     vm.jit_compile();
 
 
-    let res = vm.prog_exec_jit(&mut packet);
-    println!("Program returned: {:?} ({:#x})", res, res);
-    assert_eq!(res, 0xffffffff);
+    unsafe {
+        let res = vm.prog_exec_jit(&mut packet);
+        println!("Program returned: {:?} ({:#x})", res, res);
+        assert_eq!(res, 0xffffffff);
+    }
 }
 }
 
 
 // Program and memory come from uBPF test ldxh.
 // Program and memory come from uBPF test ldxh.
@@ -299,7 +301,9 @@ fn test_jit_mbuff() {
         *data_end = mem.as_ptr() as u64 + mem.len() as u64;
         *data_end = mem.as_ptr() as u64 + mem.len() as u64;
     }
     }
 
 
-    let mut vm = rbpf::EbpfVmMbuff::new(&prog);
-    vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem, &mut mbuff), 0x2211);
+    unsafe {
+        let mut vm = rbpf::EbpfVmMbuff::new(&prog);
+        vm.jit_compile();
+        assert_eq!(vm.prog_exec_jit(&mut mem, &mut mbuff), 0x2211);
+    }
 }
 }

+ 95 - 95
tests/ubpf_jit_x86_64.rs

@@ -36,7 +36,7 @@ fn test_jit_add() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x3);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x3); }
 }
 }
 
 
 #[test]
 #[test]
@@ -64,7 +64,7 @@ fn test_jit_alu64_arith() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x2a);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x2a); }
 }
 }
 
 
 #[test]
 #[test]
@@ -96,7 +96,7 @@ fn test_jit_alu64_bit() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x11);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x11); }
 }
 }
 
 
 #[test]
 #[test]
@@ -124,7 +124,7 @@ fn test_jit_alu_arith() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x2a);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x2a); }
 }
 }
 
 
 #[test]
 #[test]
@@ -154,7 +154,7 @@ fn test_jit_alu_bit() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x11);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x11); }
 }
 }
 
 
 #[test]
 #[test]
@@ -168,7 +168,7 @@ fn test_jit_arsh32_high_shift() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x4);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x4); }
 }
 }
 
 
 #[test]
 #[test]
@@ -181,7 +181,7 @@ fn test_jit_arsh() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xffff8000);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xffff8000); }
 }
 }
 
 
 #[test]
 #[test]
@@ -196,7 +196,7 @@ fn test_jit_arsh64() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xfffffffffffffff8);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xfffffffffffffff8); }
 }
 }
 
 
 #[test]
 #[test]
@@ -210,7 +210,7 @@ fn test_jit_arsh_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xffff8000);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xffff8000); }
 }
 }
 
 
 #[test]
 #[test]
@@ -225,7 +225,7 @@ fn test_jit_be16() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x1122);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x1122); }
 }
 }
 
 
 #[test]
 #[test]
@@ -240,7 +240,7 @@ fn test_jit_be16_high() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x1122);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x1122); }
 }
 }
 
 
 #[test]
 #[test]
@@ -255,7 +255,7 @@ fn test_jit_be32() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x11223344);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x11223344); }
 }
 }
 
 
 #[test]
 #[test]
@@ -270,7 +270,7 @@ fn test_jit_be32_high() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x11223344);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x11223344); }
 }
 }
 
 
 #[test]
 #[test]
@@ -285,7 +285,7 @@ fn test_jit_be64() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x1122334455667788);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x1122334455667788); }
 }
 }
 
 
 #[test]
 #[test]
@@ -302,7 +302,7 @@ fn test_jit_call() {
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.register_helper(0, helpers::gather_bytes);
     vm.register_helper(0, helpers::gather_bytes);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x0102030405);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x0102030405); }
 }
 }
 
 
 #[test]
 #[test]
@@ -322,7 +322,7 @@ fn test_jit_call_memfrob() {
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.register_helper(1, helpers::memfrob);
     vm.register_helper(1, helpers::memfrob);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x102292e2f2c0708);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x102292e2f2c0708); }
 }
 }
 
 
 // TODO: helpers::trash_registers needs asm!().
 // TODO: helpers::trash_registers needs asm!().
@@ -345,7 +345,7 @@ fn test_jit_call_memfrob() {
     //let mut vm = rbpf::EbpfVmNoData::new(&prog);
     //let mut vm = rbpf::EbpfVmNoData::new(&prog);
     //vm.register_helper(2, helpers::trash_registers);
     //vm.register_helper(2, helpers::trash_registers);
     //vm.jit_compile();
     //vm.jit_compile();
-    //assert_eq!(vm.prog_exec_jit(), 0x4321);
+    //unsafe { assert_eq!(vm.prog_exec_jit(), 0x4321); }
 //}
 //}
 
 
 #[test]
 #[test]
@@ -359,7 +359,7 @@ fn test_jit_div32_high_divisor() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x3);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x3); }
 }
 }
 
 
 #[test]
 #[test]
@@ -372,7 +372,7 @@ fn test_jit_div32_imm() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x3);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x3); }
 }
 }
 
 
 #[test]
 #[test]
@@ -386,7 +386,7 @@ fn test_jit_div32_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x3);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x3); }
 }
 }
 
 
 #[test]
 #[test]
@@ -399,7 +399,7 @@ fn test_jit_div64_imm() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x300000000);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x300000000); }
 }
 }
 
 
 #[test]
 #[test]
@@ -413,7 +413,7 @@ fn test_jit_div64_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x300000000);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x300000000); }
 }
 }
 
 
 #[test]
 #[test]
@@ -426,7 +426,7 @@ fn test_jit_early_exit() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x3);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x3); }
 }
 }
 
 
 // uBPF limits the number of user functions at 64. We don't.
 // uBPF limits the number of user functions at 64. We don't.
@@ -448,7 +448,7 @@ fn test_jit_err_call_unreg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    vm.prog_exec_jit();
+    unsafe { vm.prog_exec_jit(); }
 }
 }
 
 
 // TODO: Should panic!() instead, but I could not make it panic in JIT-compiled code, so the
 // TODO: Should panic!() instead, but I could not make it panic in JIT-compiled code, so the
@@ -464,7 +464,7 @@ fn test_jit_err_div64_by_zero_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff); }
 }
 }
 
 
 // TODO: Same remark as above
 // TODO: Same remark as above
@@ -479,7 +479,7 @@ fn test_jit_err_div_by_zero_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff); }
 }
 }
 
 
 // TODO: Same remark as above
 // TODO: Same remark as above
@@ -494,7 +494,7 @@ fn test_jit_err_mod64_by_zero_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff); }
 }
 }
 
 
 // TODO: Same remark as above
 // TODO: Same remark as above
@@ -509,7 +509,7 @@ fn test_jit_err_mod_by_zero_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff); }
 }
 }
 
 
 // TODO SKIP: JIT disabled for this testcase (stack oob check not implemented)
 // TODO SKIP: JIT disabled for this testcase (stack oob check not implemented)
@@ -522,7 +522,7 @@ fn test_jit_err_mod_by_zero_reg() {
 //     ];
 //     ];
 //     let mut vm = rbpf::EbpfVmNoData::new(&prog);
 //     let mut vm = rbpf::EbpfVmNoData::new(&prog);
 //     vm.jit_compile();
 //     vm.jit_compile();
-//     vm.prog_exec_jit();
+//     unsafe { vm.prog_exec_jit(); }
 // }
 // }
 
 
 #[test]
 #[test]
@@ -533,7 +533,7 @@ fn test_jit_exit() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x0);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x0); }
 }
 }
 
 
 #[test]
 #[test]
@@ -546,7 +546,7 @@ fn test_jit_ja() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -563,7 +563,7 @@ fn test_jit_jeq_imm() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -581,7 +581,7 @@ fn test_jit_jeq_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -598,7 +598,7 @@ fn test_jit_jge_imm() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -615,7 +615,7 @@ fn test_jit_jgt_imm() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -634,7 +634,7 @@ fn test_jit_jgt_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -650,7 +650,7 @@ fn test_jit_jit_bounce() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -668,7 +668,7 @@ fn test_jit_jne_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -685,7 +685,7 @@ fn test_jit_jset_imm() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -703,7 +703,7 @@ fn test_jit_jset_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -721,7 +721,7 @@ fn test_jit_jsge_imm() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -741,7 +741,7 @@ fn test_jit_jsge_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -758,7 +758,7 @@ fn test_jit_jsgt_imm() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -776,7 +776,7 @@ fn test_jit_jsgt_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -788,7 +788,7 @@ fn test_jit_lddw() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1122334455667788);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1122334455667788); }
 }
 }
 
 
 #[test]
 #[test]
@@ -800,7 +800,7 @@ fn test_jit_lddw2() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x80000000);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x80000000); }
 }
 }
 
 
 #[test]
 #[test]
@@ -844,7 +844,7 @@ fn test_jit_ldxb_all() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x9876543210);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x9876543210); }
 }
 }
 
 
 #[test]
 #[test]
@@ -858,7 +858,7 @@ fn test_jit_ldxb() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x11);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x11); }
 }
 }
 
 
 #[test]
 #[test]
@@ -873,7 +873,7 @@ fn test_jit_ldxdw() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x8877665544332211);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x8877665544332211); }
 }
 }
 
 
 #[test]
 #[test]
@@ -928,7 +928,7 @@ fn test_jit_ldxh_all() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x9876543210);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x9876543210); }
 }
 }
 
 
 #[test]
 #[test]
@@ -973,7 +973,7 @@ fn test_jit_ldxh_all2() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x3ff);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x3ff); }
 }
 }
 
 
 #[test]
 #[test]
@@ -987,7 +987,7 @@ fn test_jit_ldxh() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x2211);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x2211); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1003,7 +1003,7 @@ fn test_jit_ldxh_same_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x1234);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x1234); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1050,7 +1050,7 @@ fn test_jit_ldxw_all() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x030f0f);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x030f0f); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1064,7 +1064,7 @@ fn test_jit_ldxw() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x44332211);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x44332211); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1079,7 +1079,7 @@ fn test_jit_le16() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x1122);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x1122); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1094,7 +1094,7 @@ fn test_jit_le32() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x11223344);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x11223344); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1109,7 +1109,7 @@ fn test_jit_le64() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x1122334455667788);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x1122334455667788); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1122,7 +1122,7 @@ fn test_jit_lsh_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x10);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x10); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1136,7 +1136,7 @@ fn test_jit_mod() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x5);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x5); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1149,7 +1149,7 @@ fn test_jit_mod32() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x0);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x0); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1167,7 +1167,7 @@ fn test_jit_mod64() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x30ba5a04);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x30ba5a04); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1179,7 +1179,7 @@ fn test_jit_mov() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1191,7 +1191,7 @@ fn test_jit_mul32_imm() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xc);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xc); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1204,7 +1204,7 @@ fn test_jit_mul32_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xc);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xc); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1217,7 +1217,7 @@ fn test_jit_mul32_reg_overflow() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x4);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x4); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1229,7 +1229,7 @@ fn test_jit_mul64_imm() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x100000004);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x100000004); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1242,7 +1242,7 @@ fn test_jit_mul64_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x100000004);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x100000004); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1261,7 +1261,7 @@ fn test_jit_mul_loop() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x75db9c97);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x75db9c97); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1273,7 +1273,7 @@ fn test_jit_neg64() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xfffffffffffffffe);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xfffffffffffffffe); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1285,7 +1285,7 @@ fn test_jit_neg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xfffffffe);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xfffffffe); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1310,7 +1310,7 @@ fn test_jit_prime() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1323,7 +1323,7 @@ fn test_jit_rhs32() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x00ffffff);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x00ffffff); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1336,7 +1336,7 @@ fn test_jit_rsh_reg() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1354,7 +1354,7 @@ fn test_jit_stack() {
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0xcd);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0xcd); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1381,7 +1381,7 @@ fn test_jit_stack2() {
     vm.register_helper(0, helpers::gather_bytes);
     vm.register_helper(0, helpers::gather_bytes);
     vm.register_helper(1, helpers::memfrob);
     vm.register_helper(1, helpers::memfrob);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x01020304);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x01020304); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1396,7 +1396,7 @@ fn test_jit_stb() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x11);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x11); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1412,7 +1412,7 @@ fn test_jit_stdw() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x44332211);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x44332211); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1427,7 +1427,7 @@ fn test_jit_sth() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x2211);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x2211); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1465,7 +1465,7 @@ fn test_jit_string_stack() {
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     let mut vm = rbpf::EbpfVmNoData::new(&prog);
     vm.register_helper(4, helpers::strcmp);
     vm.register_helper(4, helpers::strcmp);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(), 0x0);
+    unsafe { assert_eq!(vm.prog_exec_jit(), 0x0); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1480,7 +1480,7 @@ fn test_jit_stw() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x44332211);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x44332211); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1496,7 +1496,7 @@ fn test_jit_stxb() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x11);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x11); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1527,7 +1527,7 @@ fn test_jit_stxb_all() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0xf0f2f3f4f5f6f7f8);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0xf0f2f3f4f5f6f7f8); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1547,7 +1547,7 @@ fn test_jit_stxb_all2() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0xf1f9);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0xf1f9); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1581,7 +1581,7 @@ fn test_jit_stxb_chain() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x2a);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x2a); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1600,7 +1600,7 @@ fn test_jit_stxdw() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x8877665544332211);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x8877665544332211); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1616,7 +1616,7 @@ fn test_jit_stxh() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x2211);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x2211); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1632,7 +1632,7 @@ fn test_jit_stxw() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x44332211);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x44332211); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1667,7 +1667,7 @@ fn test_jit_subnet() {
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     let mut vm = rbpf::EbpfVmRaw::new(&prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x1); }
 }
 }
 
 
 
 
@@ -1713,7 +1713,7 @@ fn test_jit_tcp_port80_match() {
     let prog = &PROG_TCP_PORT_80.to_vec();
     let prog = &PROG_TCP_PORT_80.to_vec();
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1736,7 +1736,7 @@ fn test_jit_tcp_port80_nomatch() {
     let prog = &PROG_TCP_PORT_80.to_vec();
     let prog = &PROG_TCP_PORT_80.to_vec();
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x0);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x0); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1759,7 +1759,7 @@ fn test_jit_tcp_port80_nomatch_ethertype() {
     let prog = &PROG_TCP_PORT_80.to_vec();
     let prog = &PROG_TCP_PORT_80.to_vec();
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x0);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x0); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1782,7 +1782,7 @@ fn test_jit_tcp_port80_nomatch_proto() {
     let prog = &PROG_TCP_PORT_80.to_vec();
     let prog = &PROG_TCP_PORT_80.to_vec();
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x0);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x0); }
 }
 }
 
 
 const PROG_TCP_SACK: [u8;352] = [
 const PROG_TCP_SACK: [u8;352] = [
@@ -1849,7 +1849,7 @@ fn test_jit_tcp_sack_match() {
     let prog = &PROG_TCP_SACK.to_vec();
     let prog = &PROG_TCP_SACK.to_vec();
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x1);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x1); }
 }
 }
 
 
 #[test]
 #[test]
@@ -1868,5 +1868,5 @@ fn test_jit_tcp_sack_nomatch() {
     let prog = &PROG_TCP_SACK.to_vec();
     let prog = &PROG_TCP_SACK.to_vec();
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     let mut vm = rbpf::EbpfVmRaw::new(prog);
     vm.jit_compile();
     vm.jit_compile();
-    assert_eq!(vm.prog_exec_jit(&mut mem), 0x0);
+    unsafe { assert_eq!(vm.prog_exec_jit(&mut mem), 0x0); }
 }
 }