lib.rs 69 KB

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