lib.rs 69 KB

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