Skip to content

Commit e1eec13

Browse files
alexandruagacatangiu
authored andcommitted
added supplementary vsock and memory unit tests
Signed-off-by: Alexandru Agache <[email protected]>
1 parent cdc628f commit e1eec13

File tree

4 files changed

+122
-2
lines changed

4 files changed

+122
-2
lines changed

devices/src/virtio/queue.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,8 @@ pub mod tests {
606606

607607
#[test]
608608
fn test_checked_new_descriptor_chain() {
609-
let m = &GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
609+
let m = &GuestMemory::new(&[(GuestAddress(0), 0x10000), (GuestAddress(0x20000), 0x2000)])
610+
.unwrap();
610611
let vq = VirtQueue::new(GuestAddress(0), m, 16);
611612

612613
assert!(vq.end().0 < 0x1000);
@@ -621,6 +622,14 @@ pub mod tests {
621622
vq.dtable[0].addr.set(0x0fff_ffff_ffff);
622623
assert!(DescriptorChain::checked_new(m, vq.dtable_start(), 16, 0).is_none());
623624

625+
// The following configuration is invalid because the addr + len crosses over the gap
626+
// between the two memory regions we configured.
627+
{
628+
vq.dtable[0].addr.set(0x1000);
629+
vq.dtable[0].len.set(0x20000);
630+
assert!(DescriptorChain::checked_new(m, vq.dtable_start(), 16, 0).is_none());
631+
}
632+
624633
// let's create some invalid chains
625634

626635
{

devices/src/virtio/vsock/device.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,5 +322,4 @@ mod tests {
322322
)
323323
.unwrap();
324324
}
325-
326325
}

devices/src/virtio/vsock/epoll_handler.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

devices/src/virtio/vsock/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,14 +237,21 @@ mod tests {
237237
}
238238
impl VsockChannel for TestBackend {
239239
fn recv_pkt(&mut self, _pkt: &mut VsockPacket) -> Result<()> {
240+
let cool_buf = [0xDu8, 0xE, 0xA, 0xD, 0xB, 0xE, 0xE, 0xF];
240241
match self.rx_err.take() {
241242
None => {
243+
if let Some(buf) = _pkt.buf_mut() {
244+
for i in 0..buf.len() {
245+
buf[i] = cool_buf[i % cool_buf.len()];
246+
}
247+
}
242248
self.rx_ok_cnt += 1;
243249
Ok(())
244250
}
245251
Some(e) => Err(e),
246252
}
247253
}
254+
248255
fn send_pkt(&mut self, _pkt: &VsockPacket) -> Result<()> {
249256
match self.tx_err.take() {
250257
None => {
@@ -254,6 +261,7 @@ mod tests {
254261
Some(e) => Err(e),
255262
}
256263
}
264+
257265
fn has_pending_rx(&self) -> bool {
258266
self.pending_rx
259267
}
@@ -318,6 +326,7 @@ mod tests {
318326
1,
319327
);
320328
guest_rxvq.dtable[1].set(0x0040_1000, 4096, VIRTQ_DESC_F_WRITE, 0);
329+
321330
guest_rxvq.avail.ring[0].set(0);
322331
guest_rxvq.avail.idx.set(1);
323332

0 commit comments

Comments
 (0)