Skip to content

Commit 403cc5e

Browse files
committed
Do not align cmsg access on first header
The implementation of CmsgInterator did not correctly mirror the way the CMSG_FIRSTHDR and CMSG_NEXTHDR macros work in C. CMSG_FIRSTHDR does not attempt to align access since the pointer is already aligned due to being part of the msghdr struct. CmsgInterator was always aligning access which happened to work on all platforms except OpenBSD where the use of alignment was adding unexpected bytes to the expected size and causing the `cmsg_align(cmsg_len) > self.buf.len()` guard clause to return early.
1 parent 4c4f3c3 commit 403cc5e

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

src/sys/socket/mod.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,17 @@ impl<'a> RecvMsg<'a> {
121121
/// Iterate over the valid control messages pointed to by this
122122
/// msghdr.
123123
pub fn cmsgs(&self) -> CmsgIterator {
124-
CmsgIterator(self.cmsg_buffer)
124+
CmsgIterator{
125+
buf: self.cmsg_buffer,
126+
next: 0
127+
}
125128
}
126129
}
127130

128-
pub struct CmsgIterator<'a>(&'a [u8]);
131+
pub struct CmsgIterator<'a> {
132+
buf: &'a [u8],
133+
next: usize,
134+
}
129135

130136
impl<'a> Iterator for CmsgIterator<'a> {
131137
type Item = ControlMessage<'a>;
@@ -134,12 +140,11 @@ impl<'a> Iterator for CmsgIterator<'a> {
134140
// although we handle the invariants in slightly different places to
135141
// get a better iterator interface.
136142
fn next(&mut self) -> Option<ControlMessage<'a>> {
137-
let buf = self.0;
138143
let sizeof_cmsghdr = mem::size_of::<cmsghdr>();
139-
if buf.len() < sizeof_cmsghdr {
144+
if self.buf.len() < sizeof_cmsghdr {
140145
return None;
141146
}
142-
let cmsg: &cmsghdr = unsafe { mem::transmute(buf.as_ptr()) };
147+
let cmsg: &cmsghdr = unsafe { mem::transmute(self.buf.as_ptr()) };
143148

144149
// This check is only in the glibc implementation of CMSG_NXTHDR
145150
// (although it claims the kernel header checks this), but such
@@ -151,11 +156,21 @@ impl<'a> Iterator for CmsgIterator<'a> {
151156
let len = cmsg_len - sizeof_cmsghdr;
152157

153158
// Advance our internal pointer.
154-
if cmsg_align(cmsg_len) > buf.len() {
155-
println!("cmsg_align(cmsg_len) > buf.len(): {} > {}", cmsg_align(cmsg_len), buf.len());
156-
return None;
159+
if self.next == 0 {
160+
// CMSG_FIRSTHDR
161+
if cmsg_len > self.buf.len() {
162+
return None;
163+
}
164+
self.buf = &self.buf[cmsg_len..];
165+
}
166+
else {
167+
// CMSG_NXTHDR
168+
if cmsg_align(cmsg_len) > self.buf.len() {
169+
return None;
170+
}
171+
self.buf = &self.buf[cmsg_align(cmsg_len)..];
157172
}
158-
self.0 = &buf[cmsg_align(cmsg_len)..];
173+
self.next += 1;
159174

160175
match (cmsg.cmsg_level, cmsg.cmsg_type) {
161176
(SOL_SOCKET, SCM_RIGHTS) => unsafe {

0 commit comments

Comments
 (0)