Skip to content

Commit fc296c9

Browse files
committed
fix(vmnet): skip zero-length buffers
The second buffer returned from split_at_checked may have length 0. Signed-off-by: Changyuan Lyu <changyuanl@google.com>
1 parent e4c317d commit fc296c9

1 file changed

Lines changed: 29 additions & 45 deletions

File tree

alioth/src/virtio/dev/net/vmnet.rs

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -404,28 +404,7 @@ impl VirtioMio for Net {
404404

405405
fn read_from_vmnet(interface: *mut VmnetInterface) -> impl FnMut(&mut DescChain) -> Result<Status> {
406406
move |chain: &mut DescChain| {
407-
let mut trim_len = size_of::<VirtioNetHdr>();
408-
let mut iov = Vec::with_capacity(chain.writable.len());
409-
410-
for buf in chain.writable.iter_mut() {
411-
if trim_len > 0 {
412-
if let Some((_, tail)) = buf.split_at_mut_checked(trim_len) {
413-
iov.push(libc::iovec {
414-
iov_base: tail.as_ptr() as *mut c_void,
415-
iov_len: tail.len(),
416-
});
417-
trim_len = 0;
418-
} else {
419-
trim_len -= buf.len();
420-
}
421-
} else {
422-
iov.push(libc::iovec {
423-
iov_base: buf.as_ptr() as *mut c_void,
424-
iov_len: buf.len(),
425-
});
426-
}
427-
}
428-
407+
let mut iov = trim_desc_chain(chain.writable.iter().map(|b| &**b));
429408
let size = iov.iter().map(|s| s.iov_len).sum();
430409
let mut packets = VmPktDesc {
431410
vm_pkt_size: size,
@@ -455,32 +434,11 @@ fn read_from_vmnet(interface: *mut VmnetInterface) -> impl FnMut(&mut DescChain)
455434

456435
fn write_to_vmnet(interface: *mut VmnetInterface) -> impl FnMut(&mut DescChain) -> Result<Status> {
457436
move |chain: &mut DescChain| {
458-
let mut trim_len = size_of::<VirtioNetHdr>();
459-
let mut iov = Vec::with_capacity(chain.readable.len());
460-
461-
for buf in chain.readable.iter() {
462-
if trim_len > 0 {
463-
if let Some((_, tail)) = buf.split_at_checked(trim_len) {
464-
iov.push(libc::iovec {
465-
iov_base: tail.as_ptr() as *mut c_void,
466-
iov_len: tail.len(),
467-
});
468-
trim_len = 0;
469-
} else {
470-
trim_len -= buf.len();
471-
}
472-
} else {
473-
iov.push(libc::iovec {
474-
iov_base: buf.as_ptr() as *mut c_void,
475-
iov_len: buf.len(),
476-
});
477-
}
478-
}
479-
437+
let mut iov = trim_desc_chain(chain.readable.iter().map(|b| &**b));
480438
let size = iov.iter().map(|s| s.iov_len).sum();
481439
let mut packets = VmPktDesc {
482440
vm_pkt_size: size,
483-
vm_pkt_iov: iov.as_ptr() as *mut libc::iovec,
441+
vm_pkt_iov: iov.as_mut_ptr(),
484442
vm_pkt_iovcnt: iov.len() as u32,
485443
vm_flags: 0,
486444
};
@@ -508,3 +466,29 @@ impl DevParam for NetVmnetParam {
508466
Net::new(self, name)
509467
}
510468
}
469+
470+
fn trim_desc_chain<'m>(bufs: impl Iterator<Item = &'m [u8]>) -> Vec<libc::iovec> {
471+
let mut iov = Vec::new();
472+
let mut trim_len = size_of::<VirtioNetHdr>();
473+
474+
for buf in bufs {
475+
let b = if trim_len > 0 {
476+
if let Some((_, tail)) = buf.split_at_checked(trim_len)
477+
&& !tail.is_empty()
478+
{
479+
trim_len = 0;
480+
tail
481+
} else {
482+
trim_len -= buf.len();
483+
continue;
484+
}
485+
} else {
486+
buf
487+
};
488+
iov.push(libc::iovec {
489+
iov_base: b.as_ptr() as *mut c_void,
490+
iov_len: b.len(),
491+
});
492+
}
493+
iov
494+
}

0 commit comments

Comments
 (0)