fix(client): align the error-queue control buffer
The MSG_ERRQUEUE control buffer was a plain [u8; N], which only guarantees byte alignment. recvmsg's cmsgs() walks cmsghdr references out of that storage and requires cmsghdr alignment, so this mirrors the parent module's #[repr(align(8))] ControlBuffer instead of relying on incidental stack alignment.
This commit is contained in:
1 file changed
+15
-2
@@ -131,6 +131,19 @@ pub(crate) fn classify(cmsgs: impl Iterator<Item = ControlMessageOwned>) -> Erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reusable per-receive control buffer. `recvmsg` control data must satisfy
|
||||||
|
/// `cmsghdr` alignment; a plain `[u8; N]` only guarantees byte alignment, so
|
||||||
|
/// this mirrors the parent module's `ControlBuffer` rather than reading
|
||||||
|
/// `cmsghdr`s out of unaligned storage.
|
||||||
|
#[repr(align(8))]
|
||||||
|
struct ErrorQueueControlBuffer([u8; ERROR_QUEUE_CONTROL_LEN]);
|
||||||
|
|
||||||
|
impl ErrorQueueControlBuffer {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self([0; ERROR_QUEUE_CONTROL_LEN])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Nonblocking drain of a single record from `fd`'s `MSG_ERRQUEUE`.
|
/// Nonblocking drain of a single record from `fd`'s `MSG_ERRQUEUE`.
|
||||||
///
|
///
|
||||||
/// Returns `Ok(None)` when the queue is empty (`EAGAIN`/`EWOULDBLOCK`).
|
/// Returns `Ok(None)` when the queue is empty (`EAGAIN`/`EWOULDBLOCK`).
|
||||||
@@ -140,12 +153,12 @@ pub(crate) fn classify(cmsgs: impl Iterator<Item = ControlMessageOwned>) -> Erro
|
|||||||
pub(crate) fn try_recv_error_queue_record(fd: RawFd) -> io::Result<Option<ErrorQueueRecord>> {
|
pub(crate) fn try_recv_error_queue_record(fd: RawFd) -> io::Result<Option<ErrorQueueRecord>> {
|
||||||
let mut payload: [u8; 0] = [];
|
let mut payload: [u8; 0] = [];
|
||||||
let mut iov = [IoSliceMut::new(&mut payload)];
|
let mut iov = [IoSliceMut::new(&mut payload)];
|
||||||
let mut control = [0_u8; ERROR_QUEUE_CONTROL_LEN];
|
let mut control = ErrorQueueControlBuffer::new();
|
||||||
|
|
||||||
match recvmsg::<()>(
|
match recvmsg::<()>(
|
||||||
fd,
|
fd,
|
||||||
&mut iov,
|
&mut iov,
|
||||||
Some(&mut control),
|
Some(&mut control.0),
|
||||||
MsgFlags::MSG_ERRQUEUE | MsgFlags::MSG_DONTWAIT,
|
MsgFlags::MSG_ERRQUEUE | MsgFlags::MSG_DONTWAIT,
|
||||||
) {
|
) {
|
||||||
Ok(msg) => {
|
Ok(msg) => {
|
||||||
|
|||||||
Reference in new issue
Block a user