Skip to content

Commit 2fd78ae

Browse files
committed
fix: pmem: add validation for head and status descriptors lengths
Head and status descriptors must be 4 bytes long by the spec. Add validation for this. Signed-off-by: Egor Lazarchuk <yegorlz@amazon.co.uk>
1 parent 80ab750 commit 2fd78ae

1 file changed

Lines changed: 45 additions & 0 deletions

File tree

src/vmm/src/devices/virtio/pmem/device.rs

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

Comments
 (0)