@@ -5,7 +5,20 @@ use std::collections::HashMap;
55use  std:: io:: Read ; 
66use  std:: sync:: Arc ; 
77
8- use  bincode:: { DefaultOptions ,  Options } ; 
8+ use  bincode:: config; 
9+ use  bincode:: config:: { Configuration ,  Fixint ,  Limit ,  LittleEndian } ; 
10+ 
11+ // This byte limit is passed to `bincode` to guard against a potential memory 
12+ // allocation DOS caused by binary filters that are too large. 
13+ // This limit can be safely determined since the maximum length of a BPF 
14+ // filter is 4096 instructions and Firecracker has a finite number of threads. 
15+ const  DESERIALIZATION_BYTES_LIMIT :  usize  = 100_000 ; 
16+ 
17+ const  BINCODE_CONFIG :  Configuration < LittleEndian ,  Fixint ,  Limit < DESERIALIZATION_BYTES_LIMIT > >  =
18+     config:: standard ( ) 
19+         . with_fixed_int_encoding ( ) 
20+         . with_limit :: < DESERIALIZATION_BYTES_LIMIT > ( ) 
21+         . with_little_endian ( ) ; 
922
1023/// Each BPF instruction is 8 bytes long and 4 byte aligned. 
1124/// This alignment needs to be satisfied in order for a BPF code to be accepted 
@@ -22,7 +35,7 @@ pub type BpfProgramRef<'a> = &'a [BpfInstruction];
2235pub  type  BpfThreadMap  = HashMap < String ,  Arc < BpfProgram > > ; 
2336
2437/// Binary filter deserialization errors. 
25- pub  type  DeserializationError  = bincode:: Error ; 
38+ pub  type  DeserializationError  = bincode:: error :: DecodeError ; 
2639
2740/// Retrieve empty seccomp filters. 
2841pub  fn  get_empty_filters ( )  -> BpfThreadMap  { 
@@ -34,19 +47,8 @@ pub fn get_empty_filters() -> BpfThreadMap {
3447} 
3548
3649/// Deserialize binary with bpf filters 
37- pub  fn  deserialize_binary < R :  Read > ( 
38-     reader :  R , 
39-     bytes_limit :  Option < u64 > , 
40- )  -> Result < BpfThreadMap ,  DeserializationError >  { 
41-     let  result = match  bytes_limit { 
42-         Some ( limit)  => DefaultOptions :: new ( ) 
43-             . with_fixint_encoding ( ) 
44-             . allow_trailing_bytes ( ) 
45-             . with_limit ( limit) 
46-             . deserialize_from :: < R ,  HashMap < String ,  BpfProgram > > ( reader) , 
47-         // No limit is the default. 
48-         None  => bincode:: deserialize_from :: < R ,  HashMap < String ,  BpfProgram > > ( reader) , 
49-     } ?; 
50+ pub  fn  deserialize_binary < R :  Read > ( mut  reader :  R )  -> Result < BpfThreadMap ,  DeserializationError >  { 
51+     let  result:  HashMap < String ,  _ >  = bincode:: decode_from_std_read ( & mut  reader,  BINCODE_CONFIG ) ?; 
5052
5153    Ok ( result
5254        . into_iter ( ) 
@@ -134,49 +136,28 @@ mod tests {
134136    #[ test]  
135137    fn  test_deserialize_binary ( )  { 
136138        // Malformed bincode binary. 
137-         { 
138-             let  data = "adassafvc" . to_string ( ) ; 
139-             deserialize_binary ( data. as_bytes ( ) ,  None ) . unwrap_err ( ) ; 
140-         } 
139+         let  data = "adassafvc" . to_string ( ) ; 
140+         deserialize_binary ( data. as_bytes ( ) ) . unwrap_err ( ) ; 
141141
142142        // Test that the binary deserialization is correct, and that the thread keys 
143143        // have been lowercased. 
144-         { 
145-             let  bpf_prog = vec ! [ 0 ;  2 ] ; 
146-             let  mut  filter_map:  HashMap < String ,  BpfProgram >  = HashMap :: new ( ) ; 
147-             filter_map. insert ( "VcpU" . to_string ( ) ,  bpf_prog. clone ( ) ) ; 
148-             let  bytes = bincode:: serialize ( & filter_map) . unwrap ( ) ; 
149- 
150-             let  mut  expected_res = BpfThreadMap :: new ( ) ; 
151-             expected_res. insert ( "vcpu" . to_string ( ) ,  Arc :: new ( bpf_prog) ) ; 
152-             assert_eq ! ( deserialize_binary( & bytes[ ..] ,  None ) . unwrap( ) ,  expected_res) ; 
153-         } 
154- 
155-         // Test deserialization with binary_limit. 
156-         { 
157-             let  bpf_prog = vec ! [ 0 ;  2 ] ; 
158- 
159-             let  mut  filter_map:  HashMap < String ,  BpfProgram >  = HashMap :: new ( ) ; 
160-             filter_map. insert ( "t1" . to_string ( ) ,  bpf_prog. clone ( ) ) ; 
161- 
162-             let  bytes = bincode:: serialize ( & filter_map) . unwrap ( ) ; 
163- 
164-             // Binary limit too low. 
165-             assert ! ( matches!( 
166-                 deserialize_binary( & bytes[ ..] ,  Some ( 20 ) ) . unwrap_err( ) , 
167-                 error
168-                     if  error. to_string( )  == "the size limit has been reached" 
169-             ) ) ; 
170- 
171-             let  mut  expected_res = BpfThreadMap :: new ( ) ; 
172-             expected_res. insert ( "t1" . to_string ( ) ,  Arc :: new ( bpf_prog) ) ; 
173- 
174-             // Correct binary limit. 
175-             assert_eq ! ( 
176-                 deserialize_binary( & bytes[ ..] ,  Some ( 50 ) ) . unwrap( ) , 
177-                 expected_res
178-             ) ; 
179-         } 
144+         let  bpf_prog = vec ! [ 0 ;  2 ] ; 
145+         let  mut  filter_map:  HashMap < String ,  BpfProgram >  = HashMap :: new ( ) ; 
146+         filter_map. insert ( "VcpU" . to_string ( ) ,  bpf_prog. clone ( ) ) ; 
147+         let  bytes = bincode:: serde:: encode_to_vec ( & filter_map,  BINCODE_CONFIG ) . unwrap ( ) ; 
148+ 
149+         let  mut  expected_res = BpfThreadMap :: new ( ) ; 
150+         expected_res. insert ( "vcpu" . to_string ( ) ,  Arc :: new ( bpf_prog) ) ; 
151+         assert_eq ! ( deserialize_binary( & bytes[ ..] ) . unwrap( ) ,  expected_res) ; 
152+ 
153+         let  bpf_prog = vec ! [ 0 ;  DESERIALIZATION_BYTES_LIMIT  + 1 ] ; 
154+         let  mut  filter_map:  HashMap < String ,  BpfProgram >  = HashMap :: new ( ) ; 
155+         filter_map. insert ( "VcpU" . to_string ( ) ,  bpf_prog. clone ( ) ) ; 
156+         let  bytes = bincode:: serde:: encode_to_vec ( & filter_map,  BINCODE_CONFIG ) . unwrap ( ) ; 
157+         assert ! ( matches!( 
158+             deserialize_binary( & bytes[ ..] ) . unwrap_err( ) , 
159+             bincode:: error:: DecodeError :: LimitExceeded 
160+         ) ) ; 
180161    } 
181162
182163    #[ test]  
0 commit comments