lib.rs 53 KB

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