@@ -99,9 +99,9 @@ pub mod lib {
99
99
// BTree-based implementations of Maps and Sets. The cranelift module uses
100
100
// BTrees by default, hence we need to expose it twice here.
101
101
#[ cfg( not( feature = "std" ) ) ]
102
- pub use alloc:: collections:: { BTreeMap } ;
102
+ pub use alloc:: collections:: BTreeMap ;
103
103
#[ cfg( feature = "std" ) ]
104
- pub use std:: collections:: { BTreeMap } ;
104
+ pub use std:: collections:: BTreeMap ;
105
105
106
106
/// In no_std we use a custom implementation of the error which acts as a
107
107
/// replacement for the io Error.
@@ -179,6 +179,8 @@ pub struct EbpfVmMbuff<'a> {
179
179
verifier : Verifier ,
180
180
#[ cfg( not( windows) ) ]
181
181
jit : Option < jit:: JitMemory < ' a > > ,
182
+ #[ cfg( all( not( windows) , not( feature = "std" ) ) ) ]
183
+ custom_exec_memory : Option < & ' a mut [ u8 ] > ,
182
184
#[ cfg( feature = "cranelift" ) ]
183
185
cranelift_prog : Option < cranelift:: CraneliftProgram > ,
184
186
helpers : HashMap < u32 , ebpf:: Helper > ,
@@ -217,6 +219,8 @@ impl<'a> EbpfVmMbuff<'a> {
217
219
verifier : verifier:: check,
218
220
#[ cfg( not( windows) ) ]
219
221
jit : None ,
222
+ #[ cfg( all( not( windows) , not( feature = "std" ) ) ) ]
223
+ custom_exec_memory : None ,
220
224
#[ cfg( feature = "cranelift" ) ]
221
225
cranelift_prog : None ,
222
226
helpers : HashMap :: new ( ) ,
@@ -332,6 +336,27 @@ impl<'a> EbpfVmMbuff<'a> {
332
336
Ok ( ( ) )
333
337
}
334
338
339
+ /// Set a custom executable memory for the JIT-compiled program.
340
+ /// We need this for no_std because we cannot use the default memory allocator.
341
+ ///
342
+ /// # Examples
343
+ ///
344
+ /// ```
345
+ /// let prog = &[
346
+ /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
347
+ /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
348
+ /// ];
349
+ /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
350
+ /// let mut memory = [0u8; 1024];
351
+ /// // Use mmap or other means to modify the permissions of the memory to be executable.
352
+ /// vm.set_jit_exec_memory(&mut memory);
353
+ /// ```
354
+ #[ cfg( all( not( windows) , not( feature = "std" ) ) ) ]
355
+ pub fn set_jit_exec_memory ( & mut self , memory : & ' a mut [ u8 ] ) -> Result < ( ) , Error > {
356
+ self . custom_exec_memory = Some ( memory) ;
357
+ Ok ( ( ) )
358
+ }
359
+
335
360
/// Register a built-in or user-defined helper function in order to use it later from within
336
361
/// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
337
362
///
@@ -476,7 +501,7 @@ impl<'a> EbpfVmMbuff<'a> {
476
501
///
477
502
/// vm.jit_compile();
478
503
/// ```
479
- #[ cfg( all ( not( windows) , feature = "std" ) ) ]
504
+ #[ cfg( not( windows) ) ]
480
505
pub fn jit_compile ( & mut self ) -> Result < ( ) , Error > {
481
506
let prog = match self . prog {
482
507
Some ( prog) => prog,
@@ -485,29 +510,27 @@ impl<'a> EbpfVmMbuff<'a> {
485
510
"Error: No program set, call prog_set() to load one" ,
486
511
) ) ?,
487
512
} ;
488
- self . jit = Some ( jit:: JitMemory :: new ( prog, & self . helpers , true , false ) ?) ;
489
- Ok ( ( ) )
490
- }
491
-
492
- /// JIT-compile the loaded program. The user has to provide a mutable slice of memory that
493
- /// will be used for the JIT-compiled code. For more information, see the [EbpfVmMbuff::jit_compile]
494
- /// function.
495
- #[ cfg( all( not( windows) , not( feature = "std" ) ) ) ]
496
- pub fn jit_compile ( & mut self , executable_memory : & ' a mut [ u8 ] ) -> Result < ( ) , Error > {
497
- let prog = match self . prog {
498
- Some ( prog) => prog,
499
- None => Err ( Error :: new (
500
- ErrorKind :: Other ,
501
- "Error: No program set, call prog_set() to load one" ,
502
- ) ) ?,
503
- } ;
504
- self . jit = Some ( jit:: JitMemory :: new (
505
- prog,
506
- executable_memory,
507
- & self . helpers ,
508
- true ,
509
- false ,
510
- ) ?) ;
513
+ #[ cfg( feature = "std" ) ]
514
+ {
515
+ self . jit = Some ( jit:: JitMemory :: new ( prog, & self . helpers , true , false ) ?) ;
516
+ }
517
+ #[ cfg( not( feature = "std" ) ) ]
518
+ {
519
+ let exec_memory = match self . custom_exec_memory . take ( ) {
520
+ Some ( memory) => memory,
521
+ None => return Err ( Error :: new (
522
+ ErrorKind :: Other ,
523
+ "Error: No custom executable memory set, call set_jit_exec_memory() to set one" ,
524
+ ) ) ?,
525
+ } ;
526
+ self . jit = Some ( jit:: JitMemory :: new (
527
+ prog,
528
+ exec_memory,
529
+ & self . helpers ,
530
+ true ,
531
+ false ,
532
+ ) ?) ;
533
+ }
511
534
Ok ( ( ) )
512
535
}
513
536
@@ -929,6 +952,27 @@ impl<'a> EbpfVmFixedMbuff<'a> {
929
952
self . parent . set_stack_usage_calculator ( calculator, data)
930
953
}
931
954
955
+ /// Set a custom executable memory for the JIT-compiled program.
956
+ /// We need this for no_std because we cannot use the default memory allocator.
957
+ ///
958
+ /// # Examples
959
+ ///
960
+ /// ```
961
+ /// let prog = &[
962
+ /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
963
+ /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
964
+ /// ];
965
+ /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
966
+ /// let mut memory = [0u8; 1024];
967
+ /// // Use mmap or other means to modify the permissions of the memory to be executable.
968
+ /// vm.set_jit_exec_memory(&mut memory);
969
+ /// ```
970
+ #[ cfg( all( not( windows) , not( feature = "std" ) ) ) ]
971
+ pub fn set_jit_exec_memory ( & mut self , memory : & ' a mut [ u8 ] ) -> Result < ( ) , Error > {
972
+ self . parent . custom_exec_memory = Some ( memory) ;
973
+ Ok ( ( ) )
974
+ }
975
+
932
976
/// Register a built-in or user-defined helper function in order to use it later from within
933
977
/// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
934
978
///
@@ -1088,7 +1132,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
1088
1132
///
1089
1133
/// vm.jit_compile();
1090
1134
/// ```
1091
- #[ cfg( all ( not( windows) , feature = "std" ) ) ]
1135
+ #[ cfg( not( windows) ) ]
1092
1136
pub fn jit_compile ( & mut self ) -> Result < ( ) , Error > {
1093
1137
let prog = match self . parent . prog {
1094
1138
Some ( prog) => prog,
@@ -1097,29 +1141,27 @@ impl<'a> EbpfVmFixedMbuff<'a> {
1097
1141
"Error: No program set, call prog_set() to load one" ,
1098
1142
) ) ?,
1099
1143
} ;
1100
- self . parent . jit = Some ( jit:: JitMemory :: new ( prog, & self . parent . helpers , true , true ) ?) ;
1101
- Ok ( ( ) )
1102
- }
1103
-
1104
- /// JIT-compile the loaded program. The user has to provide a mutable slice of memory that
1105
- /// will be used for the JIT-compiled code. For more information, see the [EbpfVmFixedMbuff::jit_compile]
1106
- /// function.
1107
- #[ cfg( all( not( windows) , not( feature = "std" ) ) ) ]
1108
- pub fn jit_compile ( & mut self , executable_memory : & ' a mut [ u8 ] ) -> Result < ( ) , Error > {
1109
- let prog = match self . parent . prog {
1110
- Some ( prog) => prog,
1111
- None => Err ( Error :: new (
1112
- ErrorKind :: Other ,
1113
- "Error: No program set, call prog_set() to load one" ,
1114
- ) ) ?,
1115
- } ;
1116
- self . parent . jit = Some ( jit:: JitMemory :: new (
1117
- prog,
1118
- executable_memory,
1119
- & self . parent . helpers ,
1120
- true ,
1121
- true ,
1122
- ) ?) ;
1144
+ #[ cfg( feature = "std" ) ]
1145
+ {
1146
+ self . parent . jit = Some ( jit:: JitMemory :: new ( prog, & self . parent . helpers , true , true ) ?) ;
1147
+ }
1148
+ #[ cfg( not( feature = "std" ) ) ]
1149
+ {
1150
+ let exec_memory = match self . parent . custom_exec_memory . take ( ) {
1151
+ Some ( memory) => memory,
1152
+ None => return Err ( Error :: new (
1153
+ ErrorKind :: Other ,
1154
+ "Error: No custom executable memory set, call set_jit_exec_memory() to set one" ,
1155
+ ) ) ?,
1156
+ } ;
1157
+ self . parent . jit = Some ( jit:: JitMemory :: new (
1158
+ prog,
1159
+ exec_memory,
1160
+ & self . parent . helpers ,
1161
+ true ,
1162
+ true ,
1163
+ ) ?) ;
1164
+ }
1123
1165
Ok ( ( ) )
1124
1166
}
1125
1167
@@ -1464,6 +1506,27 @@ impl<'a> EbpfVmRaw<'a> {
1464
1506
self . parent . set_stack_usage_calculator ( calculator, data)
1465
1507
}
1466
1508
1509
+ /// Set a custom executable memory for the JIT-compiled program.
1510
+ /// We need this for no_std because we cannot use the default memory allocator.
1511
+ ///
1512
+ /// # Examples
1513
+ ///
1514
+ /// ```
1515
+ /// let prog = &[
1516
+ /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
1517
+ /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
1518
+ /// ];
1519
+ /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
1520
+ /// let mut memory = [0u8; 1024];
1521
+ /// // Use mmap or other means to modify the permissions of the memory to be executable.
1522
+ /// vm.set_jit_exec_memory(&mut memory);
1523
+ /// ```
1524
+ #[ cfg( all( not( windows) , not( feature = "std" ) ) ) ]
1525
+ pub fn set_jit_exec_memory ( & mut self , memory : & ' a mut [ u8 ] ) -> Result < ( ) , Error > {
1526
+ self . parent . custom_exec_memory = Some ( memory) ;
1527
+ Ok ( ( ) )
1528
+ }
1529
+
1467
1530
/// Register a built-in or user-defined helper function in order to use it later from within
1468
1531
/// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
1469
1532
///
@@ -1589,7 +1652,7 @@ impl<'a> EbpfVmRaw<'a> {
1589
1652
///
1590
1653
/// vm.jit_compile();
1591
1654
/// ```
1592
- #[ cfg( all ( not( windows) , feature = "std" ) ) ]
1655
+ #[ cfg( not( windows) ) ]
1593
1656
pub fn jit_compile ( & mut self ) -> Result < ( ) , Error > {
1594
1657
let prog = match self . parent . prog {
1595
1658
Some ( prog) => prog,
@@ -1598,34 +1661,32 @@ impl<'a> EbpfVmRaw<'a> {
1598
1661
"Error: No program set, call prog_set() to load one" ,
1599
1662
) ) ?,
1600
1663
} ;
1601
- self . parent . jit = Some ( jit:: JitMemory :: new (
1602
- prog,
1603
- & self . parent . helpers ,
1604
- false ,
1605
- false ,
1606
- ) ?) ;
1607
- Ok ( ( ) )
1608
- }
1609
-
1610
- /// JIT-compile the loaded program. The user has to provide a mutable slice of memory that
1611
- /// will be used for the JIT-compiled code. For more information, see the [EbpfVmRaw::jit_compile]
1612
- /// function.
1613
- #[ cfg( all( not( windows) , not( feature = "std" ) ) ) ]
1614
- pub fn jit_compile ( & mut self , executable_memory : & ' a mut [ u8 ] ) -> Result < ( ) , Error > {
1615
- let prog = match self . parent . prog {
1616
- Some ( prog) => prog,
1617
- None => Err ( Error :: new (
1618
- ErrorKind :: Other ,
1619
- "Error: No program set, call prog_set() to load one" ,
1620
- ) ) ?,
1621
- } ;
1622
- self . parent . jit = Some ( jit:: JitMemory :: new (
1623
- prog,
1624
- executable_memory,
1625
- & self . parent . helpers ,
1626
- false ,
1627
- false ,
1628
- ) ?) ;
1664
+ #[ cfg( feature = "std" ) ]
1665
+ {
1666
+ self . parent . jit = Some ( jit:: JitMemory :: new (
1667
+ prog,
1668
+ & self . parent . helpers ,
1669
+ false ,
1670
+ false ,
1671
+ ) ?) ;
1672
+ }
1673
+ #[ cfg( not( feature = "std" ) ) ]
1674
+ {
1675
+ let exec_memory = match self . parent . custom_exec_memory . take ( ) {
1676
+ Some ( memory) => memory,
1677
+ None => return Err ( Error :: new (
1678
+ ErrorKind :: Other ,
1679
+ "Error: No custom executable memory set, call set_jit_exec_memory() to set one" ,
1680
+ ) ) ?,
1681
+ } ;
1682
+ self . parent . jit = Some ( jit:: JitMemory :: new (
1683
+ prog,
1684
+ exec_memory,
1685
+ & self . parent . helpers ,
1686
+ false ,
1687
+ false ,
1688
+ ) ?) ;
1689
+ }
1629
1690
Ok ( ( ) )
1630
1691
}
1631
1692
@@ -1905,6 +1966,26 @@ impl<'a> EbpfVmNoData<'a> {
1905
1966
self . parent . set_stack_usage_calculator ( calculator, data)
1906
1967
}
1907
1968
1969
+ /// Set a custom executable memory for the JIT-compiled program.
1970
+ /// We need this for no_std because we cannot use the default memory allocator.
1971
+ ///
1972
+ /// # Examples
1973
+ ///
1974
+ /// ```
1975
+ /// let prog = &[
1976
+ /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
1977
+ /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
1978
+ /// ];
1979
+ /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
1980
+ /// let mut memory = [0u8; 1024];
1981
+ /// // Use mmap or other means to modify the permissions of the memory to be executable.
1982
+ /// vm.set_jit_exec_memory(&mut memory);
1983
+ /// ```
1984
+ #[ cfg( all( not( windows) , not( feature = "std" ) ) ) ]
1985
+ pub fn set_jit_exec_memory ( & mut self , memory : & ' a mut [ u8 ] ) -> Result < ( ) , Error > {
1986
+ self . parent . set_jit_exec_memory ( memory)
1987
+ }
1988
+
1908
1989
/// Register a built-in or user-defined helper function in order to use it later from within
1909
1990
/// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
1910
1991
///
@@ -1999,19 +2080,11 @@ impl<'a> EbpfVmNoData<'a> {
1999
2080
///
2000
2081
/// vm.jit_compile();
2001
2082
/// ```
2002
- #[ cfg( all ( not( windows) , feature = "std" ) ) ]
2083
+ #[ cfg( not( windows) ) ]
2003
2084
pub fn jit_compile ( & mut self ) -> Result < ( ) , Error > {
2004
2085
self . parent . jit_compile ( )
2005
2086
}
2006
2087
2007
- /// JIT-compile the loaded program. The user has to provide a mutable slice of memory that
2008
- /// will be used for the JIT-compiled code. For more information, see the [EbpfVmNoData::jit_compile]
2009
- /// function.
2010
- #[ cfg( all( not( windows) , not( feature = "std" ) ) ) ]
2011
- pub fn jit_compile ( & mut self , executable_memory : & ' a mut [ u8 ] ) -> Result < ( ) , Error > {
2012
- self . parent . jit_compile ( executable_memory)
2013
- }
2014
-
2015
2088
/// Execute the program loaded, without providing pointers to any memory area whatsoever.
2016
2089
///
2017
2090
/// # Examples
0 commit comments