@@ -113,17 +113,16 @@ impl<'a, M: GuestMemory> DescriptorChain<'a, M> {
113113 // bounds.
114114 let desc_head = desc_table. unchecked_add ( u64:: from ( index) * 16 ) ;
115115
116- // These reads can't fail unless Guest memory is hopelessly broken.
117- let desc = match mem. read_obj :: < Descriptor > ( desc_head) {
118- Ok ( ret) => ret,
119- Err ( err) => {
120- error ! (
121- "Failed to read virtio descriptor from memory at address {:#x}: {}" ,
122- desc_head. 0 , err
123- ) ;
124- return None ;
125- }
126- } ;
116+ // SAFETY:
117+ // This can't fail as we checked the `desc_head`
118+ let ptr = mem. get_host_address ( desc_head) . unwrap ( ) ;
119+
120+ // SAFETY:
121+ // Safe as we know that `ptr` is inside guest memory and
122+ // following `std::mem::size_of::<Descriptor>` bytes belong
123+ // to the descriptor table
124+ let desc: & Descriptor = unsafe { & * ptr. cast :: < Descriptor > ( ) } ;
125+
127126 let chain = DescriptorChain {
128127 mem,
129128 desc_table,
@@ -423,7 +422,12 @@ impl Queue {
423422 // `self.is_valid()` already performed all the bound checks on the descriptor table
424423 // and virtq rings, so it's safe to unwrap guest memory reads and to use unchecked
425424 // offsets.
426- let desc_index: u16 = mem. read_obj ( desc_index_address) . unwrap ( ) ;
425+ let slice = mem
426+ . get_slice ( desc_index_address, std:: mem:: size_of :: < u16 > ( ) )
427+ . unwrap ( ) ;
428+ // SAFETY:
429+ // We transforming valid memory slice
430+ let desc_index = unsafe { * slice. ptr_guard ( ) . as_ptr ( ) . cast :: < u16 > ( ) } ;
427431
428432 DescriptorChain :: checked_new ( mem, self . desc_table , self . actual_size ( ) , desc_index) . map (
429433 |dc| {
@@ -1218,9 +1222,6 @@ mod tests {
12181222 // index >= queue_size
12191223 assert ! ( DescriptorChain :: checked_new( m, vq. dtable_start( ) , 16 , 16 ) . is_none( ) ) ;
12201224
1221- // desc_table address is way off
1222- assert ! ( DescriptorChain :: checked_new( m, GuestAddress ( 0x00ff_ffff_ffff ) , 16 , 0 ) . is_none( ) ) ;
1223-
12241225 // Let's create an invalid chain.
12251226 {
12261227 // The first desc has a normal len, and the next_descriptor flag is set.
@@ -1254,6 +1255,16 @@ mod tests {
12541255 }
12551256 }
12561257
1258+ #[ test]
1259+ #[ should_panic]
1260+ fn test_checked_new_descriptor_chain_panic ( ) {
1261+ let m = & multi_region_mem ( & [ ( GuestAddress ( 0 ) , 0x10000 ) ] ) ;
1262+
1263+ // `checked_new` does assume that `desc_table` is valid.
1264+ // When desc_table address is way off, it should panic.
1265+ DescriptorChain :: checked_new ( m, GuestAddress ( 0x00ff_ffff_ffff ) , 16 , 0 ) ;
1266+ }
1267+
12571268 #[ test]
12581269 fn test_queue_validation ( ) {
12591270 let m = & default_mem ( ) ;
0 commit comments