@@ -227,6 +227,7 @@ mod tests {
227227 use super :: super :: * ;
228228 use super :: * ;
229229 use crate :: virtio:: vsock:: defs:: { BACKEND_EVENT , EVQ_EVENT , RXQ_EVENT , TXQ_EVENT } ;
230+ use crate :: virtio:: vsock:: packet:: VSOCK_PKT_HDR_SIZE ;
230231
231232 #[ test]
232233 fn test_irq ( ) {
@@ -460,4 +461,106 @@ mod tests {
460461 other => panic ! ( "{:?}" , other) ,
461462 }
462463 }
464+
465+ // Creates an epoll handler context and attempts to assemble a VsockPkt from the descriptor
466+ // chains available on the rx and tx virtqueues, but first it will set the addr and len
467+ // of the descriptor specified by desc_idx to the provided values. We are only using this
468+ // function for testing error cases, so the asserts always expect is_err() to be true. When
469+ // desc_idx = 0 we are altering the header (first descriptor in the chain), and when
470+ // desc_idx = 1 we are altering the packet buffer.
471+ fn vsock_bof_helper ( test_ctx : & mut TestContext , desc_idx : usize , addr : u64 , len : u32 ) {
472+ use memory_model:: GuestAddress ;
473+
474+ assert ! ( desc_idx <= 1 ) ;
475+
476+ {
477+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
478+ ctx. guest_rxvq . dtable [ desc_idx] . addr . set ( addr) ;
479+ ctx. guest_rxvq . dtable [ desc_idx] . len . set ( len) ;
480+ // If the descriptor chain is already declared invalid, there's no reason to assemble
481+ // a packet.
482+ if let Some ( rx_desc) = ctx. handler . rxvq . pop ( & test_ctx. mem ) {
483+ assert ! ( VsockPacket :: from_rx_virtq_head( & rx_desc) . is_err( ) ) ;
484+ }
485+ }
486+
487+ {
488+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
489+
490+ // When modifiyng the buffer descriptor, make sure the len field is altered in the
491+ // vsock packet header descriptor as well.
492+ if desc_idx == 1 {
493+ // The vsock packet len field has offset 24 in the header.
494+ let hdr_len_addr = GuestAddress ( ctx. guest_txvq . dtable [ 0 ] . addr . get ( ) as usize + 24 ) ;
495+ test_ctx
496+ . mem
497+ . write_obj_at_addr ( len. to_le_bytes ( ) , hdr_len_addr)
498+ . unwrap ( ) ;
499+ }
500+
501+ ctx. guest_txvq . dtable [ desc_idx] . addr . set ( addr) ;
502+ ctx. guest_txvq . dtable [ desc_idx] . len . set ( len) ;
503+
504+ if let Some ( tx_desc) = ctx. handler . txvq . pop ( & test_ctx. mem ) {
505+ assert ! ( VsockPacket :: from_tx_virtq_head( & tx_desc) . is_err( ) ) ;
506+ }
507+ }
508+ }
509+
510+ #[ test]
511+ fn test_vsock_bof ( ) {
512+ use memory_model:: GuestAddress ;
513+
514+ const GAP_SIZE : usize = 768 << 20 ;
515+ const FIRST_AFTER_GAP : usize = 1 << 32 ;
516+ const GAP_START_ADDR : usize = FIRST_AFTER_GAP - GAP_SIZE ;
517+ const MIB : usize = 1 << 20 ;
518+
519+ let mut test_ctx = TestContext :: new ( ) ;
520+ test_ctx. mem = GuestMemory :: new ( & [
521+ ( GuestAddress ( 0 ) , 8 * MIB ) ,
522+ ( GuestAddress ( GAP_START_ADDR - MIB ) , MIB ) ,
523+ ( GuestAddress ( FIRST_AFTER_GAP ) , MIB ) ,
524+ ] )
525+ . unwrap ( ) ;
526+
527+ // The default configured descriptor chains are valid.
528+ {
529+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
530+ let rx_desc = ctx. handler . rxvq . pop ( & test_ctx. mem ) . unwrap ( ) ;
531+ assert ! ( VsockPacket :: from_rx_virtq_head( & rx_desc) . is_ok( ) ) ;
532+ }
533+
534+ {
535+ let mut ctx = test_ctx. create_epoll_handler_context ( ) ;
536+ let tx_desc = ctx. handler . txvq . pop ( & test_ctx. mem ) . unwrap ( ) ;
537+ assert ! ( VsockPacket :: from_tx_virtq_head( & tx_desc) . is_ok( ) ) ;
538+ }
539+
540+ // Let's check what happens when the header descriptor is right before the gap.
541+ vsock_bof_helper (
542+ & mut test_ctx,
543+ 0 ,
544+ GAP_START_ADDR as u64 - 1 ,
545+ VSOCK_PKT_HDR_SIZE as u32 ,
546+ ) ;
547+
548+ // Let's check what happens when the buffer descriptor crosses into the gap, but does
549+ // not go past its right edge.
550+ vsock_bof_helper (
551+ & mut test_ctx,
552+ 1 ,
553+ GAP_START_ADDR as u64 - 4 ,
554+ GAP_SIZE as u32 + 4 ,
555+ ) ;
556+
557+ // Let's modify the buffer descriptor addr and len such that it crosses over the MMIO gap,
558+ // and check we cannot assemble the VsockPkts.
559+ vsock_bof_helper (
560+ & mut test_ctx,
561+ 1 ,
562+ GAP_START_ADDR as u64 - 4 ,
563+ GAP_SIZE as u32 + 100 ,
564+ ) ;
565+ }
463566}
0 commit comments