@@ -227,6 +227,7 @@ mod tests {
227
227
use super :: super :: * ;
228
228
use super :: * ;
229
229
use crate :: virtio:: vsock:: defs:: { BACKEND_EVENT , EVQ_EVENT , RXQ_EVENT , TXQ_EVENT } ;
230
+ use crate :: virtio:: vsock:: packet:: VSOCK_PKT_HDR_SIZE ;
230
231
231
232
#[ test]
232
233
fn test_irq ( ) {
@@ -460,4 +461,106 @@ mod tests {
460
461
other => panic ! ( "{:?}" , other) ,
461
462
}
462
463
}
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
+ }
463
566
}
0 commit comments