Skip to content

Commit e839b08

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

File tree

3 files changed

+122
-1
lines changed

3 files changed

+122
-1
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/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
@@ -241,14 +241,21 @@ mod tests {
241241
}
242242
impl VsockChannel for TestBackend {
243243
fn recv_pkt(&mut self, _pkt: &mut VsockPacket) -> Result<()> {
244+
let cool_buf = [0xDu8, 0xE, 0xA, 0xD, 0xB, 0xE, 0xE, 0xF];
244245
match self.rx_err.take() {
245246
None => {
247+
if let Some(buf) = _pkt.buf_mut() {
248+
for i in 0..buf.len() {
249+
buf[i] = cool_buf[i % cool_buf.len()];
250+
}
251+
}
246252
self.rx_ok_cnt += 1;
247253
Ok(())
248254
}
249255
Some(e) => Err(e),
250256
}
251257
}
258+
252259
fn send_pkt(&mut self, _pkt: &VsockPacket) -> Result<()> {
253260
match self.tx_err.take() {
254261
None => {
@@ -258,6 +265,7 @@ mod tests {
258265
Some(e) => Err(e),
259266
}
260267
}
268+
261269
fn has_pending_rx(&self) -> bool {
262270
self.pending_rx
263271
}
@@ -322,6 +330,7 @@ mod tests {
322330
1,
323331
);
324332
guest_rxvq.dtable[1].set(0x0040_1000, 4096, VIRTQ_DESC_F_WRITE, 0);
333+
325334
guest_rxvq.avail.ring[0].set(0);
326335
guest_rxvq.avail.idx.set(1);
327336

0 commit comments

Comments
 (0)