@@ -182,6 +182,7 @@ pub struct EbpfVmMbuff<'a> {
182
182
#[ cfg( feature = "cranelift" ) ]
183
183
cranelift_prog : Option < cranelift:: CraneliftProgram > ,
184
184
helpers : HashMap < u32 , ebpf:: Helper > ,
185
+ allowed_memory : HashSet < u64 > ,
185
186
}
186
187
187
188
impl < ' a > EbpfVmMbuff < ' a > {
@@ -213,6 +214,7 @@ impl<'a> EbpfVmMbuff<'a> {
213
214
#[ cfg( feature = "cranelift" ) ]
214
215
cranelift_prog : None ,
215
216
helpers : HashMap :: new ( ) ,
217
+ allowed_memory : HashSet :: new ( ) ,
216
218
} )
217
219
}
218
220
@@ -320,6 +322,46 @@ impl<'a> EbpfVmMbuff<'a> {
320
322
Ok ( ( ) )
321
323
}
322
324
325
+ /// Register a set of addresses that the ebpf program is allowed to load and store.
326
+ ///
327
+ /// When using certain helpers, typically map lookups, the linux kernel will return pointers
328
+ /// to structs that the ebpf program needs to interact with. By default rbpf only allows the
329
+ /// program to interact with its stack, the memory buffer and the program itself, making it
330
+ /// impossible to supply functional implementations of these helpers.
331
+ /// This option allows you to pass in a list of addresses that rbpf will allow the program
332
+ /// to load and store to. Given rust's memory model you will always know these addresses up
333
+ /// front when implementing the helpers.
334
+ ///
335
+ /// Each invocation of this method will append to the set of allowed addresses.
336
+ ///
337
+ /// # Examples
338
+ ///
339
+ /// ```
340
+ /// use std::iter::FromIterator;
341
+ /// use std::ptr::addr_of;
342
+ ///
343
+ /// struct MapValue {
344
+ /// data: u8
345
+ /// }
346
+ /// static VALUE: MapValue = MapValue { data: 1 };
347
+ ///
348
+ /// let prog = &[
349
+ /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
350
+ /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
351
+ /// ];
352
+ ///
353
+ /// // Instantiate a VM.
354
+ /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
355
+ /// let start = addr_of!(VALUE) as u64;
356
+ /// let addrs = Vec::from_iter(start..start+size_of::<MapValue>() as u64);
357
+ /// vm.register_allowed_memory(&addrs);
358
+ /// ```
359
+ pub fn register_allowed_memory ( & mut self , addrs : & [ u64 ] ) -> ( ) {
360
+ for i in addrs {
361
+ self . allowed_memory . insert ( * i) ;
362
+ }
363
+ }
364
+
323
365
/// Execute the program loaded, with the given packet data and metadata buffer.
324
366
///
325
367
/// If the program is made to be compatible with Linux kernel, it is expected to load the
@@ -357,7 +399,7 @@ impl<'a> EbpfVmMbuff<'a> {
357
399
/// assert_eq!(res, 0x2211);
358
400
/// ```
359
401
pub fn execute_program ( & self , mem : & [ u8 ] , mbuff : & [ u8 ] ) -> Result < u64 , Error > {
360
- interpreter:: execute_program ( self . prog , mem, mbuff, & self . helpers )
402
+ interpreter:: execute_program ( self . prog , mem, mbuff, & self . helpers , & self . allowed_memory )
361
403
}
362
404
363
405
/// JIT-compile the loaded program. No argument required for this.
@@ -826,6 +868,44 @@ impl<'a> EbpfVmFixedMbuff<'a> {
826
868
self . parent . register_helper ( key, function)
827
869
}
828
870
871
+ /// Register an object that the ebpf program is allowed to load and store.
872
+ ///
873
+ /// When using certain helpers, typically map lookups, the linux kernel will return pointers
874
+ /// to structs that the ebpf program needs to interact with. By default rbpf only allows the
875
+ /// program to interact with its stack, the memory buffer and the program itself, making it
876
+ /// impossible to supply functional implementations of these helpers.
877
+ /// This option allows you to pass in a list of addresses that rbpf will allow the program
878
+ /// to load and store to. Given rust's memory model you will always know these addresses up
879
+ /// front when implementing the helpers.
880
+ ///
881
+ /// Each invocation of this method will append to the set of allowed addresses.
882
+ ///
883
+ /// # Examples
884
+ ///
885
+ /// ```
886
+ /// use std::iter::FromIterator;
887
+ /// use std::ptr::addr_of;
888
+ ///
889
+ /// struct MapValue {
890
+ /// data: u8
891
+ /// }
892
+ /// static VALUE: MapValue = MapValue { data: 1 };
893
+ ///
894
+ /// let prog = &[
895
+ /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
896
+ /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
897
+ /// ];
898
+ ///
899
+ /// // Instantiate a VM.
900
+ /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
901
+ /// let start = addr_of!(VALUE) as u64;
902
+ /// let addrs = Vec::from_iter(start..start+size_of::<MapValue>() as u64);
903
+ /// vm.register_allowed_memory(&addrs);
904
+ /// ```
905
+ pub fn register_allowed_memory ( & mut self , allowed : & [ u64 ] ) -> ( ) {
906
+ self . parent . register_allowed_memory ( allowed)
907
+ }
908
+
829
909
/// Execute the program loaded, with the given packet data.
830
910
///
831
911
/// If the program is made to be compatible with Linux kernel, it is expected to load the
@@ -1260,6 +1340,44 @@ impl<'a> EbpfVmRaw<'a> {
1260
1340
self . parent . register_helper ( key, function)
1261
1341
}
1262
1342
1343
+ /// Register an object that the ebpf program is allowed to load and store.
1344
+ ///
1345
+ /// When using certain helpers, typically map lookups, the linux kernel will return pointers
1346
+ /// to structs that the ebpf program needs to interact with. By default rbpf only allows the
1347
+ /// program to interact with its stack, the memory buffer and the program itself, making it
1348
+ /// impossible to supply functional implementations of these helpers.
1349
+ /// This option allows you to pass in a list of addresses that rbpf will allow the program
1350
+ /// to load and store to. Given rust's memory model you will always know these addresses up
1351
+ /// front when implementing the helpers.
1352
+ ///
1353
+ /// Each invocation of this method will append to the set of allowed addresses.
1354
+ ///
1355
+ /// # Examples
1356
+ ///
1357
+ /// ```
1358
+ /// use std::iter::FromIterator;
1359
+ /// use std::ptr::addr_of;
1360
+ ///
1361
+ /// struct MapValue {
1362
+ /// data: u8
1363
+ /// }
1364
+ /// static VALUE: MapValue = MapValue { data: 1 };
1365
+ ///
1366
+ /// let prog = &[
1367
+ /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
1368
+ /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
1369
+ /// ];
1370
+ ///
1371
+ /// // Instantiate a VM.
1372
+ /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
1373
+ /// let start = addr_of!(VALUE) as u64;
1374
+ /// let addrs = Vec::from_iter(start..start+size_of::<MapValue>() as u64);
1375
+ /// vm.register_allowed_memory(&addrs);
1376
+ /// ```
1377
+ pub fn register_allowed_memory ( & mut self , allowed : & [ u64 ] ) -> ( ) {
1378
+ self . parent . register_allowed_memory ( allowed)
1379
+ }
1380
+
1263
1381
/// Execute the program loaded, with the given packet data.
1264
1382
///
1265
1383
/// # Examples
@@ -1602,6 +1720,44 @@ impl<'a> EbpfVmNoData<'a> {
1602
1720
self . parent . register_helper ( key, function)
1603
1721
}
1604
1722
1723
+ /// Register an object that the ebpf program is allowed to load and store.
1724
+ ///
1725
+ /// When using certain helpers, typically map lookups, the linux kernel will return pointers
1726
+ /// to structs that the ebpf program needs to interact with. By default rbpf only allows the
1727
+ /// program to interact with its stack, the memory buffer and the program itself, making it
1728
+ /// impossible to supply functional implementations of these helpers.
1729
+ /// This option allows you to pass in a list of addresses that rbpf will allow the program
1730
+ /// to load and store to. Given rust's memory model you will always know these addresses up
1731
+ /// front when implementing the helpers.
1732
+ ///
1733
+ /// Each invocation of this method will append to the set of allowed addresses.
1734
+ ///
1735
+ /// # Examples
1736
+ ///
1737
+ /// ```
1738
+ /// use std::iter::FromIterator;
1739
+ /// use std::ptr::addr_of;
1740
+ ///
1741
+ /// struct MapValue {
1742
+ /// data: u8
1743
+ /// }
1744
+ /// static VALUE: MapValue = MapValue { data: 1 };
1745
+ ///
1746
+ /// let prog = &[
1747
+ /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
1748
+ /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
1749
+ /// ];
1750
+ ///
1751
+ /// // Instantiate a VM.
1752
+ /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
1753
+ /// let start = addr_of!(VALUE) as u64;
1754
+ /// let addrs = Vec::from_iter(start..start+size_of::<MapValue>() as u64);
1755
+ /// vm.register_allowed_memory(&addrs);
1756
+ /// ```
1757
+ pub fn register_allowed_memory ( & mut self , allowed : & [ u64 ] ) -> ( ) {
1758
+ self . parent . register_allowed_memory ( allowed)
1759
+ }
1760
+
1605
1761
/// JIT-compile the loaded program. No argument required for this.
1606
1762
///
1607
1763
/// If using helper functions, be sure to register them into the VM before calling this
0 commit comments