-
Notifications
You must be signed in to change notification settings - Fork 666
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix control message *decoding* and add support for ScmCredentials
#923
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good, especially the tests. Any idea why Travis didn't build this PR?
src/sys/socket/mod.rs
Outdated
// (although it claims the kernel header checks this), but such | ||
// a structure is clearly invalid, either way. | ||
// Safe if: `self.buf` is `cmsghdr`-aligned. | ||
let cmsg: &'a cmsghdr = unsafe { &*(self.buf[..mem::size_of::<cmsghdr>()].as_ptr() as *const cmsghdr) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you guarantee that self.buf is correctly aligned?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The caller does. In this case its done by the CmsgSpace
, which ensures alignment using a properly aligned member.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it's not the caller but whoever creates the iterator. Here, the buffer comes from recvmsg
and is a CmsgSpace
which guarantees alignment.
cmsg_data.as_ptr() as *const _, | ||
len)))) | ||
} | ||
let cmsg_data = &self.buf[cmsg_align(mem::size_of::<cmsghdr>())..cmsg_len]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Up above you requird self.buf to be aligned. Here, you seem to be handling the case where it isn't. Or am I misunderstanding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cmsg_align
just rounds up the size of cmsghdr
to the right alignment. This is needed to include the right padding to reach the payload.
src/sys/socket/mod.rs
Outdated
@@ -567,57 +569,95 @@ impl<'a> ControlMessage<'a> { | |||
} | |||
} | |||
|
|||
/// Returns the value to put into the `cmsg_type` field of the header. | |||
fn type_(&self) -> libc::c_int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like trailing underscores. How about naming this method cmsg_type
instead?
src/sys/socket/mod.rs
Outdated
|
||
match *self { | ||
ControlMessage::ScmRights(fds) => { | ||
let padlen = cmsg_align(mem::size_of_val(&cmsg)) - |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like padlen
and buf are identical for all cases. Can you move their definitions outside of the match
block?
I added (the previous commit was built by Travis and passed) |
Uh, now the old test fails? That's odd. EDIT: Uh okay the tests are really flaky - I suspect there's still some issues left |
I think the issues are in qemu. I haven't managed to get any socket tests failing on my Raspberry Pi 1 (armv6) or 2 (armv7). Additionally, I wrote a test program in C (https://gist.github.com/jonas-schievink/cb6e6584a055539d2113f22d91068e2d) that works fine on bare metal but also shows this behavior under qemu. The control message encoding for nix and the test program is identical, and it's the kernel (or qemu) that strips out the second message, not our decoder doing weird stuff. I'm going to build a smaller reproducer and report the bug to qemu, then |
test/sys/test_socket.rs
Outdated
@@ -301,14 +301,36 @@ fn test_scm_credentials() { | |||
/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single | |||
/// `sendmsg` call. | |||
#[cfg(any(target_os = "android", target_os = "linux"))] | |||
// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86-64 | |||
#[cfg_attr(not(target_arch = "x86_64"), ignore)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about i386? That doesn't use qemu on FreeBSD, and I don't think it does on Linux either.
test/sys/test_socket.rs
Outdated
@@ -301,14 +301,36 @@ fn test_scm_credentials() { | |||
/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single | |||
/// `sendmsg` call. | |||
#[cfg(any(target_os = "android", target_os = "linux"))] | |||
// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86-64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add an upstream bug link? Your C test case should make it easy to report.
src/sys/socket/mod.rs
Outdated
// (although it claims the kernel header checks this), but such | ||
// a structure is clearly invalid, either way. | ||
// Safe if: `self.buf` is `cmsghdr`-aligned. | ||
let cmsg: &'a cmsghdr = unsafe { &*(self.buf[..mem::size_of::<cmsghdr>()].as_ptr() as *const cmsghdr) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap to 80 columns, please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, now it LGTM. All it needs is a squash. @Susurrus any comments?
@jonas-schievink please squash this; then I'll merge it. |
@asomers This all look good? You asked for it to be squashed, which is has been. We could split this up into two commits with the other one added the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I'm cool.
bors r+ |
923: Fix control message *decoding* and add support for `ScmCredentials` r=asomers a=jonas-schievink While #918 fixed the *encoding*, the *decoding* done by the `CmsgIterator` still remained broken when multiple messages are received. However, since nix didn't support any control message that could reliably be sent twice in one `sendmsg` call, this couldn't be tested properly. This PR addresses this by adding `SCM_CREDENTIALS` support and testing all of this by passing both an `SCM_CREDENTIALS` and a `SCM_RIGHTS` message at the same time. I've also verified that the resulting encoding is the same as for roughly equivalent C code. Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
Timed out |
bors retry |
923: Fix control message *decoding* and add support for `ScmCredentials` r=asomers a=jonas-schievink While #918 fixed the *encoding*, the *decoding* done by the `CmsgIterator` still remained broken when multiple messages are received. However, since nix didn't support any control message that could reliably be sent twice in one `sendmsg` call, this couldn't be tested properly. This PR addresses this by adding `SCM_CREDENTIALS` support and testing all of this by passing both an `SCM_CREDENTIALS` and a `SCM_RIGHTS` message at the same time. I've also verified that the resulting encoding is the same as for roughly equivalent C code. Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
While #918 fixed the encoding, the decoding done by the
CmsgIterator
still remained broken when multiple messages are received. However, since nix didn't support any control message that could reliably be sent twice in onesendmsg
call, this couldn't be tested properly.This PR addresses this by adding
SCM_CREDENTIALS
support and testing all of this by passing both anSCM_CREDENTIALS
and aSCM_RIGHTS
message at the same time.I've also verified that the resulting encoding is the same as for roughly equivalent C code.