@@ -113,17 +113,16 @@ impl<'a, M: GuestMemory> DescriptorChain<'a, M> {
113
113
// bounds.
114
114
let desc_head = desc_table. unchecked_add ( u64:: from ( index) * 16 ) ;
115
115
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
+
127
126
let chain = DescriptorChain {
128
127
mem,
129
128
desc_table,
@@ -423,7 +422,12 @@ impl Queue {
423
422
// `self.is_valid()` already performed all the bound checks on the descriptor table
424
423
// and virtq rings, so it's safe to unwrap guest memory reads and to use unchecked
425
424
// 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 > ( ) } ;
427
431
428
432
DescriptorChain :: checked_new ( mem, self . desc_table , self . actual_size ( ) , desc_index) . map (
429
433
|dc| {
@@ -1218,9 +1222,6 @@ mod tests {
1218
1222
// index >= queue_size
1219
1223
assert ! ( DescriptorChain :: checked_new( m, vq. dtable_start( ) , 16 , 16 ) . is_none( ) ) ;
1220
1224
1221
- // desc_table address is way off
1222
- assert ! ( DescriptorChain :: checked_new( m, GuestAddress ( 0x00ff_ffff_ffff ) , 16 , 0 ) . is_none( ) ) ;
1223
-
1224
1225
// Let's create an invalid chain.
1225
1226
{
1226
1227
// The first desc has a normal len, and the next_descriptor flag is set.
@@ -1254,6 +1255,16 @@ mod tests {
1254
1255
}
1255
1256
}
1256
1257
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
+
1257
1268
#[ test]
1258
1269
fn test_queue_validation ( ) {
1259
1270
let m = & default_mem ( ) ;
0 commit comments