Skip to content

Commit

Permalink
Fix spurious errors using sendmmsg with multiple cmsgs
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
eaufavor committed Apr 7, 2021
1 parent 6af11c1 commit 50fc2db
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
11 changes: 5 additions & 6 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1101,23 +1101,22 @@ pub fn sendmmsg<'a, I, C>(

let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);

let mut cmsgs_buffer = vec![0u8; 0];
let mut cmsgs_buffers = Vec::<Vec<u8>>::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 _) };
Expand Down

0 comments on commit 50fc2db

Please sign in to comment.