fix(udp): zero control message array on fast-apple-datapath

`quinn-udp` with fast-apple-datapath previously did not initialize the
control message array memory before passing it to `recvmsg_x`.

On MacOS 10.15 `recvmsg_x` does not seem to set `msg_controllen`. Thus
`CMSG_NXTHDR` reads beyond the control messages written by `recvmsg_x`,
into the unitinialized memory region.

With this commit, the control message array is initialized (with zeroes)
before passing it to `recvmsg_x`, thus no longer reading unset control
messages.

See https://github.com/quinn-rs/quinn/issues/2214 for details.
This commit is contained in:
Max Leonard Inden
2025-04-29 09:58:19 +02:00
committed by Dirkjan Ochtman
parent 8936cc059c
commit 76b89160fa
+8 -2
View File
@@ -506,7 +506,13 @@ fn recv(io: SockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) ->
#[cfg(apple_fast)]
fn recv(io: SockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) -> io::Result<usize> {
let mut names = [MaybeUninit::<libc::sockaddr_storage>::uninit(); BATCH_SIZE];
let mut ctrls = [cmsg::Aligned(MaybeUninit::<[u8; CMSG_LEN]>::uninit()); BATCH_SIZE];
// MacOS 10.15 `recvmsg_x` does not override the `msghdr_x`
// `msg_controllen`. Thus, after the call to `recvmsg_x`, one does not know
// which control messages have been written to. To prevent reading
// uninitialized memory, do not use `MaybeUninit` for `ctrls`, instead
// initialize `ctrls` with `0`s. A control message of all `0`s is
// automatically skipped by `libc::CMSG_NXTHDR`.
let mut ctrls = [cmsg::Aligned([0u8; CMSG_LEN]); BATCH_SIZE];
let mut hdrs = unsafe { mem::zeroed::<[msghdr_x; BATCH_SIZE]>() };
let max_msg_count = bufs.len().min(BATCH_SIZE);
for i in 0..max_msg_count {
@@ -674,7 +680,7 @@ fn prepare_recv(
fn prepare_recv(
buf: &mut IoSliceMut,
name: &mut MaybeUninit<libc::sockaddr_storage>,
ctrl: &mut cmsg::Aligned<MaybeUninit<[u8; CMSG_LEN]>>,
ctrl: &mut cmsg::Aligned<[u8; CMSG_LEN]>,
hdr: &mut msghdr_x,
) {
hdr.msg_name = name.as_mut_ptr() as _;