From 50fc2dbdfac25b228d7f7907a5ef471ac226b190 Mon Sep 17 00:00:00 2001 From: Yuchen Wu Date: Thu, 1 Apr 2021 17:39:30 -0700 Subject: Fix spurious errors using `sendmmsg` with multiple cmsgs Before this fix, the buffer that holds cmsgs may move due to the resize() call. That causes msg_hdr pointing to invalid memory, which ends up breaking the sendmmsg() call, resulting in EINVAL. This change fixes it by avoiding re-allocating the buffers. --- CHANGELOG.md | 2 ++ src/sys/socket/mod.rs | 11 +++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9636942d..3faafca7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Allow `sockaddr_ll` size, as reported by the Linux kernel, to be smaller then it's definition (#[1395](https://github.com/nix-rust/nix/pull/1395)) +- Fix spurious errors using `sendmmsg` with multiple cmsgs + (#[1414](https://github.com/nix-rust/nix/pull/1414)) ### Removed diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 2725e57c..76bfa761 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1101,23 +1101,22 @@ pub fn sendmmsg<'a, I, C>( let mut output = Vec::::with_capacity(reserve_items); - let mut cmsgs_buffer = vec![0u8; 0]; + let mut cmsgs_buffers = Vec::>::with_capacity(reserve_items); for d in iter { - let cmsgs_start = cmsgs_buffer.len(); - let cmsgs_required_capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum(); - let cmsgs_buffer_need_capacity = cmsgs_start + cmsgs_required_capacity; - cmsgs_buffer.resize(cmsgs_buffer_need_capacity, 0); + let capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum(); + let mut cmsgs_buffer = vec![0u8; capacity]; output.push(libc::mmsghdr { msg_hdr: pack_mhdr_to_send( - &mut cmsgs_buffer[cmsgs_start..], + &mut cmsgs_buffer, &d.iov, &d.cmsgs, d.addr.as_ref() ), msg_len: 0, }); + cmsgs_buffers.push(cmsgs_buffer); }; let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) }; -- cgit v1.2.3