Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gracefully handle program rejection from verifier #31

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/load_elf.rs
Expand Up @@ -111,7 +111,7 @@ fn main() {
0x64, 0x66, 0x0au8
];

let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50);
let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf);

let res = vm.prog_exec(packet1);
Expand Down
4 changes: 2 additions & 2 deletions examples/uptime.rs
Expand Up @@ -39,7 +39,7 @@ fn main() {
];

// Create a VM: this one takes no data. Load prog1 in it.
let mut vm = rbpf::EbpfVmNoData::new(prog1);
let mut vm = rbpf::EbpfVmNoData::new(prog1).unwrap();
// Execute prog1.
assert_eq!(vm.prog_exec(), 0x3);

Expand All @@ -51,7 +51,7 @@ fn main() {
// In the following example we use a helper to get the elapsed time since boot time: we
// reimplement uptime in eBPF, in Rust. Because why not.

vm.set_prog(prog2);
vm.set_prog(prog2).unwrap();
vm.register_helper(helpers::BPF_KTIME_GETNS_IDX, helpers::bpf_time_getns);

let time;
Expand Down
108 changes: 56 additions & 52 deletions src/lib.rs
Expand Up @@ -75,7 +75,7 @@ struct MetaBuff {
/// }
///
/// // Instantiate a VM.
/// let mut vm = rbpf::EbpfVmMbuff::new(prog);
/// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
///
/// // Provide both a reference to the packet data, and to the metadata buffer.
/// let res = vm.prog_exec(mem, &mut mbuff);
Expand Down Expand Up @@ -106,21 +106,21 @@ impl<'a> EbpfVmMbuff<'a> {
/// ];
///
/// // Instantiate a VM.
/// let mut vm = rbpf::EbpfVmMbuff::new(prog);
/// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
/// ```
pub fn new(prog: &'a [u8]) -> EbpfVmMbuff<'a> {
verifier::check(prog);
pub fn new(prog: &'a [u8]) -> Result<EbpfVmMbuff<'a>, String> {
verifier::check(prog)?;

fn no_jit(_mbuff: *mut u8, _len: usize, _mem: *mut u8, _mem_len: usize,
_nodata_offset: usize, _nodata_end_offset: usize) -> u64 {
panic!("Error: program has not been JIT-compiled");
}

EbpfVmMbuff {
Ok(EbpfVmMbuff {
prog: prog,
jit: no_jit,
helpers: HashMap::new(),
}
})
}

/// Load a new eBPF program into the virtual machine instance.
Expand All @@ -143,12 +143,13 @@ impl<'a> EbpfVmMbuff<'a> {
/// ];
///
/// // Instantiate a VM.
/// let mut vm = rbpf::EbpfVmMbuff::new(prog1);
/// let mut vm = rbpf::EbpfVmMbuff::new(prog1).unwrap();
/// vm.set_prog(prog2);
/// ```
pub fn set_prog(&mut self, prog: &'a [u8]) {
verifier::check(prog);
pub fn set_prog(&mut self, prog: &'a [u8]) -> Result<(), String> {
verifier::check(prog)?;
self.prog = prog;
Ok(())
}

/// Register a built-in or user-defined helper function in order to use it later from within
Expand Down Expand Up @@ -179,7 +180,7 @@ impl<'a> EbpfVmMbuff<'a> {
/// ];
///
/// // Instantiate a VM.
/// let mut vm = rbpf::EbpfVmMbuff::new(prog);
/// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
///
/// // Register a helper.
/// // On running the program this helper will print the content of registers r3, r4 and r5 to
Expand Down Expand Up @@ -226,7 +227,7 @@ impl<'a> EbpfVmMbuff<'a> {
/// }
///
/// // Instantiate a VM.
/// let mut vm = rbpf::EbpfVmMbuff::new(prog);
/// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
///
/// // Provide both a reference to the packet data, and to the metadata buffer.
/// let res = vm.prog_exec(mem, &mut mbuff);
Expand Down Expand Up @@ -572,7 +573,7 @@ impl<'a> EbpfVmMbuff<'a> {
/// ];
///
/// // Instantiate a VM.
/// let mut vm = rbpf::EbpfVmMbuff::new(prog);
/// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
///
/// vm.jit_compile();
/// ```
Expand Down Expand Up @@ -625,7 +626,7 @@ impl<'a> EbpfVmMbuff<'a> {
/// }
///
/// // Instantiate a VM.
/// let mut vm = rbpf::EbpfVmMbuff::new(prog);
/// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
///
/// # #[cfg(not(windows))]
/// vm.jit_compile();
Expand Down Expand Up @@ -711,7 +712,7 @@ impl<'a> EbpfVmMbuff<'a> {
/// ];
///
/// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50);
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
///
/// // Provide only a reference to the packet data. We do not manage the metadata buffer.
/// let res = vm.prog_exec(mem1);
Expand Down Expand Up @@ -748,21 +749,21 @@ impl<'a> EbpfVmFixedMbuff<'a> {
/// ];
///
/// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50);
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
/// ```
pub fn new(prog: &'a [u8], data_offset: usize, data_end_offset: usize) -> EbpfVmFixedMbuff<'a> {
let parent = EbpfVmMbuff::new(prog);
pub fn new(prog: &'a [u8], data_offset: usize, data_end_offset: usize) -> Result<EbpfVmFixedMbuff<'a>, String> {
let parent = EbpfVmMbuff::new(prog)?;
let get_buff_len = | x: usize, y: usize | if x >= y { x + 8 } else { y + 8 };
let buffer = vec![0u8; get_buff_len(data_offset, data_end_offset)];
let mbuff = MetaBuff {
data_offset: data_offset,
data_end_offset: data_end_offset,
buffer: buffer,
};
EbpfVmFixedMbuff {
Ok(EbpfVmFixedMbuff {
parent: parent,
mbuff: mbuff,
}
})
}

/// Load a new eBPF program into the virtual machine instance.
Expand Down Expand Up @@ -795,19 +796,20 @@ impl<'a> EbpfVmFixedMbuff<'a> {
/// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27,
/// ];
///
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog1, 0, 0);
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog1, 0, 0).unwrap();
/// vm.set_prog(prog2, 0x40, 0x50);
///
/// let res = vm.prog_exec(mem);
/// assert_eq!(res, 0x27);
/// ```
pub fn set_prog(&mut self, prog: &'a [u8], data_offset: usize, data_end_offset: usize) {
pub fn set_prog(&mut self, prog: &'a [u8], data_offset: usize, data_end_offset: usize) -> Result<(), String> {
let get_buff_len = | x: usize, y: usize | if x >= y { x + 8 } else { y + 8 };
let buffer = vec![0u8; get_buff_len(data_offset, data_end_offset)];
self.mbuff.buffer = buffer;
self.mbuff.data_offset = data_offset;
self.mbuff.data_end_offset = data_end_offset;
self.parent.set_prog(prog)
self.parent.set_prog(prog)?;
Ok(())
}

/// Register a built-in or user-defined helper function in order to use it later from within
Expand Down Expand Up @@ -844,7 +846,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
/// ];
///
/// // Instantiate a VM.
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50);
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
///
/// // Register a helper. This helper will store the result of the square root of r1 into r0.
/// vm.register_helper(1, helpers::sqrti);
Expand Down Expand Up @@ -886,7 +888,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
/// ];
///
/// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50);
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
///
/// // Provide only a reference to the packet data. We do not manage the metadata buffer.
/// let res = vm.prog_exec(mem);
Expand Down Expand Up @@ -928,7 +930,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
/// ];
///
/// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50);
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
///
/// vm.jit_compile();
/// ```
Expand Down Expand Up @@ -975,7 +977,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
/// ];
///
/// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50);
/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
///
/// # #[cfg(not(windows))]
/// vm.jit_compile();
Expand Down Expand Up @@ -1020,7 +1022,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
/// ];
///
/// // Instantiate a VM.
/// let vm = rbpf::EbpfVmRaw::new(prog);
/// let vm = rbpf::EbpfVmRaw::new(prog).unwrap();
///
/// // Provide only a reference to the packet data.
/// let res = vm.prog_exec(mem);
Expand Down Expand Up @@ -1050,13 +1052,13 @@ impl<'a> EbpfVmRaw<'a> {
/// ];
///
/// // Instantiate a VM.
/// let vm = rbpf::EbpfVmRaw::new(prog);
/// let vm = rbpf::EbpfVmRaw::new(prog).unwrap();
/// ```
pub fn new(prog: &'a [u8]) -> EbpfVmRaw<'a> {
let parent = EbpfVmMbuff::new(prog);
EbpfVmRaw {
pub fn new(prog: &'a [u8]) -> Result<EbpfVmRaw<'a>, String> {
let parent = EbpfVmMbuff::new(prog)?;
Ok(EbpfVmRaw {
parent: parent,
}
})
}

/// Load a new eBPF program into the virtual machine instance.
Expand All @@ -1083,14 +1085,15 @@ impl<'a> EbpfVmRaw<'a> {
/// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27,
/// ];
///
/// let mut vm = rbpf::EbpfVmRaw::new(prog1);
/// let mut vm = rbpf::EbpfVmRaw::new(prog1).unwrap();
/// vm.set_prog(prog2);
///
/// let res = vm.prog_exec(mem);
/// assert_eq!(res, 0x22cc);
/// ```
pub fn set_prog(&mut self, prog: &'a [u8]) {
self.parent.set_prog(prog)
pub fn set_prog(&mut self, prog: &'a [u8]) -> Result<(), String> {
self.parent.set_prog(prog)?;
Ok(())
}

/// Register a built-in or user-defined helper function in order to use it later from within
Expand Down Expand Up @@ -1120,7 +1123,7 @@ impl<'a> EbpfVmRaw<'a> {
/// ];
///
/// // Instantiate a VM.
/// let mut vm = rbpf::EbpfVmRaw::new(prog);
/// let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
///
/// // Register a helper. This helper will store the result of the square root of r1 into r0.
/// vm.register_helper(1, helpers::sqrti);
Expand Down Expand Up @@ -1154,7 +1157,7 @@ impl<'a> EbpfVmRaw<'a> {
/// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
/// ];
///
/// let mut vm = rbpf::EbpfVmRaw::new(prog);
/// let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
///
/// let res = vm.prog_exec(mem);
/// assert_eq!(res, 0x22cc);
Expand Down Expand Up @@ -1183,7 +1186,7 @@ impl<'a> EbpfVmRaw<'a> {
/// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
/// ];
///
/// let mut vm = rbpf::EbpfVmRaw::new(prog);
/// let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
///
/// vm.jit_compile();
/// ```
Expand Down Expand Up @@ -1222,7 +1225,7 @@ impl<'a> EbpfVmRaw<'a> {
/// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
/// ];
///
/// let mut vm = rbpf::EbpfVmRaw::new(prog);
/// let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
///
/// # #[cfg(not(windows))]
/// vm.jit_compile();
Expand Down Expand Up @@ -1272,7 +1275,7 @@ impl<'a> EbpfVmRaw<'a> {
/// ];
///
/// // Instantiate a VM.
/// let vm = rbpf::EbpfVmNoData::new(prog);
/// let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
///
/// // Provide only a reference to the packet data.
/// let res = vm.prog_exec();
Expand Down Expand Up @@ -1301,13 +1304,13 @@ impl<'a> EbpfVmNoData<'a> {
/// ];
///
/// // Instantiate a VM.
/// let vm = rbpf::EbpfVmNoData::new(prog);
/// let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
/// ```
pub fn new(prog: &'a [u8]) -> EbpfVmNoData<'a> {
let parent = EbpfVmRaw::new(prog);
EbpfVmNoData {
pub fn new(prog: &'a [u8]) -> Result<EbpfVmNoData<'a>, String> {
let parent = EbpfVmRaw::new(prog)?;
Ok(EbpfVmNoData {
parent: parent,
}
})
}

/// Load a new eBPF program into the virtual machine instance.
Expand All @@ -1329,7 +1332,7 @@ impl<'a> EbpfVmNoData<'a> {
/// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
/// ];
///
/// let mut vm = rbpf::EbpfVmNoData::new(prog1);
/// let mut vm = rbpf::EbpfVmNoData::new(prog1).unwrap();
///
/// let res = vm.prog_exec();
/// assert_eq!(res, 0x2211);
Expand All @@ -1339,8 +1342,9 @@ impl<'a> EbpfVmNoData<'a> {
/// let res = vm.prog_exec();
/// assert_eq!(res, 0x1122);
/// ```
pub fn set_prog(&mut self, prog: &'a [u8]) {
self.parent.set_prog(prog)
pub fn set_prog(&mut self, prog: &'a [u8]) -> Result<(), String> {
self.parent.set_prog(prog)?;
Ok(())
}

/// Register a built-in or user-defined helper function in order to use it later from within
Expand All @@ -1365,7 +1369,7 @@ impl<'a> EbpfVmNoData<'a> {
/// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
/// ];
///
/// let mut vm = rbpf::EbpfVmNoData::new(prog);
/// let mut vm = rbpf::EbpfVmNoData::new(prog).unwrap();
///
/// // Register a helper. This helper will store the result of the square root of r1 into r0.
/// vm.register_helper(1, helpers::sqrti);
Expand Down Expand Up @@ -1396,7 +1400,7 @@ impl<'a> EbpfVmNoData<'a> {
/// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
/// ];
///
/// let mut vm = rbpf::EbpfVmNoData::new(prog);
/// let mut vm = rbpf::EbpfVmNoData::new(prog).unwrap();
///
///
/// vm.jit_compile();
Expand All @@ -1423,7 +1427,7 @@ impl<'a> EbpfVmNoData<'a> {
/// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
/// ];
///
/// let vm = rbpf::EbpfVmNoData::new(prog);
/// let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
///
/// // For this kind of VM, the `prog_exec()` function needs no argument.
/// let res = vm.prog_exec();
Expand Down Expand Up @@ -1458,7 +1462,7 @@ impl<'a> EbpfVmNoData<'a> {
/// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
/// ];
///
/// let mut vm = rbpf::EbpfVmNoData::new(prog);
/// let mut vm = rbpf::EbpfVmNoData::new(prog).unwrap();
///
/// # #[cfg(not(windows))]
/// vm.jit_compile();
Expand Down