@@ -18,6 +18,8 @@ pub enum IoVecError {
1818 WriteOnlyDescriptor ,
1919 /// Tried to create an 'IoVecMut` from a read-only descriptor chain
2020 ReadOnlyDescriptor ,
21+ /// Tried to create an `IoVec` or `IoVecMut` from a descriptor chain that was too large
22+ OverflowedDescriptor ,
2123 /// Guest memory error: {0}
2224 GuestMemory ( #[ from] GuestMemoryError ) ,
2325}
@@ -40,14 +42,14 @@ pub struct IoVecBuffer {
4042 // container of the memory regions included in this IO vector
4143 vecs : IoVecVec ,
4244 // Total length of the IoVecBuffer
43- len : usize ,
45+ len : u32 ,
4446}
4547
4648impl IoVecBuffer {
4749 /// Create an `IoVecBuffer` from a `DescriptorChain`
4850 pub fn from_descriptor_chain ( head : DescriptorChain ) -> Result < Self , IoVecError > {
4951 let mut vecs = IoVecVec :: new ( ) ;
50- let mut len = 0usize ;
52+ let mut len = 0u32 ;
5153
5254 let mut next_descriptor = Some ( head) ;
5355 while let Some ( desc) = next_descriptor {
@@ -68,7 +70,9 @@ impl IoVecBuffer {
6870 iov_base,
6971 iov_len : desc. len as size_t ,
7072 } ) ;
71- len += desc. len as usize ;
73+ len = len
74+ . checked_add ( desc. len )
75+ . ok_or ( IoVecError :: OverflowedDescriptor ) ?;
7276
7377 next_descriptor = desc. next_descriptor ( ) ;
7478 }
@@ -77,7 +81,7 @@ impl IoVecBuffer {
7781 }
7882
7983 /// 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 {
8185 self . len
8286 }
8387
@@ -106,7 +110,7 @@ impl IoVecBuffer {
106110 mut buf : & mut [ u8 ] ,
107111 offset : usize ,
108112 ) -> Result < ( ) , VolatileMemoryError > {
109- if offset < self . len ( ) {
113+ if offset < self . len ( ) as usize {
110114 let expected = buf. len ( ) ;
111115 let bytes_read = self . read_volatile_at ( & mut buf, offset, expected) ?;
112116
@@ -188,14 +192,14 @@ pub struct IoVecBufferMut {
188192 // container of the memory regions included in this IO vector
189193 vecs : IoVecVec ,
190194 // Total length of the IoVecBufferMut
191- len : usize ,
195+ len : u32 ,
192196}
193197
194198impl IoVecBufferMut {
195199 /// Create an `IoVecBufferMut` from a `DescriptorChain`
196200 pub fn from_descriptor_chain ( head : DescriptorChain ) -> Result < Self , IoVecError > {
197201 let mut vecs = IoVecVec :: new ( ) ;
198- let mut len = 0usize ;
202+ let mut len = 0u32 ;
199203
200204 for desc in head {
201205 if !desc. is_write_only ( ) {
@@ -217,14 +221,16 @@ impl IoVecBufferMut {
217221 iov_base,
218222 iov_len : desc. len as size_t ,
219223 } ) ;
220- len += desc. len as usize ;
224+ len = len
225+ . checked_add ( desc. len )
226+ . ok_or ( IoVecError :: OverflowedDescriptor ) ?;
221227 }
222228
223229 Ok ( Self { vecs, len } )
224230 }
225231
226232 /// 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 {
228234 self . len
229235 }
230236
@@ -244,7 +250,7 @@ impl IoVecBufferMut {
244250 mut buf : & [ u8 ] ,
245251 offset : usize ,
246252 ) -> Result < ( ) , VolatileMemoryError > {
247- if offset < self . len ( ) {
253+ if offset < self . len ( ) as usize {
248254 let expected = buf. len ( ) ;
249255 let bytes_written = self . write_volatile_at ( & mut buf, offset, expected) ?;
250256
@@ -335,18 +341,18 @@ mod tests {
335341 iov_len: buf. len( ) ,
336342 } ]
337343 . into ( ) ,
338- len : buf. len ( ) ,
344+ len : buf. len ( ) . try_into ( ) . unwrap ( ) ,
339345 }
340346 }
341347 }
342348
343349 impl < ' a > From < Vec < & ' a [ u8 ] > > for IoVecBuffer {
344350 fn from ( buffer : Vec < & ' a [ u8 ] > ) -> Self {
345- let mut len = 0 ;
351+ let mut len = 0_u32 ;
346352 let vecs = buffer
347353 . into_iter ( )
348354 . map ( |slice| {
349- len += slice. len ( ) ;
355+ len += TryInto :: < u32 > :: try_into ( slice. len ( ) ) . unwrap ( ) ;
350356 iovec {
351357 iov_base : slice. as_ptr ( ) as * mut c_void ,
352358 iov_len : slice. len ( ) ,
@@ -366,7 +372,7 @@ mod tests {
366372 iov_len: buf. len( ) ,
367373 } ]
368374 . into ( ) ,
369- len : buf. len ( ) ,
375+ len : buf. len ( ) . try_into ( ) . unwrap ( ) ,
370376 }
371377 }
372378 }
@@ -607,7 +613,6 @@ mod verification {
607613
608614 use libc:: { c_void, iovec} ;
609615 use vm_memory:: bitmap:: BitmapSlice ;
610- use vm_memory:: volatile_memory:: Error ;
611616 use vm_memory:: VolatileSlice ;
612617
613618 use super :: { IoVecBuffer , IoVecBufferMut , IoVecVec } ;
@@ -622,10 +627,10 @@ mod verification {
622627 // >= 1.
623628 const MAX_DESC_LENGTH : usize = 4 ;
624629
625- fn create_iovecs ( mem : * mut u8 , size : usize ) -> ( IoVecVec , usize ) {
630+ fn create_iovecs ( mem : * mut u8 , size : usize ) -> ( IoVecVec , u32 ) {
626631 let nr_descs: usize = kani:: any_where ( |& n| n <= MAX_DESC_LENGTH ) ;
627632 let mut vecs: Vec < iovec > = Vec :: with_capacity ( nr_descs) ;
628- let mut len = 0usize ;
633+ let mut len = 0u32 ;
629634 for _ in 0 ..nr_descs {
630635 // The `IoVecBuffer(Mut)` constructors ensure that the memory region described by every
631636 // `Descriptor` in the chain is a valid, i.e. it is memory with then guest's memory
@@ -637,7 +642,7 @@ mod verification {
637642 let iov_base = unsafe { mem. offset ( addr. try_into ( ) . unwrap ( ) ) } as * mut c_void ;
638643
639644 vecs. push ( iovec { iov_base, iov_len } ) ;
640- len += iov_len;
645+ len += u32 :: try_from ( iov_len) . unwrap ( ) ;
641646 }
642647
643648 ( vecs, len)
@@ -712,7 +717,7 @@ mod verification {
712717 let iov: IoVecBuffer = kani:: any ( ) ;
713718
714719 let mut buf = vec ! [ 0 ; GUEST_MEMORY_SIZE ] ;
715- let offset: usize = kani:: any ( ) ;
720+ let offset: u32 = kani:: any ( ) ;
716721
717722 // We can't really check the contents that the operation here writes into `buf`, because
718723 // our `IoVecBuffer` being completely arbitrary can contain overlapping memory regions, so
@@ -724,9 +729,13 @@ mod verification {
724729 // Furthermore, we know our Read-/WriteVolatile implementation above is infallible, so
725730 // provided that the logic inside read_volatile_at is correct, we should always get Ok(...)
726731 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 )
730739 ) ;
731740 }
732741
@@ -737,7 +746,7 @@ mod verification {
737746 let mut iov_mut: IoVecBufferMut = kani:: any ( ) ;
738747
739748 let mut buf = kani:: vec:: any_vec :: < u8 , GUEST_MEMORY_SIZE > ( ) ;
740- let offset: usize = kani:: any ( ) ;
749+ let offset: u32 = kani:: any ( ) ;
741750
742751 // We can't really check the contents that the operation here writes into `IoVecBufferMut`,
743752 // because our `IoVecBufferMut` being completely arbitrary can contain overlapping memory
@@ -750,9 +759,13 @@ mod verification {
750759 // provided that the logic inside write_volatile_at is correct, we should always get Ok(...)
751760 assert_eq ! (
752761 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+ )
754767 . unwrap( ) ,
755- buf. len( ) . min( iov_mut. len( ) . saturating_sub( offset) )
768+ buf. len( ) . min( iov_mut. len( ) . saturating_sub( offset) as usize )
756769 ) ;
757770 }
758771}
0 commit comments