@@ -44,6 +44,10 @@ pub enum PmemError {
4444 ReadOnlyDescriptor ,
4545 /// Unexpected write-only descriptor
4646 WriteOnlyDescriptor ,
47+ /// Head descriptor has invalid length of {0} instead of 4
48+ Non4byteHeadDescriptor ( u32 ) ,
49+ /// Status descriptor has invalid length of {0} instead of 4
50+ Non4byteStatusDescriptor ( u32 ) ,
4751 /// UnknownRequestType: {0}
4852 UnknownRequestType ( u32 ) ,
4953 /// Descriptor chain too short
@@ -286,6 +290,9 @@ impl Pmem {
286290 if head. is_write_only ( ) {
287291 return Err ( PmemError :: WriteOnlyDescriptor ) ;
288292 }
293+ if head. len != 4 {
294+ return Err ( PmemError :: Non4byteHeadDescriptor ( head. len ) ) ;
295+ }
289296 let request: u32 = active_state. mem . read_obj ( head. addr ) ?;
290297 if request != VIRTIO_PMEM_REQ_TYPE_FLUSH {
291298 return Err ( PmemError :: UnknownRequestType ( request) ) ;
@@ -296,6 +303,9 @@ impl Pmem {
296303 if !status_descriptor. is_write_only ( ) {
297304 return Err ( PmemError :: ReadOnlyDescriptor ) ;
298305 }
306+ if status_descriptor. len != 4 {
307+ return Err ( PmemError :: Non4byteStatusDescriptor ( status_descriptor. len ) ) ;
308+ }
299309 let mut result = SUCCESS ;
300310 // SAFETY: We are calling the system call with valid arguments and checking the returned
301311 // value
@@ -556,5 +566,40 @@ mod tests {
556566 PmemError :: ReadOnlyDescriptor ,
557567 ) ) ;
558568 }
569+
570+ // Invalid length head descriptor
571+ {
572+ vq. avail . ring [ 0 ] . set ( 0 ) ;
573+ vq. dtable [ 0 ] . set ( 0x1000 , 0x69 , VIRTQ_DESC_F_NEXT , 1 ) ;
574+ mem. write_obj :: < u32 > ( 0 , GuestAddress ( 0x1000 ) ) . unwrap ( ) ;
575+
576+ pmem. queues [ 0 ] = vq. create_queue ( ) ;
577+ vq. used . idx . set ( 0 ) ;
578+ vq. avail . idx . set ( 1 ) ;
579+ let head = pmem. queues [ 0 ] . pop ( ) . unwrap ( ) . unwrap ( ) ;
580+ assert ! ( matches!(
581+ pmem. process_chain( head) . unwrap_err( ) ,
582+ PmemError :: Non4byteHeadDescriptor ( 0x69 ) ,
583+ ) ) ;
584+ }
585+
586+ // Invalid length status descriptor
587+ {
588+ vq. avail . ring [ 0 ] . set ( 0 ) ;
589+ vq. dtable [ 0 ] . set ( 0x1000 , 4 , VIRTQ_DESC_F_NEXT , 1 ) ;
590+ vq. avail . ring [ 1 ] . set ( 1 ) ;
591+ vq. dtable [ 1 ] . set ( 0x2000 , 0x69 , VIRTQ_DESC_F_WRITE , 0 ) ;
592+ mem. write_obj :: < u32 > ( 0 , GuestAddress ( 0x1000 ) ) . unwrap ( ) ;
593+ mem. write_obj :: < u32 > ( 0x69 , GuestAddress ( 0x2000 ) ) . unwrap ( ) ;
594+
595+ pmem. queues [ 0 ] = vq. create_queue ( ) ;
596+ vq. used . idx . set ( 0 ) ;
597+ vq. avail . idx . set ( 1 ) ;
598+ let head = pmem. queues [ 0 ] . pop ( ) . unwrap ( ) . unwrap ( ) ;
599+ assert ! ( matches!(
600+ pmem. process_chain( head) . unwrap_err( ) ,
601+ PmemError :: Non4byteStatusDescriptor ( 0x69 ) ,
602+ ) ) ;
603+ }
559604 }
560605}
0 commit comments