@@ -18,6 +18,8 @@ pub enum IoVecError {
18
18
WriteOnlyDescriptor ,
19
19
/// Tried to create an 'IoVecMut` from a read-only descriptor chain
20
20
ReadOnlyDescriptor ,
21
+ /// Tried to create an `IoVec` or `IoVecMut` from a descriptor chain that was too large
22
+ OverflowedDescriptor ,
21
23
/// Guest memory error: {0}
22
24
GuestMemory ( #[ from] GuestMemoryError ) ,
23
25
}
@@ -40,14 +42,14 @@ pub struct IoVecBuffer {
40
42
// container of the memory regions included in this IO vector
41
43
vecs : IoVecVec ,
42
44
// Total length of the IoVecBuffer
43
- len : usize ,
45
+ len : u32 ,
44
46
}
45
47
46
48
impl IoVecBuffer {
47
49
/// Create an `IoVecBuffer` from a `DescriptorChain`
48
50
pub fn from_descriptor_chain ( head : DescriptorChain ) -> Result < Self , IoVecError > {
49
51
let mut vecs = IoVecVec :: new ( ) ;
50
- let mut len = 0usize ;
52
+ let mut len = 0u32 ;
51
53
52
54
let mut next_descriptor = Some ( head) ;
53
55
while let Some ( desc) = next_descriptor {
@@ -68,7 +70,9 @@ impl IoVecBuffer {
68
70
iov_base,
69
71
iov_len : desc. len as size_t ,
70
72
} ) ;
71
- len += desc. len as usize ;
73
+ len = len
74
+ . checked_add ( desc. len )
75
+ . ok_or ( IoVecError :: OverflowedDescriptor ) ?;
72
76
73
77
next_descriptor = desc. next_descriptor ( ) ;
74
78
}
@@ -77,7 +81,7 @@ impl IoVecBuffer {
77
81
}
78
82
79
83
/// Get the total length of the memory regions covered by this `IoVecBuffer`
80
- pub ( crate ) fn len ( & self ) -> usize {
84
+ pub ( crate ) fn len ( & self ) -> u32 {
81
85
self . len
82
86
}
83
87
@@ -106,7 +110,7 @@ impl IoVecBuffer {
106
110
mut buf : & mut [ u8 ] ,
107
111
offset : usize ,
108
112
) -> Result < ( ) , VolatileMemoryError > {
109
- if offset < self . len ( ) {
113
+ if offset < self . len ( ) as usize {
110
114
let expected = buf. len ( ) ;
111
115
let bytes_read = self . read_volatile_at ( & mut buf, offset, expected) ?;
112
116
@@ -188,14 +192,14 @@ pub struct IoVecBufferMut {
188
192
// container of the memory regions included in this IO vector
189
193
vecs : IoVecVec ,
190
194
// Total length of the IoVecBufferMut
191
- len : usize ,
195
+ len : u32 ,
192
196
}
193
197
194
198
impl IoVecBufferMut {
195
199
/// Create an `IoVecBufferMut` from a `DescriptorChain`
196
200
pub fn from_descriptor_chain ( head : DescriptorChain ) -> Result < Self , IoVecError > {
197
201
let mut vecs = IoVecVec :: new ( ) ;
198
- let mut len = 0usize ;
202
+ let mut len = 0u32 ;
199
203
200
204
for desc in head {
201
205
if !desc. is_write_only ( ) {
@@ -217,14 +221,16 @@ impl IoVecBufferMut {
217
221
iov_base,
218
222
iov_len : desc. len as size_t ,
219
223
} ) ;
220
- len += desc. len as usize ;
224
+ len = len
225
+ . checked_add ( desc. len )
226
+ . ok_or ( IoVecError :: OverflowedDescriptor ) ?;
221
227
}
222
228
223
229
Ok ( Self { vecs, len } )
224
230
}
225
231
226
232
/// Get the total length of the memory regions covered by this `IoVecBuffer`
227
- pub ( crate ) fn len ( & self ) -> usize {
233
+ pub ( crate ) fn len ( & self ) -> u32 {
228
234
self . len
229
235
}
230
236
@@ -244,7 +250,7 @@ impl IoVecBufferMut {
244
250
mut buf : & [ u8 ] ,
245
251
offset : usize ,
246
252
) -> Result < ( ) , VolatileMemoryError > {
247
- if offset < self . len ( ) {
253
+ if offset < self . len ( ) as usize {
248
254
let expected = buf. len ( ) ;
249
255
let bytes_written = self . write_volatile_at ( & mut buf, offset, expected) ?;
250
256
@@ -335,18 +341,18 @@ mod tests {
335
341
iov_len: buf. len( ) ,
336
342
} ]
337
343
. into ( ) ,
338
- len : buf. len ( ) ,
344
+ len : buf. len ( ) . try_into ( ) . unwrap ( ) ,
339
345
}
340
346
}
341
347
}
342
348
343
349
impl < ' a > From < Vec < & ' a [ u8 ] > > for IoVecBuffer {
344
350
fn from ( buffer : Vec < & ' a [ u8 ] > ) -> Self {
345
- let mut len = 0 ;
351
+ let mut len = 0_u32 ;
346
352
let vecs = buffer
347
353
. into_iter ( )
348
354
. map ( |slice| {
349
- len += slice. len ( ) ;
355
+ len += TryInto :: < u32 > :: try_into ( slice. len ( ) ) . unwrap ( ) ;
350
356
iovec {
351
357
iov_base : slice. as_ptr ( ) as * mut c_void ,
352
358
iov_len : slice. len ( ) ,
@@ -366,7 +372,7 @@ mod tests {
366
372
iov_len: buf. len( ) ,
367
373
} ]
368
374
. into ( ) ,
369
- len : buf. len ( ) ,
375
+ len : buf. len ( ) . try_into ( ) . unwrap ( ) ,
370
376
}
371
377
}
372
378
}
@@ -607,7 +613,6 @@ mod verification {
607
613
608
614
use libc:: { c_void, iovec} ;
609
615
use vm_memory:: bitmap:: BitmapSlice ;
610
- use vm_memory:: volatile_memory:: Error ;
611
616
use vm_memory:: VolatileSlice ;
612
617
613
618
use super :: { IoVecBuffer , IoVecBufferMut , IoVecVec } ;
@@ -622,10 +627,10 @@ mod verification {
622
627
// >= 1.
623
628
const MAX_DESC_LENGTH : usize = 4 ;
624
629
625
- fn create_iovecs ( mem : * mut u8 , size : usize ) -> ( IoVecVec , usize ) {
630
+ fn create_iovecs ( mem : * mut u8 , size : usize ) -> ( IoVecVec , u32 ) {
626
631
let nr_descs: usize = kani:: any_where ( |& n| n <= MAX_DESC_LENGTH ) ;
627
632
let mut vecs: Vec < iovec > = Vec :: with_capacity ( nr_descs) ;
628
- let mut len = 0usize ;
633
+ let mut len = 0u32 ;
629
634
for _ in 0 ..nr_descs {
630
635
// The `IoVecBuffer(Mut)` constructors ensure that the memory region described by every
631
636
// `Descriptor` in the chain is a valid, i.e. it is memory with then guest's memory
@@ -637,7 +642,7 @@ mod verification {
637
642
let iov_base = unsafe { mem. offset ( addr. try_into ( ) . unwrap ( ) ) } as * mut c_void ;
638
643
639
644
vecs. push ( iovec { iov_base, iov_len } ) ;
640
- len += iov_len;
645
+ len += u32 :: try_from ( iov_len) . unwrap ( ) ;
641
646
}
642
647
643
648
( vecs, len)
@@ -712,7 +717,7 @@ mod verification {
712
717
let iov: IoVecBuffer = kani:: any ( ) ;
713
718
714
719
let mut buf = vec ! [ 0 ; GUEST_MEMORY_SIZE ] ;
715
- let offset: usize = kani:: any ( ) ;
720
+ let offset: u32 = kani:: any ( ) ;
716
721
717
722
// We can't really check the contents that the operation here writes into `buf`, because
718
723
// our `IoVecBuffer` being completely arbitrary can contain overlapping memory regions, so
@@ -724,9 +729,13 @@ mod verification {
724
729
// Furthermore, we know our Read-/WriteVolatile implementation above is infallible, so
725
730
// provided that the logic inside read_volatile_at is correct, we should always get Ok(...)
726
731
assert_eq ! (
727
- iov. read_volatile_at( & mut KaniBuffer ( & mut buf) , offset, GUEST_MEMORY_SIZE )
728
- . unwrap( ) ,
729
- buf. len( ) . min( iov. len( ) . saturating_sub( offset) )
732
+ iov. read_volatile_at(
733
+ & mut KaniBuffer ( & mut buf) ,
734
+ offset as usize ,
735
+ GUEST_MEMORY_SIZE
736
+ )
737
+ . unwrap( ) ,
738
+ buf. len( ) . min( iov. len( ) . saturating_sub( offset) as usize )
730
739
) ;
731
740
}
732
741
@@ -737,7 +746,7 @@ mod verification {
737
746
let mut iov_mut: IoVecBufferMut = kani:: any ( ) ;
738
747
739
748
let mut buf = kani:: vec:: any_vec :: < u8 , GUEST_MEMORY_SIZE > ( ) ;
740
- let offset: usize = kani:: any ( ) ;
749
+ let offset: u32 = kani:: any ( ) ;
741
750
742
751
// We can't really check the contents that the operation here writes into `IoVecBufferMut`,
743
752
// because our `IoVecBufferMut` being completely arbitrary can contain overlapping memory
@@ -750,9 +759,13 @@ mod verification {
750
759
// provided that the logic inside write_volatile_at is correct, we should always get Ok(...)
751
760
assert_eq ! (
752
761
iov_mut
753
- . write_volatile_at( & mut KaniBuffer ( & mut buf) , offset, GUEST_MEMORY_SIZE )
762
+ . write_volatile_at(
763
+ & mut KaniBuffer ( & mut buf) ,
764
+ offset as usize ,
765
+ GUEST_MEMORY_SIZE
766
+ )
754
767
. unwrap( ) ,
755
- buf. len( ) . min( iov_mut. len( ) . saturating_sub( offset) )
768
+ buf. len( ) . min( iov_mut. len( ) . saturating_sub( offset) as usize )
756
769
) ;
757
770
}
758
771
}
0 commit comments