lib.rs 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
  1. // Derived from uBPF <https://github.com/iovisor/ubpf>
  2. // Copyright 2015 Big Switch Networks, Inc
  3. // (uBPF: VM architecture, parts of the interpreter, originally in C)
  4. // Copyright 2016 Quentin Monnet <quentin.monnet@6wind.com>
  5. // (Translation to Rust, MetaBuff/multiple classes addition, hashmaps for helpers)
  6. //
  7. // Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
  8. // the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
  9. // copied, modified, or distributed except according to those terms.
  10. //! Virtual machine and JIT compiler for eBPF programs.
  11. #![doc(html_logo_url = "https://raw.githubusercontent.com/qmonnet/rbpf/master/misc/rbpf.png",
  12. html_favicon_url = "https://raw.githubusercontent.com/qmonnet/rbpf/master/misc/rbpf.ico")]
  13. #![warn(missing_docs)]
  14. use std::u32;
  15. use std::collections::HashMap;
  16. extern crate libc;
  17. pub mod ebpf;
  18. pub mod helpers;
  19. mod verifier;
  20. mod jit;
  21. pub mod disassembler;
  22. // A metadata buffer with two offset indications. It can be used in one kind of eBPF VM to simulate
  23. // the use of a metadata buffer each time the program is executed, without the user having to
  24. // actually handle it. The offsets are used to tell the VM where in the buffer the pointers to
  25. // packet data start and end should be stored each time the program is run on a new packet.
  26. struct MetaBuff {
  27. data_offset: usize,
  28. data_end_offset: usize,
  29. buffer: Vec<u8>,
  30. }
  31. /// A virtual machine to run eBPF program. This kind of VM is used for programs expecting to work
  32. /// on a metadata buffer containing pointers to packet data.
  33. ///
  34. /// # Examples
  35. ///
  36. /// ```
  37. /// let prog = vec![
  38. /// 0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff at offset 8 into R1.
  39. /// 0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
  40. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  41. /// ];
  42. /// let mut mem = vec![
  43. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
  44. /// ];
  45. ///
  46. /// // Just for the example we create our metadata buffer from scratch, and we store the pointers
  47. /// // to packet data start and end in it.
  48. /// let mut mbuff = vec![0u8; 32];
  49. /// unsafe {
  50. /// let mut data = mbuff.as_ptr().offset(8) as *mut u64;
  51. /// let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
  52. /// *data = mem.as_ptr() as u64;
  53. /// *data_end = mem.as_ptr() as u64 + mem.len() as u64;
  54. /// }
  55. ///
  56. /// // Instantiate a VM.
  57. /// let mut vm = rbpf::EbpfVmMbuff::new(&prog);
  58. ///
  59. /// // Provide both a reference to the packet data, and to the metadata buffer.
  60. /// let res = vm.prog_exec(&mut mem, &mut mbuff);
  61. /// assert_eq!(res, 0x2211);
  62. /// ```
  63. pub struct EbpfVmMbuff<'a> {
  64. prog: &'a [u8],
  65. jit: (unsafe fn (*mut u8, usize, *mut u8, usize, usize, usize) -> u64),
  66. helpers: HashMap<u32, fn (u64, u64, u64, u64, u64) -> u64>,
  67. }
  68. impl<'a> EbpfVmMbuff<'a> {
  69. /// Create a new virtual machine instance, and load an eBPF program into that instance.
  70. /// When attempting to load the program, it passes through a simple verifier.
  71. ///
  72. /// # Panics
  73. ///
  74. /// The simple verifier may panic if it finds errors in the eBPF program at load time.
  75. ///
  76. /// # Examples
  77. ///
  78. /// ```
  79. /// let prog = vec![
  80. /// 0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into R1.
  81. /// 0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
  82. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  83. /// ];
  84. ///
  85. /// // Instantiate a VM.
  86. /// let mut vm = rbpf::EbpfVmMbuff::new(&prog);
  87. /// ```
  88. pub fn new(prog: &'a [u8]) -> EbpfVmMbuff<'a> {
  89. verifier::check(prog);
  90. #[allow(unused_variables)]
  91. fn no_jit(foo: *mut u8, foo_len: usize, bar: *mut u8, bar_len: usize,
  92. nodata_offset: usize, nodata_end_offset: usize) -> u64 {
  93. panic!("Error: program has not been JIT-compiled");
  94. }
  95. EbpfVmMbuff {
  96. prog: prog,
  97. jit: no_jit,
  98. helpers: HashMap::new(),
  99. }
  100. }
  101. /// Load a new eBPF program into the virtual machine instance.
  102. ///
  103. /// # Panics
  104. ///
  105. /// The simple verifier may panic if it finds errors in the eBPF program at load time.
  106. ///
  107. /// # Examples
  108. ///
  109. /// ```
  110. /// let prog1 = vec![
  111. /// 0xb7, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  112. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  113. /// ];
  114. /// let prog2 = vec![
  115. /// 0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into R1.
  116. /// 0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
  117. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  118. /// ];
  119. ///
  120. /// // Instantiate a VM.
  121. /// let mut vm = rbpf::EbpfVmMbuff::new(&prog1);
  122. /// vm.set_prog(&prog2);
  123. /// ```
  124. pub fn set_prog(&mut self, prog: &'a [u8]) {
  125. verifier::check(prog);
  126. self.prog = prog;
  127. }
  128. /// Register a built-in or user-defined helper function in order to use it later from within
  129. /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
  130. ///
  131. /// If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the
  132. /// program. You should be able to change registered helpers after compiling, but not to add
  133. /// new ones (i.e. with new keys).
  134. ///
  135. /// # Examples
  136. ///
  137. /// ```
  138. /// use rbpf::helpers;
  139. ///
  140. /// // This program was compiled with clang, from a C program containing the following single
  141. /// // instruction: `return bpf_trace_printk("foo %c %c %c\n", 10, 1, 2, 3);`
  142. /// let prog = vec![
  143. /// 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load 0 as u64 into r1 (That would be
  144. /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // replaced by tc by the address of
  145. /// // the format string, in the .map
  146. /// // section of the ELF file).
  147. /// 0xb7, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, // mov r2, 10
  148. /// 0xb7, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // mov r3, 1
  149. /// 0xb7, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // mov r4, 2
  150. /// 0xb7, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // mov r5, 3
  151. /// 0x85, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, // call helper with key 6
  152. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  153. /// ];
  154. ///
  155. /// // Instantiate a VM.
  156. /// let mut vm = rbpf::EbpfVmMbuff::new(&prog);
  157. ///
  158. /// // Register a helper.
  159. /// // On running the program this helper will print the content of registers r3, r4 and r5 to
  160. /// // standard output.
  161. /// vm.register_helper(6, helpers::bpf_trace_printf);
  162. /// ```
  163. pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) {
  164. self.helpers.insert(key, function);
  165. }
  166. /// Execute the program loaded, with the given packet data and metadata buffer.
  167. ///
  168. /// If the program is made to be compatible with Linux kernel, it is expected to load the
  169. /// address of the beginning and of the end of the memory area used for packet data from the
  170. /// metadata buffer, at some appointed offsets. It is up to the user to ensure that these
  171. /// pointers are correctly stored in the buffer.
  172. ///
  173. /// # Panics
  174. ///
  175. /// This function is currently expected to panic if it encounters any error during the program
  176. /// execution, such as out of bounds accesses or division by zero attempts. This may be changed
  177. /// in the future (we could raise errors instead).
  178. ///
  179. /// # Examples
  180. ///
  181. /// ```
  182. /// let prog = vec![
  183. /// 0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into R1.
  184. /// 0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
  185. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  186. /// ];
  187. /// let mut mem = vec![
  188. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
  189. /// ];
  190. ///
  191. /// // Just for the example we create our metadata buffer from scratch, and we store the
  192. /// // pointers to packet data start and end in it.
  193. /// let mut mbuff = vec![0u8; 32];
  194. /// unsafe {
  195. /// let mut data = mbuff.as_ptr().offset(8) as *mut u64;
  196. /// let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
  197. /// *data = mem.as_ptr() as u64;
  198. /// *data_end = mem.as_ptr() as u64 + mem.len() as u64;
  199. /// }
  200. ///
  201. /// // Instantiate a VM.
  202. /// let mut vm = rbpf::EbpfVmMbuff::new(&prog);
  203. ///
  204. /// // Provide both a reference to the packet data, and to the metadata buffer.
  205. /// let res = vm.prog_exec(&mut mem, &mut mbuff);
  206. /// assert_eq!(res, 0x2211);
  207. /// ```
  208. pub fn prog_exec(&self, mem: &[u8], mbuff: &[u8]) -> u64 {
  209. const U32MAX: u64 = u32::MAX as u64;
  210. let stack = vec![0u8;ebpf::STACK_SIZE];
  211. // R1 points to beginning of memory area, R10 to stack
  212. let mut reg: [u64;11] = [
  213. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, stack.as_ptr() as u64 + stack.len() as u64
  214. ];
  215. if mbuff.len() > 0 {
  216. reg[1] = mbuff.as_ptr() as u64;
  217. }
  218. else if mem.len() > 0 {
  219. reg[1] = mem.as_ptr() as u64;
  220. }
  221. let check_mem_load = | addr: u64, len: usize, insn_ptr: usize | {
  222. EbpfVmMbuff::check_mem(addr, len, "load", insn_ptr, &mbuff, &mem, &stack);
  223. };
  224. let check_mem_store = | addr: u64, len: usize, insn_ptr: usize | {
  225. EbpfVmMbuff::check_mem(addr, len, "store", insn_ptr, &mbuff, &mem, &stack);
  226. };
  227. // Loop on instructions
  228. let mut insn_ptr:usize = 0;
  229. while insn_ptr * ebpf::INSN_SIZE < self.prog.len() {
  230. let insn = ebpf::get_insn(self.prog, insn_ptr);
  231. insn_ptr += 1;
  232. let _dst = insn.dst as usize;
  233. let _src = insn.src as usize;
  234. match insn.opc {
  235. // BPF_LD class
  236. ebpf::LD_ABS_B => unimplemented!(),
  237. ebpf::LD_ABS_H => unimplemented!(),
  238. ebpf::LD_ABS_W => unimplemented!(),
  239. ebpf::LD_ABS_DW => unimplemented!(),
  240. ebpf::LD_IND_B => unimplemented!(),
  241. ebpf::LD_IND_H => unimplemented!(),
  242. ebpf::LD_IND_W => unimplemented!(),
  243. ebpf::LD_IND_DW => unimplemented!(),
  244. // BPF_LDX class
  245. ebpf::LD_DW_IMM => {
  246. let next_insn = ebpf::get_insn(self.prog, insn_ptr);
  247. insn_ptr += 1;
  248. reg[_dst] = ((insn.imm as u32) as u64) + ((next_insn.imm as u64) << 32);
  249. },
  250. ebpf::LD_B_REG => reg[_dst] = unsafe {
  251. let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u8;
  252. check_mem_load(x as u64, 1, insn_ptr);
  253. *x as u64
  254. },
  255. ebpf::LD_H_REG => reg[_dst] = unsafe {
  256. let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u16;
  257. check_mem_load(x as u64, 2, insn_ptr);
  258. *x as u64
  259. },
  260. ebpf::LD_W_REG => reg[_dst] = unsafe {
  261. let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u32;
  262. check_mem_load(x as u64, 4, insn_ptr);
  263. *x as u64
  264. },
  265. ebpf::LD_DW_REG => reg[_dst] = unsafe {
  266. let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u64;
  267. check_mem_load(x as u64, 8, insn_ptr);
  268. *x as u64
  269. },
  270. // BPF_ST class
  271. ebpf::ST_B_IMM => unsafe {
  272. let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u8;
  273. check_mem_store(x as u64, 1, insn_ptr);
  274. *x = insn.imm as u8;
  275. },
  276. ebpf::ST_H_IMM => unsafe {
  277. let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u16;
  278. check_mem_store(x as u64, 2, insn_ptr);
  279. *x = insn.imm as u16;
  280. },
  281. ebpf::ST_W_IMM => unsafe {
  282. let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u32;
  283. check_mem_store(x as u64, 4, insn_ptr);
  284. *x = insn.imm as u32;
  285. },
  286. ebpf::ST_DW_IMM => unsafe {
  287. let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u64;
  288. check_mem_store(x as u64, 8, insn_ptr);
  289. *x = insn.imm as u64;
  290. },
  291. // BPF_STX class
  292. ebpf::ST_B_REG => unsafe {
  293. let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u8;
  294. check_mem_store(x as u64, 1, insn_ptr);
  295. *x = reg[_src] as u8;
  296. },
  297. ebpf::ST_H_REG => unsafe {
  298. let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u16;
  299. check_mem_store(x as u64, 2, insn_ptr);
  300. *x = reg[_src] as u16;
  301. },
  302. ebpf::ST_W_REG => unsafe {
  303. let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u32;
  304. check_mem_store(x as u64, 4, insn_ptr);
  305. *x = reg[_src] as u32;
  306. },
  307. ebpf::ST_DW_REG => unsafe {
  308. let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u64;
  309. check_mem_store(x as u64, 8, insn_ptr);
  310. *x = reg[_src] as u64;
  311. },
  312. ebpf::ST_W_XADD => unimplemented!(),
  313. ebpf::ST_DW_XADD => unimplemented!(),
  314. // BPF_ALU class
  315. // TODO Check how overflow works in kernel. Should we &= U32MAX all src register value
  316. // before we do the operation?
  317. // Cf ((0x11 << 32) - (0x1 << 32)) as u32 VS ((0x11 << 32) as u32 - (0x1 << 32) as u32
  318. ebpf::ADD32_IMM => reg[_dst] = (reg[_dst] as i32).wrapping_add(insn.imm) as u64, //((reg[_dst] & U32MAX) + insn.imm as u64) & U32MAX,
  319. ebpf::ADD32_REG => reg[_dst] = (reg[_dst] as i32).wrapping_add(reg[_src] as i32) as u64, //((reg[_dst] & U32MAX) + (reg[_src] & U32MAX)) & U32MAX,
  320. ebpf::SUB32_IMM => reg[_dst] = (reg[_dst] as i32).wrapping_sub(insn.imm) as u64,
  321. ebpf::SUB32_REG => reg[_dst] = (reg[_dst] as i32).wrapping_sub(reg[_src] as i32) as u64,
  322. ebpf::MUL32_IMM => reg[_dst] = (reg[_dst] as i32).wrapping_mul(insn.imm) as u64,
  323. ebpf::MUL32_REG => reg[_dst] = (reg[_dst] as i32).wrapping_mul(reg[_src] as i32) as u64,
  324. ebpf::DIV32_IMM => reg[_dst] = (reg[_dst] as u32 / insn.imm as u32) as u64,
  325. ebpf::DIV32_REG => {
  326. if reg[_src] == 0 {
  327. panic!("Error: division by 0");
  328. }
  329. reg[_dst] = (reg[_dst] as u32 / reg[_src] as u32) as u64;
  330. },
  331. ebpf::OR32_IMM => reg[_dst] = (reg[_dst] as u32 | insn.imm as u32) as u64,
  332. ebpf::OR32_REG => reg[_dst] = (reg[_dst] as u32 | reg[_src] as u32) as u64,
  333. ebpf::AND32_IMM => reg[_dst] = (reg[_dst] as u32 & insn.imm as u32) as u64,
  334. ebpf::AND32_REG => reg[_dst] = (reg[_dst] as u32 & reg[_src] as u32) as u64,
  335. ebpf::LSH32_IMM => reg[_dst] = (reg[_dst] as u32).wrapping_shl(insn.imm as u32) as u64,
  336. ebpf::LSH32_REG => reg[_dst] = (reg[_dst] as u32).wrapping_shl(reg[_src] as u32) as u64,
  337. ebpf::RSH32_IMM => reg[_dst] = (reg[_dst] as u32).wrapping_shr(insn.imm as u32) as u64,
  338. ebpf::RSH32_REG => reg[_dst] = (reg[_dst] as u32).wrapping_shr(reg[_src] as u32) as u64,
  339. ebpf::NEG32 => { reg[_dst] = (reg[_dst] as i32).wrapping_neg() as u64; reg[_dst] &= U32MAX; },
  340. ebpf::MOD32_IMM => reg[_dst] = (reg[_dst] as u32 % insn.imm as u32) as u64,
  341. ebpf::MOD32_REG => {
  342. if reg[_src] == 0 {
  343. panic!("Error: division by 0");
  344. }
  345. reg[_dst] = (reg[_dst] as u32 % reg[_src] as u32) as u64;
  346. },
  347. ebpf::XOR32_IMM => reg[_dst] = (reg[_dst] as u32 ^ insn.imm as u32) as u64,
  348. ebpf::XOR32_REG => reg[_dst] = (reg[_dst] as u32 ^ reg[_src] as u32) as u64,
  349. ebpf::MOV32_IMM => reg[_dst] = insn.imm as u64,
  350. ebpf::MOV32_REG => reg[_dst] = (reg[_src] as u32) as u64,
  351. ebpf::ARSH32_IMM => { reg[_dst] = (reg[_dst] as i32).wrapping_shr(insn.imm as u32) as u64; reg[_dst] &= U32MAX; },
  352. ebpf::ARSH32_REG => { reg[_dst] = (reg[_dst] as i32).wrapping_shr(reg[_src] as u32) as u64; reg[_dst] &= U32MAX; },
  353. ebpf::LE => {
  354. reg[_dst] = match insn.imm {
  355. 16 => (reg[_dst] as u16).to_le() as u64,
  356. 32 => (reg[_dst] as u32).to_le() as u64,
  357. 64 => reg[_dst].to_le(),
  358. _ => unreachable!(),
  359. };
  360. },
  361. ebpf::BE => {
  362. reg[_dst] = match insn.imm {
  363. 16 => (reg[_dst] as u16).to_be() as u64,
  364. 32 => (reg[_dst] as u32).to_be() as u64,
  365. 64 => reg[_dst].to_be(),
  366. _ => unreachable!(),
  367. };
  368. },
  369. // BPF_ALU64 class
  370. ebpf::ADD64_IMM => reg[_dst] = reg[_dst].wrapping_add(insn.imm as u64),
  371. ebpf::ADD64_REG => reg[_dst] = reg[_dst].wrapping_add(reg[_src]),
  372. ebpf::SUB64_IMM => reg[_dst] = reg[_dst].wrapping_sub(insn.imm as u64),
  373. ebpf::SUB64_REG => reg[_dst] = reg[_dst].wrapping_sub(reg[_src]),
  374. ebpf::MUL64_IMM => reg[_dst] = reg[_dst].wrapping_mul(insn.imm as u64),
  375. ebpf::MUL64_REG => reg[_dst] = reg[_dst].wrapping_mul(reg[_src]),
  376. ebpf::DIV64_IMM => reg[_dst] /= insn.imm as u64,
  377. ebpf::DIV64_REG => {
  378. if reg[_src] == 0 {
  379. panic!("Error: division by 0");
  380. }
  381. reg[_dst] /= reg[_src];
  382. },
  383. ebpf::OR64_IMM => reg[_dst] |= insn.imm as u64,
  384. ebpf::OR64_REG => reg[_dst] |= reg[_src],
  385. ebpf::AND64_IMM => reg[_dst] &= insn.imm as u64,
  386. ebpf::AND64_REG => reg[_dst] &= reg[_src],
  387. ebpf::LSH64_IMM => reg[_dst] <<= insn.imm as u64,
  388. ebpf::LSH64_REG => reg[_dst] <<= reg[_src],
  389. ebpf::RSH64_IMM => reg[_dst] >>= insn.imm as u64,
  390. ebpf::RSH64_REG => reg[_dst] >>= reg[_src],
  391. ebpf::NEG64 => reg[_dst] = -(reg[_dst] as i64) as u64,
  392. ebpf::MOD64_IMM => reg[_dst] %= insn.imm as u64,
  393. ebpf::MOD64_REG => {
  394. if reg[_src] == 0 {
  395. panic!("Error: division by 0");
  396. }
  397. reg[_dst] %= reg[_src];
  398. },
  399. ebpf::XOR64_IMM => reg[_dst] ^= insn.imm as u64,
  400. ebpf::XOR64_REG => reg[_dst] ^= reg[_src],
  401. ebpf::MOV64_IMM => reg[_dst] = insn.imm as u64,
  402. ebpf::MOV64_REG => reg[_dst] = reg[_src],
  403. ebpf::ARSH64_IMM => reg[_dst] = (reg[_dst] as i64 >> insn.imm) as u64,
  404. ebpf::ARSH64_REG => reg[_dst] = (reg[_dst] as i64 >> reg[_src]) as u64,
  405. // BPF_JMP class
  406. // TODO: check this actually works as expected for signed / unsigned ops
  407. ebpf::JA => insn_ptr = (insn_ptr as i16 + insn.off) as usize,
  408. ebpf::JEQ_IMM => if reg[_dst] == insn.imm as u64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  409. ebpf::JEQ_REG => if reg[_dst] == reg[_src] { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  410. ebpf::JGT_IMM => if reg[_dst] > insn.imm as u64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  411. ebpf::JGT_REG => if reg[_dst] > reg[_src] { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  412. ebpf::JGE_IMM => if reg[_dst] >= insn.imm as u64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  413. ebpf::JGE_REG => if reg[_dst] >= reg[_src] { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  414. ebpf::JSET_IMM => if reg[_dst] & insn.imm as u64 != 0 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  415. ebpf::JSET_REG => if reg[_dst] & reg[_src] != 0 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  416. ebpf::JNE_IMM => if reg[_dst] != insn.imm as u64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  417. ebpf::JNE_REG => if reg[_dst] != reg[_src] { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  418. ebpf::JSGT_IMM => if reg[_dst] as i64 > insn.imm as i64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  419. ebpf::JSGT_REG => if reg[_dst] as i64 > reg[_src] as i64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  420. ebpf::JSGE_IMM => if reg[_dst] as i64 >= insn.imm as i64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  421. ebpf::JSGE_REG => if reg[_dst] as i64 >= reg[_src] as i64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
  422. // Do not delegate the check to the verifier, since registered functions can be
  423. // changed after the program has been verified.
  424. ebpf::CALL => if let Some(function) = self.helpers.get(&(insn.imm as u32)) {
  425. reg[0] = function(reg[1], reg[2], reg[3], reg[4], reg[5]);
  426. } else {
  427. panic!("Error: unknown helper function (id: {:#x})", insn.imm as u32);
  428. },
  429. ebpf::TAIL_CALL => unimplemented!(),
  430. ebpf::EXIT => return reg[0],
  431. _ => unreachable!()
  432. }
  433. }
  434. return 0;
  435. }
  436. fn check_mem(addr: u64, len: usize, access_type: &str, insn_ptr: usize,
  437. mbuff: &[u8], mem: &[u8], stack: &[u8]) {
  438. if mbuff.as_ptr() as u64 <= addr && addr + len as u64 <= mbuff.as_ptr() as u64 + mbuff.len() as u64 {
  439. return
  440. }
  441. if mem.as_ptr() as u64 <= addr && addr + len as u64 <= mem.as_ptr() as u64 + mem.len() as u64 {
  442. return
  443. }
  444. if stack.as_ptr() as u64 <= addr && addr + len as u64 <= stack.as_ptr() as u64 + stack.len() as u64 {
  445. return
  446. }
  447. panic!(
  448. "Error: out of bounds memory {} (insn #{:?}), addr {:#x}, size {:?}\nmbuff: {:#x}/{:#x}, mem: {:#x}/{:#x}, stack: {:#x}/{:#x}",
  449. access_type, insn_ptr, addr, len,
  450. mbuff.as_ptr() as u64, mbuff.len(),
  451. mem.as_ptr() as u64, mem.len(),
  452. stack.as_ptr() as u64, stack.len()
  453. );
  454. }
  455. /// JIT-compile the loaded program. No argument required for this.
  456. ///
  457. /// If using helper functions, be sure to register them into the VM before calling this
  458. /// function.
  459. ///
  460. /// # Panics
  461. ///
  462. /// This function panics if an error occurs during JIT-compiling, such as the occurrence of an
  463. /// unknown eBPF operation code.
  464. ///
  465. /// # Examples
  466. ///
  467. /// ```
  468. /// let prog = vec![
  469. /// 0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into R1.
  470. /// 0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
  471. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  472. /// ];
  473. ///
  474. /// // Instantiate a VM.
  475. /// let mut vm = rbpf::EbpfVmMbuff::new(&prog);
  476. ///
  477. /// vm.jit_compile();
  478. /// ```
  479. pub fn jit_compile(&mut self) {
  480. self.jit = jit::compile(&self.prog, &self.helpers, true, false);
  481. }
  482. /// Execute the previously JIT-compiled program, with the given packet data and metadata
  483. /// buffer, in a manner very similar to `prog_exec()`.
  484. ///
  485. /// If the program is made to be compatible with Linux kernel, it is expected to load the
  486. /// address of the beginning and of the end of the memory area used for packet data from the
  487. /// metadata buffer, at some appointed offsets. It is up to the user to ensure that these
  488. /// pointers are correctly stored in the buffer.
  489. ///
  490. /// # Panics
  491. ///
  492. /// This function panics if an error occurs during the execution of the program.
  493. ///
  494. /// # Safety
  495. ///
  496. /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
  497. /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
  498. /// very bad (program may segfault). It may be wise to check that the program works with the
  499. /// interpreter before running the JIT-compiled version of it.
  500. ///
  501. /// For this reason the function should be called from within an `unsafe` bloc.
  502. ///
  503. /// # Examples
  504. ///
  505. /// ```
  506. /// let prog = vec![
  507. /// 0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into r1.
  508. /// 0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
  509. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  510. /// ];
  511. /// let mut mem = vec![
  512. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
  513. /// ];
  514. ///
  515. /// // Just for the example we create our metadata buffer from scratch, and we store the
  516. /// // pointers to packet data start and end in it.
  517. /// let mut mbuff = vec![0u8; 32];
  518. /// unsafe {
  519. /// let mut data = mbuff.as_ptr().offset(8) as *mut u64;
  520. /// let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
  521. /// *data = mem.as_ptr() as u64;
  522. /// *data_end = mem.as_ptr() as u64 + mem.len() as u64;
  523. /// }
  524. ///
  525. /// // Instantiate a VM.
  526. /// let mut vm = rbpf::EbpfVmMbuff::new(&prog);
  527. ///
  528. /// vm.jit_compile();
  529. ///
  530. /// // Provide both a reference to the packet data, and to the metadata buffer.
  531. /// unsafe {
  532. /// let res = vm.prog_exec_jit(&mut mem, &mut mbuff);
  533. /// assert_eq!(res, 0x2211);
  534. /// }
  535. /// ```
  536. pub unsafe fn prog_exec_jit(&self, mem: &mut [u8], mbuff: &'a mut [u8]) -> u64 {
  537. // If packet data is empty, do not send the address of an empty vector; send a null
  538. // pointer (zero value) as first argument instead, as this is uBPF's behavior (empty
  539. // packet should not happen in the kernel; anyway the verifier would prevent the use of
  540. // uninitialized registers). See `mul_loop` test.
  541. let mem_ptr = match mem.len() {
  542. 0 => 0 as *mut u8,
  543. _ => mem.as_ptr() as *mut u8
  544. };
  545. // The last two arguments are not used in this function. They would be used if there was a
  546. // need to indicate to the JIT at which offset in the mbuff mem_ptr and mem_ptr + mem.len()
  547. // should be stored; this is what happens with struct EbpfVmFixedMbuff.
  548. (self.jit)(mbuff.as_ptr() as *mut u8, mbuff.len(), mem_ptr, mem.len(), 0, 0)
  549. }
  550. }
  551. /// A virtual machine to run eBPF program. This kind of VM is used for programs expecting to work
  552. /// on a metadata buffer containing pointers to packet data, but it internally handles the buffer
  553. /// so as to save the effort to manually handle the metadata buffer for the user.
  554. ///
  555. /// This struct implements a static internal buffer that is passed to the program. The user has to
  556. /// indicate the offset values at which the eBPF program expects to find the start and the end of
  557. /// packet data in the buffer. On calling the `prog_exec()` or `prog_exec_jit()` functions, the
  558. /// struct automatically updates the addresses in this static buffer, at the appointed offsets, for
  559. /// the start and the end of the packet data the program is called upon.
  560. ///
  561. /// # Examples
  562. ///
  563. /// This was compiled with clang from the following program, in C:
  564. ///
  565. /// ```c
  566. /// #include <linux/bpf.h>
  567. /// #include "path/to/linux/samples/bpf/bpf_helpers.h"
  568. ///
  569. /// SEC(".classifier")
  570. /// int classifier(struct __sk_buff *skb)
  571. /// {
  572. /// void *data = (void *)(long)skb->data;
  573. /// void *data_end = (void *)(long)skb->data_end;
  574. ///
  575. /// // Check program is long enough.
  576. /// if (data + 5 > data_end)
  577. /// return 0;
  578. ///
  579. /// return *((char *)data + 5);
  580. /// }
  581. /// ```
  582. ///
  583. /// Some small modifications have been brought to have it work, see comments.
  584. ///
  585. /// ```
  586. /// let prog = vec![
  587. /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  588. /// // Here opcode 0x61 had to be replace by 0x79 so as to load a 8-bytes long address.
  589. /// // Also, offset 0x4c had to be replace with e.g. 0x40 so as to prevent the two pointers
  590. /// // from overlapping in the buffer.
  591. /// 0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load pointer to mem from r1[0x40] to r2
  592. /// 0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
  593. /// // Here opcode 0x61 had to be replace by 0x79 so as to load a 8-bytes long address.
  594. /// 0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load ptr to mem_end from r1[0x50] to r1
  595. /// 0x2d, 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
  596. /// 0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
  597. /// 0x67, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, // r0 >>= 56
  598. /// 0xc7, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, // r0 <<= 56 (arsh) extend byte sign to u64
  599. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  600. /// ];
  601. /// let mut mem1 = vec![
  602. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
  603. /// ];
  604. /// let mut mem2 = vec![
  605. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
  606. /// ];
  607. ///
  608. /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
  609. /// let mut vm = rbpf::EbpfVmFixedMbuff::new(&prog, 0x40, 0x50);
  610. ///
  611. /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
  612. /// let res = vm.prog_exec(&mut mem1);
  613. /// assert_eq!(res, 0xffffffffffffffdd);
  614. ///
  615. /// let res = vm.prog_exec(&mut mem2);
  616. /// assert_eq!(res, 0x27);
  617. /// ```
  618. pub struct EbpfVmFixedMbuff<'a> {
  619. parent: EbpfVmMbuff<'a>,
  620. mbuff: MetaBuff,
  621. }
  622. impl<'a> EbpfVmFixedMbuff<'a> {
  623. /// Create a new virtual machine instance, and load an eBPF program into that instance.
  624. /// When attempting to load the program, it passes through a simple verifier.
  625. ///
  626. /// # Panics
  627. ///
  628. /// The simple verifier may panic if it finds errors in the eBPF program at load time.
  629. ///
  630. /// # Examples
  631. ///
  632. /// ```
  633. /// let prog = vec![
  634. /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  635. /// 0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
  636. /// 0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
  637. /// 0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
  638. /// 0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
  639. /// 0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
  640. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  641. /// ];
  642. ///
  643. /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
  644. /// let mut vm = rbpf::EbpfVmFixedMbuff::new(&prog, 0x40, 0x50);
  645. /// ```
  646. pub fn new(prog: &'a [u8], data_offset: usize, data_end_offset: usize) -> EbpfVmFixedMbuff<'a> {
  647. let parent = EbpfVmMbuff::new(prog);
  648. let get_buff_len = | x: usize, y: usize | if x >= y { x + 8 } else { y + 8 };
  649. let buffer = vec![0u8; get_buff_len(data_offset, data_end_offset)];
  650. let mbuff = MetaBuff {
  651. data_offset: data_offset,
  652. data_end_offset: data_end_offset,
  653. buffer: buffer,
  654. };
  655. EbpfVmFixedMbuff {
  656. parent: parent,
  657. mbuff: mbuff,
  658. }
  659. }
  660. /// Load a new eBPF program into the virtual machine instance.
  661. ///
  662. /// At the same time, load new offsets for storing pointers to start and end of packet data in
  663. /// the internal metadata buffer.
  664. ///
  665. /// # Panics
  666. ///
  667. /// The simple verifier may panic if it finds errors in the eBPF program at load time.
  668. ///
  669. /// # Examples
  670. ///
  671. /// ```
  672. /// let prog1 = vec![
  673. /// 0xb7, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  674. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  675. /// ];
  676. /// let prog2 = vec![
  677. /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  678. /// 0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
  679. /// 0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
  680. /// 0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
  681. /// 0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
  682. /// 0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
  683. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  684. /// ];
  685. ///
  686. /// let mut mem = vec![
  687. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27,
  688. /// ];
  689. ///
  690. /// let mut vm = rbpf::EbpfVmFixedMbuff::new(&prog1, 0, 0);
  691. /// vm.set_prog(&prog2, 0x40, 0x50);
  692. ///
  693. /// let res = vm.prog_exec(&mut mem);
  694. /// assert_eq!(res, 0x27);
  695. /// ```
  696. pub fn set_prog(&mut self, prog: &'a [u8], data_offset: usize, data_end_offset: usize) {
  697. let get_buff_len = | x: usize, y: usize | if x >= y { x + 8 } else { y + 8 };
  698. let buffer = vec![0u8; get_buff_len(data_offset, data_end_offset)];
  699. self.mbuff.buffer = buffer;
  700. self.mbuff.data_offset = data_offset;
  701. self.mbuff.data_end_offset = data_end_offset;
  702. self.parent.set_prog(prog)
  703. }
  704. /// Register a built-in or user-defined helper function in order to use it later from within
  705. /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
  706. ///
  707. /// If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the
  708. /// program. You should be able to change registered helpers after compiling, but not to add
  709. /// new ones (i.e. with new keys).
  710. ///
  711. /// # Examples
  712. ///
  713. /// ```
  714. /// use rbpf::helpers;
  715. ///
  716. /// // This program was compiled with clang, from a C program containing the following single
  717. /// // instruction: `return bpf_trace_printk("foo %c %c %c\n", 10, 1, 2, 3);`
  718. /// let prog = vec![
  719. /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  720. /// 0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
  721. /// 0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
  722. /// 0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
  723. /// 0x2d, 0x12, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 6 instructions
  724. /// 0x71, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r1
  725. /// 0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r2, 0
  726. /// 0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r3, 0
  727. /// 0xb7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r4, 0
  728. /// 0xb7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r5, 0
  729. /// 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // call helper with key 1
  730. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  731. /// ];
  732. ///
  733. /// let mut mem = vec![
  734. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x09,
  735. /// ];
  736. ///
  737. /// // Instantiate a VM.
  738. /// let mut vm = rbpf::EbpfVmFixedMbuff::new(&prog, 0x40, 0x50);
  739. ///
  740. /// // Register a helper. This helper will store the result of the square root of r1 into r0.
  741. /// vm.register_helper(1, helpers::sqrti);
  742. ///
  743. /// let res = vm.prog_exec(&mut mem);
  744. /// assert_eq!(res, 3);
  745. /// ```
  746. pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) {
  747. self.parent.register_helper(key, function);
  748. }
  749. /// Execute the program loaded, with the given packet data.
  750. ///
  751. /// If the program is made to be compatible with Linux kernel, it is expected to load the
  752. /// address of the beginning and of the end of the memory area used for packet data from some
  753. /// metadata buffer, which in the case of this VM is handled internally. The offsets at which
  754. /// the addresses should be placed should have be set at the creation of the VM.
  755. ///
  756. /// # Panics
  757. ///
  758. /// This function is currently expected to panic if it encounters any error during the program
  759. /// execution, such as out of bounds accesses or division by zero attempts. This may be changed
  760. /// in the future (we could raise errors instead).
  761. ///
  762. /// # Examples
  763. ///
  764. /// ```
  765. /// let prog = vec![
  766. /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  767. /// 0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
  768. /// 0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
  769. /// 0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
  770. /// 0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
  771. /// 0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
  772. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  773. /// ];
  774. /// let mut mem = vec![
  775. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
  776. /// ];
  777. ///
  778. /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
  779. /// let mut vm = rbpf::EbpfVmFixedMbuff::new(&prog, 0x40, 0x50);
  780. ///
  781. /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
  782. /// let res = vm.prog_exec(&mut mem);
  783. /// assert_eq!(res, 0xdd);
  784. /// ```
  785. pub fn prog_exec(&mut self, mem: &'a mut [u8]) -> u64 {
  786. let l = self.mbuff.buffer.len();
  787. // Can this ever happen? Probably not, should be ensured at mbuff creation.
  788. if self.mbuff.data_offset + 8 > l || self.mbuff.data_end_offset + 8 > l {
  789. panic!("Error: buffer too small ({:?}), cannot use data_offset {:?} and data_end_offset {:?}",
  790. l, self.mbuff.data_offset, self.mbuff.data_end_offset);
  791. }
  792. unsafe {
  793. let mut data = self.mbuff.buffer.as_ptr().offset(self.mbuff.data_offset as isize) as *mut u64;
  794. let mut data_end = self.mbuff.buffer.as_ptr().offset(self.mbuff.data_end_offset as isize) as *mut u64;
  795. *data = mem.as_ptr() as u64;
  796. *data_end = mem.as_ptr() as u64 + mem.len() as u64;
  797. }
  798. self.parent.prog_exec(mem, &mut self.mbuff.buffer)
  799. }
  800. /// JIT-compile the loaded program. No argument required for this.
  801. ///
  802. /// If using helper functions, be sure to register them into the VM before calling this
  803. /// function.
  804. ///
  805. /// # Panics
  806. ///
  807. /// This function panics if an error occurs during JIT-compiling, such as the occurrence of an
  808. /// unknown eBPF operation code.
  809. ///
  810. /// # Examples
  811. ///
  812. /// ```
  813. /// let prog = vec![
  814. /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  815. /// 0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
  816. /// 0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
  817. /// 0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
  818. /// 0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
  819. /// 0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
  820. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  821. /// ];
  822. ///
  823. /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
  824. /// let mut vm = rbpf::EbpfVmFixedMbuff::new(&prog, 0x40, 0x50);
  825. ///
  826. /// vm.jit_compile();
  827. /// ```
  828. pub fn jit_compile(&mut self) {
  829. self.parent.jit = jit::compile(&self.parent.prog, &self.parent.helpers, true, true);
  830. }
  831. /// Execute the previously JIT-compiled program, with the given packet data, in a manner very
  832. /// similar to `prog_exec()`.
  833. ///
  834. /// If the program is made to be compatible with Linux kernel, it is expected to load the
  835. /// address of the beginning and of the end of the memory area used for packet data from some
  836. /// metadata buffer, which in the case of this VM is handled internally. The offsets at which
  837. /// the addresses should be placed should have be set at the creation of the VM.
  838. ///
  839. /// # Panics
  840. ///
  841. /// This function panics if an error occurs during the execution of the program.
  842. ///
  843. /// # Safety
  844. ///
  845. /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
  846. /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
  847. /// very bad (program may segfault). It may be wise to check that the program works with the
  848. /// interpreter before running the JIT-compiled version of it.
  849. ///
  850. /// For this reason the function should be called from within an `unsafe` bloc.
  851. ///
  852. /// # Examples
  853. ///
  854. /// ```
  855. /// let prog = vec![
  856. /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  857. /// 0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
  858. /// 0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
  859. /// 0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
  860. /// 0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
  861. /// 0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
  862. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  863. /// ];
  864. /// let mut mem = vec![
  865. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
  866. /// ];
  867. ///
  868. /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
  869. /// let mut vm = rbpf::EbpfVmFixedMbuff::new(&prog, 0x40, 0x50);
  870. ///
  871. /// vm.jit_compile();
  872. ///
  873. /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
  874. /// unsafe {
  875. /// let res = vm.prog_exec_jit(&mut mem);
  876. /// assert_eq!(res, 0xdd);
  877. /// }
  878. /// ```
  879. // This struct redefines the `prog_exec_jit()` function, in order to pass the offsets
  880. // associated with the fixed mbuff.
  881. pub unsafe fn prog_exec_jit(&mut self, mem: &'a mut [u8]) -> u64 {
  882. // If packet data is empty, do not send the address of an empty vector; send a null
  883. // pointer (zero value) as first argument instead, as this is uBPF's behavior (empty
  884. // packet should not happen in the kernel; anyway the verifier would prevent the use of
  885. // uninitialized registers). See `mul_loop` test.
  886. let mem_ptr = match mem.len() {
  887. 0 => 0 as *mut u8,
  888. _ => mem.as_ptr() as *mut u8
  889. };
  890. (self.parent.jit)(self.mbuff.buffer.as_ptr() as *mut u8, self.mbuff.buffer.len(),
  891. mem_ptr, mem.len(), self.mbuff.data_offset, self.mbuff.data_end_offset)
  892. }
  893. }
  894. /// A virtual machine to run eBPF program. This kind of VM is used for programs expecting to work
  895. /// directly on the memory area representing packet data.
  896. ///
  897. /// # Examples
  898. ///
  899. /// ```
  900. /// let prog = vec![
  901. /// 0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
  902. /// 0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
  903. /// 0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
  904. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  905. /// ];
  906. /// let mut mem = vec![
  907. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
  908. /// ];
  909. ///
  910. /// // Instantiate a VM.
  911. /// let vm = rbpf::EbpfVmRaw::new(&prog);
  912. ///
  913. /// // Provide only a reference to the packet data.
  914. /// let res = vm.prog_exec(&mut mem);
  915. /// assert_eq!(res, 0x22cc);
  916. /// ```
  917. pub struct EbpfVmRaw<'a> {
  918. parent: EbpfVmMbuff<'a>,
  919. }
  920. impl<'a> EbpfVmRaw<'a> {
  921. /// Create a new virtual machine instance, and load an eBPF program into that instance.
  922. /// When attempting to load the program, it passes through a simple verifier.
  923. ///
  924. /// # Panics
  925. ///
  926. /// The simple verifier may panic if it finds errors in the eBPF program at load time.
  927. ///
  928. /// # Examples
  929. ///
  930. /// ```
  931. /// let prog = vec![
  932. /// 0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
  933. /// 0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
  934. /// 0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
  935. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  936. /// ];
  937. ///
  938. /// // Instantiate a VM.
  939. /// let vm = rbpf::EbpfVmRaw::new(&prog);
  940. /// ```
  941. pub fn new(prog: &'a [u8]) -> EbpfVmRaw<'a> {
  942. let parent = EbpfVmMbuff::new(prog);
  943. EbpfVmRaw {
  944. parent: parent,
  945. }
  946. }
  947. /// Load a new eBPF program into the virtual machine instance.
  948. ///
  949. /// # Panics
  950. ///
  951. /// The simple verifier may panic if it finds errors in the eBPF program at load time.
  952. ///
  953. /// # Examples
  954. ///
  955. /// ```
  956. /// let prog1 = vec![
  957. /// 0xb7, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  958. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  959. /// ];
  960. /// let prog2 = vec![
  961. /// 0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
  962. /// 0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
  963. /// 0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
  964. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  965. /// ];
  966. ///
  967. /// let mut mem = vec![
  968. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27,
  969. /// ];
  970. ///
  971. /// let mut vm = rbpf::EbpfVmRaw::new(&prog1);
  972. /// vm.set_prog(&prog2);
  973. ///
  974. /// let res = vm.prog_exec(&mut mem);
  975. /// assert_eq!(res, 0x22cc);
  976. /// ```
  977. pub fn set_prog(&mut self, prog: &'a [u8]) {
  978. self.parent.set_prog(prog)
  979. }
  980. /// Register a built-in or user-defined helper function in order to use it later from within
  981. /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
  982. ///
  983. /// If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the
  984. /// program. You should be able to change registered helpers after compiling, but not to add
  985. /// new ones (i.e. with new keys).
  986. ///
  987. /// # Examples
  988. ///
  989. /// ```
  990. /// use rbpf::helpers;
  991. ///
  992. /// let prog = vec![
  993. /// 0x79, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxdw r1, r1[0x00]
  994. /// 0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r2, 0
  995. /// 0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r3, 0
  996. /// 0xb7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r4, 0
  997. /// 0xb7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r5, 0
  998. /// 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // call helper with key 1
  999. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1000. /// ];
  1001. ///
  1002. /// let mut mem = vec![
  1003. /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
  1004. /// ];
  1005. ///
  1006. /// // Instantiate a VM.
  1007. /// let mut vm = rbpf::EbpfVmRaw::new(&prog);
  1008. ///
  1009. /// // Register a helper. This helper will store the result of the square root of r1 into r0.
  1010. /// vm.register_helper(1, helpers::sqrti);
  1011. ///
  1012. /// let res = vm.prog_exec(&mut mem);
  1013. /// assert_eq!(res, 0x10000000);
  1014. /// ```
  1015. pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) {
  1016. self.parent.register_helper(key, function);
  1017. }
  1018. /// Execute the program loaded, with the given packet data.
  1019. ///
  1020. /// # Panics
  1021. ///
  1022. /// This function is currently expected to panic if it encounters any error during the program
  1023. /// execution, such as out of bounds accesses or division by zero attempts. This may be changed
  1024. /// in the future (we could raise errors instead).
  1025. ///
  1026. /// # Examples
  1027. ///
  1028. /// ```
  1029. /// let prog = vec![
  1030. /// 0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
  1031. /// 0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
  1032. /// 0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
  1033. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1034. /// ];
  1035. ///
  1036. /// let mut mem = vec![
  1037. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
  1038. /// ];
  1039. ///
  1040. /// let mut vm = rbpf::EbpfVmRaw::new(&prog);
  1041. ///
  1042. /// let res = vm.prog_exec(&mut mem);
  1043. /// assert_eq!(res, 0x22cc);
  1044. /// ```
  1045. pub fn prog_exec(&self, mem: &'a mut [u8]) -> u64 {
  1046. let mut mbuff = vec![];
  1047. self.parent.prog_exec(mem, &mut mbuff)
  1048. }
  1049. /// JIT-compile the loaded program. No argument required for this.
  1050. ///
  1051. /// If using helper functions, be sure to register them into the VM before calling this
  1052. /// function.
  1053. ///
  1054. /// # Panics
  1055. ///
  1056. /// This function panics if an error occurs during JIT-compiling, such as the occurrence of an
  1057. /// unknown eBPF operation code.
  1058. ///
  1059. /// # Examples
  1060. ///
  1061. /// ```
  1062. /// let prog = vec![
  1063. /// 0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
  1064. /// 0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
  1065. /// 0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
  1066. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1067. /// ];
  1068. ///
  1069. /// let mut vm = rbpf::EbpfVmRaw::new(&prog);
  1070. ///
  1071. /// vm.jit_compile();
  1072. /// ```
  1073. pub fn jit_compile(&mut self) {
  1074. self.parent.jit = jit::compile(&self.parent.prog, &self.parent.helpers, false, false);
  1075. }
  1076. /// Execute the previously JIT-compiled program, with the given packet data, in a manner very
  1077. /// similar to `prog_exec()`.
  1078. ///
  1079. /// # Panics
  1080. ///
  1081. /// This function panics if an error occurs during the execution of the program.
  1082. ///
  1083. /// # Safety
  1084. ///
  1085. /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
  1086. /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
  1087. /// very bad (program may segfault). It may be wise to check that the program works with the
  1088. /// interpreter before running the JIT-compiled version of it.
  1089. ///
  1090. /// For this reason the function should be called from within an `unsafe` bloc.
  1091. ///
  1092. /// # Examples
  1093. ///
  1094. /// ```
  1095. /// let prog = vec![
  1096. /// 0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
  1097. /// 0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
  1098. /// 0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
  1099. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1100. /// ];
  1101. ///
  1102. /// let mut mem = vec![
  1103. /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
  1104. /// ];
  1105. ///
  1106. /// let mut vm = rbpf::EbpfVmRaw::new(&prog);
  1107. ///
  1108. /// vm.jit_compile();
  1109. ///
  1110. /// unsafe {
  1111. /// let res = vm.prog_exec_jit(&mut mem);
  1112. /// assert_eq!(res, 0x22cc);
  1113. /// }
  1114. /// ```
  1115. pub unsafe fn prog_exec_jit(&self, mem: &'a mut [u8]) -> u64 {
  1116. let mut mbuff = vec![];
  1117. self.parent.prog_exec_jit(mem, &mut mbuff)
  1118. }
  1119. }
  1120. /// A virtual machine to run eBPF program. This kind of VM is used for programs that do not work
  1121. /// with any memory area—no metadata buffer, no packet data either.
  1122. ///
  1123. /// # Examples
  1124. ///
  1125. /// ```
  1126. /// let prog = vec![
  1127. /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
  1128. /// 0xb7, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // mov r1, 1
  1129. /// 0xb7, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // mov r2, 2
  1130. /// 0xb7, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // mov r3, 3
  1131. /// 0xb7, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, // mov r4, 4
  1132. /// 0xb7, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // mov r5, 5
  1133. /// 0xb7, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, // mov r6, 6
  1134. /// 0xb7, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, // mov r7, 7
  1135. /// 0xb7, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // mov r8, 8
  1136. /// 0x4f, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // or r0, r5
  1137. /// 0x47, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, // or r0, 0xa0
  1138. /// 0x57, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, // and r0, 0xa3
  1139. /// 0xb7, 0x09, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, // mov r9, 0x91
  1140. /// 0x5f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // and r0, r9
  1141. /// 0x67, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, // lsh r0, 32
  1142. /// 0x67, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, // lsh r0, 22
  1143. /// 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // lsh r0, r8
  1144. /// 0x77, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, // rsh r0, 32
  1145. /// 0x77, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, // rsh r0, 19
  1146. /// 0x7f, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // rsh r0, r7
  1147. /// 0xa7, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // xor r0, 0x03
  1148. /// 0xaf, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xor r0, r2
  1149. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1150. /// ];
  1151. ///
  1152. /// // Instantiate a VM.
  1153. /// let vm = rbpf::EbpfVmNoData::new(&prog);
  1154. ///
  1155. /// // Provide only a reference to the packet data.
  1156. /// let res = vm.prog_exec();
  1157. /// assert_eq!(res, 0x11);
  1158. /// ```
  1159. pub struct EbpfVmNoData<'a> {
  1160. parent: EbpfVmRaw<'a>,
  1161. }
  1162. impl<'a> EbpfVmNoData<'a> {
  1163. /// Create a new virtual machine instance, and load an eBPF program into that instance.
  1164. /// When attempting to load the program, it passes through a simple verifier.
  1165. ///
  1166. /// # Panics
  1167. ///
  1168. /// The simple verifier may panic if it finds errors in the eBPF program at load time.
  1169. ///
  1170. /// # Examples
  1171. ///
  1172. /// ```
  1173. /// let prog = vec![
  1174. /// 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
  1175. /// 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
  1176. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1177. /// ];
  1178. ///
  1179. /// // Instantiate a VM.
  1180. /// let vm = rbpf::EbpfVmNoData::new(&prog);
  1181. /// ```
  1182. pub fn new(prog: &'a [u8]) -> EbpfVmNoData<'a> {
  1183. let parent = EbpfVmRaw::new(prog);
  1184. EbpfVmNoData {
  1185. parent: parent,
  1186. }
  1187. }
  1188. /// Load a new eBPF program into the virtual machine instance.
  1189. ///
  1190. /// # Panics
  1191. ///
  1192. /// The simple verifier may panic if it finds errors in the eBPF program at load time.
  1193. ///
  1194. /// # Examples
  1195. ///
  1196. /// ```
  1197. /// let prog1 = vec![
  1198. /// 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
  1199. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1200. /// ];
  1201. /// let prog2 = vec![
  1202. /// 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
  1203. /// 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
  1204. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1205. /// ];
  1206. ///
  1207. /// let mut vm = rbpf::EbpfVmNoData::new(&prog1);
  1208. ///
  1209. /// let res = vm.prog_exec();
  1210. /// assert_eq!(res, 0x2211);
  1211. ///
  1212. /// vm.set_prog(&prog2);
  1213. ///
  1214. /// let res = vm.prog_exec();
  1215. /// assert_eq!(res, 0x1122);
  1216. /// ```
  1217. pub fn set_prog(&mut self, prog: &'a [u8]) {
  1218. self.parent.set_prog(prog)
  1219. }
  1220. /// Register a built-in or user-defined helper function in order to use it later from within
  1221. /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
  1222. ///
  1223. /// If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the
  1224. /// program. You should be able to change registered helpers after compiling, but not to add
  1225. /// new ones (i.e. with new keys).
  1226. ///
  1227. /// # Examples
  1228. ///
  1229. /// ```
  1230. /// use rbpf::helpers;
  1231. ///
  1232. /// let prog = vec![
  1233. /// 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // mov r1, 0x010000000
  1234. /// 0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r2, 0
  1235. /// 0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r3, 0
  1236. /// 0xb7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r4, 0
  1237. /// 0xb7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r5, 0
  1238. /// 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // call helper with key 1
  1239. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1240. /// ];
  1241. ///
  1242. /// let mut vm = rbpf::EbpfVmNoData::new(&prog);
  1243. ///
  1244. /// // Register a helper. This helper will store the result of the square root of r1 into r0.
  1245. /// vm.register_helper(1, helpers::sqrti);
  1246. ///
  1247. /// let res = vm.prog_exec();
  1248. /// assert_eq!(res, 0x1000);
  1249. /// ```
  1250. pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) {
  1251. self.parent.register_helper(key, function);
  1252. }
  1253. /// JIT-compile the loaded program. No argument required for this.
  1254. ///
  1255. /// If using helper functions, be sure to register them into the VM before calling this
  1256. /// function.
  1257. ///
  1258. /// # Panics
  1259. ///
  1260. /// This function panics if an error occurs during JIT-compiling, such as the occurrence of an
  1261. /// unknown eBPF operation code.
  1262. ///
  1263. /// # Examples
  1264. ///
  1265. /// ```
  1266. /// let prog = vec![
  1267. /// 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
  1268. /// 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
  1269. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1270. /// ];
  1271. ///
  1272. /// let mut vm = rbpf::EbpfVmNoData::new(&prog);
  1273. ///
  1274. ///
  1275. /// vm.jit_compile();
  1276. /// ```
  1277. pub fn jit_compile(&mut self) {
  1278. self.parent.jit_compile();
  1279. }
  1280. /// Execute the program loaded, without providing pointers to any memory area whatsoever.
  1281. ///
  1282. /// # Panics
  1283. ///
  1284. /// This function is currently expected to panic if it encounters any error during the program
  1285. /// execution, such as memory accesses or division by zero attempts. This may be changed in the
  1286. /// future (we could raise errors instead).
  1287. ///
  1288. /// # Examples
  1289. ///
  1290. /// ```
  1291. /// let prog = vec![
  1292. /// 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
  1293. /// 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
  1294. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1295. /// ];
  1296. ///
  1297. /// let vm = rbpf::EbpfVmNoData::new(&prog);
  1298. ///
  1299. /// // For this kind of VM, the `prog_exec()` function needs no argument.
  1300. /// let res = vm.prog_exec();
  1301. /// assert_eq!(res, 0x1122);
  1302. /// ```
  1303. pub fn prog_exec(&self) -> u64 {
  1304. self.parent.prog_exec(&mut vec![])
  1305. }
  1306. /// Execute the previously JIT-compiled program, without providing pointers to any memory area
  1307. /// whatsoever, in a manner very similar to `prog_exec()`.
  1308. ///
  1309. /// # Panics
  1310. ///
  1311. /// This function panics if an error occurs during the execution of the program.
  1312. ///
  1313. /// # Safety
  1314. ///
  1315. /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
  1316. /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
  1317. /// very bad (program may segfault). It may be wise to check that the program works with the
  1318. /// interpreter before running the JIT-compiled version of it.
  1319. ///
  1320. /// For this reason the function should be called from within an `unsafe` bloc.
  1321. ///
  1322. /// # Examples
  1323. ///
  1324. /// ```
  1325. /// let prog = vec![
  1326. /// 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
  1327. /// 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
  1328. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
  1329. /// ];
  1330. ///
  1331. /// let mut vm = rbpf::EbpfVmNoData::new(&prog);
  1332. ///
  1333. /// vm.jit_compile();
  1334. ///
  1335. /// unsafe {
  1336. /// let res = vm.prog_exec_jit();
  1337. /// assert_eq!(res, 0x1122);
  1338. /// }
  1339. /// ```
  1340. pub unsafe fn prog_exec_jit(&self) -> u64 {
  1341. self.parent.prog_exec_jit(&mut vec![])
  1342. }
  1343. }